Page MenuHomePhorge

kolab_sync.php
No OneTemporary

kolab_sync.php

<?php
/**
* Main application class (based on Roundcube Framework)
*/
class kolab_sync extends rcube
{
public $app_name = 'ActiveSync for Kolab'; // no double quotes inside
private $data = array();
const CHARSET = 'UTF-8';
/**
* This implements the 'singleton' design pattern
*
* @return kolab_sync The one and only instance
*/
static function get_instance()
{
if (!self::$instance || !is_a(self::$instance, 'kolab_sync')) {
self::$instance = new kolab_sync();
self::$instance->startup(); // init AFTER object was linked with self::$instance
}
return self::$instance;
}
public function startup()
{
// Initialize Syncroton Logger
$this->logger = new Zend_Log();
$priority = Zend_Log::DEBUG;
$writer = new Zend_Log_Writer_Stream('logs/console');
$filter = new Zend_Log_Filter_Priority($priority);
$this->logger->addWriter($writer);
$this->logger->addFilter($filter);
}
/**
* Application execution (authentication and ActiveSync)
*/
public function run()
{
// when used with (f)cgi no PHP_AUTH* variables are available without defining a special rewrite rule
if (!isset($_SERVER['PHP_AUTH_USER'])) {
// "Basic didhfiefdhfu4fjfjdsa34drsdfterrde..."
if (isset($_SERVER["REMOTE_USER"])) {
$basicAuthData = base64_decode(substr($_SERVER["REMOTE_USER"], 6));
} elseif (isset($_SERVER["REDIRECT_REMOTE_USER"])) {
$basicAuthData = base64_decode(substr($_SERVER["REDIRECT_REMOTE_USER"], 6));
} elseif (isset($_SERVER["Authorization"])) {
$basicAuthData = base64_decode(substr($_SERVER["Authorization"], 6));
} elseif (isset($_SERVER["HTTP_AUTHORIZATION"])) {
$basicAuthData = base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"], 6));
}
if (isset($basicAuthData) && !empty($basicAuthData)) {
list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) = explode(":", $basicAuthData);
}
}
if (!empty($_SERVER['PHP_AUTH_USER']) && !empty($_SERVER['PHP_AUTH_PW'])) {
// Nokia N9 sends username in form domain.tld\username
$username = explode("\\", $_SERVER['PHP_AUTH_USER']);
if (count($username) == 2) {
$_SERVER['PHP_AUTH_USER'] = $username[1];
}
$userid = $this->authenticate($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']);
}
if (empty($userid)) {
header('WWW-Authenticate: Basic realm="' . $this->app_name .'"');
header('HTTP/1.1 401 Unauthorized');
exit;
}
// Register Syncroton backends
Syncroton_Registry::set('loggerBackend', $this->logger);
Syncroton_Registry::set(Syncroton_Registry::DATABASE, new kolab_sync_db);
Syncroton_Registry::set(Syncroton_Registry::TRANSACTIONMANAGER, kolab_sync_transaction_manager::getInstance());
Syncroton_Registry::set(Syncroton_Registry::DEVICEBACKEND, new kolab_sync_backend_device);
Syncroton_Registry::set(Syncroton_Registry::FOLDERBACKEND, new kolab_sync_backend_folder);
Syncroton_Registry::set(Syncroton_Registry::SYNCSTATEBACKEND, new kolab_sync_backend_state);
Syncroton_Registry::set(Syncroton_Registry::CONTENTSTATEBACKEND, new kolab_sync_backend_content);
Syncroton_Registry::setContactsDataClass('kolab_sync_data_contacts');
Syncroton_Registry::setCalendarDataClass('kolab_sync_data_calendar');
// Syncroton_Registry::setEmailDataClass('kolab_sync_data_email');
// Syncroton_Registry::setTasksDataClass('kolab_sync_data_tasks');
// Run Syncroton
$syncroton = new Syncroton_Server($userid);
$syncroton->handle();
}
/**
* Authenticates a user in LDAP and Roundcube
*/
public function authenticate($username, $password)
{
// Get IMAP host
$host = $this->config->get('default_host');
$host = rcube_utils::parse_host($host);
// Get user
$user = $this->get_ldap_user($username, $host);
// Get Roundcube user ID
$userid = $this->get_rcube_user($user, $password, $host);
return $userid;
}
/**
* Returns user login attribute from LDAP server
*/
private function get_ldap_user($username, $host)
{
$login_attr = $this->config->get('kolab_auth_login');
$addressbook = $this->config->get('kolab_auth_addressbook');
$filter = $this->config->get('kolab_auth_filter');
$filter = $this->parse_vars($filter, $username, $host);
if (!is_array($addressbook)) {
$ldap_config = (array)$this->config->get('ldap_public');
$addressbook = $ldap_config[$addressbook];
}
if (empty($addressbook)) {
return null;
}
if (empty($login_attr)) {
return null;
}
$addressbook['filter'] = $filter;
$addressbook['sizelimit'] = 2;
$this->ldap = new rcube_ldap(
$addressbook,
$this->config->get('ldap_debug'),
$this->config->mail_domain($host)
);
if (!$this->ldap->ready) {
return null;
}
// get record
$results = $this->ldap->list_records();
if (count($results->records) != 1) {
return null;
}
if ($record = $results->records[0]) {
return is_array($record[$login_attr]) ? $record[$login_attr][0] : $record[$login_attr];
}
}
/**
* Prepares filter query for LDAP search
*/
private function parse_vars($str, $user, $host)
{
$domain = $this->config->get('username_domain');
if (!empty($domain) && strpos($user, '@') === false) {
if (is_array($domain) && isset($domain[$host]))
$user .= '@'.rcube_utils::parse_host($domain[$host], $host);
else if (is_string($domain))
$user .= '@'.rcube_utils::parse_host($domain, $host);
}
// replace variables in filter
list($u, $d) = explode('@', $user);
$dc = 'dc='.strtr($d, array('.' => ',dc=')); // hierarchal domain string
$replaces = array('%dc' => $dc, '%d' => $d, '%fu' => $user, '%u' => $u);
return strtr($str, $replaces);
}
/**
* Returns Roundcube user ID for specified username and host.
* Also sets IMAP connection credentials.
*/
private function get_rcube_user($username, $password, $host)
{
if (empty($username)) {
return null;
}
$login_lc = $this->config->get('login_lc');
// parse $host
$a_host = parse_url($host);
if ($a_host['host']) {
$host = $a_host['host'];
$ssl = (isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'))) ? $a_host['scheme'] : null;
if (!empty($a_host['port'])) {
$port = $a_host['port'];
}
else if ($ssl && $ssl != 'tls' && (!$config['default_port'] || $config['default_port'] == 143)) {
$port = 993;
}
}
if (!$port) {
$port = $this->config->get('default_port');
}
// Convert username to lowercase. If storage backend
// is case-insensitive we need to store always the same username
if ($login_lc) {
$username = mb_strtolower($username);
}
// Here we need IDNA ASCII
// Only rcube_contacts class is using domain names in Unicode
$host = rcube_utils::idn_to_ascii($host);
if (strpos($username, '@')) {
// lowercase domain name
list($local, $domain) = explode('@', $username);
$username = $local . '@' . mb_strtolower($domain);
$username = rcube_utils::idn_to_ascii($username);
}
// user already registered?
$user = rcube_user::query($username, $host);
if (!is_object($user)) {
// @TODO: log error
return null;
}
// Configure environment
$this->user = $user;
// rcube::get_storage() uses session, kolab-sync doesn't
// @TODO: modify framework to support private class variables
// or other method to provide storage credentials
global $_SESSION;
$_SESSION['storage_host'] = $host;
$_SESSION['username'] = $username;
$_SESSION['storage_port'] = $port;
$_SESSION['storage_ssl'] = $ssl;
$_SESSION['password'] = $this->encrypt($password);
// $this->set_storage_prop();
// force reloading complete list of subscribed mailboxes
// $storage->clear_cache('mailboxes', true);
// overwrite config with user preferences
$this->config->set_user_prefs((array)$this->user->get_prefs());
return $user->ID;
}
/**
* Function to be executed in script shutdown
*/
public function shutdown()
{
parent::shutdown();
if ($this->ldap) {
$this->ldap->close();
}
// write performance stats to logs/console
if ($this->config->get('devel_mode')) {
if (function_exists('memory_get_usage'))
$mem = sprintf('%.1f', memory_get_usage() / 1048576);
if (function_exists('memory_get_peak_usage'))
$mem .= '/' . sprintf('%.1f', memory_get_peak_usage() / 1048576);
$log = $_SERVER['REQUEST_URI'] . ($mem ? " [$mem]" : '');
if (defined('RCMAIL_START'))
self::print_timer(RCMAIL_START, $log);
else
self::console($log);
}
}
}

File Metadata

Mime Type
text/x-php
Expires
Mon, Aug 25, 10:14 PM (3 m, 2 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
257090
Default Alt Text
kolab_sync.php (9 KB)

Event Timeline