steffen: server/kolab-resource-handlers/kolab-resource-handlers/freebusy freebusyimapcache.class.php, NONE, 1.1 freebusyldap_dummy.class.php, NONE, 1.1 freebusy.class.php.in, 1.5, 1.6 freebusy.conf, 1.2, 1.3 freebusy.php.in, 1.3, 1.4 freebusycache.class.php.in, 1.5, 1.6 misc.php, 1.6, 1.7 pfb.php.in, 1.5, 1.6

cvs at kolab.org cvs at kolab.org
Wed Oct 25 04:28:59 CEST 2006


Author: steffen

Update of /kolabrepository/server/kolab-resource-handlers/kolab-resource-handlers/freebusy
In directory doto:/tmp/cvs-serv30232/kolab-resource-handlers/freebusy

Modified Files:
	freebusy.class.php.in freebusy.conf freebusy.php.in 
	freebusycache.class.php.in misc.php pfb.php.in 
Added Files:
	freebusyimapcache.class.php freebusyldap_dummy.class.php 
Log Message:
freebusy imap caching from Martin

--- NEW FILE: freebusyimapcache.class.php ---
<?php
/*
 *  Copyright (c) 2005 Intra2net AG
 *  Copyright (c) 2006 erfrakon Partnerschaftsgesellschaft
 *
 *    Written by Thomas Jarosch <thomas.jarosch at intra2net.com>
 *    Written by Martin Konold <martin.konold at erfrakon.de>
 *
 *  This  program is free  software; you can redistribute  it and/or
 *  modify it  under the terms of the GNU  General Public License as
 *  published by the  Free Software Foundation; either version 2, or
 *  (at your option) any later version.
 *
 *  This program is  distributed in the hope that it will be useful,
 *  but WITHOUT  ANY WARRANTY; without even the  implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 *  General Public License for more details.
 *
 *  You can view the  GNU General Public License, online, at the GNU
 *  Project's homepage; see <http://www.gnu.org/licenses/gpl.html>.
 */

 /* Class to efficently cache kolab events stored on an IMAP server */

class FreeBusyIMAPCache {
  var $version;       // internal version of format
  var $store_prefix;  // prefix to prepend to all file operations
  var $owner;         // folder owner
  var $foldername;    // folder name
  var $cache_modified;      // indicates if we have to writeout the cache
  var $cache;         // cache data

  function FreeBusyIMAPCache($store_prefix, &$owner, &$foldername) {
    $this->store_prefix = $store_prefix;
    $this->owner = $owner;
    $this->foldername = $foldername;
    $this->version = 1;
    $this->reset_cache();
  }
  
  function reset_cache() {
    $this->cache = array();
    $this->cache["version"] = $this->version;
    $this->cache["uidvalidity"] = -1;
    $this->cache["uidnext"] = -1;
    $this->cache["incidences-for"] = "";
    $this->cache["imap2fb"] = array();
    $this->cache_modified = true;
  }

  function check_folder_changed($uidvalidity, $uidnext, $incidences_for, &$new_uids) {
    $changed = false;
    // uidvalidity changed?
    if ($uidvalidity != $this->cache["uidvalidity"]) {
      myLog("uidvalidity changed (old: ".$this->cache["uidvalidity"].", new: $uidvalidity), clearing cache", RM_LOG_DEBUG);
      $this->reset_cache();
      $changed = true;
    }

    // uidnext changed?
    if ($uidnext != $this->cache["uidnext"]) {
      myLog("uidnext on folder changed (old: ".$this->cache["uidnext"].", new: ".$uidnext.")", RM_LOG_DEBUG);
      $changed = true;
    }

    // incidences-for changed?
    if ($incidences_for != $this->cache["incidences-for"]) {
      myLog("incidences-for changed (old: ".$this->cache["incidences-for"].", new: $incidences_for), clearing cache", RM_LOG_DEBUG);
      $this->reset_cache();
      $changed = true;
    }

    $this->cache["uidvalidity"] = $uidvalidity;
    $this->cache["uidnext"] = $uidnext;
    $this->cache["incidences-for"] = $incidences_for;

    // deleted a message?
    $old_uids = array_keys($this->cache["imap2fb"]);
    while(list($key, $old_uid) = each($old_uids)) {
      if (!in_array($old_uid, $new_uids)) {
        unset($this->cache["imap2fb"][$old_uid]);
        $this->cache_modified = true;
        $changed = true;
      }
    }

    if (!$changed)
      myLog("check_changed: folder didn't change", RM_LOG_DEBUG);
      return $changed;
    }

