gunnar: server/kolab-freebusy/freebusy config.php, NONE, 1.1 freebusy.php, NONE, 1.1 pfb.php, NONE, 1.1

cvs at kolab.org cvs at kolab.org
Wed Aug 8 11:47:31 CEST 2007


Author: gunnar

Update of /kolabrepository/server/kolab-freebusy/freebusy
In directory doto:/tmp/cvs-serv4139/freebusy

Added Files:
	config.php freebusy.php pfb.php 
Log Message:
A draft version of the new kolab-freebusy package. This is now only the webserver part and also requires the PEAR-style Kolab_Freebusy library within php-kolab.

--- NEW FILE: config.php ---
<?php

// Kolab prefix
$params['kolab_prefix'] = '/kolab';

// What is the address of the Cyrus server where the calendar data is stored?
// This is also used as the LDAP server address where user objects reside
$params['server'] = 'localhost';

// What is the address of the LDAP server address where user objects reside
$params['ldap_uri'] = "ldap://127.0.0.1:389";

// What is the Base DN of our LDAP database?
$params['base_dn'] = 'dc=example,dc=com';

// What DN should we use to bind to the LDAP server?
$params['bind_dn'] = 'cn=nobody,cn=internal,' . $params['base_dn'];

// What password should we use with the above DN when binding?
$params['bind_pw'] = 'php password from kolab.conf';

// Are we using a multi-location setup? If this is true, we check the users'
// LDAP object for the next attribute - if it is different than $params['server']
// we get the free/busy information from the script running on the other box
$params['multi_location'] = true;

// What LDAP attribute is used to store the users' home server address?
$params['home_server'] = 'kolabhomeserver';

// What is our default mail domain? This is used if any users do not have
// '@domain' specified after their username as part of their email address.
$params['email_domain'] = 'example.com';

// Are we using virtual domains with Cyrus?
$params['virtual_domains'] = true;

// Should we append domains to mailbox URIs? This only applies when
// virtual_domains is true, and when using manager accounts.
$params['append_domains'] = false;

// What account should we use to read in calendar data in the case the user
// does not supply credentials? This account should
// have access to the calendar mailbox of all the users for which free/busy
// information is to be retrieved.
//$params['calendar_user'] = '@ @@cyrus-admins@@@';

// What password should we use with the above account?
//$params['calendar_pass'] = '@ @@bind_pw@@@';

// What is the name of the users' calendar mailbox?
$params['calendar_store'] = 'Calendar';

// How many days of free/busy data should we generate?
$params['freebusy_days'] = 56;

// Should we generate extended free/busy information? This can be overridden by
// the URL parameter "x" (= 0 or 1).
$params['extended'] = false;

// Should we use the caching mechanism, which avoids having to always re-read
// all the events? This can be overridden by the URL parameter "c" (= 0 or 1).
$params['cache'] = true;

// Should we redirect using a Location header, if the user is not local? If this
// is false we silently download the file ourselves and output it so that it
// looks as though the free/busy information is coming from us.
$params['redirect'] = false;

// Should we send a Content-Type header, indicating what the mime type of the
// resulting VFB file is?
$params['send_content_type'] = false;

// Should we send a Content-Length header, indicating how large the resulting
// VFB file is?
$params['send_content_length'] = false;

// Should we send a Content-Disposition header, indicating what the name of the
// resulting VFB file should be?
$params['send_content_disposition'] = false;

// Where are we logging to?
$params['log'] = 'file:file:/kolab/var/resmgr/freebusy.log';                // File...
// $params['log'] = 'syslog:cons, pid';            // Or syslog...

// What level of output should we log? Higher levels give more verbose output.
// One of: 0 (RM_LOG_SILENT); 1 (RM_LOG_ERROR); 2 (RM_LOG_WARN); 3 (RM_LOG_INFO) or 4 (RM_LOG_DEBUG).
$params['log_level'] = 4;

// What db type to use for freebusy caches
$params['dbtype'] = 'db4';

