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 |
36 | if (!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 |
51 | class abook_database extends addressbook_backend { |
52 | var $btype = 'local'; |
53 | var $bname = 'database'; |
7902aca2 |
54 | |
9b9474d6 |
55 | var $dsn = ''; |
56 | var $table = ''; |
57 | var $owner = ''; |
58 | var $dbh = false; |
7902aca2 |
59 | |
9b9474d6 |
60 | var $writeable = true; |
7902aca2 |
61 | |
9b9474d6 |
62 | /* ========================== Private ======================= */ |
7902aca2 |
63 | |
9b9474d6 |
64 | /* Constructor */ |
65 | function abook_database($param) { |
66 | $this->sname = _("Personal address book"); |
7902aca2 |
67 | |
9b9474d6 |
68 | if (is_array($param)) { |
69 | if (empty($param['dsn']) || |
70 | empty($param['table']) || |
71 | empty($param['owner'])) { |
72 | return $this->set_error('Invalid parameters'); |
73 | } |
7902aca2 |
74 | |
91be2362 |
75 | $this->dsn = $param['dsn']; |
76 | $this->table = $param['table']; |
77 | $this->owner = $param['owner']; |
7902aca2 |
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 | } |
7902aca2 |
97 | |
98 | |
9b9474d6 |
99 | /* Open the database. New connection if $new is true */ |
100 | function open($new = false) { |
101 | $this->error = ''; |
7902aca2 |
102 | |
9b9474d6 |
103 | /* Return true is file is open and $new is unset */ |
104 | if ($this->dbh && !$new) { |
7902aca2 |
105 | return true; |
9b9474d6 |
106 | } |
7902aca2 |
107 | |
9b9474d6 |
108 | /* Close old file, if any */ |
109 | if ($this->dbh) { |
110 | $this->close(); |
111 | } |
7902aca2 |
112 | |
9b9474d6 |
113 | $dbh = DB::connect($this->dsn, true); |
7902aca2 |
114 | |
286fe80b |
115 | if (DB::isError($dbh)) { |
701c9c6b |
116 | return $this->set_error(sprintf(_("Database error: %s"), |
7902aca2 |
117 | DB::errorMessage($dbh))); |
9b9474d6 |
118 | } |
7902aca2 |
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 ======================== */ |
7902aca2 |
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 | } |
7902aca2 |
172 | |
9b9474d6 |
173 | /* Lookup alias */ |
174 | function &lookup($alias) { |
175 | if (empty($alias)) { |
7902aca2 |
176 | return array(); |
9b9474d6 |
177 | } |
7902aca2 |
178 | |
9b9474d6 |
179 | $alias = strtolower($alias); |
7902aca2 |
180 | |
9b9474d6 |
181 | if (!$this->open()) { |
7902aca2 |
182 | return false; |
9b9474d6 |
183 | } |
7902aca2 |
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 | } |
30e9932c |
214 | |
168c8dd0 |
215 | if(isset($this->listing) && !$this->listing) { |
30e9932c |
216 | return array(); |
217 | } |
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); |
224 | |
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 | } |
7902aca2 |
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']), |
266 | $this->dbh->quoteString($userdata['firstname']), |
267 | $this->dbh->quoteString($userdata['lastname']), |
268 | $this->dbh->quoteString($userdata['email']), |
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 | } |
7902aca2 |
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 | } |
7902aca2 |
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'", |
336 | $this->table, |
337 | $this->dbh->quoteString($userdata['nickname']), |
338 | $this->dbh->quoteString($userdata['firstname']), |
339 | $this->dbh->quoteString($userdata['lastname']), |
340 | $this->dbh->quoteString($userdata['email']), |
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 | |
358 | // vim: et ts=4 |
9b9474d6 |
359 | ?> |