    function check_uid_exists($uid) {
      return array_key_exists($uid, $this->cache["imap2fb"]);
    }

    function add_empty_imap2fb(&$imap_uid) {
      $this->cache["imap2fb"][$imap_uid] = array();
      $this->cache_modified = true;
    }

    function add_imap2fb(&$imap_uid, $fb_start, $fb_end, $fb_duration, $fb_extra) {
      /*
           Internal imap2fb array structure:
           0..n IMAP uid
           |----------- 0..n free/busy periods
                        |----------- start
                        |----------- end
                        |----------- duration
                        |----------- extra
      */
      myLog("added event to store: uid: $imap_uid, start: $fb_start, end: $fb_end, duration: $fb_duration", RM_LOG_DEBUG);

      $store = array();
      $store["start"] = $fb_start;
      $store["end"] = $fb_end;
      $store["duration"] = $fb_duration;
      $store["extra"] = $fb_extra;

      $this->cache["imap2fb"][$imap_uid][] = $store;
      $this->cache_modified = true;
    }

    function output_fb(&$vFb) {
      reset($this->cache["imap2fb"]);
      while(list($uid, $periods) = each($this->cache["imap2fb"]))
         while(list($key, $period) = each($periods))
            $vFb->addBusyPeriod('BUSY', $period["start"], $period["end"], $period["duration"], $period["extra"]);
    }


    function compute_filename() {
      $folder_parts = explode('/', $this->foldername);
      unset($folder_parts[0]);
      $folder_storename = join('/', $folder_parts);

      $folder_storename = str_replace(".", "^", $folder_storename);
      $folder_storename = str_replace("\0", "", $folder_storename);

       $full_path = $this->store_prefix.$folder_storename.".imapcache";
       return $full_path;
    }

    function cache_load() {
      $filename = $this->compute_filename();

      myLog("Trying to load file: $filename", RM_LOG_DEBUG);

      if (!is_readable($filename))
        return false;

      $this->cache = unserialize(file_get_contents($filename));

      // Delete disc cache if it's from an old version
      if ($this->cache["version"] != $this->version) {
        myLog("Version mismatch (got: ".$this->cache["version"].", current: ".$this->version.", dropping cache", RM_LOG_WARN);
        $this->reset_cache();
      } 
      else $this->cache_modified = false;
      return true;
    }

    function cache_store($force=false) {
      if ($this->cache_modified || $force) {
        $filename = $this->compute_filename();
        myLog("Trying to save cache to file: $filename", RM_LOG_DEBUG);

        if (!$this->mkdirhier(dirname($filename))) {
          myLog("can't create director hierachy: ".dirname($filename), RM_LOG_ERROR);
          return;
        }

        $tmpname = tempnam(dirname($this->store_prefix), 'imapcache');
        $fp = fopen($tmpname, 'w');
        if(!$fp) return false;
          if (fwrite($fp, serialize($this->cache)) === false) {
            fclose ($fp);
            myLog("can't write to file: $tmpname. Out of discspace?", RM_LOG_ERROR);
            return;
          }

        if(!rename($tmpname, $filename)) {
           myLog("can't rename $tmpname to $filename", RM_LOG_ERROR);
           return false;
        }
        fclose($fp);
        $this->cache_modified = false;
      } 
      else {
        myLog("IMAPcache unmodified, not saving", RM_LOG_DEBUG);
      }	
    }

   function cache_delete() {
     unlink($this->compute_filename());
     $this->reset_cache();
   }

   function mkdirhier( $dirname ) {
     $base = substr($dirname,0,strrpos($dirname,'/'));
     $base = str_replace(".", "^", $base);
     if( !empty( $base ) && !is_dir( $base ) ) {
       if( !$this->mkdirhier( $base ) ) return false;
     }
     if( !file_exists( $dirname ) ) return mkdir( $dirname, 0755 );
     return true;
    }
};

?>


--- NEW FILE: freebusyldap_dummy.class.php ---
<?php
/*
 *  Copyright (c) 2005 Intra2net AG
 *  Copyright (c) 2006 erfrakon Partnerschaftsgesellschaft
 *
 *    Written by Thomas Jarosch <thomas.jarosch at intra2net.com>
 *    Written by Martin Konold <martin.konold at erfrakon.de>
 *
 *  This  program is free  software; you can redistribute  it and/or
 *  modify it  under the terms of the GNU  General Public License as
 *  published by the  Free Software Foundation; either version 2, or
 *  (at your option) any later version.
 *
 *  This program is  distributed in the hope that it will be useful,
 *  but WITHOUT  ANY WARRANTY; without even the  implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 *  General Public License for more details.
 *
 *  You can view the  GNU General Public License, online, at the GNU
 *  Project's homepage; see <http://www.gnu.org/licenses/gpl.html>.
 */

