documenting options class
[squirrelmail.git] / functions / abook_database.php
CommitLineData
9b9474d6 1<?php
62f7daa5 2
35586184 3/**
4 * abook_database.php
5 *
82d304a0 6 * Copyright (c) 1999-2004 The SquirrelMail Project Team
35586184 7 * Licensed under the GNU GPL. For full terms see the file COPYING.
8 *
9 * Backend for personal addressbook stored in a database,
10 * accessed using the DB-classes in PEAR.
11 *
12 * IMPORTANT: The PEAR modules must be in the include path
13 * for this class to work.
14 *
15 * An array with the following elements must be passed to
16 * the class constructor (elements marked ? are optional):
17 *
18 * dsn => database DNS (see PEAR for syntax)
19 * table => table to store addresses in (must exist)
20 * owner => current user (owner of address data)
21 * ? writeable => set writeable flag (true/false)
22 *
23 * The table used should have the following columns:
24 * owner, nickname, firstname, lastname, email, label
25 * The pair (owner,nickname) should be unique (primary key).
26 *
27 * NOTE. This class should not be used directly. Use the
28 * "AddressBook" class instead.
29 *
a9d318b0 30 * @version $Id$
d6c32258 31 * @package squirrelmail
a9d318b0 32 * @subpackage addressbook
35586184 33 */
d6c32258 34
62f7daa5 35/** Needs the DB functions */
c9fcea56 36if (!include_once('DB.php')) {
37 // same error also in db_prefs.php
38 require_once(SM_PATH . 'functions/display_messages.php');
39 $error = _("Could not include PEAR database functions required for the database backend.") . "<br />\n";
2ad4cea9 40 $error .= sprintf(_("Is PEAR installed, and is the include path set correctly to find %s?"),
41 '<tt>DB.php</tt>') . "<br />\n";
c9fcea56 42 $error .= _("Please contact your system administrator and report this error.");
43 error_box($error, $color);
17fca61d 44 exit;
c9fcea56 45}
d6c32258 46
47/**
48 * Undocumented class - stores the addressbook in a sql database
49 * @package squirrelmail
50 */
9b9474d6 51class abook_database extends addressbook_backend {
52 var $btype = 'local';
53 var $bname = 'database';
62f7daa5 54
9b9474d6 55 var $dsn = '';
56 var $table = '';
57 var $owner = '';
58 var $dbh = false;
62f7daa5 59
9b9474d6 60 var $writeable = true;
62f7daa5 61
9b9474d6 62 /* ========================== Private ======================= */
62f7daa5 63
9b9474d6 64 /* Constructor */
65 function abook_database($param) {
66 $this->sname = _("Personal address book");
62f7daa5 67
9b9474d6 68 if (is_array($param)) {
62f7daa5 69 if (empty($param['dsn']) ||
70 empty($param['table']) ||
9b9474d6 71 empty($param['owner'])) {
72 return $this->set_error('Invalid parameters');
73 }
62f7daa5 74
91be2362 75 $this->dsn = $param['dsn'];
76 $this->table = $param['table'];
77 $this->owner = $param['owner'];
62f7daa5 78
9b9474d6 79 if (!empty($param['name'])) {
91be2362 80 $this->sname = $param['name'];
9b9474d6 81 }
7902aca2 82
9b9474d6 83 if (isset($param['writeable'])) {
91be2362 84 $this->writeable = $param['writeable'];
9b9474d6 85 }
7902aca2 86
30e9932c 87 if (isset($param['listing'])) {
88 $this->listing = $param['listing'];
89 }
90
7902aca2 91 $this->open(true);
9b9474d6 92 }
93 else {
91be2362 94 return $this->set_error('Invalid argument to constructor');
9b9474d6 95 }
96 }
62f7daa5 97
98
9b9474d6 99 /* Open the database. New connection if $new is true */
100 function open($new = false) {
101 $this->error = '';
62f7daa5 102
9b9474d6 103 /* Return true is file is open and $new is unset */
104 if ($this->dbh && !$new) {
7902aca2 105 return true;
9b9474d6 106 }
62f7daa5 107
9b9474d6 108 /* Close old file, if any */
109 if ($this->dbh) {
110 $this->close();
111 }
62f7daa5 112
9b9474d6 113 $dbh = DB::connect($this->dsn, true);
62f7daa5 114
286fe80b 115 if (DB::isError($dbh)) {
701c9c6b 116 return $this->set_error(sprintf(_("Database error: %s"),
7902aca2 117 DB::errorMessage($dbh)));
9b9474d6 118 }
62f7daa5 119
9b9474d6 120 $this->dbh = $dbh;
121 return true;
122 }
7902aca2 123
9b9474d6 124 /* Close the file and forget the filehandle */
125 function close() {
126 $this->dbh->disconnect();
127 $this->dbh = false;
128 }
7902aca2 129
9b9474d6 130 /* ========================== Public ======================== */
62f7daa5 131
9b9474d6 132 /* Search the file */
133 function &search($expr) {
134 $ret = array();
135 if(!$this->open()) {
7902aca2 136 return false;
9b9474d6 137 }
30e9932c 138
9b9474d6 139 /* To be replaced by advanded search expression parsing */
140 if (is_array($expr)) {
141 return;
142 }
143
144 /* Make regexp from glob'ed expression */
145 $expr = str_replace('?', '_', $expr);
146 $expr = str_replace('*', '%', $expr);
147 $expr = $this->dbh->quoteString($expr);
148 $expr = "%$expr%";
149
150 $query = sprintf("SELECT * FROM %s WHERE owner='%s' AND " .
151 "(firstname LIKE '%s' OR lastname LIKE '%s')",
152 $this->table, $this->owner, $expr, $expr);
153 $res = $this->dbh->query($query);
154
155 if (DB::isError($res)) {
701c9c6b 156 return $this->set_error(sprintf(_("Database error: %s"),
7902aca2 157 DB::errorMessage($res)));
9b9474d6 158 }
7902aca2 159
9b9474d6 160 while ($row = $res->fetchRow(DB_FETCHMODE_ASSOC)) {
91be2362 161 array_push($ret, array('nickname' => $row['nickname'],
162 'name' => "$row[firstname] $row[lastname]",
163 'firstname' => $row['firstname'],
164 'lastname' => $row['lastname'],
165 'email' => $row['email'],
166 'label' => $row['label'],
167 'backend' => $this->bnum,
168 'source' => &$this->sname));
9b9474d6 169 }
170 return $ret;
171 }
62f7daa5 172
9b9474d6 173 /* Lookup alias */
174 function &lookup($alias) {
175 if (empty($alias)) {
7902aca2 176 return array();
9b9474d6 177 }
62f7daa5 178
9b9474d6 179 $alias = strtolower($alias);
7902aca2 180
9b9474d6 181 if (!$this->open()) {
7902aca2 182 return false;
9b9474d6 183 }
62f7daa5 184
2c90a9f2 185 $query = sprintf("SELECT * FROM %s WHERE owner='%s' AND LOWER(nickname)='%s'",
11f2b6ba 186 $this->table, $this->owner, $this->dbh->quoteString($alias));
7902aca2 187
9b9474d6 188 $res = $this->dbh->query($query);
7902aca2 189
9b9474d6 190 if (DB::isError($res)) {
701c9c6b 191 return $this->set_error(sprintf(_("Database error: %s"),
7902aca2 192 DB::errorMessage($res)));
9b9474d6 193 }
7902aca2 194
9b9474d6 195 if ($row = $res->fetchRow(DB_FETCHMODE_ASSOC)) {
91be2362 196 return array('nickname' => $row['nickname'],
197 'name' => "$row[firstname] $row[lastname]",
198 'firstname' => $row['firstname'],
199 'lastname' => $row['lastname'],
200 'email' => $row['email'],
201 'label' => $row['label'],
202 'backend' => $this->bnum,
203 'source' => &$this->sname);
9b9474d6 204 }
205 return array();
206 }
207
208 /* List all addresses */
209 function &list_addr() {
210 $ret = array();
211 if (!$this->open()) {
7902aca2 212 return false;
9b9474d6 213 }
62f7daa5 214
91e0dccc 215 if(isset($this->listing) && !$this->listing) {
216 return array();
217 }
30e9932c 218
7902aca2 219
9b9474d6 220 $query = sprintf("SELECT * FROM %s WHERE owner='%s'",
221 $this->table, $this->owner);
7902aca2 222
9b9474d6 223 $res = $this->dbh->query($query);
62f7daa5 224
9b9474d6 225 if (DB::isError($res)) {
701c9c6b 226 return $this->set_error(sprintf(_("Database error: %s"),
7902aca2 227 DB::errorMessage($res)));
9b9474d6 228 }
7902aca2 229
9b9474d6 230 while ($row = $res->fetchRow(DB_FETCHMODE_ASSOC)) {
91be2362 231 array_push($ret, array('nickname' => $row['nickname'],
232 'name' => "$row[firstname] $row[lastname]",
233 'firstname' => $row['firstname'],
234 'lastname' => $row['lastname'],
235 'email' => $row['email'],
236 'label' => $row['label'],
237 'backend' => $this->bnum,
238 'source' => &$this->sname));
9b9474d6 239 }
240 return $ret;
241 }
7902aca2 242
9b9474d6 243 /* Add address */
244 function add($userdata) {
245 if (!$this->writeable) {
701c9c6b 246 return $this->set_error(_("Addressbook is read-only"));
9b9474d6 247 }
7902aca2 248
9b9474d6 249 if (!$this->open()) {
7902aca2 250 return false;
9b9474d6 251 }
62f7daa5 252
9b9474d6 253 /* See if user exist already */
254 $ret = $this->lookup($userdata['nickname']);
255 if (!empty($ret)) {
b9bfd165 256 return $this->set_error(sprintf(_("User '%s' already exist"),
91be2362 257 $ret['nickname']));
9b9474d6 258 }
259
260 /* Create query */
261 $query = sprintf("INSERT INTO %s (owner, nickname, firstname, " .
262 "lastname, email, label) VALUES('%s','%s','%s'," .
263 "'%s','%s','%s')",
264 $this->table, $this->owner,
265 $this->dbh->quoteString($userdata['nickname']),
62f7daa5 266 $this->dbh->quoteString($userdata['firstname']),
9b9474d6 267 $this->dbh->quoteString($userdata['lastname']),
62f7daa5 268 $this->dbh->quoteString($userdata['email']),
9b9474d6 269 $this->dbh->quoteString($userdata['label']) );
270
271 /* Do the insert */
7902aca2 272 $r = $this->dbh->simpleQuery($query);
9b9474d6 273 if ($r == DB_OK) {
274 return true;
275 }
7902aca2 276
9b9474d6 277 /* Fail */
701c9c6b 278 return $this->set_error(sprintf(_("Database error: %s"),
7902aca2 279 DB::errorMessage($r)));
9b9474d6 280 }
7902aca2 281
9b9474d6 282 /* Delete address */
283 function remove($alias) {
284 if (!$this->writeable) {
701c9c6b 285 return $this->set_error(_("Addressbook is read-only"));
9b9474d6 286 }
7902aca2 287
9b9474d6 288 if (!$this->open()) {
7902aca2 289 return false;
9b9474d6 290 }
62f7daa5 291
9b9474d6 292 /* Create query */
293 $query = sprintf("DELETE FROM %s WHERE owner='%s' AND (",
294 $this->table, $this->owner);
7902aca2 295
9b9474d6 296 $sepstr = '';
297 while (list($undef, $nickname) = each($alias)) {
16a973d7 298 $query .= sprintf("%s nickname='%s' ", $sepstr,
7902aca2 299 $this->dbh->quoteString($nickname));
91be2362 300 $sepstr = 'OR';
9b9474d6 301 }
302 $query .= ')';
7902aca2 303
9b9474d6 304 /* Delete entry */
305 $r = $this->dbh->simpleQuery($query);
306 if ($r == DB_OK) {
307 return true;
308 }
7902aca2 309
9b9474d6 310 /* Fail */
311 return $this->set_error(sprintf(_("Database error: %s"),
7902aca2 312 DB::errorMessage($r)));
9b9474d6 313 }
7902aca2 314
9b9474d6 315 /* Modify address */
316 function modify($alias, $userdata) {
317 if (!$this->writeable) {
701c9c6b 318 return $this->set_error(_("Addressbook is read-only"));
9b9474d6 319 }
7902aca2 320
9b9474d6 321 if (!$this->open()) {
7902aca2 322 return false;
9b9474d6 323 }
62f7daa5 324
9b9474d6 325 /* See if user exist */
326 $ret = $this->lookup($alias);
327 if (empty($ret)) {
701c9c6b 328 return $this->set_error(sprintf(_("User '%s' does not exist"),
7902aca2 329 $alias));
9b9474d6 330 }
331
332 /* Create query */
333 $query = sprintf("UPDATE %s SET nickname='%s', firstname='%s', ".
334 "lastname='%s', email='%s', label='%s' ".
335 "WHERE owner='%s' AND nickname='%s'",
62f7daa5 336 $this->table,
9b9474d6 337 $this->dbh->quoteString($userdata['nickname']),
62f7daa5 338 $this->dbh->quoteString($userdata['firstname']),
9b9474d6 339 $this->dbh->quoteString($userdata['lastname']),
62f7daa5 340 $this->dbh->quoteString($userdata['email']),
9b9474d6 341 $this->dbh->quoteString($userdata['label']),
342 $this->owner,
343 $this->dbh->quoteString($alias) );
344
345 /* Do the insert */
346 $r = $this->dbh->simpleQuery($query);
347 if ($r == DB_OK) {
348 return true;
349 }
7902aca2 350
9b9474d6 351 /* Fail */
352 return $this->set_error(sprintf(_("Database error: %s"),
353 DB::errorMessage($r)));
354 }
355} /* End of class abook_database */
7902aca2 356
c9fcea56 357// vim: et ts=4
62f7daa5 358?>