Fix for namespace parsing. UWash has a namespace prefix without a delimiter, which...
[squirrelmail.git] / functions / abook_local_file.php
index 274e19dad0b4c3c88bbace443271cdbb5331b776..4b2b9a751407b608cab107ec1fa4bbb7dc77dede 100644 (file)
@@ -81,6 +81,13 @@ class abook_local_file extends addressbook_backend {
      * @var string
      */
     var $umask;
+    /**
+     * Sets max entry size (number of bytes used for all address book fields 
+     * (including escapes) + 4 delimiters + 1 linefeed)
+     * @var integer
+     * @since 1.5.2
+     */
+    var $line_length = 2048;
 
     /* ========================== Private ======================= */
 
@@ -122,6 +129,9 @@ class abook_local_file extends addressbook_backend {
             if(isset($param['listing'])) {
                 $this->listing = $param['listing'];
             }
+            if(isset($param['line_length']) && ! empty($param['line_length'])) {
+                $this->line_length = (int) $param['line_length'];
+            }
 
             $this->open(true);
         } else {
@@ -274,22 +284,32 @@ class abook_local_file extends addressbook_backend {
         }
         @rewind($this->filehandle);
 
-        while ($row = @fgetcsv($this->filehandle, 2048, '|')) {
-            $line = join(' ', $row);
-            /**
-             * TODO: regexp search is supported only in local_file backend.
-             * Do we check format of regexp or ignore errors?
-             */
-            // errors on eregi call are suppressed in order to prevent display of regexp compilation errors
-            if(@eregi($expr, $line)) {
-                array_push($res, array('nickname'  => $row[0],
-                    'name'      => $row[1] . ' ' . $row[2],
-                    'firstname' => $row[1],
-                    'lastname'  => $row[2],
-                    'email'     => $row[3],
-                    'label'     => $row[4],
-                    'backend'   => $this->bnum,
-                    'source'    => &$this->sname));
+        while ($row = @fgetcsv($this->filehandle, $this->line_length, '|')) {
+            if (count($row)<5) {
+                /**
+                 * address book is corrupted.
+                 */
+                global $oTemplate;
+                error_box(_("Address book is corrupted. Required fields are missing."));
+                $oTemplate->display('footer.tpl');
+                die();
+            } else {
+                $line = join(' ', $row);
+                /**
+                 * TODO: regexp search is supported only in local_file backend.
+                 * Do we check format of regexp or ignore errors?
+                 */
+                // errors on eregi call are suppressed in order to prevent display of regexp compilation errors
+                if(@eregi($expr, $line)) {
+                    array_push($res, array('nickname'  => $row[0],
+                        'name'      => $this->fullname($row[1], $row[2]),
+                        'firstname' => $row[1],
+                        'lastname'  => $row[2],
+                        'email'     => $row[3],
+                        'label'     => $row[4],
+                        'backend'   => $this->bnum,
+                        'source'    => &$this->sname));
+                }
             }
         }
 
@@ -311,16 +331,26 @@ class abook_local_file extends addressbook_backend {
         $this->open();
         @rewind($this->filehandle);
 
-        while ($row = @fgetcsv($this->filehandle, 2048, '|')) {
-            if(strtolower($row[0]) == $alias) {
-                return array('nickname'  => $row[0],
-                  'name'      => $row[1] . ' ' . $row[2],
-                  'firstname' => $row[1],
-                  'lastname'  => $row[2],
-                  'email'     => $row[3],
-                  'label'     => $row[4],
-                  'backend'   => $this->bnum,
-                  'source'    => &$this->sname);
+        while ($row = @fgetcsv($this->filehandle, $this->line_length, '|')) {
+            if (count($row)<5) {
+                /**
+                 * address book is corrupted.
+                 */
+                global $oTemplate;
+                error_box(_("Address book is corrupted. Required fields are missing."));
+                $oTemplate->display('footer.tpl');
+                die();
+            } else {
+                if(strtolower($row[0]) == $alias) {
+                   return array('nickname'  => $row[0],
+                      'name'      => $this->fullname($row[1], $row[2]),
+                      'firstname' => $row[1],
+                      'lastname'  => $row[2],
+                      'email'     => $row[3],
+                      'label'     => $row[4],
+                      'backend'   => $this->bnum,
+                      'source'    => &$this->sname);
+                }
             }
         }
 
@@ -341,15 +371,26 @@ class abook_local_file extends addressbook_backend {
         $this->open();
         @rewind($this->filehandle);
 
-        while ($row = @fgetcsv($this->filehandle, 2048, '|')) {
-            array_push($res, array('nickname'  => $row[0],
-                'name'      => $row[1] . ' ' . $row[2],
-                'firstname' => $row[1],
-                'lastname'  => $row[2],
-                'email'     => $row[3],
-                'label'     => $row[4],
-                'backend'   => $this->bnum,
-                'source'    => &$this->sname));
+        while ($row = @fgetcsv($this->filehandle, $this->line_length, '|')) {
+            if (count($row)<5) {
+                /**
+                 * address book is corrupted. Don't be nice to people that 
+                 * violate address book formating.
+                 */
+                global $oTemplate;
+                error_box(_("Address book is corrupted. Required fields are missing."));
+                $oTemplate->display('footer.tpl');
+                die();
+            } else {
+                array_push($res, array('nickname'  => $row[0],
+                    'name'      => $this->fullname($row[1], $row[2]),
+                    'firstname' => $row[1],
+                    'lastname'  => $row[2],
+                    'email'     => $row[3],
+                    'label'     => $row[4],
+                    'backend'   => $this->bnum,
+                    'source'    => &$this->sname));
+            }
         }
         return $res;
     }
@@ -361,7 +402,7 @@ class abook_local_file extends addressbook_backend {
      */
     function add($userdata) {
         if(!$this->writeable) {
-            return $this->set_error(_("Addressbook is read-only"));
+            return $this->set_error(_("Address book is read-only"));
         }
         /* See if user exists already */
         $ret = $this->lookup($userdata['nickname']);
@@ -379,13 +420,22 @@ class abook_local_file extends addressbook_backend {
 
         /* Strip linefeeds */
         $data = ereg_replace("[\r\n]", ' ', $data);
+
+        /**
+         * Make sure that entry fits into allocated record space.
+         * One byte is reserved for linefeed
+         */
+        if (strlen($data) >= $this->line_length) {
+            return $this->set_error(_("Address book entry is too big"));
+        }
+
         /* 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"));
+            return $this->set_error(_("Address book is read-only"));
         }
 
         /* Lock the file */
@@ -402,7 +452,7 @@ class abook_local_file extends addressbook_backend {
         /* Test write result */
         if($r === FALSE) {
             /* Fail */
-            $this->set_error(_("Write to addressbook failed"));
+            $this->set_error(_("Write to address book failed"));
             return FALSE;
         }
 
@@ -416,7 +466,7 @@ class abook_local_file extends addressbook_backend {
      */
     function remove($alias) {
         if(!$this->writeable) {
-            return $this->set_error(_("Addressbook is read-only"));
+            return $this->set_error(_("Address book is read-only"));
         }
 
         /* Lock the file to make sure we're the only process working
@@ -429,7 +479,7 @@ class abook_local_file extends addressbook_backend {
         @rewind($this->filehandle);
         $i = 0;
         $rows = array();
-        while($row = @fgetcsv($this->filehandle, 2048, '|')) {
+        while($row = @fgetcsv($this->filehandle, $this->line_length, '|')) {
             if(!in_array($row[0], $alias)) {
                 $rows[$i++] = $row;
             }
@@ -453,7 +503,7 @@ class abook_local_file extends addressbook_backend {
      */
     function modify($alias, $userdata) {
         if(!$this->writeable) {
-            return $this->set_error(_("Addressbook is read-only"));
+            return $this->set_error(_("Address book is read-only"));
         }
 
         /* See if user exists */
@@ -462,20 +512,39 @@ class abook_local_file extends addressbook_backend {
             // i18n: don't use html formating in translation
             return $this->set_error(sprintf(_("User \"%s\" does not exist"),$alias));
         }
-
+        
+        /* If the alias changed, see if the new alias exists */
+        if (strtolower($alias) != strtolower($userdata['nickname'])) {
+            $ret = $this->lookup($userdata['nickname']);
+            if (!empty($ret)) {
+                return $this->set_error(sprintf(_("User \"%s\" already exists"), $userdata['nickname']));
+            }
+        }
+        
         /* 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"));
         }
 
+        /* calculate userdata size */
+        $data = $this->quotevalue($userdata['nickname']) . '|'
+            . $this->quotevalue($userdata['firstname']) . '|'
+            . $this->quotevalue((!empty($userdata['lastname'])?$userdata['lastname']:'')) . '|'
+            . $this->quotevalue($userdata['email']) . '|'
+            . $this->quotevalue((!empty($userdata['label'])?$userdata['label']:''));
+        /* make sure that it fits into allocated space */
+        if (strlen($data) >= $this->line_length) {
+            return $this->set_error(_("Address book entry is too big"));
+        }
+        
         /* Read file into memory, modifying the data for the
          * user identified by $alias */
         $this->open(true);
         @rewind($this->filehandle);
         $i = 0;
         $rows = array();
-        while($row = @fgetcsv($this->filehandle, 2048, '|')) {
+        while($row = @fgetcsv($this->filehandle, $this->line_length, '|')) {
             if(strtolower($row[0]) != strtolower($alias)) {
                 $rows[$i++] = $row;
             } else {
@@ -510,6 +579,4 @@ class abook_local_file extends addressbook_backend {
         }
         return $value;
     }
-
-} /* End of class abook_local_file */
-?>
+}