class FreeBusyLDAP {
  function FreeBusyLDAP( $uri, $base ) {
    return true;
  }

  function error() {
    return "LDAP::error not implemented";
  }

  function close() {
    return true;
  }

  function bind( $dn = false , $pw = '' ) {
    return true;
  }

  function freeBusyPast() {
    return 0;  // Default
  }

  // Return a hash of info about a user
  function userInfo( $uid ) {
    $rtn = array();

    $rtn["MAIL"] = $uid;
    $rtn["HOMESERVER"] = "";
    $rtn["FBFUTURE"] = 60;

    return $rtn;
  }

  function mailForUid( $uid ) {
    return $uid;
  }

  function homeServer( $uid ) {
    return "localhost";
  }

  function dn( $uid ) {
    return "";
  }

  function distlists( $dn ) {
    return array();
  }
};

?>


Index: freebusy.class.php.in
===================================================================
RCS file: /kolabrepository/server/kolab-resource-handlers/kolab-resource-handlers/freebusy/freebusy.class.php.in,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- freebusy.class.php.in	30 Apr 2006 02:35:47 -0000	1.5
+++ freebusy.class.php.in	25 Oct 2006 02:28:57 -0000	1.6
@@ -1,8 +1,11 @@
 <?php
 /*
- *  Copyright (c) 2004 Klaraelvdalens Datakonsult AB
+ *  Copyright (c) 2004-12006 Klaraelvdalens Datakonsult AB, Intra2net AG,
+ *                            erfrakon Partnerschaftsgesellschaft
  *
  *    Written by Steffen Hansen <steffen at klaralvdalens-datakonsult.se>
+ *               Thomas Jarosch <thomas.jarosch at intra2net.com>
+ *               Martin Konold <martin.konold at erfrakon.de>
  *
  *  This  program is free  software; you can redistribute  it and/or
  *  modify it  under the terms of the GNU  General Public License as
@@ -18,75 +21,104 @@
  *  Project's homepage; see <http://www.gnu.org/licenses/gpl.html>.
  */
 
