mirror of
https://git.friendi.ca/friendica/friendica-addons.git
synced 2025-07-10 18:38:49 +00:00
Initial Release of the calendar plugin
This commit is contained in:
parent
45cc9885fc
commit
7115197a33
561 changed files with 189494 additions and 0 deletions
248
dav/SabreDAV/bin/googlecode_upload.py
Executable file
248
dav/SabreDAV/bin/googlecode_upload.py
Executable 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
378
dav/SabreDAV/bin/gwdg.php
Executable 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();
|
||||
|
||||
}
|
232
dav/SabreDAV/bin/migrateto17.php
Normal file
232
dav/SabreDAV/bin/migrateto17.php
Normal 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,
|
||||
);
|
||||
|
||||
}
|
140
dav/SabreDAV/bin/naturalselection.py
Executable file
140
dav/SabreDAV/bin/naturalselection.py
Executable 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
321
dav/SabreDAV/bin/pearpackage3.php
Executable 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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue