richard: server/kolab-resource-handlers/kolab-resource-handlers/freebusy freebusy.class.php.in, NONE, 1.1 freebusycache.class.php.in, NONE, 1.1 freebusy.class.php, 1.29, NONE freebusycache.class.php, 1.17, NONE

cvs at intevation.de cvs at intevation.de
Sun Feb 5 21:02:04 CET 2006


Author: richard

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

Added Files:
	freebusy.class.php.in freebusycache.class.php.in 
Removed Files:
	freebusy.class.php freebusycache.class.php 
Log Message:
Use the new kolab_php_module_prefix variable



--- NEW FILE: freebusy.class.php.in ---
<?php
/*
 *  Copyright (c) 2004 Klaraelvdalens Datakonsult AB
 *
 *    Written by Steffen Hansen <steffen at klaralvdalens-datakonsult.se>
 *
 *  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>.
 */

require_once 'freebusy/recurrence.class.php';

class FreeBusyRecurrence extends Recurrence {
  function FreeBusyRecurrence( &$vfb, &$extra ) {
    $this->vfb =& $vfb;
    $this->extra =& $extra;
  }

  function setBusy( $start, $end, $duration ) {
    $this->vfb->addBusyPeriod('BUSY', $start, null, $duration, $this->extra);
  }

  var $vfb;
  var $extra;
};

class FreeBusy {
  function FreeBusy( $username, 
		     $password, 
		     $imaphost,
		     $fbfuture=60,
		     $fbpast=0 ) {
    $this->username = $username;
    $this->password = $password;
    $this->imaphost = $imaphost;
    $this->fbfuture = $fbfuture;
    $this->fbpast   = $fbpast;
  }

  function imapConnect() {
    require_once('Net/IMAP.php');
    $this->imap = &new Net_IMAP( $this->imaphost, $this->imapport );
    #$this->imap->setDebug(true);
    return $this->imap;
  }

  function imapDisconnect() {
    return $this->imap->disconnect();
  }

