abook_database.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. <?php {
  2. /**
  3. ** abook_database.php
  4. **
  5. ** Backend for personal addressbook stored in a database,
  6. ** accessed using the DB-classes in PEAR.
  7. **
  8. ** IMPORTANT: The PEAR modules must be in the include path
  9. ** for this class to work.
  10. **
  11. ** An array with the following elements must be passed to
  12. ** the class constructor (elements marked ? are optional):
  13. **
  14. ** dsn => database DNS (see PEAR for syntax)
  15. ** table => table to store addresses in (must exist)
  16. ** owner => current user (owner of address data)
  17. ** ? writeable => set writeable flag (true/false)
  18. **
  19. ** The table used should have the following columns:
  20. ** owner, nickname, firstname, lastname, email, label
  21. ** The pair (owner,nickname) should be unique (primary key).
  22. **
  23. ** NOTE. This class should not be used directly. Use the
  24. ** "AddressBook" class instead.
  25. **
  26. ** $Id$
  27. **/
  28. require_once('DB.php');
  29. class abook_database extends addressbook_backend {
  30. var $btype = 'local';
  31. var $bname = 'database';
  32. var $dsn = '';
  33. var $table = '';
  34. var $owner = '';
  35. var $dbh = false;
  36. var $writeable = true;
  37. // ========================== Private =======================
  38. // Constructor
  39. function abook_database($param) {
  40. $this->sname = _("Personal address book");
  41. if(is_array($param)) {
  42. if(empty($param['dsn']) ||
  43. empty($param['table']) ||
  44. empty($param['owner']))
  45. return $this->set_error('Invalid parameters');
  46. $this->dsn = $param['dsn'];
  47. $this->table = $param['table'];
  48. $this->owner = $param['owner'];
  49. if(!empty($param['name']))
  50. $this->sname = $param['name'];
  51. if(isset($param['writeable']))
  52. $this->writeable = $param['writeable'];
  53. $this->open(true);
  54. } else {
  55. return $this->set_error('Invalid argument to constructor');
  56. }
  57. }
  58. // Open the database. New connection if $new is true
  59. function open($new = false) {
  60. $this->error = '';
  61. // Return true is file is open and $new is unset
  62. if($this->dbh && !$new)
  63. return true;
  64. // Close old file, if any
  65. if($this->dbh) $this->close();
  66. $dbh = DB::connect($this->dsn, true);
  67. if(DB::isError($dbh) || DB::isWarning($dbh))
  68. return $this->set_error(sprintf(_("Database error: %s"),
  69. DB::errorMessage($dbh)));
  70. $this->dbh = $dbh;
  71. return true;
  72. }
  73. // Close the file and forget the filehandle
  74. function close() {
  75. $this->dbh->disconnect();
  76. $this->dbh = false;
  77. }
  78. // ========================== Public ========================
  79. // Search the file
  80. function &search($expr) {
  81. $ret = array();
  82. if(!$this->open())
  83. return false;
  84. // To be replaced by advanded search expression parsing
  85. if(is_array($expr)) return;
  86. // Make regexp from glob'ed expression
  87. $expr = str_replace('?', '_', $expr);
  88. $expr = str_replace('*', '%', $expr);
  89. $expr = $this->dbh->quoteString($expr);
  90. $expr = "%$expr%";
  91. $query = sprintf("SELECT * FROM %s WHERE owner='%s' AND " .
  92. "(firstname LIKE '%s' OR lastname LIKE '%s')",
  93. $this->table, $this->owner, $expr, $expr);
  94. $res = $this->dbh->query($query);
  95. if(DB::isError($res))
  96. return $this->set_error(sprintf(_("Database error: %s"),
  97. DB::errorMessage($res)));
  98. while ($row = $res->fetchRow(DB_FETCHMODE_ASSOC)) {
  99. array_push($ret, array('nickname' => $row['nickname'],
  100. 'name' => "$row[firstname] $row[lastname]",
  101. 'firstname' => $row['firstname'],
  102. 'lastname' => $row['lastname'],
  103. 'email' => $row['email'],
  104. 'label' => $row['label'],
  105. 'backend' => $this->bnum,
  106. 'source' => &$this->sname));
  107. }
  108. return $ret;
  109. }
  110. // Lookup alias
  111. function &lookup($alias) {
  112. if(empty($alias))
  113. return array();
  114. $alias = strtolower($alias);
  115. if(!$this->open())
  116. return false;
  117. $query = sprintf("SELECT * FROM %s WHERE owner='%s' AND nickname='%s'",
  118. $this->table, $this->owner, $alias);
  119. $res = $this->dbh->query($query);
  120. if(DB::isError($res))
  121. return $this->set_error(sprintf(_("Database error: %s"),
  122. DB::errorMessage($res)));
  123. if ($row = $res->fetchRow(DB_FETCHMODE_ASSOC)) {
  124. return array('nickname' => $row['nickname'],
  125. 'name' => "$row[firstname] $row[lastname]",
  126. 'firstname' => $row['firstname'],
  127. 'lastname' => $row['lastname'],
  128. 'email' => $row['email'],
  129. 'label' => $row['label'],
  130. 'backend' => $this->bnum,
  131. 'source' => &$this->sname);
  132. }
  133. return array();
  134. }
  135. // List all addresses
  136. function &list_addr() {
  137. $ret = array();
  138. if(!$this->open())
  139. return false;
  140. $query = sprintf("SELECT * FROM %s WHERE owner='%s'",
  141. $this->table, $this->owner);
  142. $res = $this->dbh->query($query);
  143. if(DB::isError($res))
  144. return $this->set_error(sprintf(_("Database error: %s"),
  145. DB::errorMessage($res)));
  146. while ($row = $res->fetchRow(DB_FETCHMODE_ASSOC)) {
  147. array_push($ret, array('nickname' => $row['nickname'],
  148. 'name' => "$row[firstname] $row[lastname]",
  149. 'firstname' => $row['firstname'],
  150. 'lastname' => $row['lastname'],
  151. 'email' => $row['email'],
  152. 'label' => $row['label'],
  153. 'backend' => $this->bnum,
  154. 'source' => &$this->sname));
  155. }
  156. return $ret;
  157. }
  158. // Add address
  159. function add($userdata) {
  160. if(!$this->writeable)
  161. return $this->set_error(_("Addressbook is read-only"));
  162. if(!$this->open())
  163. return false;
  164. // See if user exist already
  165. $ret = $this->lookup($userdata['nickname']);
  166. if(!empty($ret))
  167. return $this->set_error(sprintf(_("User '%s' already exist"),
  168. $ret['nickname']));
  169. // Create query
  170. $query = sprintf("INSERT INTO %s (owner, nickname, firstname, " .
  171. "lastname, email, label) VALUES('%s','%s','%s'," .
  172. "'%s','%s','%s')",
  173. $this->table, $this->owner,
  174. $this->dbh->quoteString($userdata['nickname']),
  175. $this->dbh->quoteString($userdata['firstname']),
  176. $this->dbh->quoteString($userdata['lastname']),
  177. $this->dbh->quoteString($userdata['email']),
  178. $this->dbh->quoteString($userdata['label']) );
  179. // Do the insert
  180. $r = $this->dbh->simpleQuery($query);
  181. if($r == DB_OK) return true;
  182. // Fail
  183. return $this->set_error(sprintf(_("Database error: %s"),
  184. DB::errorMessage($r)));
  185. }
  186. // Delete address
  187. function remove($alias) {
  188. if(!$this->writeable)
  189. return $this->set_error(_("Addressbook is read-only"));
  190. if(!$this->open())
  191. return false;
  192. // Create query
  193. $query = sprintf("DELETE FROM %s WHERE owner='%s' AND (",
  194. $this->table, $this->owner);
  195. $sepstr = '';
  196. while(list($undef, $nickname) = each($alias)) {
  197. $query .= sprintf("%s nickname='%s' ", $sepstr,
  198. $this->dbh->quoteString($nickname));
  199. $sepstr = 'OR';
  200. }
  201. $query .= ')';
  202. // Delete entry
  203. $r = $this->dbh->simpleQuery($query);
  204. if($r == DB_OK) return true;
  205. // Fail
  206. return $this->set_error(sprintf(_("Database error: %s"),
  207. DB::errorMessage($r)));
  208. }
  209. // Modify address
  210. function modify($alias, $userdata) {
  211. if(!$this->writeable)
  212. return $this->set_error(_("Addressbook is read-only"));
  213. if(!$this->open())
  214. return false;
  215. // See if user exist
  216. $ret = $this->lookup($alias);
  217. if(empty($ret))
  218. return $this->set_error(sprintf(_("User '%s' does not exist"),
  219. $alias));
  220. // Create query
  221. $query = sprintf("UPDATE %s SET nickname='%s', firstname='%s', ".
  222. "lastname='%s', email='%s', label='%s' ".
  223. "WHERE owner='%s' AND nickname='%s'",
  224. $this->table,
  225. $this->dbh->quoteString($userdata['nickname']),
  226. $this->dbh->quoteString($userdata['firstname']),
  227. $this->dbh->quoteString($userdata['lastname']),
  228. $this->dbh->quoteString($userdata['email']),
  229. $this->dbh->quoteString($userdata['label']),
  230. $this->owner,
  231. $this->dbh->quoteString($alias) );
  232. // Do the insert
  233. $r = $this->dbh->simpleQuery($query);
  234. if($r == DB_OK) return true;
  235. // Fail
  236. return $this->set_error(sprintf(_("Database error: %s"),
  237. DB::errorMessage($r)));
  238. }
  239. } // End of class abook_database
  240. } ?>