Initial Release of the calendar plugin

This commit is contained in:
Tobias Hößl 2012-06-03 18:19:28 +00:00
parent 45cc9885fc
commit 7115197a33
561 changed files with 189494 additions and 0 deletions

View file

@ -0,0 +1,248 @@
#!/usr/bin/env python
#
# Copyright 2006, 2007 Google Inc. All Rights Reserved.
# Author: danderson@google.com (David Anderson)
#
# Script for uploading files to a Google Code project.
#
# This is intended to be both a useful script for people who want to
# streamline project uploads and a reference implementation for
# uploading files to Google Code projects.
#
# To upload a file to Google Code, you need to provide a path to the
# file on your local machine, a small summary of what the file is, a
# project name, and a valid account that is a member or owner of that
# project. You can optionally provide a list of labels that apply to
# the file. The file will be uploaded under the same name that it has
# in your local filesystem (that is, the "basename" or last path
# component). Run the script with '--help' to get the exact syntax
# and available options.
#
# Note that the upload script requests that you enter your
# googlecode.com password. This is NOT your Gmail account password!
# This is the password you use on googlecode.com for committing to
# Subversion and uploading files. You can find your password by going
# to http://code.google.com/hosting/settings when logged in with your
# Gmail account. If you have already committed to your project's
# Subversion repository, the script will automatically retrieve your
# credentials from there (unless disabled, see the output of '--help'
# for details).
#
# If you are looking at this script as a reference for implementing
# your own Google Code file uploader, then you should take a look at
# the upload() function, which is the meat of the uploader. You
# basically need to build a multipart/form-data POST request with the
# right fields and send it to https://PROJECT.googlecode.com/files .
# Authenticate the request using HTTP Basic authentication, as is
# shown below.
#
# Licensed under the terms of the Apache Software License 2.0:
# http://www.apache.org/licenses/LICENSE-2.0
#
# Questions, comments, feature requests and patches are most welcome.
# Please direct all of these to the Google Code users group:
# http://groups.google.com/group/google-code-hosting
"""Google Code file uploader script.
"""
__author__ = 'danderson@google.com (David Anderson)'
import httplib
import os.path
import optparse
import getpass
import base64
import sys
def upload(file, project_name, user_name, password, summary, labels=None):
"""Upload a file to a Google Code project's file server.
Args:
file: The local path to the file.
project_name: The name of your project on Google Code.
user_name: Your Google account name.
password: The googlecode.com password for your account.
Note that this is NOT your global Google Account password!
summary: A small description for the file.
labels: an optional list of label strings with which to tag the file.
Returns: a tuple:
http_status: 201 if the upload succeeded, something else if an
error occurred.
http_reason: The human-readable string associated with http_status
file_url: If the upload succeeded, the URL of the file on Google
Code, None otherwise.
"""
# The login is the user part of user@gmail.com. If the login provided
# is in the full user@domain form, strip it down.
if user_name.endswith('@gmail.com'):
user_name = user_name[:user_name.index('@gmail.com')]
form_fields = [('summary', summary)]
if labels is not None:
form_fields.extend([('label', l.strip()) for l in labels])
content_type, body = encode_upload_request(form_fields, file)
upload_host = '%s.googlecode.com' % project_name
upload_uri = '/files'
auth_token = base64.b64encode('%s:%s'% (user_name, password))
headers = {
'Authorization': 'Basic %s' % auth_token,
'User-Agent': 'Googlecode.com uploader v0.9.4',
'Content-Type': content_type,
}
server = httplib.HTTPSConnection(upload_host)
server.request('POST', upload_uri, body, headers)
resp = server.getresponse()
server.close()
if resp.status == 201:
location = resp.getheader('Location', None)
else:
location = None
return resp.status, resp.reason, location
def encode_upload_request(fields, file_path):
"""Encode the given fields and file into a multipart form body.
fields is a sequence of (name, value) pairs. file is the path of
the file to upload. The file will be uploaded to Google Code with
the same file name.
Returns: (content_type, body) ready for httplib.HTTP instance
"""
BOUNDARY = '----------Googlecode_boundary_reindeer_flotilla'
CRLF = '\r\n'
body = []
# Add the metadata about the upload first
for key, value in fields:
body.extend(
['--' + BOUNDARY,
'Content-Disposition: form-data; name="%s"' % key,
'',
value,
])
# Now add the file itself
file_name = os.path.basename(file_path)
f = open(file_path, 'rb')
file_content = f.read()
f.close()
body.extend(
['--' + BOUNDARY,
'Content-Disposition: form-data; name="filename"; filename="%s"'
% file_name,
# The upload server determines the mime-type, no need to set it.
'Content-Type: application/octet-stream',
'',
file_content,
])
# Finalize the form body
body.extend(['--' + BOUNDARY + '--', ''])
return 'multipart/form-data; boundary=%s' % BOUNDARY, CRLF.join(body)
def upload_find_auth(file_path, project_name, summary, labels=None,
user_name=None, password=None, tries=3):
"""Find credentials and upload a file to a Google Code project's file server.
file_path, project_name, summary, and labels are passed as-is to upload.
Args:
file_path: The local path to the file.
project_name: The name of your project on Google Code.
summary: A small description for the file.
labels: an optional list of label strings with which to tag the file.
config_dir: Path to Subversion configuration directory, 'none', or None.
user_name: Your Google account name.
tries: How many attempts to make.
"""
while tries > 0:
if user_name is None:
# Read username if not specified or loaded from svn config, or on
# subsequent tries.
sys.stdout.write('Please enter your googlecode.com username: ')
sys.stdout.flush()
user_name = sys.stdin.readline().rstrip()
if password is None:
# Read password if not loaded from svn config, or on subsequent tries.
print 'Please enter your googlecode.com password.'
print '** Note that this is NOT your Gmail account password! **'
print 'It is the password you use to access Subversion repositories,'
print 'and can be found here: http://code.google.com/hosting/settings'
password = getpass.getpass()
status, reason, url = upload(file_path, project_name, user_name, password,
summary, labels)
# Returns 403 Forbidden instead of 401 Unauthorized for bad
# credentials as of 2007-07-17.
if status in [httplib.FORBIDDEN, httplib.UNAUTHORIZED]:
# Rest for another try.
user_name = password = None
tries = tries - 1
else:
# We're done.
break
return status, reason, url
def main():
parser = optparse.OptionParser(usage='googlecode-upload.py -s SUMMARY '
'-p PROJECT [options] FILE')
parser.add_option('-s', '--summary', dest='summary',
help='Short description of the file')
parser.add_option('-p', '--project', dest='project',
help='Google Code project name')
parser.add_option('-u', '--user', dest='user',
help='Your Google Code username')
parser.add_option('-w', '--password', dest='password',
help='Your Google Code password')
parser.add_option('-l', '--labels', dest='labels',
help='An optional list of comma-separated labels to attach '
'to the file')
options, args = parser.parse_args()
if not options.summary:
parser.error('File summary is missing.')
elif not options.project:
parser.error('Project name is missing.')
elif len(args) < 1:
parser.error('File to upload not provided.')
elif len(args) > 1:
parser.error('Only one file may be specified.')
file_path = args[0]
if options.labels:
labels = options.labels.split(',')
else:
labels = None
status, reason, url = upload_find_auth(file_path, options.project,
options.summary, labels,
options.user, options.password)
if url:
print 'The file was uploaded successfully.'
print 'URL: %s' % url
return 0
else:
print 'An error occurred. Your file was not uploaded.'
print 'Google Code upload server said: %s (%s)' % (reason, status)
return 1
if __name__ == '__main__':
sys.exit(main())