  function imapLogin() {
    return $this->imap->login($this->username,$this->password, true, false);
  }

  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);
    return $rc;
  }

  function getACL() {
    return $this->imap->getACL();
  }

  function getRelevance() {
    $val = $this->imap->getAnnotation( '/vendor/kolab/incidences-for', 'value.shared' );
    if( PEAR::isError($val) || empty($val) ) {
      myLog("No /vendor/kolab/incidences-for found for ".$this->foldername, RM_LOG_DEBUG);
      return 'admins';
    } else {
      myLog("/vendor/kolab/incidences-for = ".print_r($val,true)." for ".$this->foldername, RM_LOG_DEBUG);
      return $val;
    }
  }

  function &generateFreeBusy($startstamp = NULL, $endstamp = NULL ) {
  
    require_once 'PEAR.php';
    require_once 'Horde/iCalendar.php';
    require_once 'Horde/MIME.php';
    require_once 'Horde/MIME/Message.php';
    require_once 'Horde/MIME/Structure.php';
  
    // Default the start date to today.
    if (is_null($startstamp)) {
      $month = date('n');
      $year = date('Y');
      $day = date('j');
    
      $startstamp = strtotime( '-'.$this->fbpast.' days', mktime(0, 0, 0, $month, $day, $year) );
    }
  
    // Default the end date to the start date + freebusy_days.
    if (is_null($endstamp) || $endstamp < $startstamp) {
      $endstamp = strtotime( '+'.$this->fbfuture.' days', $startstamp );
    }

    myLog("Creating pfb from $startstamp to $endstamp", RM_LOG_DEBUG);
  
    // Create the new iCalendar.
    $vCal = &new Horde_iCalendar();
    $vCal->setAttribute('PRODID', '-//proko2//freebusy 1.0//EN');
    $vCal->setAttribute('METHOD', 'PUBLISH');
  
    // Create new vFreebusy.
    $vFb = &Horde_iCalendar::newComponent('vfreebusy', $vCal);
    $vFb->setAttribute('ORGANIZER', 'MAILTO:' . $this->username);
  
    $vFb->setAttribute('DTSTAMP', time());
    $vFb->setAttribute('DTSTART', $startstamp);
    $vFb->setAttribute('DTEND', $endstamp);
    // URL is not required, so out it goes...
    //$vFb->setAttribute('URL', 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']);
  
    if( $this->imap->getNumberOfMessages() == 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');
      /* It seems to be a bad idea to put bogus values in pfbs
       * so we accept that they are not completely in line 
       * with the rfc and take care of the problem when merging 
       * pfbs to ifbs later 
       */
      //$vFb->addBusyPeriod( 'BUSY', 0,0, null );
      $vCal->addComponent($vFb);
      return array($vCal->exportvCalendar(),$vCal->exportvCalendar());
    }
	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']);
      $mimemsg = &MIME_Structure::parseTextMIMEMessage($textmsg);
    
      // Read in a Kolab event object, if one exists
      $parts = $mimemsg->contentTypeMap();
      $event = false;
      foreach ($parts as $mimeid => $conttype) {
	if ($conttype == 'application/x-vnd.kolab.event') {
	  $part = $mimemsg->getPart($mimeid);
	  $part->transferDecodeContents();
	  $event = $this->getEventHash($part->getContents());
	  if ($event === false) {
	    myLog("No x-vnd.kolab.event in ".$part->getContents(), RM_LOG_DEBUG);
	    continue;
	  }
	}
      }
    
      if ($event === false) {
	myLog("No x-vnd.kolab.events at all ", RM_LOG_DEBUG);
	continue;
      }
      
      $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;
      }
    
      $summary = ($event['sensitivity'] == 'public' ? $event['summary'] : '');
    
      //myLog("Looking at message with uid=$uid and summary=$summary", RM_LOG_DEBUG);
    
      // Get the events initial start
      $initial_start = $event['start-date'];
      $initial_end = $event['end-date'];
      if( $event['allday'] ) {
	$initial_end = strtotime( '+1 day', $initial_start );
	myLog("Detected all-day event $uid", RM_LOG_DEBUG);
      }
      $extra = array( 'X-UID'     => base64_encode($uid) );
      if (!empty($summary)) {
	$extra['X-SUMMARY'] = base64_encode($summary);
      }
      if( !empty($event['scheduling-id']) ) {
	$extra['X-SID'] = base64_encode($event['scheduling-id']);
      }

      if( array_key_exists( 'recurrence', $event ) ) {	
	myLog("Detected recurring event $uid", RM_LOG_DEBUG);
	$rec = $event['recurrence'];
	$recurrence =& new FreeBusyRecurrence( $vFb, $extra );
	$recurrence->setStartDate( $initial_start );
	$recurrence->setEndDate( $initial_end );
	$recurrence->setCycletype( $rec['cycle'] );
	if( isset($rec['type']) ) $recurrence->setType( $rec['type'] );
	if( isset($rec['interval']) ) $recurrence->setInterval( (int)$rec['interval'] );
	if( isset($rec['daynumber']) ) $recurrence->setDaynumber( $rec['daynumber'] );
	if( isset($rec['day']) ) $recurrence->setDay( $rec['day'] );
	if( isset($rec['month']) ) $recurrence->setMonth( $rec['month'] );
	if( isset($rec['exclusion'] ) ) $recurrence->setExclusionDates( $rec['exclusion'] );
	$rangetype = $rec['rangetype'];
	if( $rangetype == 'number' ) {
	  $range = (int)$rec['range'];
	} else if( $rangetype == 'date' ) {
	  $range = $this->parseDateTime( $rec['range'] );
	} else {
	  $range = false;
	}
	$recurrence->setRangetype( $rangetype );
	$recurrence->setRange( $range );
	$recurrence->expand( $startstamp, $endstamp );
      } else {
	// Normal event
    
	// Don't bother adding the initial event if it's outside our free/busy window
	if ($initial_start < $startstamp || $initial_end > $endstamp) {
	  continue;
	}
		
	$vFb->addBusyPeriod('BUSY', $initial_start/* + FreeBusy::tzOffset($initial_start)*/, 
			    $initial_end/* + FreeBusy::tzOffset($initial_end)*/, null, $extra);
      }
    }
  
    $xvCal = $vCal;
    $xvCal->addComponent($vFb);
    $vCal->addComponent($this->clearExtra($vFb));
  
    // Generate the vCal file.
    return array( $vCal->exportvCalendar(), $xvCal->exportvCalendar() );
  }

  /********************** Private API below this line ********************/

  function tzOffset( $ts ) {
    $dstr = date('O',$ts);
    return 3600 * substr( $dstr, 0, 3) + 60 * substr( $dstr, 3, 2);
  }

  // static function to compute foldername for imap
  function imapFolderName( $user, $owner, $folder = false, $default_domain = false ) {
    $userdom = false;
    $ownerdom = false;
    if( ereg( '(.*)@(.*)', $user, $regs ) ) {
      // Regular user
      $user = $regs[1];
      $userdom  = $regs[2];
    } else {
      // Domainless user (ie. manager)
    }

    if( ereg( '(.*)@(.*)', $owner, $regs ) ) {      
      $owner = $regs[1];
      $ownerdom = $regs[2];
    } else {
    }

    $fldrcomp = array('user',$owner );
    if( $folder ) $fldrcomp[] = $folder;
    $fldr = join('/', $fldrcomp );
    if( $ownerdom && !$userdom ) $fldr .= '@'.$ownerdom;
    return $fldr;
  }

  // Date/Time value parsing, courtesy of the Horde iCalendar library
  function parseTime($text) {
    // There must be a trailing 'Z' on a time
    if (strlen($text) != 9) {
      return false;
    }

    $time['hour']  = intval(substr($text, 0, 2));
    $time['minute'] = intval(substr($text, 3, 2));
    $time['second']  = intval(substr($text, 6, 2));
    return $time;
  }

  function parseDate($text) {
    if (strlen($text) != 10) {
      return false;
    }
    
    $date['year']  = intval(substr($text, 0, 4));
    $date['month'] = intval(substr($text, 5, 2));
    $date['mday']  = intval(substr($text, 8, 2));
    
    return $date;
  }

  function parseDateTime($text) {
    $dateParts = split('T', $text);
    if (count($dateParts) != 2 && !empty($text)) {
      // Not a datetime field but may be just a date field.
      if (!$date = FreeBusy::parseDate($text)) {
	return $date;
      }
      return @gmmktime(0, 0, 0, $date['month'], $date['mday'], $date['year']);
    }
    
    if (!$date = FreeBusy::parseDate($dateParts[0])) {
      return $date;
    }
    if (!$time = FreeBusy::parseTime($dateParts[1])) {
      return $time;
    }
    
    return @gmmktime($time['hour'], $time['minute'], $time['second'],
                     $date['month'], $date['mday'], $date['year']);
  }

  function getEventHash($xml_text) {
    $xmldoc = @domxml_open_mem($xml_text, DOMXML_LOAD_PARSING +
			       DOMXML_LOAD_COMPLETE_ATTRS + DOMXML_LOAD_SUBSTITUTE_ENTITIES +
			       DOMXML_LOAD_DONT_KEEP_BLANKS, $error);
    
    if (!empty($error)) {
      // There were errors parsing the XML data - abort
      myLog( "Error parsing \"$xml_txt\": $error", RM_LOG_ERROR);
      return false;
    }
    
    $noderoot = $xmldoc->document_element();
    $childnodes = $noderoot->child_nodes();
    
    $event_hash = array();
    
    // Build the event hash
    foreach ($childnodes as $value) {
      //myLog("Looking at tag ".($value->tagname), RM_LOG_DEBUG);
      if( $value->tagname == 'recurrence' ) {
	$rhash = array();
	$attrs = $value->attributes();
	foreach( $attrs as $attr ) {
	  //myLog("getEventHash setting rhash[".$attr->name."] = ".$attr->value, RM_LOG_DEBUG);
	  $rhash[$attr->name] = $attr->value;
	}
	foreach( $value->child_nodes() as $v ) {
	  if( $v->tagname == 'day' || $v->tagname == 'exclusion' ) {
	    $rhash[$v->tagname][] = $v->get_content();
	  } else {
	    $rhash[$v->tagname] = $v->get_content();
	    if( $v->tagname == 'range' && $v->has_attribute('type') ) {
	      $rhash['rangetype'] = $v->get_attribute('type');
	    }
	  }
	}	
	$event_hash[$value->tagname] = $rhash;
      } else {
	$event_hash[$value->tagname] = $value->get_content();
      }
    }
    
    //myLog("RAW Event: ".print_r($event_hash, true), RM_LOG_DEBUG);

    // Perform some sanity checks on the event
    if (
        empty($event_hash['uid']) ||
        empty($event_hash['start-date']) ||
        empty($event_hash['end-date'])
	) {
      return false;
    }
    

    if (empty($event_hash['sensitivity'])) {
      $event_hash['sensitivity'] = 'public';
    }
    
    // Set the summary if it's not present, so we don't get PHP warnings
    // about accessing non-present keys
    if (empty($event_hash['summary'])) {
      $event_hash['summary'] = '';
    }
    
    // Convert our date-time values to timestamps
    if( strpos( $event_hash['start-date'], 'T' ) === false &&
	strpos( $event_hash['end-date'], 'T' ) === false &&
	$event_hash['start-date'] == $event_hash['end-date'] ) {
      $event_hash['allday'] = true;
    } else {
      $event_hash['allday'] = false;      
    }
    $event_hash['start-date'] = FreeBusy::parseDateTime($event_hash['start-date']);
    $event_hash['end-date'] = FreeBusy::parseDateTime($event_hash['end-date']);
    
    return $event_hash;
  }

  function clearExtra( $vFb ) {
    $vFb->_extraParams = array();
    return $vFb;
  }
 
  var $username;
  var $password;
  var $imaphost;
  var $imapport = 143;
  var $foldername;

  // Settings
  var $fbfuture;
  var $fbpast;
  var $default_domain = 'foo';
  var $week_starts_on_sunday = false;

  var $imap;
};

