094467650af3daa73e04628a12373390fd7fd958
4 ** abook_local_file.php
6 ** Backend for addressbook as a pipe separated file
8 ** An array with the following elements must be passed to
9 ** the class constructor (elements marked ? are optional):
11 ** filename => path to addressbook file
12 ** ? create => if true: file is created if it does not exist.
13 ** ? umask => umask set before opening file.
15 ** NOTE. This class should not be used directly. Use the
16 ** "AddressBook" class instead.
21 class abook_local_file
extends addressbook_backend
{
23 var $bname = 'local_file';
30 // ========================== Private =======================
33 function abook_local_file($param) {
34 $this->sname
= _('Personal address book');
35 $this->umask
= Umask();
37 if(is_array($param)) {
38 if(empty($param['filename']))
39 return $this->set_error('Invalid parameters');
40 if(!is_string($param['filename']))
41 return $this->set_error($param['filename'] . ': '.
42 _('Not a file name'));
44 $this->filename
= $param['filename'];
48 if(isset($param['umask']))
49 $this->umask
= $param['umask'];
51 if(!empty($param['name']))
52 $this->sname
= $param['name'];
56 $this->set_error('Invalid argument to constructor');
60 // Open the addressbook file and store the file pointer.
61 // Use $file as the file to open, or the class' own
62 // filename property. If $param is empty and file is
64 function open($new = false) {
66 $file = $this->filename
;
67 $create = $this->create
;
69 // Return true is file is open and $new is unset
70 if($this->filehandle
&& !$new)
73 // Check that new file exitsts
74 if((!(file_exists($file) && is_readable($file))) && !$create)
75 return $this->set_error("$file: " . _('No such file or directory'));
77 // Close old file, if any
78 if($this->filehandle
) $this->close();
80 // Open file. First try to open for reading and writing,
81 // but fall back to read only.
83 $fh = @fopen
($file, 'a+');
85 $this->filehandle
= &$fh;
86 $this->filename
= $file;
87 $this->writeable
= true;
89 $fh = @fopen
($file, 'r');
91 $this->filehandle
= &$fh;
92 $this->filename
= $file;
93 $this->writeable
= false;
95 return $this->set_error("$file: " . _('Open failed'));
102 // Close the file and forget the filehandle
104 @fclose
($this->filehandle
);
105 $this->filehandle
= 0;
106 $this->filename
= '';
107 $this->writable
= false;
110 // Lock the datafile - try 20 times in 5 seconds
112 for($i = 0 ; $i < 20 ; $i++
) {
113 if(flock($this->filehandle
, 2 +
4))
123 return flock($this->filehandle
, 3);
126 // Overwrite the file with data from $rows
127 // NOTE! Previous locks are broken by this function
128 function overwrite($rows) {
129 $newfh = @fopen
($this->filename
, 'w');
131 return $this->set_error("$file: " . _('Open failed'));
133 for($i = 0 ; $i < sizeof($rows) ; $i++
) {
134 if(is_array($rows[$i]))
135 fwrite($newfh, join('|', $rows[$i]) . "\n");
144 // ========================== Public ========================
147 function search($expr) {
149 // To be replaced by advanded search expression parsing
150 if(is_array($expr)) return;
152 // Make regexp from glob'ed expression
153 $expr = ereg_replace('\?', '.', $expr);
154 $expr = ereg_replace('\*', '.*', $expr);
160 @rewind
($this->filehandle
);
162 while ($row = @fgetcsv
($this->filehandle
, 2048, '|')) {
163 $line = join(' ', $row);
164 if(eregi($expr, $line)) {
165 array_push($res, array('nickname' => $row[0],
166 'name' => $row[1] . ' ' . $row[2],
167 'firstname' => $row[1],
168 'lastname' => $row[2],
171 'backend' => $this->bnum
,
172 'source' => &$this->sname
));
180 function lookup($alias) {
184 $alias = strtolower($alias);
187 @rewind
($this->filehandle
);
189 while ($row = @fgetcsv
($this->filehandle
, 2048, '|')) {
190 if(strtolower($row[0]) == $alias) {
191 return array('nickname' => $row[0],
192 'name' => $row[1] . ' ' . $row[2],
193 'firstname' => $row[1],
194 'lastname' => $row[2],
197 'backend' => $this->bnum
,
198 'source' => &$this->sname
);
205 // List all addresses
206 function list_addr() {
209 @rewind
($this->filehandle
);
211 while ($row = @fgetcsv
($this->filehandle
, 2048, '|')) {
212 array_push($res, array('nickname' => $row[0],
213 'name' => $row[1] . ' ' . $row[2],
214 'firstname' => $row[1],
215 'lastname' => $row[2],
218 'backend' => $this->bnum
,
219 'source' => &$this->sname
));
225 function add($userdata) {
226 if(!$this->writeable
)
227 return $this->set_error(_('Addressbook is read-only'));
229 // See if user exist already
230 $ret = $this->lookup($userdata['nickname']);
232 return $this->set_error(sprintf(_('User \'%s\' already exist'),
235 // Here is the data to write
236 $data = $userdata['nickname'] . '|' . $userdata['firstname'] . '|' .
237 $userdata['lastname'] . '|' . $userdata['email'] . '|' .
240 $data = ereg_replace("[\r\n]", ' ', $data);
241 // Add linefeed at end
242 $data = $data . "\n";
244 // Reopen file, just to be sure
246 if(!$this->writeable
)
247 return $this->set_error(_('Addressbook is read-only'));
251 return $this->set_error(_('Could not lock datafile'));
254 $r = fwrite($this->filehandle
, $data);
259 // Test write result and exit if OK
260 if($r > 0) return true;
263 $this->set_error(_('Write to addressbook failed'));
268 function remove($alias) {
269 if(!$this->writeable
)
270 return $this->set_error(_('Addressbook is read-only'));
272 // Lock the file to make sure we're the only process working
275 return $this->set_error(_('Could not lock datafile'));
277 // Read file into memory, ignoring nicknames to delete
279 @rewind
($this->filehandle
);
282 while($row = @fgetcsv
($this->filehandle
, 2048, '|')) {
283 if(!in_array($row[0], $alias))
288 if(!$this->overwrite(&$rows)) {
298 function modify($alias, $userdata) {
299 if(!$this->writeable
)
300 return $this->set_error(_('Addressbook is read-only'));
303 $ret = $this->lookup($alias);
305 return $this->set_error(sprintf(_('User \'%s\' does not exist'),
308 // Lock the file to make sure we're the only process working
311 return $this->set_error(_('Could not lock datafile'));
313 // Read file into memory, modifying the data for the
314 // user identifyed by $alias
316 @rewind
($this->filehandle
);
319 while($row = @fgetcsv
($this->filehandle
, 2048, '|')) {
320 if(strtolower($row[0]) != strtolower($alias)) {
323 $rows[$i++
] = array(0 => $userdata['nickname'],
324 1 => $userdata['firstname'],
325 2 => $userdata['lastname'],
326 3 => $userdata['email'],
327 4 => $userdata['label']);
332 if(!$this->overwrite(&$rows)) {
341 } // End of class abook_local_file