378
dav/SabreDAV/bin/gwdg.php Executable file
View file

@ -0,0 +1,378 @@
#!/usr/bin/env php
<?php
/**
* Documentation generator
*
* This scripts scans all files in the lib/ directory, and generates
* Google Code wiki documentation.
*
* This script is rather crappy. It does what it needs to do, but uses global
* variables and it might be a hard to read.
*
* I'm not sure if I care though. Maybe one day this can become a separate
* project
*
* To run this script, just execute on the command line. The script assumes
* it's in the standard bin/ directory.
*/
date_default_timezone_set('UTC');
$libDir = realpath(__DIR__ . '/../lib');
$outputDir = __DIR__ . '/../docs/wikidocs';
if (!is_dir($outputDir)) mkdir($outputDir);
$files = new RecursiveDirectoryIterator($libDir);
$files = new RecursiveIteratorIterator($files, RecursiveIteratorIterator::LEAVES_ONLY);
include_once $libDir . '/Sabre/autoload.php';
// Finding all classnames
$classNames = findClassNames($files);
echo "Found: " . count($classNames) . " classes and interfaces\n";
echo "Generating class tree\n";
$classTree = getClassTree($classNames);
$packageList = array();
foreach($classNames as $className) {
echo "Creating docs for: " . $className . "\n";
$output = createDoc($className,isset($classTree[$className])?$classTree[$className]:array());
file_put_contents($outputDir . '/' . $className . '.wiki', $output);
}
echo "Creating indexes\n";
$output = createSidebarIndex($packageList);
file_put_contents($outputDir . '/APIIndex.wiki', $output);
function findClassNames($files) {
$classNames = array();
foreach($files as $fileName=>$fileInfo) {
$tokens = token_get_all(file_get_contents($fileName));
foreach($tokens as $tokenIndex=>$token) {
if ($token[0]===T_CLASS || $token[0]===T_INTERFACE) {
$classNames[] = $tokens[$tokenIndex+2][1];
}
}
}
return $classNames;
}
function getClassTree($classNames) {
$classTree = array();
foreach($classNames as $className) {
if (!class_exists($className) && !interface_exists($className)) continue;
$rClass = new ReflectionClass($className);
$parent = $rClass->getParentClass();
if ($parent) $parent = $parent->name;
if (!isset($classTree[$parent])) $classTree[$parent] = array();
$classTree[$parent][] = $className;
foreach($rClass->getInterfaceNames() as $interface) {
if (!isset($classTree[$interface])) {
$classTree[$interface] = array();
}
$classTree[$interface][] = $className;
}
}
return $classTree;
}
function createDoc($className, $extendedBy) {
// ew
global $packageList;
ob_start();
$rClass = new ReflectionClass($className);
echo "#summary API documentation for: ", $rClass->getName() , "\n";
echo "#labels APIDoc\n";
echo "#sidebar APIIndex\n";
echo "=`" . $rClass->getName() . "`=\n";
echo "\n";
$docs = parseDocs($rClass->getDocComment());
echo $docs['description'] . "\n";
echo "\n";
$parentClass = $rClass->getParentClass();
if($parentClass) {
echo " * Parent class: [" . $parentClass->getName() . "]\n";
}
if ($interfaces = $rClass->getInterfaceNames()) {
$interfaces = array_map(function($int) { return '[' . $int . ']'; },$interfaces);
echo " * Implements: " . implode(", ", $interfaces) . "\n";
}
$classType = $rClass->isInterface()?'interface':'class';
if (isset($docs['deprecated'])) {
echo " * *Warning: This $classType is deprecated, and should not longer be used.*\n";
}
if ($rClass->isInterface()) {
echo " * This is an interface.\n";
} elseif ($rClass->isAbstract()) {
echo " * This is an abstract class.\n";
}
if (isset($docs['package'])) {
$package = $docs['package'];
if (isset($docs['subpackage'])) {
$package.='_' . $docs['subpackage'];
}
if (!isset($packageList[$package])) {
$packageList[$package] = array();
}
$packageList[$package][] = $rClass->getName();
}
if ($extendedBy) {
echo "\n";
if ($classType==='interface') {
echo "This interface is extended by the following interfaces:\n";
foreach($extendedBy as $className) {
if (interface_exists($className)) {
echo " * [" . $className . "]\n";
}
}
echo "\n";
echo "This interface is implemented by the following classes:\n";
} else {
echo "This class is extended by the following classes:\n";
}
foreach($extendedBy as $className) {
if (class_exists($className)) {
echo " * [" . $className . "]\n";
}
}
echo "\n";
}
echo "\n";
echo "==Properties==\n";
echo "\n";
$properties = $rClass->getProperties(ReflectionProperty::IS_STATIC | ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED);
if (count($properties)>0) {
foreach($properties as $rProperty) {
createPropertyDoc($rProperty);
}
} else {
echo "This $classType does not define any public or protected properties.\n";
}
echo "\n";
echo "==Methods==\n";
echo "\n";
$methods = $rClass->getMethods(ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED);
if (count($methods)>0) {
foreach($methods as $rMethod) {
createMethodDoc($rMethod, $rClass);
}
} else {
echo "\nThis $classType does not define any public or protected methods.\n";
}
return ob_get_clean();
}
function createMethodDoc($rMethod, $rClass) {
echo "===`" . $rMethod->getName() . "`===\n";
echo "\n";
$docs = parseDocs($rMethod->getDocComment());
$return = isset($docs['return'])?$docs['return']:'void';
echo "{{{\n";
echo $return . " " . $rMethod->class . "::" . $rMethod->getName() . "(";
foreach($rMethod->getParameters() as $parameter) {
if ($parameter->getPosition()>0) echo ", ";
if ($class = $parameter->getClass()) {
echo $class->name . " ";
} elseif (isset($docs['param'][$parameter->name])) {
echo $docs['param'][$parameter->name] . " ";
}
echo '$' . $parameter->name;
if ($parameter->isOptional() && $parameter->isDefaultValueAvailable()) {
$default = $parameter->getDefaultValue();
$default = var_export($default,true);
$default = str_replace("\n","",$default);
echo " = " . $default;
}
}
echo ")\n";
echo "}}}\n";
echo "\n";
echo $docs['description'] . "\n";
echo "\n";
$hasProp = false;
if (isset($docs['deprecated'])) {
echo " * *Warning: This method is deprecated, and should not longer be used.*\n";
$hasProp = true;
}
if ($rMethod->isProtected()) {
echo " * This method is protected.\n";
$hasProp = true;
}
if ($rMethod->isPrivate()) {
echo " * This method is private.\n";
$hasProp = true;
}
if ($rMethod->isAbstract()) {
echo " * This is an abstract method\n";
$hasProp = true;
}
if ($rMethod->class != $rClass->name) {
echo " * Defined in [" . $rMethod->class . "]\n";
$hasProp = true;
}
if ($hasProp) echo "\n";
}
function createPropertyDoc($rProperty) {
echo "===`" . $rProperty->getName() . "`===\n";
echo "\n";
$docs = parseDocs($rProperty->getDocComment());
$visibility = 'public';
if ($rProperty->isProtected()) $visibility = 'protected';
if ($rProperty->isPrivate()) $visibility = 'private';
echo "{{{\n";
echo $visibility . " " . $rProperty->class . "::$" . $rProperty->getName();
echo "\n}}}\n";
echo "\n";
echo $docs['description'] . "\n";
echo "\n";
$hasProp = false;
if (isset($docs['deprecated'])) {
echo " * *Warning: This property is deprecated, and should not longer be used.*\n";
$hasProp = true;
}
if ($rProperty->isProtected()) {
echo " * This property is protected.\n";
$hasProp = true;
}
if ($rProperty->isPrivate()) {
echo " * This property is private.\n";
$hasProp = true;
}
if ($rProperty->isStatic()) {
echo " * This property is static.\n";
$hasProp = true;
}
if ($hasProp) echo "\n";
}
function parseDocs($docString) {
$params = array();
$description = array();
// Trimming all the comment characters
$docString = trim($docString,"\n*/ ");
$docString = explode("\n",$docString);
foreach($docString as $str) {
$str = ltrim($str,'* ');
$str = trim($str);
if ($str && $str[0]==='@') {
$r = explode(' ',substr($str,1),2);
$paramName = $r[0];
$paramValue = (count($r)>1)?$r[1]:'';
// 'param' paramName is special. Confusing, I know.
if ($paramName==='param') {
if (!isset($params['param'])) $params['param'] = array();
$paramValue = explode(' ', $paramValue,3);
$params['param'][substr($paramValue[1],1)] = $paramValue[0];
} else {
$params[$paramName] = trim($paramValue);
}
} else {
$description[]=$str;
}
}
$params['description'] = trim(implode("\n",$description),"\n ");
return $params;
}
function createSidebarIndex($packageList) {
ob_start();
echo "#labels APIDocs\n";
echo "#summary List of all classes, neatly organized\n";
echo "=API Index=\n";
foreach($packageList as $package=>$classes) {
echo " * $package\n";
sort($classes);
foreach($classes as $class) {
echo " * [$class $class]\n";
}
}
return ob_get_clean();
}