// IMAP options passed to imap_open
//$params['imap_options'] = "/notls/secure/readonly";
$params['imap_options'] = "/notls/readonly";

$params['pfb_dbformat'] = 'db4';

// Location of the cache files
$params['cache_dir'] = '/kolab/var/kolab/www/freebusy/cache';

// don't change this if you don't have to
//$params['ldap_classname_suffix'] = "_dummy";

// Activate if you wish to use the new horde framework
// (horde-framework-kolab) package instead of the old code in
// kolab-horde-framework. This is still untested and considered
// UNSAFE!
$params['use_new_horde'] = false;

//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
// If you modify this file, please do not forget to modify both the
// template and the source file in kolab-resource-handler.
//
// In order to check if both are in sync:
//
// cd server
// diff -Nau kolab-freebusy/freebusy/config.php kolabd/kolabd/templates/freebusy.conf.template.in
//
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

--- NEW FILE: freebusy.php ---
<?php
/*  
 *  COPYRIGHT
 *  ---------
 *
 *  See docs/AUTHORS file
 *
 *
 *  LICENSE
 *  -------
 *
 *  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 of the License, 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 should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  $Revision: 1.1 $
 *
 */

require_once('config.php');
require_once('Kolab/Freebusy/freebusycache.class.php');
require_once('Kolab/Freebusy/freebusycollector.class.php');

if ( empty($params['ldap_classname_suffix'])) $params['ldap_classname_suffix'] = '';
require_once('Kolab/Freebusy/freebusyldap'.$params['ldap_classname_suffix'].'.class.php');

require_once('Kolab/Freebusy/misc.php');

logInit( 'freebusy' );

$user = trim($_REQUEST['uid']);
$imapuser     = $_SERVER['PHP_AUTH_USER'];
$imappw       = $_SERVER['PHP_AUTH_PW'];

$req_cache    = false;
$req_extended = false;
if ( !empty($_REQUEST['cache']))    $req_cache    = (bool)$_REQUEST['cache'];
if ( !empty($_REQUEST['extended'])) $req_extended = (bool)$_REQUEST['extended'];

myLog("---FreeBusy Script starting (".$_SERVER['REQUEST_URI'].")---", RM_LOG_DEBUG );
myLog("user=$user, imapuser=$imapuser, req_cache=$req_cache, req_extended=$req_extended", RM_LOG_DEBUG );

$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 );
$user = $ldap->mailForUidOrAlias( $user );
$homeserver = $ldap->homeServer( $user );

if( $homeserver === false ) {
  notFound("Resource ".$_SERVER['REQUEST_URI']." (user=$user, req_extended=$req_extended, req_cache=$req_cache) not found");
}

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 ".removePassword($redirect));
    }
  }
  shutdown();
  exit;
}

$user = strtolower($user);

$cache =& new FreeBusyCache( $params['cache_dir'], $params['pfb_dbformat'], $req_extended );

$collector =& new FreeBusyCollector( $user );

$groups = $ldap->distlists( $ldap->dn( $user ) );
for( $i = 0; $i < count($groups); $i++ ) {
  $groups[$i] = $groups[$i].'@'.$params['email_domain'];
}
$pfbs = $cache->findAll( $user, $groups );
$ts = 0;
if( $pfbs === false ) {
  notFound($pfb->error);
}

//myLog("Found pfbs: ".join(",",$pfbs)." for $user",RM_LOG_DEBUG);

if( $req_extended ) {
  // Get accessing users groups
  $imapgroups = $ldap->distlists( $ldap->dn( $imapuser ) );
}