+ /*
+    TODO: Looks like we don't get called for deleted folders.
+         Best thing would be to have a cron script which deletes
+         unmodified pfbs/caches after 2 months.
+ */
+
+
+require_once '@kolab_php_module_prefix at freebusy/freebusycache.class.php';
+require_once '@kolab_php_module_prefix at freebusy/freebusyimapcache.class.php';
 require_once '@kolab_php_module_prefix at freebusy/recurrence.class.php';
 
 class FreeBusyRecurrence extends Recurrence {
-  function FreeBusyRecurrence( &$vfb, &$extra ) {
+  function FreeBusyRecurrence( &$imapcache, &$imapuid, &$vfb, &$extra ) {
+    $this->imapcache =& $imapcache;
+    $this->imapuid =& $imapuid;
     $this->vfb =& $vfb;
     $this->extra =& $extra;
   }
 
   function setBusy( $start, $end, $duration ) {
-    $this->vfb->addBusyPeriod('BUSY', $start, null, $duration, $this->extra);
+    $this->imapcache->add_imap2fb($this->imapuid, $start, null, $duration, $this->extra);
   }
 
+  var $imapcache;
   var $vfb;
   var $extra;
 };
 
 class FreeBusy {
-  function FreeBusy( $username, 
+  function FreeBusy( $cache_dir,
+                     $username,
 		     $password, 
 		     $imaphost,
+		     $imapoptions,
 		     $fbfuture=60,
 		     $fbpast=0 ) {
+    $this->cache_dir = $cache_dir;
     $this->username = $username;
     $this->password = $password;
     $this->imaphost = $imaphost;
+    $this->imapoptions = $imapoptions;
     $this->fbfuture = $fbfuture;
     $this->fbpast   = $fbpast;
+    $this->relevance = null;
   }
 
   function imapConnect() {
-    require_once('Net/IMAP.php');
-    $this->imap = &new Net_IMAP( $this->imaphost, $this->imapport );
-    #$this->imap->setDebug(true);
+    $this->imap_serverstring = "{".$this->imaphost.":".$this->imapport.$this->imapoptions."}";
+    $this->imap = imap_open( $this->imap_serverstring, $this->username, $this->password );
+
     return $this->imap;
   }
 
   function imapDisconnect() {
-    return $this->imap->disconnect();
-  }
-
-  function imapLogin() {
-    return $this->imap->login($this->username,$this->password, true, false);
+    return imap_close($this->imap);
   }
 
   function imapOpenMailbox($foldername = 'INBOX') {
     $this->foldername = $foldername;
-    $rc = $this->imap->selectMailbox( $foldername );
-    $a  = $this->imap->getAnnotation( '/vendor/kolab/folder-type', '*' );
-    //myLog( "$folder has annotation: ".print_r($a,true), RM_LOG_DEBUG);
+
+    $rc = imap_reopen($this->imap, $this->imap_serverstring . $this->foldername);
+    // PHP only returns false for imap_reopen() if we use an HALF_OPEN connection. doh!
+    if (imap_last_error() !== false)
+       $rc = false;
+
+    // $a = $this->imap->getAnnotation( '/vendor/kolab/folder-type', '*' );
+    // myLog( "$folder has annotation: ".print_r($a,true), RM_LOG_DEBUG);
+    
     return $rc;
   }
 
   function getACL() {
-    return $this->imap->getACL();
+    $imap_acls = imap_getacl($this->imap, $this->foldername);
+
+    $rtn = array();
+    while (list($user, $rights) = each($imap_acls))
+        $rtn[] = array("USER" => $user, "RIGHTS" => $rights);
+
+    return $rtn;
   }
 
   function getRelevance() {
-    $val = $this->imap->getAnnotation( '/vendor/kolab/incidences-for', 'value.shared' );
-    if( PEAR::isError($val) || empty($val) ) {
+    // cached?
+    if (isset($this->relevance))
+        return $this->relevance;
+
+    $val = imap_getannotation( $this->imap, $this->foldername, '/vendor/kolab/incidences-for', 'value.shared' );
+    if( $val === false || empty($val) ) {
       myLog("No /vendor/kolab/incidences-for found for ".$this->foldername, RM_LOG_DEBUG);
-      return 'admins';
+      $this->relevance = "admins";
     } else {
       myLog("/vendor/kolab/incidences-for = ".print_r($val,true)." for ".$this->foldername, RM_LOG_DEBUG);
-      return $val;
     }
+    
+    return $this->relevance;
   }
 
   function &generateFreeBusy($startstamp = NULL, $endstamp = NULL ) {
-  
     require_once 'PEAR.php';
     require_once 'Horde/iCalendar.php';
     require_once 'Horde/MIME.php';
@@ -102,7 +134,8 @@
       $startstamp = strtotime( '-'.$this->fbpast.' days', mktime(0, 0, 0, $month, $day, $year) );
     }
   
-    // Default the end date to the start date + freebusy_days.
+    // Default the end date to the start date + fbfuture.
+
     if (is_null($endstamp) || $endstamp < $startstamp) {
       $endstamp = strtotime( '+'.$this->fbfuture.' days', $startstamp );
     }
@@ -124,7 +157,9 @@
     // URL is not required, so out it goes...
     //$vFb->setAttribute('URL', 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']);
   
-    if( $this->imap->getNumberOfMessages() == 0 ) {
+    $status = imap_status_current($this->imap, SA_MESSAGES | SA_UIDVALIDITY | SA_UIDNEXT);
+
+    if( $status->messages == 0 ) {
       $vFb->setAttribute('DTSTART', 0, array(), false );
       $vFb->setAttribute('DTEND', 0, array(), false );
       $vFb->setAttribute('COMMENT', 'This is a dummy vfreebusy that indicates an empty calendar');
@@ -138,15 +173,53 @@
       $retval = array($vCal->exportvCalendar(),$vCal->exportvCalendar());
       return $retval;
     }
-	myLog("Reading messagelist", RM_LOG_DEBUG);
-	$getMessages_start = microtime_float();
-	$msglist = $this->imap->getMessagesList();
-	//$msglist = &$this->imap->getMessages();
-	myLog("FreeBusy::imap->getMessagesList() took ".(microtime_float()-$getMessages_start)." secs.", RM_LOG_DEBUG);
-    if( PEAR::isError( $msglist ) ) return array( $msglist, null);
-	foreach ($msglist as $msginfo) {
-	  //myLog("Reading message ".$msginfo['msg_id'], RM_LOG_DEBUG);
-	  $textmsg = $this->imap->getMsg($msginfo['msg_id']);
+    myLog("Reading messagelist", RM_LOG_DEBUG);
+    $getMessages_start = microtime_float();
+//    $msglist = $this->imap->getMessagesList();
+    //$msglist = &$this->imap->getMessages();
+    myLog("FreeBusy::imap->getMessagesList() took ".(microtime_float()-$getMessages_start)." secs.", RM_LOG_DEBUG);
+//   if( PEAR::isError( $msglist ) ) return array( $msglist, null);
+//	foreach ($msglist as $msginfo) {
+
+    // This only happens in php standalone mode and is needed
+    // to make the debug log quiet
+    if (!isset($_SERVER["SERVER_NAME"]))
+        $_SERVER["SERVER_NAME"] = "localhost";
+
+    $imapcache = new FreeBusyIMAPCache($this->cache_dir."/", $this->username, $this->foldername);
+    $imapcache->cache_load();
+
+    $uids = imap_search($this->imap, "UNDELETED", SE_UID);
+
+    if ($imapcache->check_folder_changed($status->uidvalidity, $status->uidnext, $this->getRelevance(), $uids)) {
+        reset ($uids);
+        while(list($key, $uid) = each($uids))
+            if (!$imapcache->check_uid_exists($uid))
+                $this->process_imap_message($imapcache, $uid, $startstamp, $endstamp);
+    }
+
+    // store cache and output free busy list
+    $imapcache->cache_store();
+    $imapcache->output_fb($vFb);
+
+    $xvCal = $vCal;
+    $xvCal->addComponent($vFb);
+    $vCal->addComponent($this->clearExtra($vFb));
+
+    // Generate the vCal file.
+    $result = array( $vCal->exportvCalendar(), $xvCal->exportvCalendar() );
+    return $result;
+  }
+
+  /********************** Private API below this line ********************/
+
+  function process_imap_message(&$imapcache, &$imapuid, &$startstamp, &$endstamp)
+  {
+      myLog("Processing new message $imapuid", RM_LOG_DEBUG);
+      $imapcache->add_empty_imap2fb($imapuid);
+
+      $textmsg = imap_fetchheader($this->imap, $imapuid, FT_UID).imap_body($this->imap, $imapuid, FT_UID);
+
       $mimemsg = &MIME_Structure::parseTextMIMEMessage($textmsg);
     
       // Read in a Kolab event object, if one exists
@@ -166,21 +239,14 @@
     
       if ($event === false) {
 	myLog("No x-vnd.kolab.events at all ", RM_LOG_DEBUG);
-	continue;
+	return;
       }
       
       $uid = $event['uid'];
-      /*
-      // See if we need to ignore this event
-      if (isset($params['ignore'][$uid])) {
-	trigger_error("Ignoring event with uid=$uid", E_USER_NOTICE);
-	continue;
-      }
-      */
 
       if( array_key_exists( 'show-time-as', $event ) && 
 	  strtolower(trim($event['show-time-as'])) == 'free' ) {
-	continue;
+	return;
       }
     
       $summary = ($event['sensitivity'] == 'public' ? $event['summary'] : '');
@@ -205,7 +271,7 @@
       if( array_key_exists( 'recurrence', $event ) ) {	
 	myLog("Detected recurring event $uid", RM_LOG_DEBUG);
 	$rec = $event['recurrence'];
-	$recurrence =& new FreeBusyRecurrence( $vFb, $extra );
+	$recurrence =& new FreeBusyRecurrence( $imapcache, $imapuid, $vFb, $extra );
 	$recurrence->setStartDate( $initial_start );
 	$recurrence->setEndDate( $initial_end );
 	$recurrence->setCycletype( $rec['cycle'] );
@@ -231,25 +297,15 @@
     
 	// Don't bother adding the initial event if it's outside our free/busy window
 	if ($initial_start < $startstamp || $initial_end > $endstamp) {
-	  continue;
+	  return;
 	}
-		
-	$vFb->addBusyPeriod('BUSY', $initial_start/* + FreeBusy::tzOffset($initial_start)*/, 
-			    $initial_end/* + FreeBusy::tzOffset($initial_end)*/, null, $extra);
+
+        // $initial_start/* + FreeBusy::tzOffset($initial_start)
+        $imapcache->add_imap2fb($imapuid, $initial_start, $initial_end, null, $extra);
+
       }
-    }
-  
-    $xvCal = $vCal;
-    $xvCal->addComponent($vFb);
-    $vCal->addComponent($this->clearExtra($vFb));
-  
-    // Generate the vCal file.
-    $result = array( $vCal->exportvCalendar(), $xvCal->exportvCalendar() );
-    return $result;
   }
 
-  /********************** Private API below this line ********************/
-
   function tzOffset( $ts ) {
     $dstr = date('O',$ts);
     return 3600 * substr( $dstr, 0, 3) + 60 * substr( $dstr, 3, 2);
@@ -408,12 +464,15 @@
     $vFb->_extraParams = array();
     return $vFb;
   }
- 
+
+  var $cache_dir;
   var $username;
   var $password;
   var $imaphost;
   var $imapport = 143;
+  var $imapoptions;
   var $foldername;
+  var $relevance;
 
   // Settings
   var $fbfuture;
@@ -422,6 +481,8 @@
   var $week_starts_on_sunday = false;
 
   var $imap;
+  var $imap_serverstring;  
 };
 
 ?>
+

Index: freebusy.conf
===================================================================
RCS file: /kolabrepository/server/kolab-resource-handlers/kolab-resource-handlers/freebusy/freebusy.conf,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- freebusy.conf	3 Feb 2006 07:05:11 -0000	1.2
+++ freebusy.conf	25 Oct 2006 02:28:57 -0000	1.3
@@ -65,3 +65,21 @@
 
 // What db type to use for freebusy caches 
 $params['dbtype'] = 'gdbm';
+
+// Logging
+$params['log'] = "syslog:";
+$params['log_level'] = 2;
+
+// IMAP options passed to imap_open
+$params['imap_options'] = "/notls/secure/readonly";
+
+// Directory prefixes
+$params['kolab_prefix'] = "";
+$params['cache_dir'] = "/datastore/freebusy";          // default: /var/kolab/www/freebusy/cache
+
+$params['pfb_dbformat'] = "";          // default: gdbm
+
+// don't change this if you don't have to
++$params['ldap_uri'] = "";
++$params['ldap_classname_suffix'] = "_dummy";
+

Index: freebusy.php.in
===================================================================
RCS file: /kolabrepository/server/kolab-resource-handlers/kolab-resource-handlers/freebusy/freebusy.php.in,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- freebusy.php.in	5 Feb 2006 20:15:10 -0000	1.3
+++ freebusy.php.in	25 Oct 2006 02:28:57 -0000	1.4
@@ -1,8 +1,12 @@
 <?php
 /*
  *  Copyright (c) 2004 Klaraelvdalens Datakonsult AB
+    Copyright (c) 2006 Intra2net AG, erfrakon Partnerschaftsgesellschaft
+ *                    
  *
  *    Written by Steffen Hansen <steffen at klaralvdalens-datakonsult.se>
+ *               Thomas Jarosch <thomas.jarosch at intra2net.com>
+ *               Martin Konold <martin.konold at erfrakon.de>
  *
  *  This  program is free  software; you can redistribute  it and/or
  *  modify it  under the terms of the GNU  General Public License as
@@ -18,12 +22,12 @@
  *  Project's homepage; see <http://www.gnu.org/licenses/gpl.html>.
  */
 
+require_once('@resmgr_confdir@/freebusy.conf');
 require_once('@kolab_php_module_prefix at freebusy/freebusycache.class.php');
 require_once('@kolab_php_module_prefix at freebusy/freebusycollector.class.php');
-require_once('@kolab_php_module_prefix at freebusy/freebusyldap.class.php');
-require_once('@kolab_php_module_prefix at freebusy/misc.php');
+require_once('@kolab_php_module_prefix at freebusy/freebusyldap'.$params['ldap_classname_suffix'].'.class.php');
 
-require_once('@resmgr_confdir@/freebusy.conf');
+require_once('@kolab_php_module_prefix at freebusy/misc.php');
 
 logInit( 'freebusy' );
 
@@ -68,7 +72,8 @@
 }
 
 $user = strtolower($user);
-$cache =& new FreeBusyCache( '@freebusy_cachedir@', $req_extended );
+$cache =& new FreeBusyCache( '@freebusy_cachedir@', $params['pfb_dbformat'], $req_extended );
+
 $collector =& new FreeBusyCollector( $user );
 
 $groups = $ldap->distlists( $ldap->dn( $user ) );
@@ -128,3 +133,4 @@
 
 echo $vfb;
 ?>
+

Index: freebusycache.class.php.in
===================================================================
RCS file: /kolabrepository/server/kolab-resource-handlers/kolab-resource-handlers/freebusy/freebusycache.class.php.in,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- freebusycache.class.php.in	9 Apr 2006 18:28:35 -0000	1.5
+++ freebusycache.class.php.in	25 Oct 2006 02:28:57 -0000	1.6
@@ -1,8 +1,12 @@
 <?php
 /*
  *  Copyright (c) 2004 Klaraelvdalens Datakonsult AB
+ *  Copyright (c) 2005 Intra2net AG
+ *  Copyright (c) 2006 erfrakon Partnerschaftsgesellschaft
  *
  *    Written by Steffen Hansen <steffen at klaralvdalens-datakonsult.se>
+ *    Written by Thomas Jarosch <thomas.jarosch at intra2net.com>
+ *    Written by Martin Konold <martin.konold at erfrakon.de>
  *
  *  This  program is free  software; you can redistribute  it and/or
  *  modify it  under the terms of the GNU  General Public License as
@@ -25,8 +29,9 @@
 require_once('@resmgr_confdir@/freebusy.conf');
 
 class FreeBusyCache {
-  function FreeBusyCache( $basedir, $extended = false ) {
+  function FreeBusyCache( $basedir, $dbformat, $extended = false ) {
     $this->basedir = $basedir;
+    $this->dbformat = $dbformat;
     $this->extended = $extended;
 	 /* make sure that a database really exists before accessing it */
     if( !file_exists( $this->basedir.'/pfbcache.db' ) ) {
@@ -37,10 +42,6 @@
 
   function store( $filename, $fbdata, $acl, $relevance ) {
     global $params;
-    if( ereg( '\.\.', $filename ) ) {
-      $this->error = $filename._(' is not absolute');
-      return false;
-    }
 
     $fbfilename = $this->mkfbfilename($filename);
     myLog("FreeBusyCache::store( file=$fbfilename, acl=[ "
@@ -150,6 +151,7 @@
 	    ."] )", RM_LOG_DEBUG);
       return file_get_contents($fbfilename);
     }
+    myLog("FreeBusyCache: file $fbfilename does not exist", RM_LOG_ERROR);
     return false;
   }
 
@@ -203,8 +205,10 @@
   }
 
   /*************** Private API below this line *************/
+  // a copy of this function exists in freebusyimapcache.class.php
   function mkdirhier( $dirname ) {
     $base = substr($dirname,0,strrpos($dirname,'/'));
+    $base = str_replace(".", "^", $base);
     if( !empty( $base ) && !is_dir( $base ) ) {
       if( !$this->mkdirhier( $base ) ) return false;
     }
@@ -213,13 +217,14 @@
   }
 
   function mkfbfilename( $fbfilename ) {
-    $fbfilename = str_replace( '..', '', $fbfilename );
+    $fbfilename = str_replace( '.', '^', $fbfilename );
+
     $fbfilename = str_replace( "\0", '', $fbfilename );    
     return $this->basedir.'/'.$fbfilename.($this->extended?'.xpfb':'.pfb');
   }
 
   function mkaclfilename( $fbfilename ) {
-    $fbfilename = str_replace( '..', '', $fbfilename );
+    $fbfilename = str_replace( '.', '^', $fbfilename );
     $fbfilename = str_replace( "\0", '', $fbfilename );    
     return $this->basedir.'/'.$fbfilename.($this->extended?'.xpfb':'.pfb').'.acl';
   }
@@ -339,7 +344,9 @@
   }
 
   var $basedir;
