4 ** abook_local_file.php
6 ** Copyright (c) 1999-2001 The Squirrelmail Development Team
7 ** Licensed under the GNU GPL. For full terms see the file COPYING.
9 ** Backend for addressbook as a pipe separated file
11 ** An array with the following elements must be passed to
12 ** the class constructor (elements marked ? are optional):
14 ** filename => path to addressbook file
15 ** ? create => if true: file is created if it does not exist.
16 ** ? umask => umask set before opening file.
18 ** NOTE. This class should not be used directly. Use the
19 ** "AddressBook" class instead.
24 class abook_local_file
extends addressbook_backend
{
26 var $bname = 'local_file';
33 // ========================== Private =======================
36 function abook_local_file($param) {
37 $this->sname
= _("Personal address book");
38 $this->umask
= Umask();
40 if(is_array($param)) {
41 if(empty($param['filename']))
42 return $this->set_error('Invalid parameters');
43 if(!is_string($param['filename']))
44 return $this->set_error($param['filename'] . ': '.
45 _("Not a file name"));
47 $this->filename
= $param['filename'];
51 if(isset($param['umask']))
52 $this->umask
= $param['umask'];
54 if(!empty($param['name']))
55 $this->sname
= $param['name'];
59 $this->set_error('Invalid argument to constructor');
63 // Open the addressbook file and store the file pointer.
64 // Use $file as the file to open, or the class' own
65 // filename property. If $param is empty and file is
67 function open($new = false) {
69 $file = $this->filename
;
70 $create = $this->create
;
72 // Return true is file is open and $new is unset
73 if($this->filehandle
&& !$new)
76 // Check that new file exitsts
77 if((!(file_exists($file) && is_readable($file))) && !$create)
78 return $this->set_error("$file: " . _("No such file or directory"));
80 // Close old file, if any
81 if($this->filehandle
) $this->close();
83 // Open file. First try to open for reading and writing,
84 // but fall back to read only.
86 $fh = @fopen
($file, 'a+');
88 $this->filehandle
= &$fh;
89 $this->filename
= $file;
90 $this->writeable
= true;
92 $fh = @fopen
($file, 'r');
94 $this->filehandle
= &$fh;
95 $this->filename
= $file;
96 $this->writeable
= false;
98 return $this->set_error("$file: " . _("Open failed"));
105 // Close the file and forget the filehandle
107 @fclose
($this->filehandle
);
108 $this->filehandle
= 0;
109 $this->filename
= '';
110 $this->writable
= false;
113 // Lock the datafile - try 20 times in 5 seconds
115 for($i = 0 ; $i < 20 ; $i++
) {
116 if(flock($this->filehandle
, 2 +
4))
126 return flock($this->filehandle
, 3);
129 // Overwrite the file with data from $rows
130 // NOTE! Previous locks are broken by this function
131 function overwrite(&$rows) {
132 $newfh = @fopen
($this->filename
, 'w');
134 return $this->set_error("$file: " . _("Open failed"));
136 for($i = 0 ; $i < sizeof($rows) ; $i++
) {
137 if(is_array($rows[$i]))
138 fwrite($newfh, join('|', $rows[$i]) . "\n");
147 // ========================== Public ========================
150 function search($expr) {
152 // To be replaced by advanded search expression parsing
153 if(is_array($expr)) return;
155 // Make regexp from glob'ed expression
156 // May want to quote other special characters like (, ), -, [, ], etc.
157 $expr = str_replace('?', '.', $expr);
158 $expr = str_replace('*', '.*', $expr);
164 @rewind
($this->filehandle
);
166 while ($row = @fgetcsv
($this->filehandle
, 2048, '|')) {
167 $line = join(' ', $row);
168 if(eregi($expr, $line)) {
169 array_push($res, array('nickname' => $row[0],
170 'name' => $row[1] . ' ' . $row[2],
171 'firstname' => $row[1],
172 'lastname' => $row[2],
175 'backend' => $this->bnum
,
176 'source' => &$this->sname
));
184 function lookup($alias) {
188 $alias = strtolower($alias);
191 @rewind
($this->filehandle
);
193 while ($row = @fgetcsv
($this->filehandle
, 2048, '|')) {
194 if(strtolower($row[0]) == $alias) {
195 return array('nickname' => $row[0],
196 'name' => $row[1] . ' ' . $row[2],
197 'firstname' => $row[1],
198 'lastname' => $row[2],
201 'backend' => $this->bnum
,
202 'source' => &$this->sname
);
209 // List all addresses
210 function list_addr() {
213 @rewind
($this->filehandle
);
215 while ($row = @fgetcsv
($this->filehandle
, 2048, '|')) {
216 array_push($res, array('nickname' => $row[0],
217 'name' => $row[1] . ' ' . $row[2],
218 'firstname' => $row[1],
219 'lastname' => $row[2],
222 'backend' => $this->bnum
,
223 'source' => &$this->sname
));
229 function add($userdata) {
230 if(!$this->writeable
)
231 return $this->set_error(_("Addressbook is read-only"));
233 // See if user exist already
234 $ret = $this->lookup($userdata['nickname']);
236 return $this->set_error(sprintf(_("User '%s' already exist"),
239 // Here is the data to write
240 $data = $userdata['nickname'] . '|' . $userdata['firstname'] . '|' .
241 $userdata['lastname'] . '|' . $userdata['email'] . '|' .
244 $data = ereg_replace("[\r\n]", ' ', $data);
245 // Add linefeed at end
246 $data = $data . "\n";
248 // Reopen file, just to be sure
250 if(!$this->writeable
)
251 return $this->set_error(_("Addressbook is read-only"));
255 return $this->set_error(_("Could not lock datafile"));
258 $r = fwrite($this->filehandle
, $data);
263 // Test write result and exit if OK
264 if($r > 0) return true;
267 $this->set_error(_("Write to addressbook failed"));
272 function remove($alias) {
273 if(!$this->writeable
)
274 return $this->set_error(_("Addressbook is read-only"));
276 // Lock the file to make sure we're the only process working
279 return $this->set_error(_("Could not lock datafile"));
281 // Read file into memory, ignoring nicknames to delete
282 @rewind
($this->filehandle
);
285 while($row = @fgetcsv
($this->filehandle
, 2048, '|')) {
286 if(!in_array($row[0], $alias))
291 if(!$this->overwrite($rows)) {
301 function modify($alias, $userdata) {
302 if(!$this->writeable
)
303 return $this->set_error(_("Addressbook is read-only"));
306 $ret = $this->lookup($alias);
308 return $this->set_error(sprintf(_("User '%s' does not exist"),
311 // Lock the file to make sure we're the only process working
314 return $this->set_error(_("Could not lock datafile"));
316 // Read file into memory, modifying the data for the
317 // user identifyed by $alias
319 @rewind
($this->filehandle
);
322 while($row = @fgetcsv
($this->filehandle
, 2048, '|')) {
323 if(strtolower($row[0]) != strtolower($alias)) {
326 $rows[$i++
] = array(0 => $userdata['nickname'],
327 1 => $userdata['firstname'],
328 2 => $userdata['lastname'],
329 3 => $userdata['email'],
330 4 => $userdata['label']);
335 if(!$this->overwrite($rows)) {
344 } // End of class abook_local_file