foreach( $pfbs as $pfb ) {
  $fb = $cache->load( $pfb, $ts2, $acl );
  if( $fb ) myLog("Found fb for $pfb", RM_LOG_DEBUG);
  else myLog("No fb found for $pfb", RM_LOG_DEBUG);
  if( $acl && $req_extended ) {
    $r = $cache->getRights( $acl, $imapuser, $imapgroups );
    if( !$fb || !array_key_exists( 'r', $r ) ) {
      $cache->extended = false; // HACK!
      $fb = $cache->load( $pfb, $ts2, $acl );    
      $cache->extended = true;
      myLog("Falling back to non-extended fb", RM_LOG_DEBUG );
    }
  }
  $ts = max( $ts, $ts2 );
  if( $fb ) {
    if( $collector->addFreebusy( $fb ) == FB_TOO_OLD ) {
      $cache->delete( $pfb );
    }
  }
}
$vfb = $collector->exportvCalendar();

// And finally send it out, ensuring it doesn't get cached along the way
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate("D, d M Y H:i:s",$ts) . ' GMT');
header('Pragma: public');
header('Content-Transfer-Encoding: none');
if ($params['send_content_type']) {
    header('Content-Type: text/calendar');
}
if ($params['send_content_length']) {
    header('Content-Length: ' . strlen($vfb));
}
if ($params['send_content_disposition']) {
    header('Content-Disposition: attachment; filename="' . $user . '.ifb"');
}

echo $vfb;
?>

--- NEW FILE: pfb.php ---
<?php
/*  
 *  COPYRIGHT
 *  ---------
 *
 *  See docs/AUTHORS file
 *
 *
 *  LICENSE
 *  -------
 *
 *  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 of the License, 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 should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  $Revision: 1.1 $
 *
 */

  // Profiling
function microtime_float() {
    list($usec, $sec) = explode(" ", microtime());
    return ((float)$usec + (float)$sec);
}
$start_time = microtime_float();


error_reporting(E_ALL);
$max_execution_time = ini_get('max_execution_time');
if( $max_execution_time < 200 ) ini_set('max_execution_time', '200');

require_once('Kolab/Freebusy/misc.php');
require_once('config.php');

if ( empty($params['ldap_classname_suffix'])) $params['ldap_classname_suffix'] = '';
require_once('Kolab/Freebusy/freebusyldap'.$params['ldap_classname_suffix'].'.class.php');

require_once('Kolab/Freebusy/freebusycache.class.php');

logInit('pfb');

$imapuser     = isset($_SERVER['PHP_AUTH_USER'])?$_SERVER['PHP_AUTH_USER']:false;
$imappw       = isset($_SERVER['PHP_AUTH_PW'])?$_SERVER['PHP_AUTH_PW']:false;
$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);

$ldap =& new FreeBusyLDAP( $params['ldap_uri'], $params['base_dn'] );
if( !$ldap->bind( $params['bind_dn'], $params['bind_pw'] ) ) {
  notFound( "Bind failed: ".$ldap->error() );
  exit;
}

$userinfo = $ldap->userInfo( $imapuser );
if( $userinfo ) {
  if( $userinfo['MAIL'] ) $imapuser = $userinfo['MAIL'];
  //$homeserver = $userinfo['HOMESERVER'];  
}

$folder = explode('/', $req_folder);

if( count($folder) < 1 ) {
  // error
  notFound( _('No such folder ').htmlentities($req_folder) );
}

// Make sure email address is in lowercase
$folder[0] = strtolower($folder[0]);
$req_folder = implode('/', $folder);

$uinfo = $ldap->userInfo($folder[0]);
$owner = $uinfo['MAIL'];
$homeserver = $uinfo['HOMESERVER'];  
if( empty($owner) || false===strpos($owner,'@')) {
    // try guessing the domain
  $idx = strpos( $imapuser, '@' );
  if( $idx !== false ) {
    $domain = substr( $imapuser, $idx+1 );
    myLog("Trying to append $domain to ".$folder[0], RM_LOG_DEBUG);
    $uinfo = $ldap->userInfo($folder[0].'@'.$domain);
    $owner = $uinfo['MAIL'];
  }
}