+  var $dbformat;  
   var $error;
 };
 
 ?>
+

Index: misc.php
===================================================================
RCS file: /kolabrepository/server/kolab-resource-handlers/kolab-resource-handlers/freebusy/misc.php,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- misc.php	16 Jan 2005 08:17:49 -0000	1.6
+++ misc.php	25 Oct 2006 02:28:57 -0000	1.7
@@ -256,4 +256,4 @@
   return assembleUri($parsed);
 }
 
-?>
\ No newline at end of file
+?>

Index: pfb.php.in
===================================================================
RCS file: /kolabrepository/server/kolab-resource-handlers/kolab-resource-handlers/freebusy/pfb.php.in,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- pfb.php.in	23 Oct 2006 21:37:50 -0000	1.5
+++ pfb.php.in	25 Oct 2006 02:28:57 -0000	1.6
@@ -1,8 +1,12 @@
 <?php
 /*
  *  Copyright (c) 2004 Klaraelvdalens Datakonsult AB
+ *  Copyright (c) 2005 Intra2net AG
+ *  Copyright (c) 2006 erfrakon Partnerschaftsgesellschaft
  *
  *    Written by Steffen Hansen <steffen at klaralvdalens-datakonsult.se>
+ *               Thomas Jarosch <thomas.jarosch at intra2net.com> 
+ *               Martin Konold <martin.konold at erfrakon.de>
  *
  *  This  program is free  software; you can redistribute  it and/or
  *  modify it  under the terms of the GNU  General Public License as
@@ -30,11 +34,11 @@
 $max_execution_time = ini_get('max_execution_time');
 if( $max_execution_time < 200 ) ini_set('max_execution_time', '200');
 
-require_once('@kolab_php_module_prefix at freebusy/freebusyldap.class.php');
-require_once('@kolab_php_module_prefix at freebusy/freebusycache.class.php');
 require_once('@kolab_php_module_prefix at freebusy/misc.php');
-
 require_once('@resmgr_confdir@/freebusy.conf');
+require_once('@kolab_php_module_prefix at freebusy/freebusyldap'.$params['ldap_classname_suffix'].'.class.php');
+
+require_once('@kolab_php_module_prefix at freebusy/freebusycache.class.php');
 
 logInit('pfb');
 
@@ -43,6 +47,18 @@
 $req_cache    = isset($_REQUEST['cache'])?(bool)$_REQUEST['cache']:false;
 $req_folder   = isset($_REQUEST['folder'])?$_REQUEST['folder']:false;
 $req_extended = isset($_REQUEST['extended'])?(bool)$_REQUEST['extended']:false;
+// convert character encoding (stores utf7 folder names also on disc)
+require_once "Horde/Util.php";
+require_once "Horde/String.php";
+$req_folder = String::convertCharset($req_folder, "UTF-8", "UTF7-IMAP");
+/*
+// Debug test values
+$imapuser = "groupware";
+$imappw = "groupware";
+$req_cache = 0;
+$req_folder = "groupware/Kalender";
+$req_extended = 0;
+*/
 
 myLog("pfb.php starting up: user=$imapuser, folder=$req_folder, extended=$req_extended", 
       RM_LOG_DEBUG);