View file

@ -0,0 +1,232 @@
<?php
echo "SabreDAV migrate script for version 1.7\n";
if ($argc<2) {
echo <<<HELLO
This script help you migrate from a pre-1.7 database to 1.7 and later\n
It is important to note, that this script only touches the 'calendarobjects'
table.
If you do not have this table, or don't use the default PDO CalDAV backend
it's pointless to run this script.
Keep in mind that some processing will be done on every single record of this
table and in addition, ALTER TABLE commands will be executed.
If you have a large calendarobjects table, this may mean that this process
takes a while.
Usage:
{$argv[0]} [pdo-dsn] [username] [password]
For example:
{$argv[0]} mysql:host=localhost;dbname=sabredav root password
{$argv[0]} sqlite:data/sabredav.db
HELLO;
exit();
}
if (file_exists(__DIR__ . '/../lib/Sabre/VObject/includes.php')) {
include __DIR__ . '/../lib/Sabre/VObject/includes.php';
} else {
// If, for some reason VObject was not found in the vicinity,
// we'll try to grab it from the default path.
require 'Sabre/VObject/includes.php';
}
$dsn = $argv[1];
$user = isset($argv[2])?$argv[2]:null;
$pass = isset($argv[3])?$argv[3]:null;
echo "Connecting to database: " . $dsn . "\n";
$pdo = new PDO($dsn, $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
echo "Validating existing table layout\n";
// The only cross-db way to do this, is to just fetch a single record.
$row = $pdo->query("SELECT * FROM calendarobjects LIMIT 1")->fetch();
if (!$row) {
echo "Error: This database did not have any records in the calendarobjects table, you should just recreate the table.\n";
exit(-1);
}
$requiredFields = array(
'id',
'calendardata',
'uri',
'calendarid',
'lastmodified',
);
foreach($requiredFields as $requiredField) {
if (!array_key_exists($requiredField,$row)) {
echo "Error: The current 'calendarobjects' table was missing a field we expected to exist.\n";
echo "For safety reasons, this process is stopped.\n";
exit(-1);
}
}
$fields17 = array(
'etag',
'size',
'componenttype',
'firstoccurence',
'lastoccurence',
);
$found = 0;
foreach($fields17 as $field) {
if (array_key_exists($field, $row)) {
$found++;
}
}
if ($found === 0) {
echo "The database had the 1.6 schema. Table will now be altered.\n";
echo "This may take some time for large tables\n";
$pdo->exec(<<<SQL
ALTER TABLE calendarobjects
ADD etag VARCHAR(32),
ADD size INT(11) UNSIGNED,
ADD componenttype VARCHAR(8),
ADD firstoccurence INT(11) UNSIGNED,
ADD lastoccurence INT(11) UNSIGNED
SQL
);
echo "Database schema upgraded.\n";
} elseif ($found === 5) {
echo "Database already had the 1.7 schema\n";
} else {
echo "The database had $found out of 5 from the changes for 1.7. This is scary and unusual, so we have to abort.\n";
echo "You can manually try to upgrade the schema, and then run this script again.\n";
exit(-1);
}
echo "Now, we need to parse every record and pull out some information.\n";
$result = $pdo->query('SELECT id, calendardata FROM calendarobjects');
$stmt = $pdo->prepare('UPDATE calendarobjects SET etag = ?, size = ?, componenttype = ?, firstoccurence = ?, lastoccurence = ? WHERE id = ?');
echo "Total records found: " . $result->rowCount() . "\n";
$done = 0;
$total = $result->rowCount();
while($row = $result->fetch()) {
try {
$newData = getDenormalizedData($row['calendardata']);
} catch (Exception $e) {
echo "===\nException caught will trying to parser calendarobject.\n";
echo "Error message: " . $e->getMessage() . "\n";
echo "Record id: " . $row['id'] . "\n";
echo "This record is ignored, you should inspect it to see if there's anything wrong.\n===\n";
continue;
}
$stmt->execute(array(
$newData['etag'],
$newData['size'],
$newData['componentType'],
$newData['firstOccurence'],
$newData['lastOccurence'],
$row['id'],
));
$done++;
if ($done % 500 === 0) {
echo "Completed: $done / $total\n";
}
}
echo "Process completed!\n";
/**
* Parses some information from calendar objects, used for optimized
* calendar-queries.
*
* Blantently copied from Sabre_CalDAV_Backend_PDO
*
* Returns an array with the following keys:
* * etag
* * size
* * componentType
* * firstOccurence
* * lastOccurence
*
* @param string $calendarData
* @return array
*/
function getDenormalizedData($calendarData) {
$vObject = Sabre_VObject_Reader::read($calendarData);
$componentType = null;
$component = null;
$firstOccurence = null;
$lastOccurence = null;
foreach($vObject->getComponents() as $component) {
if ($component->name!=='VTIMEZONE') {
$componentType = $component->name;
break;
}
}
if (!$componentType) {
throw new Sabre_DAV_Exception_BadRequest('Calendar objects must have a VJOURNAL, VEVENT or VTODO component');
}
if ($componentType === 'VEVENT') {
$firstOccurence = $component->DTSTART->getDateTime()->getTimeStamp();
// Finding the last occurence is a bit harder
if (!isset($component->RRULE)) {
if (isset($component->DTEND)) {
$lastOccurence = $component->DTEND->getDateTime()->getTimeStamp();
} elseif (isset($component->DURATION)) {
$endDate = clone $component->DTSTART->getDateTime();
$endDate->add(Sabre_VObject_DateTimeParser::parse($component->DURATION->value));
$lastOccurence = $endDate->getTimeStamp();
} elseif ($component->DTSTART->getDateType()===Sabre_VObject_Property_DateTime::DATE) {
$endDate = clone $component->DTSTART->getDateTime();
$endDate->modify('+1 day');
$lastOccurence = $endDate->getTimeStamp();
} else {
$lastOccurence = $firstOccurence;
}
} else {
$it = new Sabre_VObject_RecurrenceIterator($vObject, (string)$component->UID);
$maxDate = new DateTime(self::MAX_DATE);
if ($it->isInfinite()) {
$lastOccurence = $maxDate->getTimeStamp();
} else {
$end = $it->getDtEnd();
while($it->valid() && $end < $maxDate) {
$end = $it->getDtEnd();
$it->next();
}
$lastOccurence = $end->getTimeStamp();
}
}
}
return array(
'etag' => md5($calendarData),
'size' => strlen($calendarData),
'componentType' => $componentType,
'firstOccurence' => $firstOccurence,
'lastOccurence' => $lastOccurence,
);
}

View file

@ -0,0 +1,140 @@
#!/usr/bin/env python
#
# Copyright (c) 2009-2010 Evert Pot
# All rights reserved.
# http://www.rooftopsolutions.nl/
#
# This utility is distributed along with SabreDAV
# license: http://code.google.com/p/sabredav/wiki/License Modified BSD License
import os
from optparse import OptionParser
import time
def getfreespace(path):
stat = os.statvfs(path)
return stat.f_frsize * stat.f_bavail
def getbytesleft(path,treshold):
return getfreespace(path)-treshold
def run(cacheDir, treshold, sleep=5, simulate=False, min_erase = 0):
bytes = getbytesleft(cacheDir,treshold)
if (bytes>0):
print "Bytes to go before we hit treshhold:", bytes
else:
print "Treshold exceeded with:", -bytes, "bytes"
dir = os.listdir(cacheDir)
dir2 = []
for file in dir:
path = cacheDir + '/' + file
dir2.append({
"path" : path,
"atime": os.stat(path).st_atime,
"size" : os.stat(path).st_size
})
dir2.sort(lambda x,y: int(x["atime"]-y["atime"]))
filesunlinked = 0
gainedspace = 0
# Left is the amount of bytes that need to be freed up
# The default is the 'min_erase setting'
left = min_erase
# If the min_erase setting is lower than the amount of bytes over
# the treshold, we use that number instead.
if left < -bytes :
left = -bytes
print "Need to delete at least:", left;
for file in dir2:
# Only deleting files if we're not simulating
if not simulate: os.unlink(file["path"])
left = int(left - file["size"])
gainedspace = gainedspace + file["size"]
filesunlinked = filesunlinked + 1
if(left<0):
break
print "%d files deleted (%d bytes)" % (filesunlinked, gainedspace)
time.sleep(sleep)
def main():
parser = OptionParser(
version="naturalselecton v0.3",
description="Cache directory manager. Deletes cache entries based on accesstime and free space tresholds.\n" +
"This utility is distributed alongside SabreDAV.",
usage="usage: %prog [options] cacheDirectory",
)
parser.add_option(
'-s',
dest="simulate",
action="store_true",
help="Don't actually make changes, but just simulate the behaviour",
)
parser.add_option(
'-r','--runs',
help="How many times to check before exiting. -1 is infinite, which is the default",
type="int",
dest="runs",
default=-1
)
parser.add_option(
'-n','--interval',
help="Sleep time in seconds (default = 5)",
type="int",
dest="sleep",
default=5
)
parser.add_option(
'-l','--treshold',
help="Treshhold in bytes (default = 10737418240, which is 10GB)",
type="int",
dest="treshold",
default=10737418240
)
parser.add_option(
'-m', '--min-erase',
help="Minimum number of bytes to erase when the treshold is reached. " +
"Setting this option higher will reduce the amount of times the cache directory will need to be scanned. " +
"(the default is 1073741824, which is 1GB.)",
type="int",
dest="min_erase",
default=1073741824
)
options,args = parser.parse_args()
if len(args)<1:
parser.error("This utility requires at least 1 argument")
cacheDir = args[0]
print "Natural Selection"
print "Cache directory:", cacheDir
free = getfreespace(cacheDir);
print "Current free disk space:", free
runs = options.runs;
while runs!=0 :
run(
cacheDir,
sleep=options.sleep,
simulate=options.simulate,
treshold=options.treshold,
min_erase=options.min_erase
)
if runs>0:
runs = runs - 1
if __name__ == '__main__' :
main()

321
dav/SabreDAV/bin/pearpackage3.php Executable file
View file

@ -0,0 +1,321 @@
#!/usr/bin/env php
<?php
date_default_timezone_set('UTC');
$make = false;
$packageName = null;
foreach($argv as $index=>$arg) {
if ($index==0) continue;
if ($arg=='make') {
$make = true;
continue;
}
$packageName = $arg;
}
if (is_null($packageName)) {
echo "A packagename is required\n";
die(1);
}
if (!is_dir('build/' . $packageName)) {
echo "Could not find package directory: build/$packageName\n";
die(2);
}
// We'll figure out something better for this one day
$dependencies = array(
array(
'type' => 'php',
'min' => '5.3.1',
),
array(
'type' => 'pearinstaller',
'min' => '1.9',
),
);
switch($packageName) {
case 'Sabre' :
$summary = 'Sabretooth base package.';
$description = <<<TEXT
The base package provides some functionality used by all packages.
Currently this is only an autoloader
TEXT;
$version = '1.0.0';
$stability = 'stable';
break;
case 'Sabre_DAV' :
$summary = 'Sabre_DAV is a WebDAV framework for PHP.';
$description = <<<TEXT
SabreDAV allows you to easily integrate WebDAV access into your existing PHP application.
Feature List:
* Fully WebDAV (class 1, 2, 3) compliant
* Supports Windows clients, OS/X, DavFS, Cadaver, and pretty much everything we've come accross
* Custom property support
* RFC4918-compliant
* Authentication support
* Plugin system
TEXT;
$dependencies[] = array(
'type' => 'package',
'name' => 'Sabre',
'channel' => 'pear.sabredav.org',
'min' => '1.0.0',
);
$dependencies[] = array(
'type' => 'package',
'name' => 'Sabre_HTTP',
'channel' => 'pear.sabredav.org',
'min' => '1.6.0',
);
break;
case 'Sabre_HTTP' :
$summary = 'Sabre_HTTP provides various HTTP helpers, for input and output and authentication';
$description = <<<TEXT
Sabre_HTTP effectively wraps around \$_SERVER, php://input, php://output and the headers method,
allowing for a central interface to deal with this as well as easier unittesting.
In addition Sabre_HTTP provides classes for Basic, Digest and Amazon AWS authentication.
TEXT;
$dependencies[] = array(
'type' => 'package',
'name' => 'Sabre',
'channel' => 'pear.sabredav.org',
'min' => '1.0.0',
);
break;
case 'Sabre_DAVACL' :
$summary = 'Sabre_DAVACL provides rfc3744 support.';
$description = <<<TEXT
Sabre_DAVACL is the RFC3744 implementation for SabreDAV. It provides principals
(users and groups) and access control.
TEXT;
$dependencies[] = array(
'type' => 'package',
'name' => 'Sabre',
'channel' => 'pear.sabredav.org',
'min' => '1.0.0',
);
$dependencies[] = array(
'type' => 'package',
'name' => 'Sabre_DAV',
'channel' => 'pear.sabredav.org',
'min' => '1.6.0',
);
break;
case 'Sabre_CalDAV' :
$summary = 'Sabre_CalDAV provides CalDAV extensions to SabreDAV';
$description = <<<TEXT
Sabre_CalDAV provides RFC4791 (CalDAV) support to Sabre_DAV.
Feature list:
* Multi-user Calendar Server
* Support for Apple iCal, Evolution, Sunbird, Lightning
TEXT;
$dependencies[] = array(
'type' => 'package',
'name' => 'Sabre',
'channel' => 'pear.sabredav.org',
'min' => '1.0.0',
);
$dependencies[] = array(
'type' => 'package',
'name' => 'Sabre_HTTP',
'channel' => 'pear.sabredav.org',
'min' => '1.6.0',
);
$dependencies[] = array(
'type' => 'package',
'name' => 'Sabre_DAV',
'channel' => 'pear.sabredav.org',
'min' => '1.6.0',
);
$dependencies[] = array(
'type' => 'package',
'name' => 'Sabre_DAVACL',
'channel' => 'pear.sabredav.org',
'min' => '1.6.0',
);
$dependencies[] = array(
'type' => 'package',
'name' => 'Sabre_VObject',
'channel' => 'pear.sabredav.org',
'min' => '1.3.0',
);
break;
case 'Sabre_CardDAV' :
$summary = 'Sabre_CardDAV provides CardDAV extensions to SabreDAV';
$description = <<<TEXT
Sabre_CardDAV provides CardDAV support to Sabre_DAV.
Feature list:
* Multi-user addressbook server
* ACL support
* Support for OS/X, iOS, Evolution and probably more
* Hook-ins for creating a global \'directory\'.
TEXT;
$dependencies[] = array(
'type' => 'package',
'name' => 'Sabre',
'channel' => 'pear.sabredav.org',
'min' => '1.0.0',
);
$dependencies[] = array(
'type' => 'package',
'name' => 'Sabre_HTTP',
'channel' => 'pear.sabredav.org',
'min' => '1.6.0',
);
$dependencies[] = array(
'type' => 'package',
'name' => 'Sabre_DAV',
'channel' => 'pear.sabredav.org',
'min' => '1.6.0',
);
$dependencies[] = array(
'type' => 'package',
'name' => 'Sabre_DAVACL',
'channel' => 'pear.sabredav.org',
'min' => '1.6.0',
);
$dependencies[] = array(
'type' => 'package',
'name' => 'Sabre_VObject',
'channel' => 'pear.sabredav.org',
'min' => '1.3.0',
);
break;
case 'Sabre_VObject' :
$summary = 'Sabre_VObject is a natural-interface iCalendar and vCard reader';
$description = <<<TEXT
Sabre_VObject is an intuitive reader for iCalendar and vCard objects.
It provides a natural array/object accessor interface to the parsed tree, much like
simplexml for XML files.
TEXT;
$dependencies[] = array(
'type' => 'package',
'name' => 'Sabre',
'channel' => 'pear.sabredav.org',
'min' => '1.0.0',
);
break;
}
if (!isset($version)) {
include 'lib/' . str_replace('_','/',$packageName) . '/Version.php';
$versionClassName = $packageName . '_Version';
$version = $versionClassName::VERSION;
$stability = $versionClassName::STABILITY;
}
$lead = 'Evert Pot';
$lead_email = 'evert@rooftopsolutions.nl';
$date = date('Y-m-d');
$license = 'Modified BSD';
$licenseuri = 'http://code.google.com/p/sabredav/wiki/License';
$notes = 'New release. Read the ChangeLog and announcement for more details';
$channel = 'pear.sabredav.org';
/* This function is intended to generate the full file list */
function parsePath($fullPath, $role, $padding = 4) {
$fileList = '';
$file = basename($fullPath);
if (is_dir($fullPath)) {
$fileList .= str_repeat(' ', $padding) . "<dir name=\"{$file}\">\n";
foreach(scandir($fullPath) as $subPath) {;
if ($subPath==='.' || $subPath==='..') continue;
$fileList .= parsePath($fullPath. '/' . $subPath,$role, $padding+2);
}
$fileList .= str_repeat(' ', $padding) . "</dir><!-- {$file} -->\n";
} elseif (is_file($fullPath)) {
$fileList .= str_repeat(' ', $padding) . "<file name=\"{$file}\" role=\"{$role}\" />\n";
}
return $fileList;
}
$rootDir = realpath('build/' . $packageName);
$fileList = parsePath($rootDir . '/Sabre', 'php');
$fileList .= parsePath($rootDir . '/examples', 'doc');
$fileList .= parsePath($rootDir . '/ChangeLog', 'doc');
$fileList .= parsePath($rootDir . '/LICENSE', 'doc');
$dependenciesXML = "\n";
foreach($dependencies as $dep) {
$pad = 8;
$dependenciesXML.=str_repeat(' ',$pad) . '<' . $dep['type'] . ">\n";
foreach($dep as $key=>$value) {
if ($key=='type') continue;
$dependenciesXML.=str_repeat(' ',$pad+2) . "<$key>$value</$key>\n";
}
$dependenciesXML.=str_repeat(' ',$pad) . '</' . $dep['type'] . ">\n";
}
$package = <<<XML
<?xml version="1.0"?>
<package version="2.0"
xmlns="http://pear.php.net/dtd/package-2.0">
<name>{$packageName}</name>
<channel>{$channel}</channel>
<summary>{$summary}</summary>
<description>{$description}</description>
<lead>
<name>{$lead}</name>
<user>{$lead}</user>
<email>{$lead_email}</email>
<active>true</active>
</lead>
<date>{$date}</date>
<version>
<release>{$version}</release>
<api>{$version}</api>
</version>
<stability>
<release>{$stability}</release>
<api>{$stability}</api>
</stability>
<license uri="{$licenseuri}">{$license}</license>
<notes>{$notes}</notes>
<contents>
<dir name="/">{$fileList}
</dir>
</contents>
<dependencies>
<required>{$dependenciesXML}
</required>
</dependencies>
<phprelease />
</package>
XML;
if (isset($argv) && in_array('make',$argv)) {
file_put_contents($rootDir . '/package.xml',$package);
} else {
echo $package;
}