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