abook_database.php 10 KB

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