?>

--- NEW FILE: freebusycache.class.php.in ---
<?php
/*
 *  Copyright (c) 2004 Klaraelvdalens Datakonsult AB
 *
 *    Written by Steffen Hansen <steffen at klaralvdalens-datakonsult.se>
 *
 *  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>.
 */

/*! To load/store partial freebusy lists
    and their ACLs */
    
require_once('freebusy/misc.php');
require_once('@resmgr_confdir@/freebusy.conf');

class FreeBusyCache {
  function FreeBusyCache( $basedir, $extended = false ) {
    $this->basedir = $basedir;
    $this->extended = $extended;
  }

  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=[ "
	  .str_replace("\n",", ",$this->aclToString($acl))
	  ."], relevance=$relevance )", RM_LOG_DEBUG);
    if( $fbdata === false ) {
      // false data means delete the pfb
      unlink($fbfilename);
      $oldacl = $this->loadACL( $filename );
      $db = dba_open( $this->basedir.'/pfbcache.db', 'cd', $params['dbtype'] );
      if( $db === false ) return false;
      foreach( $oldacl as $ac ) {
	  if( dba_exists( $ac['USER'], $db ) ) {
	    $lst = dba_fetch( $ac['USER'], $db );
	    $lst = $this->decodeList( $lst );
	    $lst = array_diff( $lst, array($fbfilename));
	    myLog("(delete) dba_replace(".$uid.", \"".$this->encodeList($lst)."\")", RM_LOG_DEBUG);
	    dba_replace( $uid, $this->encodeList($lst), $db );
	  }
      }
      unlink($fbfilename.'.acl');
    } else {
      //myLog("Storing $filename with acl ".var_export($acl,true), RM_LOG_DEBUG);
      
      // Create directories if missing
      $fbdirname  = dirname( $fbfilename );
      if (!is_dir($fbdirname)) {
	if( !$this->mkdirhier($fbdirname) ) {
	  $this->error = _("Error creating dir $fbdirname");
	  return false;
	}
      }
      
      // Store the fb list
      $tmpn = tempnam($this->basedir, 'fb');
      $tmpf = fopen($tmpn, 'w');
      if( !$tmpf ) return false;
      fwrite($tmpf, $fbdata);
      if( !rename($tmpn, $fbfilename) ) {
	$this->error = _("Error renaming $tmpn to $fbfilename");
	return false;
      }
      fclose($tmpf);
      
      // Store the ACL
      $oldacl = $this->loadACL( $filename );
      if( !$this->storeACL( $filename, $acl ) ) return false;
      
      // Update overview db
      switch( $relevance ) {
      case 'admins':  $perm = 'a'; break;
      case 'readers': $perm = 'r'; break;
      case 'nobody':  $perm = 'false'; break;
      default: $perm = 'a';
      }

      $db = dba_open( $this->basedir.'/pfbcache.db', 'cd', $params['dbtype'] );
      if( $db === false ) {
	myLog('Unable to open freebusy cache db '.$this->basedir.'/pfbcache.db',
	      RM_LOG_ERROR );
	return false;
      }
      foreach( $acl as $ac ) {
	$uid = $ac['USER'];
	if( dba_exists( $uid, $db ) ) {
	  $lst = dba_fetch( $uid, $db );
	  $lst = $this->decodeList( $lst );
	  $lst = array_diff( $lst, array($filename));
	  dba_replace( $uid, $this->encodeList($lst), $db );
	}
      }
      if( $perm !== false ) {
	foreach( $acl as $ac ) {
	  if( strpos( $ac['RIGHTS'], $perm ) !== false ) {
	    if( dba_exists( $ac['USER'], $db ) ) {
	      $lst = dba_fetch( $ac['USER'], $db );
	      $lst = $this->decodeList( $lst );
	      $lst[] = $filename;
	      dba_replace( $ac['USER'], $this->encodeList(array_unique($lst)), $db );
	    } else {
	      dba_insert( $ac['USER'], $filename, $db );
	    }
	  }
	}
      }
      dba_close($db);
      return true;
    }
  }

  function load( $filename, &$ts, &$acl ) {
    myLog("FreeBusyCache::load( $filename )", RM_LOG_DEBUG);
    $fbfilename = $this->mkfbfilename($filename);
    if( file_exists($fbfilename) ) {
      if( !is_null($ts)) $ts = filectime($fbfilename);
      $acl = $this->loadACL($filename);
      myLog("FreeBusyCache::load(): ts=$ts acl=[ "
	    .str_replace("\n",", ",$this->aclToString($acl))
	    ."] )", RM_LOG_DEBUG);
      return file_get_contents($fbfilename);
    }
    return false;
  }

  function delete( $filename ) {
    global $params;
    $fbfilename = $this->mkfbfilename($filename);
    unlink($fbfilename);
    unlink($this->mkaclfilename($filename));    
    $db = dba_open( $this->basedir.'/pfbcache.db', 'cd', $params['dbtype'] );
    if( $db === false ) return false;
    for( $uid = dba_firstkey($db); $uid !== false; $uid = dba_nextkey($db)) {
      $lst = dba_fetch( $uid, $db );
      $lst = $this->decodeList( $lst );
      $lst = array_diff( $lst, array($filename));
      myLog("(delete) dba_replace(".$uid.", \"".$this->encodeList($lst)."\")", RM_LOG_DEBUG);
      dba_replace( $uid, $this->encodeList($lst), $db );      
    }
    dba_close($db);
  }

  function findAll( $uid, $groups ) {
    global $params;
    $lst = array();
    $db = dba_open( $this->basedir.'/pfbcache.db', 'rd', $params['dbtype'] );
    if( $db === false ) return false;
    $uids = $groups;
    for( $i = 0; $i < count($uids); $i++ ) $uids[$i] = 'group:'.$uids[$i];
    $uids[] = $uid;
    foreach( $uids as $uid ) {
      if( dba_exists( $uid, $db ) ) {
	$tmplst = dba_fetch( $uid, $db );
	myLog("Found ".$uid." := $tmplst", RM_LOG_DEBUG);
	$lst = array_merge( $lst, $this->decodeList( $tmplst ) );
      } else {
	myLog("$uid not found", RM_LOG_DEBUG);	
      }
    }
    dba_close($db);
    $lst = array_unique($lst);
    myLog( "FreeBusyCache::findAll( $uid, [".join(', ', $groups).'] ) = ['.join(', ',$lst).']',
	   RM_LOG_DEBUG );
    return $lst;
  }

  /*************** Private API below this line *************/
  function mkdirhier( $dirname ) {
    $base = substr($dirname,0,strrpos($dirname,'/'));
    if( !empty( $base ) && !is_dir( $base ) ) {
      if( !$this->mkdirhier( $base ) ) return false;
    }
    if( !file_exists( $dirname ) ) return mkdir( $dirname, 0755 );
    return true;
  }

  function mkfbfilename( $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( "\0", '', $fbfilename );    
    return $this->basedir.'/'.$fbfilename.($this->extended?'.xpfb':'.pfb').'.acl';
  }

  function aclToString( $acl ) {
    $aclstr = '';
    foreach( $acl as $ac ) {
      $aclstr .= $ac['USER'].' '.$ac['RIGHTS']."\n";
    }
    return $aclstr;
  }

  function aclFromString( $aclstr ) {
    $acl = array();
    foreach( split("\n", $aclstr ) as $ac ) {
      if( ereg("(.*) (.*)", $ac, $regs ) ) {
	$acl[] = array('USER' => $regs[1], 'RIGHTS' => $regs[2] );
      }
    }
    return $acl;
  }

  function loadACL( $filename ) {
    return $this->aclFromString( @file_get_contents($this->mkaclfilename($filename)) );    
  }

  function storeACL( $filename, $acl ) {
    $tmpn = tempnam($this->basedir, 'acl');
    $tmpf = fopen($tmpn, 'w');
    if( !$tmpf ) return false;
    fwrite($tmpf, $this->aclToString($acl) );

    $aclfilename = $this->mkaclfilename($filename);
    if( !rename($tmpn, $aclfilename) ) {
      $this->error = _("Error renaming $tmpn to $fbfilename");
      return false;
    }
    fclose($tmpf);    
    return true;
  }

  function aclDiff( $oldacl, $newacl ) {
    $newuids = array();
    foreach( $newacl as $ac ) {
      if( strpos( $ac['RIGHTS'], 'r' ) !== false ) {
	$newuids[$ac['USER']] = true;
      }
    }
    $deleteduids = array();
    foreach( $oldacl as $ac ) {
      if( !$newuids[$ac['USER']] ) $deleteduids[] = $ac['USER'];
    }
    return $deleteduids;
  }

  /** Returns an array with cyrus permission chars (lrsp...) as keys */
  function getRights( $acl, $uid, $groups ) {
    if( !isset($uid) ) return false;
    if( is_array( $groups ) ) $uids = $groups;
    else $uids = array();
    for( $i = 0; $i < count($uids); $i++ ) $uids[$i] = 'group:'.$uids[$i];
    $uids[] = $uid;
    $rights = array();
    $negacl = array();

    // Calc positive rights
    foreach( $acl as $ac ) {
      $r = $ac['RIGHTS'];
      $u = $ac['USER'];
      if( $r{0} == '-' ) {
	$negacl[] = array( 'USER' => $u, 'RIGHTS' => $r );
	continue;
      }
      if( in_array( $u, $uids ) ) {
	for( $i = 0; $i < strlen($r); $i++ ) {
	  $rights[$r{$i}] = true;
	}
      }
    }
    
    // Remove negative rights
    foreach( $negacl as $ac ) {
      $r = $ac['RIGHTS'];
      $u = $ac['USER'];
      if( in_array( $u, $uids ) ) {
	for( $i = 1; $i < strlen($r); $i++ ) {
	  unset($rights[$r{$i}]);
	}
      }
    }
    return $rights;
  }

  function decodeList( $str ) {
    return split( ',', $str );
  }
  function encodeList( $lst ) {
    return join(',',$lst);
  }

  function recursivedir( $dir ) {
    $dh = opendir( $dir );
    if( $dh === false ) return false;
    $dirs = array();
    while (($file = readdir($dh)) !== false) {
      if( is_dir($dir.'/'.$file) ) {
	if($file=='.' || $file=='..') continue;
	if( !ereg( ($this->extended?'/.*\.xpfb$/':'/.*\.pfb$/'), $file ) ) continue;
	$tmp = $this->recursivedir( $dir.'/'.$file );
	if( $tmp !== false ) $dirs = array_merge( $dirs, $tmp );
      } else if( is_file($dir.'/'.$file) ) {
	$dirs[] = $dir.'/'.$file;
      }
    }
    closedir( $dh );
    return $dirs;
  }

  var $basedir;
  var $error;
};

?>


--- freebusy.class.php DELETED ---

--- freebusycache.class.php DELETED ---





More information about the commits mailing list