if( $homeserver && $homeserver != $params['server'] ) {
  $redirect = 'https://'.$homeserver . $_SERVER['REQUEST_URI'];
  myLog("Found remote user, redirecting to $homeserver", RM_LOG_DEBUG);
  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 ".removePassword($redirect));
    }
  }
  shutdown();
  exit;
}

$cache =& new FreeBusyCache( $params['cache_dir'], $params['pfb_dbformat'], false );
$xcache =& new FreeBusyCache( $params['cache_dir'], $params['pfb_dbformat'], true );


if( $req_cache ) {
  $acl = false;
  if( $req_extended ) {
    $vfb = $xcache->load( $req_folder, $ts, $acl );
  } else {
    $vfb = $cache->load( $req_folder, $ts, $acl );
  }
  if( $acl && $req_extended ) {
    // Check access
    $distlists = $ldap->distlists( $userinfo['DN'] );
    if( $distlists === false ) unauthorized( $req_folder.($req_extended?'.xpfb':'.pfb' ) );
    for( $i = 0; $i < count($distlists); $i++ ) {
      $distlists[$i] = $distlists[$i].'@'.$params['email_domain'];
    }
    $rights = $xcache->getRights( $acl, $imapuser, $distlists );
    if( !$req_extended || $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 {
  if( empty($imapuser) ) {
    // Here we really need an authenticated user!
    unauthorized("Please authenticate");
  }
  require_once('Kolab/Freebusy/freebusy.class.php');

  if( empty($owner) ) {
    notFound( _('No such account ').htmlentities($folder[0]));
    return false;
  }
  unset($folder[0]);
  $folder = join('/', $folder);
  $fbpast = $ldap->freeBusyPast();
  $fb =& new FreeBusy( $params['cache_dir'], $owner, $imapuser, $imappw, 'localhost', $params['imap_options'], $uinfo['FBFUTURE'], $fbpast );

  $fb->default_domain = $params['email_domain'];
  $rc = $fb->imapConnect();
  if( $rc === false ) {
    unauthorized(imap_last_error());
    return false;
  }
  $rc = $fb->imapOpenMailbox(FreeBusy::imapFolderName( $imapuser, $owner, 
						       $folder, $params['email_domain']));
  if( $rc === false ) {
    notfound( "Folder: ".$fb->foldername.', '.imap_last_error());
    return false;
  }
  $relevance = $fb->getRelevance();
  list($vfb,$xvfb) = $fb->generateFreeBusy();
  $ts = mktime();
  if( PEAR::isError( $vfb ) ) {
    unauthorized($vfb->toString());
    return false;
  }

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

  $acl = $fb->getACL();
  if( !$cache->store( $owner.'/'.$folder, $vfb, $acl, $relevance ) ) {
    trigger_error('Could not store pfb in cache file '.$owner.'/'.$folder
		  .'.pfb: '.$cache->error, E_USER_WARNING);
  }
  if( !$xcache->store( $owner.'/'.$folder, $xvfb, $acl, $relevance ) ) {
    trigger_error('Could not store xpfb in cache file '.$owner.'/'.$folder
		  .'.xpfb: '.$cache->error, E_USER_WARNING);
  }

  if( $req_extended ) $vfb = $xvfb;
  unset($xvfb);
}

// And finally send it out, ensuring it doesn't get cached along the way
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate("D, d M Y H:i:s",$ts) . ' GMT');
header('Pragma: public');
header('Content-Transfer-Encoding: none');
if ($params['send_content_type']) {
    header('Content-Type: text/calendar');
}
if ($params['send_content_length']) {
    header('Content-Length: ' . strlen($vfb));
}
if ($params['send_content_disposition']) {
    header('Content-Disposition: attachment; filename="' . $user . '.vfb"');
}

#print "folder=$req_folder, cache=$req_cache, extended=$req_extended";
echo $vfb;
#print_r($acl);

// Finish up
myLog("pfb.php complete, execution time was ".(microtime_float()-$start_time)." secs.", RM_LOG_DEBUG);
shutdown();
?>





More information about the commits mailing list