@@ -59,7 +75,8 @@
   //$homeserver = $userinfo['HOMESERVER'];  
 }
 
-$folder = array_values(array_filter(explode('/', $req_folder )));
+$folder = explode('/', $req_folder);
+
 if( count($folder) < 1 ) {
   // error
   notFound( _('No such folder ').htmlentities($req_folder) );
@@ -101,10 +118,11 @@
   exit;
 }
 
-$cache =& new FreeBusyCache( '@freebusy_cachedir@',
-			     false );
-$xcache =& new FreeBusyCache( '@freebusy_cachedir@',
-			     true );
+$full_cache_dir = $params['kolab_prefix'] . $params['cache_dir'];
+
+$cache =& new FreeBusyCache( $full_cache_dir, $params['pfb_dbformat'], false );
+$xcache =& new FreeBusyCache( $full_cache_dir, $params['pfb_dbformat'], true );
+
 
 if( $req_cache ) {
   $acl = false;
@@ -143,35 +161,18 @@
   unset($folder[0]);
   $folder = join('/', $folder);
   $fbpast = $ldap->freeBusyPast();
-  $fb =& new FreeBusy( $imapuser, $imappw, 'localhost', $uinfo['FBFUTURE'], $fbpast );
-  $fb->freebusy_days = $params['freebusy_days'];
+  $fb =& new FreeBusy( $full_cache_dir, $imapuser, $imappw, 'localhost', $params['imap_options'], $uinfo['FBFUTURE'], $fbpast );
+
   $fb->default_domain = $params['email_domain'];
   $rc = $fb->imapConnect();
-  if( PEAR::isError( $rc ) ) {
-    unauthorized($rc->toString());
-    return false;
-  }
-  $rc = $fb->imapLogin();
-  if( PEAR::isError( $rc ) ) {
-    unauthorized("Access denied for user $imapuser: ".$rc->toString());
+  if( $rc === false ) {
+    unauthorized(imap_last_error());
     return false;
   }
   $rc = $fb->imapOpenMailbox(FreeBusy::imapFolderName( $imapuser, $owner, 
 						       $folder, $params['email_domain']));
-  if( PEAR::isError( $rc ) ) {
-    // folder doesn't exist (anymore)
-    $cache->store( $owner.'/'.$folder, false, array(), "delete folder");
-    $xcache->store( $owner.'/'.$folder, false, array(), "delete folder");
-    
-    // clear IMAP cache
-    $imapcache = new FreeBusyIMAPCache($full_cache_dir."/", $owner, $fb->foldername);
-    $imapcache->cache_delete();
-    
-    // try to unlink (parent) directory, works only if empty
-    $parent_folder = $full_cache_dir."/".str_replace(".", "^", $owner."/".$folder);
-    @rmdir($parent_folder);
-
-    notfound( "Folder: ".$fb->foldername.', '.$rc->toString());
+  if( $rc === false ) {
+    notfound( "Folder: ".$fb->foldername.', '.imap_last_error());
     return false;
   }
   $relevance = $fb->getRelevance();





More information about the commits mailing list