Page MenuHomePhorge

No OneTemporary

Size
16 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/Kolab/DAV/Locks/File.php b/lib/Kolab/DAV/Locks/File.php
index 0d8d17b..dddd936 100644
--- a/lib/Kolab/DAV/Locks/File.php
+++ b/lib/Kolab/DAV/Locks/File.php
@@ -1,201 +1,215 @@
<?php
/**
* File-based Lock manager for the Kolab WebDAV service.
*
* @author Thomas Bruederli <bruederli@kolabsys.com>
*
* Copyright (C) 2013, Kolab Systems AG <contact@kolabsys.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Kolab\DAV\Locks;
use Kolab\DAV\Auth\HTTPBasic;
use Sabre\DAV\Locks\LockInfo;
use Sabre\DAV\Locks\Backend\AbstractBackend;
/**
* The Lock manager that maintains a lock file per user in the local file system.
*/
class File extends AbstractBackend
{
/**
- * The storage file prefix
+ * The storage directory prefix
*
* @var string
*/
private $basePath;
+ /**
+ * The directory to storage the file in
+ *
+ * @var string
+ */
+ private $dataDir;
+
/**
* Constructor
*
* @param string $basePath base path to store lock files
*/
public function __construct($basePath)
{
$this->basePath = $basePath;
}
/**
* Returns a list of Sabre\DAV\Locks\LockInfo objects
*
* This method should return all the locks for a particular uri, including
* locks that might be set on a parent uri.
*
* If returnChildLocks is set to true, this method should also look for
* any locks in the subtree of the uri for locks.
*
* @param string $uri
* @param bool $returnChildLocks
* @return array
*/
public function getLocks($uri, $returnChildLocks)
{
console(__METHOD__, $uri, $returnChildLocks);
$newLocks = array();
$locks = $this->getData();
foreach ($locks as $lock) {
if ($lock->uri === $uri ||
// deep locks on parents
($lock->depth != 0 && strpos($uri, $lock->uri . '/') === 0) ||
// locks on children
($returnChildLocks && (strpos($lock->uri, $uri . '/') === 0)) ) {
$newLocks[] = $lock;
}
}
// Checking if we can remove any of these locks
foreach ($newLocks as $k => $lock) {
if (time() > $lock->timeout + $lock->created)
unset($newLocks[$k]);
}
return $newLocks;
}
/**
* Locks a uri
*
* @param string $uri
* @param LockInfo $lockInfo
* @return bool
*/
public function lock($uri, LockInfo $lockInfo)
{
console(__METHOD__, $uri, $lockInfo);
// We're making the lock timeout 30 minutes
$lockInfo->timeout = 1800;
$lockInfo->created = time();
$lockInfo->uri = $uri;
$lockInfo->owner = trim($lockInfo->owner);
$locks = $this->getData();
$now = time();
foreach ($locks as $k => $lock) {
if (($lock->token == $lockInfo->token) || ($now > $lock->timeout + $lock->created)) {
unset($locks[$k]);
}
}
$locks[] = $lockInfo;
$this->putData($locks);
return true;
}
/**
* Removes a lock from a uri
*
* @param string $uri
* @param LockInfo $lockInfo
* @return bool
*/
public function unlock($uri, LockInfo $lockInfo)
{
console(__METHOD__, $uri, $lockInfo);
$locks = $this->getData();
foreach ($locks as $k => $lock) {
if ($lock->token == $lockInfo->token) {
unset($locks[$k]);
$this->putData($locks);
return true;
}
}
return false;
}
/**
* Loads the lockdata from the filesystem.
*
* @return array
*/
protected function getData()
{
$locksFile = $this->getLocksFile();
if (!file_exists($locksFile))
return array();
// opening up the file, and creating a shared lock
$handle = fopen($locksFile, 'r');
flock($handle, LOCK_SH);
// Reading data until the eof
$data = stream_get_contents($handle);
// We're all good
fclose($handle);
// Unserializing and checking if the resource file contains data for this file
$data = unserialize($data);
return $data ?: array();
}
/**
* Compose a full path to the lock file of the current user
*/
protected function getLocksFile()
{
- return $this->basePath . '_' . str_replace('@', '_', HTTPBasic::$current_user);
+ if (!$this->dataDir) {
+ $this->dataDir = $this->basePath . '/' . str_replace('@', '_', HTTPBasic::$current_user);
+
+ if (!is_dir($this->dataDir))
+ mkdir($this->dataDir);
+ }
+
+ return $this->dataDir . '/locks';
}
/**
* Saves the lockdata
*
* @param array $newData
* @return void
*/
protected function putData(array $newData)
{
// opening up the file, and creating an exclusive lock
$handle = fopen($this->getLocksFile(), 'a+');
flock($handle, LOCK_EX);
// We can only truncate and rewind once the lock is acquired.
ftruncate($handle, 0);
rewind($handle);
fwrite($handle, serialize($newData));
fclose($handle);
}
}
diff --git a/lib/Kolab/DAV/TempFilesPlugin.php b/lib/Kolab/DAV/TempFilesPlugin.php
new file mode 100644
index 0000000..5a19cd6
--- /dev/null
+++ b/lib/Kolab/DAV/TempFilesPlugin.php
@@ -0,0 +1,85 @@
+<?php
+
+/**
+ * Temporary File Filter Plugin for the Kolab WebDAV service.
+ *
+ * @author Thomas Bruederli <bruederli@kolabsys.com>
+ *
+ * Copyright (C) 2013, Kolab Systems AG <contact@kolabsys.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace Kolab\DAV;
+
+use Sabre\DAV;
+use Kolab\DAV\Auth\HTTPBasic;
+
+/**
+ * Temporary File Filter Plugin
+ *
+ * The purpose of this filter is to intercept some of the garbage files
+ * operation systems and applications tend to generate when mounting
+ * a WebDAV share as a disk.
+ */
+class TempFilesPlugin extends DAV\TemporaryFileFilterPlugin
+{
+ protected $baseDir;
+
+ /**
+ * Creates the plugin.
+ *
+ * @param string $baseDir Temp directoy base path
+ */
+ public function __construct($baseDir)
+ {
+ $this->baseDir = $baseDir;
+ }
+
+ /**
+ * This method returns the directory where the temporary files should be stored.
+ *
+ * @return string
+ */
+ protected function getDataDir()
+ {
+ if (!$this->dataDir) {
+ $this->dataDir = $this->baseDir . '/' . str_replace('@', '_', HTTPBasic::$current_user);
+
+ if (!is_dir($this->dataDir)) {
+ mkdir($this->dataDir);
+ }
+
+ // run a cleanup routine on every 100th request
+ if (rand(0,100) == 100) {
+ $this->cleanup();
+ }
+ }
+
+ return $this->dataDir;
+ }
+
+ /**
+ * Tempfile cleanup routine to remove files not touched for 24 hours
+ */
+ protected function cleanup()
+ {
+ $expires = time() - 86400;
+ foreach (glob($this->dataDir . '/*.tempfile') as $file) {
+ if (filemtime($file) < $expires) {
+ unlink($file);
+ }
+ }
+ }
+}
diff --git a/public_html/index.php b/public_html/index.php
index 1a2b00a..a87b403 100644
--- a/public_html/index.php
+++ b/public_html/index.php
@@ -1,196 +1,196 @@
<?php
/**
* iRony, the Kolab WebDAV/CalDAV/CardDAV Server
*
* This is the public API to provide *DAV-based access to the Kolab Groupware backend
*
* @version 0.3-dev
* @author Thomas Bruederli <bruederli@kolabsys.com>
*
* Copyright (C) 2013, Kolab Systems AG <contact@kolabsys.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// define some environment variables used throughout the app and libraries
define('KOLAB_DAV_ROOT', realpath('../'));
define('KOLAB_DAV_VERSION', '0.3-dev');
define('KOLAB_DAV_START', microtime(true));
define('RCUBE_INSTALL_PATH', KOLAB_DAV_ROOT . '/');
define('RCUBE_CONFIG_DIR', KOLAB_DAV_ROOT . '/config/');
define('RCUBE_PLUGINS_DIR', KOLAB_DAV_ROOT . '/lib/plugins/');
// suppress error notices
ini_set('error_reporting', E_ALL &~ E_NOTICE &~ E_STRICT);
/**
* Mapping PHP errors to exceptions.
*
* While this is not strictly needed, it makes a lot of sense to do so. If an
* E_NOTICE or anything appears in your code, this allows SabreDAV to intercept
* the issue and send a proper response back to the client (HTTP/1.1 500).
*/
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
//set_error_handler("exception_error_handler");
// use composer's autoloader for dependencies
$loader = require_once(KOLAB_DAV_ROOT . '/vendor/autoload.php');
$loader->setUseIncludePath(true); // enable include_path to load PEAR classes from their default location
// load the Roundcube framework with its autoloader
require_once KOLAB_DAV_ROOT . '/lib/Roundcube/bootstrap.php';
// Roundcube framework initialization
$rcube = rcube::get_instance(rcube::INIT_WITH_DB | rcube::INIT_WITH_PLUGINS);
$rcube->config->load_from_file(RCUBE_CONFIG_DIR . 'dav.inc.php');
// Load plugins
$plugins = (array)$rcube->config->get('kolabdav_plugins', array('kolab_auth'));
$required = array('libkolab', 'libcalendaring');
$rcube->plugins->init($rcube);
$rcube->plugins->load_plugins($plugins, $required);
// convenience function, you know it well :-)
function console()
{
global $rcube;
// write to global console log
if ($rcube->config->get('kolabdav_console', false)) {
call_user_func_array(array('rcube', 'console'), func_get_args());
}
// dump console data per user
if ($rcube->config->get('kolabdav_user_debug', false)) {
$uname = \Kolab\DAV\Auth\HTTPBasic::$current_user;
$log_dir = $rcube->config->get('log_dir', RCUBE_INSTALL_PATH . 'logs');
if ($uname && $log_dir && is_writable($log_dir . '/' . $uname)) {
$msg = array();
foreach (func_get_args() as $arg) {
$msg[] = !is_string($arg) ? var_export($arg, true) : $arg;
}
rcube::write_log($uname . '/console', join(";\n", $msg));
}
}
}
// Make sure this setting is turned on and reflects the root url of the *DAV server.
$base_uri = $rcube->config->get('base_uri', slashify(substr(dirname($_SERVER['SCRIPT_FILENAME']), strlen($_SERVER['DOCUMENT_ROOT']))));
// add filename to base URI when called without mod_rewrite (e.g. /dav/index.php/calendar)
if (strpos($_SERVER['REQUEST_URI'], 'index.php'))
$base_uri .= 'index.php/';
// create the various backend instances
$auth_backend = new \Kolab\DAV\Auth\HTTPBasic();
$principal_backend = new \Kolab\DAVACL\PrincipalBackend();
$services = array();
foreach (array('CALDAV','CARDDAV','WEBDAV') as $skey) {
if (getenv($skey))
$services[$skey] = 1;
}
// no config means *all* services
if (empty($services))
$services = array('CALDAV' => 1, 'CARDDAV' => 1, 'WEBDAV' => 1);
// add chwala directories to include path for autoloading
if ($services['WEBDAV']) {
$include_path = ini_get('include_path') . PATH_SEPARATOR;
$include_path .= KOLAB_DAV_ROOT . '/lib/FileAPI' . PATH_SEPARATOR;
$include_path .= KOLAB_DAV_ROOT . '/lib/FileAPI/kolab' . PATH_SEPARATOR;
$include_path .= KOLAB_DAV_ROOT . '/lib/FileAPI/ext';
set_include_path($include_path);
}
// Build the directory tree
// This is an array which contains the 'top-level' directories in the WebDAV server.
if ($services['CALDAV'] || $services['CARDDAV']) {
$nodes = array(
new \Sabre\CalDAV\Principal\Collection($principal_backend),
);
if ($services['CALDAV']) {
$caldav_backend = new \Kolab\CalDAV\CalendarBackend();
$caldav_backend->setUserAgent($_SERVER['HTTP_USER_AGENT']);
$nodes[] = new \Kolab\CalDAV\CalendarRootNode($principal_backend, $caldav_backend);
}
if ($services['CARDDAV']) {
$carddav_backend = new \Kolab\CardDAV\ContactsBackend();
$carddav_backend->setUserAgent($_SERVER['HTTP_USER_AGENT']);
$nodes[] = new \Kolab\CardDAV\AddressBookRoot($principal_backend, $carddav_backend);
}
if ($services['WEBDAV']) {
$nodes[] = new \Kolab\DAV\Collection(\Kolab\DAV\Collection::ROOT_DIRECTORY);
}
}
// register WebDAV service as root
else if ($services['WEBDAV']) {
$nodes = new \Kolab\DAV\Collection('');
}
// the object tree needs in turn to be passed to the server class
$server = new \Sabre\DAV\Server($nodes);
$server->setBaseUri($base_uri);
// enable logger
if ($rcube->config->get('kolabdav_console') || $rcube->config->get('kolabdav_user_debug')) {
$server->addPlugin(new \Kolab\Utils\DAVLogger());
}
// register some plugins
$server->addPlugin(new \Sabre\DAV\Auth\Plugin($auth_backend, 'KolabDAV'));
$server->addPlugin(new \Sabre\DAVACL\Plugin());
if ($services['CALDAV']) {
$caldav_plugin = new \Kolab\CalDAV\Plugin();
$caldav_plugin->setIMipHandler(new \Kolab\CalDAV\IMip());
$server->addPlugin($caldav_plugin);
}
if ($services['CARDDAV']) {
$server->addPlugin(new \Kolab\CardDAV\Plugin());
}
if ($services['WEBDAV']) {
// the lock manager is reponsible for making sure users don't overwrite each others changes.
// TODO: replace this with a class that manages locks in the Kolab backend
- $locks_backend = new Kolab\DAV\Locks\File(KOLAB_DAV_ROOT . '/temp/locks');
+ $locks_backend = new \Kolab\DAV\Locks\File(KOLAB_DAV_ROOT . '/temp');
$server->addPlugin(new \Sabre\DAV\Locks\Plugin($locks_backend));
// intercept some of the garbage files operation systems tend to generate when mounting a WebDAV share
- $server->addPlugin(new \Sabre\DAV\TemporaryFileFilterPlugin(KOLAB_DAV_ROOT . '/temp'));
+ $server->addPlugin(new \Kolab\DAV\TempFilesPlugin(KOLAB_DAV_ROOT . '/temp'));
}
// HTML UI for browser-based access (recommended only for development)
if (getenv('DAVBROWSER')) {
$server->addPlugin(new \Sabre\DAV\Browser\Plugin());
}
// finally, process the request
$server->exec();
// trigger log
$server->broadcastEvent('exit', array());

File Metadata

Mime Type
text/x-diff
Expires
Fri, Feb 6, 12:49 AM (4 h, 3 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
428041
Default Alt Text
(16 KB)

Event Timeline