X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=functions%2Fabook_local_file.php;h=04c1eaa2137a80766b2b6741b6b1aea14161ee27;hb=d1404257de24eeda2a60f4619fe5a4875a7d9c8e;hp=904893e4ca7349b9487d0f0d81477b5595403de5;hpb=06b4facd9478c9f1b4464a0f6ef3895ec8d92bf9;p=squirrelmail.git diff --git a/functions/abook_local_file.php b/functions/abook_local_file.php index 904893e4..04c1eaa2 100644 --- a/functions/abook_local_file.php +++ b/functions/abook_local_file.php @@ -3,7 +3,7 @@ /** * abook_local_file.php * - * Copyright (c) 1999-2002 The SquirrelMail Project Team + * Copyright (c) 1999-2004 The SquirrelMail Project Team * Licensed under the GNU GPL. For full terms see the file COPYING. * * Backend for addressbook as a pipe separated file @@ -18,9 +18,15 @@ * NOTE. This class should not be used directly. Use the * "AddressBook" class instead. * - * $Id$ + * @version $Id$ + * @package squirrelmail + * @subpackage addressbook */ +/** + * Store the addressbook in a local file + * @package squirrelmail + */ class abook_local_file extends addressbook_backend { var $btype = 'local'; var $bname = 'local_file'; @@ -57,7 +63,7 @@ class abook_local_file extends addressbook_backend { if(!empty($param['name'])) { $this->sname = $param['name']; } - + $this->open(true); } else { $this->set_error('Invalid argument to constructor'); @@ -65,27 +71,27 @@ class abook_local_file extends addressbook_backend { } /* Open the addressbook file and store the file pointer. - * Use $file as the file to open, or the class' own - * filename property. If $param is empty and file is + * Use $file as the file to open, or the class' own + * filename property. If $param is empty and file is * open, do nothing. */ function open($new = false) { $this->error = ''; $file = $this->filename; $create = $this->create; - + /* Return true is file is open and $new is unset */ if($this->filehandle && !$new) { return true; } - + /* Check that new file exitsts */ if((!(file_exists($file) && is_readable($file))) && !$create) { return $this->set_error("$file: " . _("No such file or directory")); } - + /* Close old file, if any */ if($this->filehandle) { $this->close(); } - + /* Open file. First try to open for reading and writing, * but fall back to read only. */ umask($this->umask); @@ -118,7 +124,7 @@ class abook_local_file extends addressbook_backend { /* Lock the datafile - try 20 times in 5 seconds */ function lock() { for($i = 0 ; $i < 20 ; $i++) { - if(flock($this->filehandle, 2 + 4)) + if(flock($this->filehandle, 2 + 4)) return true; else usleep(250000); @@ -134,42 +140,54 @@ class abook_local_file extends addressbook_backend { /* Overwrite the file with data from $rows * NOTE! Previous locks are broken by this function */ function overwrite(&$rows) { - $newfh = @fopen($this->filename, 'w'); + $this->unlock(); + $newfh = @fopen($this->filename.'.tmp', 'w'); + if(!$newfh) { - return $this->set_error("$file: " . _("Open failed")); + return $this->set_error($this->filename. '.tmp:' . _("Open failed")); } - - for($i = 0 ; $i < sizeof($rows) ; $i++) { + + for($i = 0, $cnt=sizeof($rows) ; $i < $cnt ; $i++) { if(is_array($rows[$i])) { - fwrite($newfh, join('|', $rows[$i]) . "\n"); + for($j = 0, $cnt_part=count($rows[$i]) ; $j < $cnt_part ; $j++) { + $rows[$i][$j] = $this->quotevalue($rows[$i][$j]); + } + $tmpwrite = sq_fwrite($newfh, join('|', $rows[$i]) . "\n"); + if ($tmpwrite === FALSE) { + return $this->set_error($this->filename . '.tmp:' . _("Write failed")); + } } - } + } fclose($newfh); + if (!@copy($this->filename . '.tmp' , $this->filename)) { + return $this->set_error($this->filename . ':' . _("Unable to update")); + } + @unlink($this->filename . '.tmp'); $this->unlock(); $this->open(true); return true; } - + /* ========================== Public ======================== */ - + /* Search the file */ function search($expr) { /* To be replaced by advanded search expression parsing */ if(is_array($expr)) { return; } - + /* Make regexp from glob'ed expression * May want to quote other special characters like (, ), -, [, ], etc. */ $expr = str_replace('?', '.', $expr); $expr = str_replace('*', '.*', $expr); - + $res = array(); if(!$this->open()) { return false; } @rewind($this->filehandle); - + while ($row = @fgetcsv($this->filehandle, 2048, '|')) { $line = join(' ', $row); if(eregi($expr, $line)) { @@ -183,10 +201,10 @@ class abook_local_file extends addressbook_backend { 'source' => &$this->sname)); } } - + return $res; } - + /* Lookup alias */ function lookup($alias) { if(empty($alias)) { @@ -194,10 +212,10 @@ class abook_local_file extends addressbook_backend { } $alias = strtolower($alias); - + $this->open(); @rewind($this->filehandle); - + while ($row = @fgetcsv($this->filehandle, 2048, '|')) { if(strtolower($row[0]) == $alias) { return array('nickname' => $row[0], @@ -210,7 +228,7 @@ class abook_local_file extends addressbook_backend { 'source' => &$this->sname); } } - + return array(); } @@ -219,7 +237,7 @@ class abook_local_file extends addressbook_backend { $res = array(); $this->open(); @rewind($this->filehandle); - + while ($row = @fgetcsv($this->filehandle, 2048, '|')) { array_push($res, array('nickname' => $row[0], 'name' => $row[1] . ' ' . $row[2], @@ -244,39 +262,44 @@ class abook_local_file extends addressbook_backend { return $this->set_error(sprintf(_("User '%s' already exist"), $ret['nickname'])); } - + /* Here is the data to write */ - $data = $userdata['nickname'] . '|' . $userdata['firstname'] . '|' . - $userdata['lastname'] . '|' . $userdata['email'] . '|' . - $userdata['label']; + $data = $this->quotevalue($userdata['nickname']) . '|' . + $this->quotevalue($userdata['firstname']) . '|' . + $this->quotevalue($userdata['lastname']) . '|' . + $this->quotevalue($userdata['email']) . '|' . + $this->quotevalue($userdata['label']); + /* Strip linefeeds */ $data = ereg_replace("[\r\n]", ' ', $data); /* Add linefeed at end */ $data = $data . "\n"; - + /* Reopen file, just to be sure */ $this->open(true); if(!$this->writeable) { return $this->set_error(_("Addressbook is read-only")); } - + /* Lock the file */ if(!$this->lock()) { return $this->set_error(_("Could not lock datafile")); } - + /* Write */ - $r = fwrite($this->filehandle, $data); - + $r = sq_fwrite($this->filehandle, $data); + /* Unlock file */ $this->unlock(); - - /* Test write result and exit if OK */ - if($r > 0) return true; - - /* Fail */ - $this->set_error(_("Write to addressbook failed")); - return false; + + /* Test write result */ + if($r === FALSE) { + /* Fail */ + $this->set_error(_("Write to addressbook failed")); + return FALSE; + } + + return TRUE; } /* Delete address */ @@ -284,13 +307,13 @@ class abook_local_file extends addressbook_backend { if(!$this->writeable) { return $this->set_error(_("Addressbook is read-only")); } - + /* Lock the file to make sure we're the only process working * on it. */ if(!$this->lock()) { return $this->set_error(_("Could not lock datafile")); } - + /* Read file into memory, ignoring nicknames to delete */ @rewind($this->filehandle); $i = 0; @@ -300,13 +323,13 @@ class abook_local_file extends addressbook_backend { $rows[$i++] = $row; } } - + /* Write data back */ if(!$this->overwrite($rows)) { $this->unlock(); return false; } - + $this->unlock(); return true; } @@ -316,21 +339,21 @@ class abook_local_file extends addressbook_backend { if(!$this->writeable) { return $this->set_error(_("Addressbook is read-only")); } - + /* See if user exists */ $ret = $this->lookup($alias); if(empty($ret)) { return $this->set_error(sprintf(_("User '%s' does not exist"), $alias)); } - + /* Lock the file to make sure we're the only process working * on it. */ if(!$this->lock()) { return $this->set_error(_("Could not lock datafile")); } - - /* Read file into memory, modifying the data for the + + /* Read file into memory, modifying the data for the * user identified by $alias */ $this->open(true); @rewind($this->filehandle); @@ -343,20 +366,30 @@ class abook_local_file extends addressbook_backend { $rows[$i++] = array(0 => $userdata['nickname'], 1 => $userdata['firstname'], 2 => $userdata['lastname'], - 3 => $userdata['email'], + 3 => $userdata['email'], 4 => $userdata['label']); } } - + /* Write data back */ if(!$this->overwrite($rows)) { $this->unlock(); return false; } - + $this->unlock(); return true; } - + + /* Function for quoting values before saving */ + function quotevalue($value) { + /* Quote the field if it contains | or ". Double quotes need to + * be replaced with "" */ + if(ereg("[|\"]", $value)) { + $value = '"' . str_replace('"', '""', $value) . '"'; + } + return $value; + } + } /* End of class abook_local_file */ ?> \ No newline at end of file