steffen: server/kolab-resource-handlers/kolab-resource-handlers/freebusy freebusy.class.php, 1.1, 1.2 freebusy.php, 1.27, 1.28 freebusycache.class.php, 1.1, 1.2 freebusyldap.class.php, 1.1, 1.2 pfb.php, 1.1, 1.2

cvs at intevation.de cvs at intevation.de
Mon Oct 4 11:31:20 CEST 2004


Author: steffen

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

Modified Files:
	freebusy.class.php freebusy.php freebusycache.class.php 
	freebusyldap.class.php pfb.php 
Log Message:
fb stuff

Index: freebusy.class.php
===================================================================
RCS file: /kolabrepository/server/kolab-resource-handlers/kolab-resource-handlers/freebusy/freebusy.class.php,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- freebusy.class.php	28 Sep 2004 13:12:26 -0000	1.1
+++ freebusy.class.php	4 Oct 2004 09:31:18 -0000	1.2
@@ -29,6 +29,10 @@
     return $this->imap->selectMailbox( $foldername );
   }
 
+  function getACL() {
+    return $this->imap->getACL();
+  }
+
   function &generateFreeBusy($extended = false, $startstamp = NULL, $endstamp = NULL ) {
   
     require_once 'PEAR.php';

Index: freebusy.php
===================================================================
RCS file: /kolabrepository/server/kolab-resource-handlers/kolab-resource-handlers/freebusy/freebusy.php,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -r1.27 -r1.28
--- freebusy.php	28 Sep 2004 13:12:26 -0000	1.27
+++ freebusy.php	4 Oct 2004 09:31:18 -0000	1.28
@@ -1,21 +1,68 @@
 <?php
 require_once('freebusy/freebusycache.class.php');
 require_once('freebusy/freebusycollector.class.php');
+require_once('freebusy/freebusyldap.class.php');
 require_once('freebusy/misc.php');
 require_once('@l_prefix@/etc/resmgr/freebusy.conf');
 
 $user = trim($_REQUEST['uid']);
-$cache =& new FreeBusyCache( $params['kolab_prefix'].'/var/kolab/www/pfb/cache' );
+$imapuser     = $_SERVER['PHP_AUTH_USER'];
+$imappw       = $_SERVER['PHP_AUTH_PW'];
+$req_cache    = (bool)$_REQUEST['cache'];
+//$req_folder   = $_REQUEST['folder'];
+$req_extended = (defined( $_REQUEST['extended'] ) && $_REQUEST['extended']);
+
+$ldap =& new FreeBusyLDAP( $params['ldap_uri'], $params['base_dn'] );
+if( !$ldap->bind( $params['bind_dn'], $params['bind_pw'] ) ) {
+  notFound( "Bind failed: ".$ldap->error() );
+  exit;
+}
+
+$imapuser = $ldap->mailForUid( $imapuser );
+$homeserver = $ldap->homeServer( $user );
+
+if( $homeserver != $params['server'] ) {
+  $redirect = 'https://'.$homeserver . $_SERVER['REQUEST_URI'];
+  if ($params['redirect']) {
+    header("Location: $redirect");
+  } else {
+    header("X-Redirect-To: $redirect");
+    $redirect = 'https://' . urlencode($_SERVER['PHP_AUTH_USER']) . ':'
+      . urlencode($_SERVER['PHP_AUTH_PW']) . '@' . $homeserver
+      . $_SERVER['REQUEST_URI'];
+    if (!@readfile($redirect)) {
+      unauthorized("Unable to read free/busy information from $redirect");
+    }
+  }
+  shutdown();
+  exit;
+}
+
+
+$cache =& new FreeBusyCache( $params['kolab_prefix'].'/var/kolab/www/freebusy/cache', $req_extended );
 $collector =& new FreeBusyCollector( $user );
 
-$pfbs = $cache->findAll( $user );
+$groups = $ldap->distlists( $ldap->dn( $user ) );
+$pfbs = $cache->findAll( $user, $groups );
 $ts = 0;
 if( $pfbs === false ) {
   notFound($pfb->error);
 }
+
+if( $req_extended ) {
+  // Get accessing users groups
+  $imapgroups = $ldap->distlists( $ldap->dn( $imapuser ) );
+}
+
 foreach( $pfbs as $pfb ) {
-  $ts = max( $ts, filectime( $pfb ) );
-  $collector->addFreebusy( file_get_contents( $pfb ) );
+  $fb = $cache->load( $pfb, $ts2, $acl );
+  if( $req_extended && !$cache->checkAcl( $acl, $imapuser, $imappw ) ) {
+    $fb->extended = false; // HACK!
+    $fb = $cache->load( $pfb, $ts2, $acl );    
+    $fb->extended = true;
+  }
+  $ts = max( $ts, $ts2 );
+  if( $fb ) $collector->addFreebusy( $fb );
 }
 $vfb = $collector->exportvCalendar();
 

Index: freebusycache.class.php
===================================================================
RCS file: /kolabrepository/server/kolab-resource-handlers/kolab-resource-handlers/freebusy/freebusycache.class.php,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- freebusycache.class.php	28 Sep 2004 13:12:26 -0000	1.1
+++ freebusycache.class.php	4 Oct 2004 09:31:18 -0000	1.2
@@ -1,20 +1,21 @@
 <?php
 
+/*! To load/store partial freebusy lists
+    and their ACLs */
 class FreeBusyCache {
-  function FreeBusyCache( $basedir ) {
+  function FreeBusyCache( $basedir, $extended = false ) {
     $this->basedir = $basedir;
+    $this->extended = $extended;
   }
 
-  function store( $fbfilename, $fbdata ) {
-    $tmpn = tempnam($this->basedir, 'fb');
-    $tmpf = fopen($tmpn, 'w');
-    if( !$tmpf ) return false;
-    fwrite($tmpf, $fbdata);
-    if( ereg( '\.\.', $fbfilename ) ) {
-      $this->error = $fbfilename._(' is not absolute');
+  function store( $filename, $fbdata, $acl ) {
+    if( ereg( '\.\.', $filename ) ) {
+      $this->error = $filename._(' is not absolute');
       return false;
     }
-    $fbfilename = $this->basedir.'/'.$fbfilename;
+
+    // Create directories if missing
+    $fbfilename = $this->mkfbfilename($filename);
     $fbdirname  = dirname( $fbfilename );
     if (!is_dir($fbdirname)) {
       if( !$this->mkdirhier($fbdirname) ) {
@@ -22,31 +23,76 @@
 	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
+    $db = dba_open( $this->basedir.'/pfbcache.db', 'cd', 'gdbm' );
+    if( $db === false ) return false;
+    foreach( $acl as $ac ) {
+      if( strpos( $ac['RIGHTS'], 'r' ) !== 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 );
+	}
+      }
+    }
+    $deleteduids = $this->aclDiff( $oldacl, $acl );
+    foreach( $deleteduids as $uid ) {
+      if( dba_exists( $uid, $db ) ) {
+	$lst = dba_fetch( $uid, $db );
+	$lst = $this->decodeList( $lst );
+	$lst = array_diff( $lst, array($fbfilename));
+	dba_replace( $uid, $this->encodeList($lst), $db );
+      }     
+    }
+    dba_close($db);
     return true;
   }
 
-  function load( $fbfilename, &$ts ) {
-    $fbfilename = $this->basedir.'/'.$fbfilename;
+  function load( $filename, &$ts, &$acl ) {
+    $fbfilename = $this->mkfbfilename($filename);
     if( $fbfilename != realpath( $fbfilename )) return false;    
     if( file_exists($fbfilename) ) {
       if( !is_null($ts)) $ts = filectime($fbfilename);
+      $acl = $this->loadACL($filename);
       return file_get_contents($fbfilename);
     }
     return false;
   }
 
-  function findAll( $user ) {
-    $fbdir = $this->basedir.'/'.$user;
-    if( $fbdir != realpath($fbdir) ) {
-      $this->error = $fbdir._(' is not absolute');      
-      return false;
+  function findAll( $uid, $groups ) {
+    $lst = false;
+    $db = dba_open( $this->basedir.'/pfbcache.db', 'rd', 'gdbm' );
+    if( $db === false ) return false;
+    $uids = $groups;
+    $uids[] = $uid;
+    foreach( $uids as $uid ) {
+      if( dba_exists( $uid, $db ) ) {
+	$lst = dba_fetch( $uid, $db );
+	$lst = array_merge( $lst, $this->decodeList( $lst ) );
+      }
+      dba_close($db);
     }
-    return FreeBusyCache::recursivedir( $fbdir );
+    if( is_array( $lst ) ) return array_unique($lst);
+    else return false;
   }
 
   /*************** Private API below this line *************/
@@ -59,6 +105,105 @@
     return true;
   }
 
+  function mkfbfilename( $fbfilename ) {
+    return $this->basedir.'/'.$fbfilename.($this->extended?'.xpfb':'.pfb');
+  }
+
+  function mkaclfilename( $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;
+  }
+
+  function getRights( $acl, $uid, $groups ) {
+    $uids = array_merge( array($uid), $groups );
+    $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;
@@ -66,7 +211,8 @@
     while (($file = readdir($dh)) !== false) {
       if( is_dir($dir.'/'.$file) ) {
 	if($file=='.' || $file=='..') continue;
-	$tmp = FreeBusyCache::recursivedir( $dir.'/'.$file );
+	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;

Index: freebusyldap.class.php
===================================================================
RCS file: /kolabrepository/server/kolab-resource-handlers/kolab-resource-handlers/freebusy/freebusyldap.class.php,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- freebusyldap.class.php	28 Sep 2004 13:12:26 -0000	1.1
+++ freebusyldap.class.php	4 Oct 2004 09:31:18 -0000	1.2
@@ -45,6 +45,32 @@
     return false;
   }
 
+  function dn( $uid ) {
+    $result = ldap_search( $this->connection, $this->base, 
+			   '(&(objectClass=kolabInetOrgPerson)(|(uid='.$uid.')(mail='.$uid.')))',
+			   array( 'dn' ) );
+    if( $result ) {
+      $entries = ldap_get_entries( $this->connection, $result );
+      if( $entries['count'] > 0 ) { 
+	return $entries[0]['dn'];
+      }
+    }
+    return false;    
+  }
+  function distlists( $dn ) {
+    $result = ldap_search( $this->connection, $this->base, 
+			   '(&(objectClass=kolabGroupOfNames)(member=$dn))',
+			   array( 'cn' ) );
+    if( $result ) {
+      $entries = ldap_get_entries( $this->connection, $result );
+      $lst = array();
+      for( $i = 0; i < $entries['count']; ++$i ) {
+	$lst[] = $entries[$i]['cn'][0];
+      }
+      return $lst;
+    }
+    return false;
+  }
 
   var $connection;
   var $is_bound;

Index: pfb.php
===================================================================
RCS file: /kolabrepository/server/kolab-resource-handlers/kolab-resource-handlers/freebusy/pfb.php,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- pfb.php	28 Sep 2004 13:12:26 -0000	1.1
+++ pfb.php	4 Oct 2004 09:31:18 -0000	1.2
@@ -8,9 +8,9 @@
 
 $imapuser     = $_SERVER['PHP_AUTH_USER'];
 $imappw       = $_SERVER['PHP_AUTH_PW'];
-$req_cache    = $_REQUEST['cache'];
+$req_cache    = (bool)$_REQUEST['cache'];
 $req_folder   = $_REQUEST['folder'];
-$req_extended = $_REQUEST['extended'];
+$req_extended = (bool)$_REQUEST['extended'];
 
 $ldap =& new FreeBusyLDAP( $params['ldap_uri'], $params['base_dn'] );
 if( !$ldap->bind( $params['bind_dn'], $params['bind_pw'] ) ) {
@@ -38,28 +38,36 @@
   exit;
 }
 
-$cache =& new FreeBusyCache( $params['kolab_prefix'].'/var/kolab/www/pfb/cache' );
+$cache =& new FreeBusyCache( $params['kolab_prefix'].'/var/kolab/www/freebusy/cache',
+			     $req_extended );
 
 if( $req_cache ) {
-  $vfb = $cache->load( $req_folder.'.pfb', $ts );
-  if( !$vfb ) notFound( $req_folder.'.pfb not found in cache');
+  $acl = false;
+  $vfb = $cache->load( $req_folder, $ts, $acl );
+  if( $acl && $req_extended ) {
+    // Check access
+    $distlists = $ldap->distlists( $ldap->dn($imapuser));
+    if( $distlists === false ) unauthorized( $req_folder.($req_extended?'.xpfb':'.pfb' ) );
+    $rights = $cache->getRights( $acl, $imapuser, $distlists );
+    if( $rights['r'] ) {
+      // All OK
+    } else {
+      // Nope
+      unauthorized( $req_folder.($req_extended?'.xpfb':'.pfb' ) );
+    }
+  }
+  if( !$vfb ) notFound( $req_folder.($req_extended?'.xpfb':'.pfb').' not found in cache');
 } else {
   require_once('freebusy/freebusy.class.php');
 
   $folder = split('/', $req_folder );
-  if( count($folder) < 2 ) {
+  if( count($folder) < 1 ) {
     // error
     notFound( 'No such folder ').htmlentities($req_folder);
   }
   $owner = $folder[0];
-  $mbox = $folder[1];
   unset($folder[0]);
-  unset($folder[1]);
   $folder = join('/', $folder);
-  if( strtolower( $owner ) != strtolower( $imapuser ) ) {
-    unauthorized(_("User $imapuser is not allowed to create freebusy data for $owner"));
-    return false;    
-  }
   $fb =& new FreeBusy( $imapuser, $imappw, 'localhost' );
   $fb->freebusy_days = $params['freebusy_days'];
   $fb->default_domain = $params['email_domain'];
@@ -73,21 +81,23 @@
     unauthorized("Access denied for user $imapuser: ".$rc->toString());
     return false;
   }
-  $rc = $fb->imapOpenMailbox(FreeBusy::imapFolderName( $imapuser, $mbox, 
+  $rc = $fb->imapOpenMailbox(FreeBusy::imapFolderName( $imapuser, $owner, 
 						       $folder, $params['email_domain']));
   if( PEAR::isError( $rc ) ) {
     notfound( "Folder: ".$fb->foldername.', '.$rc->toString());
     return false;
   }  
-  $vfb = $fb->generateFreeBusy();
+  $vfb = $fb->generateFreeBusy($req_extended);
   $ts = mktime();
   if( PEAR::isError( $vfb ) ) {
     unauthorized($rc->toString());
     return false;
   }
-  if( !$cache->store( $owner.'/'.$mbox.'/'.$folder.'.pfb', $vfb ) ) {
-    trigger_error('Could not store vfb in cache file '.$owner.'/'.$mbox.'/'.$folder.'.pfb: '
-		  .$cache->error, E_USER_WARNING);
+
+  $acl = $fb->getACL();
+  if( !$cache->store( $owner.'/'.$folder, $vfb, $acl ) ) {
+    trigger_error('Could not store vfb in cache file '.$owner.'/'.$folder
+		  .($req_extended?'.xpfb':'.pfb').$cache->error, E_USER_WARNING);
   }
 }
 
@@ -109,7 +119,9 @@
     header('Content-Disposition: attachment; filename="' . $user . '.vfb"');
 }
 
+#print "folder=$req_folder, cache=$req_cache, extended=$req_extended";
 echo $vfb;
+#print_r($acl);
 
 // Finish up
 shutdown();





More information about the commits mailing list