Merge branch 'master' of gitorious.org:owncloud/owncloud

This commit is contained in:
Bjoern Schiessle 2012-06-05 10:38:42 +02:00
commit 564b0358f9
49 changed files with 1519 additions and 267 deletions

229
3rdparty/mediawiki/CSSMin.php vendored Normal file
View File

@ -0,0 +1,229 @@
<?php
/**
* Minification of CSS stylesheets.
*
* Copyright 2010 Wikimedia Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
* OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* @file
* @version 0.1.1 -- 2010-09-11
* @author Trevor Parscal <tparscal@wikimedia.org>
* @copyright Copyright 2010 Wikimedia Foundation
* @license http://www.apache.org/licenses/LICENSE-2.0
*/
/**
* Transforms CSS data
*
* This class provides minification, URL remapping, URL extracting, and data-URL embedding.
*/
class CSSMin {
/* Constants */
/**
* Maximum file size to still qualify for in-line embedding as a data-URI
*
* 24,576 is used because Internet Explorer has a 32,768 byte limit for data URIs,
* which when base64 encoded will result in a 1/3 increase in size.
*/
const EMBED_SIZE_LIMIT = 24576;
const URL_REGEX = 'url\(\s*[\'"]?(?P<file>[^\?\)\'"]*)(?P<query>\??[^\)\'"]*)[\'"]?\s*\)';
/* Protected Static Members */
/** @var array List of common image files extensions and mime-types */
protected static $mimeTypes = array(
'gif' => 'image/gif',
'jpe' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'jpg' => 'image/jpeg',
'png' => 'image/png',
'tif' => 'image/tiff',
'tiff' => 'image/tiff',
'xbm' => 'image/x-xbitmap',
);
/* Static Methods */
/**
* Gets a list of local file paths which are referenced in a CSS style sheet
*
* @param $source string CSS data to remap
* @param $path string File path where the source was read from (optional)
* @return array List of local file references
*/
public static function getLocalFileReferences( $source, $path = null ) {
$files = array();
$rFlags = PREG_OFFSET_CAPTURE | PREG_SET_ORDER;
if ( preg_match_all( '/' . self::URL_REGEX . '/', $source, $matches, $rFlags ) ) {
foreach ( $matches as $match ) {
$file = ( isset( $path )
? rtrim( $path, '/' ) . '/'
: '' ) . "{$match['file'][0]}";
// Only proceed if we can access the file
if ( !is_null( $path ) && file_exists( $file ) ) {
$files[] = $file;
}
}
}
return $files;
}
/**
* @param $file string
* @return bool|string
*/
protected static function getMimeType( $file ) {
$realpath = realpath( $file );
// Try a couple of different ways to get the mime-type of a file, in order of
// preference
if (
$realpath
&& function_exists( 'finfo_file' )
&& function_exists( 'finfo_open' )
&& defined( 'FILEINFO_MIME_TYPE' )
) {
// As of PHP 5.3, this is how you get the mime-type of a file; it uses the Fileinfo
// PECL extension
return finfo_file( finfo_open( FILEINFO_MIME_TYPE ), $realpath );
} elseif ( function_exists( 'mime_content_type' ) ) {
// Before this was deprecated in PHP 5.3, this was how you got the mime-type of a file
return mime_content_type( $file );
} else {
// Worst-case scenario has happened, use the file extension to infer the mime-type
$ext = strtolower( pathinfo( $file, PATHINFO_EXTENSION ) );
if ( isset( self::$mimeTypes[$ext] ) ) {
return self::$mimeTypes[$ext];
}
}
return false;
}
/**
* Remaps CSS URL paths and automatically embeds data URIs for URL rules
* preceded by an /* @embed * / comment
*
* @param $source string CSS data to remap
* @param $local string File path where the source was read from
* @param $remote string URL path to the file
* @param $embedData bool If false, never do any data URI embedding, even if / * @embed * / is found
* @return string Remapped CSS data
*/
public static function remap( $source, $local, $remote, $embedData = true ) {
$pattern = '/((?P<embed>\s*\/\*\s*\@embed\s*\*\/)(?P<pre>[^\;\}]*))?' .
self::URL_REGEX . '(?P<post>[^;]*)[\;]?/';
$offset = 0;
while ( preg_match( $pattern, $source, $match, PREG_OFFSET_CAPTURE, $offset ) ) {
// Skip fully-qualified URLs and data URIs
$urlScheme = parse_url( $match['file'][0], PHP_URL_SCHEME );
if ( $urlScheme ) {
// Move the offset to the end of the match, leaving it alone
$offset = $match[0][1] + strlen( $match[0][0] );
continue;
}
// URLs with absolute paths like /w/index.php need to be expanded
// to absolute URLs but otherwise left alone
if ( $match['file'][0] !== '' && $match['file'][0][0] === '/' ) {
// Replace the file path with an expanded (possibly protocol-relative) URL
// ...but only if wfExpandUrl() is even available.
// This will not be the case if we're running outside of MW
$lengthIncrease = 0;
if ( function_exists( 'wfExpandUrl' ) ) {
$expanded = wfExpandUrl( $match['file'][0], PROTO_RELATIVE );
$origLength = strlen( $match['file'][0] );
$lengthIncrease = strlen( $expanded ) - $origLength;
$source = substr_replace( $source, $expanded,
$match['file'][1], $origLength
);
}
// Move the offset to the end of the match, leaving it alone
$offset = $match[0][1] + strlen( $match[0][0] ) + $lengthIncrease;
continue;
}
// Shortcuts
$embed = $match['embed'][0];
$pre = $match['pre'][0];
$post = $match['post'][0];
$query = $match['query'][0];
$url = "{$remote}/{$match['file'][0]}";
$file = "{$local}/{$match['file'][0]}";
// bug 27052 - Guard against double slashes, because foo//../bar
// apparently resolves to foo/bar on (some?) clients
$url = preg_replace( '#([^:])//+#', '\1/', $url );
$replacement = false;
if ( $local !== false && file_exists( $file ) ) {
// Add version parameter as a time-stamp in ISO 8601 format,
// using Z for the timezone, meaning GMT
$url .= '?' . gmdate( 'Y-m-d\TH:i:s\Z', round( filemtime( $file ), -2 ) );
// Embedding requires a bit of extra processing, so let's skip that if we can
if ( $embedData && $embed ) {
$type = self::getMimeType( $file );
// Detect when URLs were preceeded with embed tags, and also verify file size is
// below the limit
var_dump($match['embed'], $file, filesize($file));
if (
$type
&& $match['embed'][1] > 0
&& filesize( $file ) < self::EMBED_SIZE_LIMIT
) {
// Strip off any trailing = symbols (makes browsers freak out)
$data = base64_encode( file_get_contents( $file ) );
// Build 2 CSS properties; one which uses a base64 encoded data URI in place
// of the @embed comment to try and retain line-number integrity, and the
// other with a remapped an versioned URL and an Internet Explorer hack
// making it ignored in all browsers that support data URIs
$replacement = "{$pre}url(data:{$type};base64,{$data}){$post};";
$replacement .= "{$pre}url({$url}){$post}!ie;";
}
}
if ( $replacement === false ) {
// Assume that all paths are relative to $remote, and make them absolute
$replacement = "{$embed}{$pre}url({$url}){$post};";
}
} elseif ( $local === false ) {
// Assume that all paths are relative to $remote, and make them absolute
$replacement = "{$embed}{$pre}url({$url}{$query}){$post};";
}
if ( $replacement !== false ) {
// Perform replacement on the source
$source = substr_replace(
$source, $replacement, $match[0][1], strlen( $match[0][0] )
);
// Move the offset to the end of the replacement in the source
$offset = $match[0][1] + strlen( $replacement );
continue;
}
// Move the offset to the end of the match, leaving it alone
$offset = $match[0][1] + strlen( $match[0][0] );
}
return $source;
}
/**
* Removes whitespace from CSS data
*
* @param $css string CSS data to minify
* @return string Minified CSS data
*/
public static function minify( $css ) {
return trim(
str_replace(
array( '; ', ': ', ' {', '{ ', ', ', '} ', ';}' ),
array( ';', ':', '{', '{', ',', '}', '}' ),
preg_replace( array( '/\s+/', '/\/\*.*?\*\//s' ), array( ' ', '' ), $css )
)
);
}
}

View File

@ -0,0 +1,606 @@
<?php
/**
* JavaScript Minifier
*
* @file
* @author Paul Copperman <paul.copperman@gmail.com>
* @license Choose any of Apache, MIT, GPL, LGPL
*/
/**
* This class is meant to safely minify javascript code, while leaving syntactically correct
* programs intact. Other libraries, such as JSMin require a certain coding style to work
* correctly. OTOH, libraries like jsminplus, that do parse the code correctly are rather
* slow, because they construct a complete parse tree before outputting the code minified.
* So this class is meant to allow arbitrary (but syntactically correct) input, while being
* fast enough to be used for on-the-fly minifying.
*/
class JavaScriptMinifier {
/* Class constants */
/* Parsing states.
* The state machine is only necessary to decide whether to parse a slash as division
* operator or as regexp literal.
* States are named after the next expected item. We only distinguish states when the
* distinction is relevant for our purpose.
*/
const STATEMENT = 0;
const CONDITION = 1;
const PROPERTY_ASSIGNMENT = 2;
const EXPRESSION = 3;
const EXPRESSION_NO_NL = 4; // only relevant for semicolon insertion
const EXPRESSION_OP = 5;
const EXPRESSION_FUNC = 6;
const EXPRESSION_TERNARY = 7; // used to determine the role of a colon
const EXPRESSION_TERNARY_OP = 8;
const EXPRESSION_TERNARY_FUNC = 9;
const PAREN_EXPRESSION = 10; // expression which is not on the top level
const PAREN_EXPRESSION_OP = 11;
const PAREN_EXPRESSION_FUNC = 12;
const PROPERTY_EXPRESSION = 13; // expression which is within an object literal
const PROPERTY_EXPRESSION_OP = 14;
const PROPERTY_EXPRESSION_FUNC = 15;
/* Token types */
const TYPE_UN_OP = 1; // unary operators
const TYPE_INCR_OP = 2; // ++ and --
const TYPE_BIN_OP = 3; // binary operators
const TYPE_ADD_OP = 4; // + and - which can be either unary or binary ops
const TYPE_HOOK = 5; // ?
const TYPE_COLON = 6; // :
const TYPE_COMMA = 7; // ,
const TYPE_SEMICOLON = 8; // ;
const TYPE_BRACE_OPEN = 9; // {
const TYPE_BRACE_CLOSE = 10; // }
const TYPE_PAREN_OPEN = 11; // ( and [
const TYPE_PAREN_CLOSE = 12; // ) and ]
const TYPE_RETURN = 13; // keywords: break, continue, return, throw
const TYPE_IF = 14; // keywords: catch, for, with, switch, while, if
const TYPE_DO = 15; // keywords: case, var, finally, else, do, try
const TYPE_FUNC = 16; // keywords: function
const TYPE_LITERAL = 17; // all literals, identifiers and unrecognised tokens
// Sanity limit to avoid excessive memory usage
const STACK_LIMIT = 1000;
/* Static functions */
/**
* Returns minified JavaScript code.
*
* NOTE: $maxLineLength isn't a strict maximum. Longer lines will be produced when
* literals (e.g. quoted strings) longer than $maxLineLength are encountered
* or when required to guard against semicolon insertion.
*
* @param $s String JavaScript code to minify
* @param $statementsOnOwnLine Bool Whether to put each statement on its own line
* @param $maxLineLength Int Maximum length of a single line, or -1 for no maximum.
* @return String Minified code
*/
public static function minify( $s, $statementsOnOwnLine = false, $maxLineLength = 1000 ) {
// First we declare a few tables that contain our parsing rules
// $opChars : characters, which can be combined without whitespace in between them
$opChars = array(
'!' => true,
'"' => true,
'%' => true,
'&' => true,
"'" => true,
'(' => true,
')' => true,
'*' => true,
'+' => true,
',' => true,
'-' => true,
'.' => true,
'/' => true,
':' => true,
';' => true,
'<' => true,
'=' => true,
'>' => true,
'?' => true,
'[' => true,
']' => true,
'^' => true,
'{' => true,
'|' => true,
'}' => true,
'~' => true
);
// $tokenTypes : maps keywords and operators to their corresponding token type
$tokenTypes = array(
'!' => self::TYPE_UN_OP,
'~' => self::TYPE_UN_OP,
'delete' => self::TYPE_UN_OP,
'new' => self::TYPE_UN_OP,
'typeof' => self::TYPE_UN_OP,
'void' => self::TYPE_UN_OP,
'++' => self::TYPE_INCR_OP,
'--' => self::TYPE_INCR_OP,
'!=' => self::TYPE_BIN_OP,
'!==' => self::TYPE_BIN_OP,
'%' => self::TYPE_BIN_OP,
'%=' => self::TYPE_BIN_OP,
'&' => self::TYPE_BIN_OP,
'&&' => self::TYPE_BIN_OP,
'&=' => self::TYPE_BIN_OP,
'*' => self::TYPE_BIN_OP,
'*=' => self::TYPE_BIN_OP,
'+=' => self::TYPE_BIN_OP,
'-=' => self::TYPE_BIN_OP,
'.' => self::TYPE_BIN_OP,
'/' => self::TYPE_BIN_OP,
'/=' => self::TYPE_BIN_OP,
'<' => self::TYPE_BIN_OP,
'<<' => self::TYPE_BIN_OP,
'<<=' => self::TYPE_BIN_OP,
'<=' => self::TYPE_BIN_OP,
'=' => self::TYPE_BIN_OP,
'==' => self::TYPE_BIN_OP,
'===' => self::TYPE_BIN_OP,
'>' => self::TYPE_BIN_OP,
'>=' => self::TYPE_BIN_OP,
'>>' => self::TYPE_BIN_OP,
'>>=' => self::TYPE_BIN_OP,
'>>>' => self::TYPE_BIN_OP,
'>>>=' => self::TYPE_BIN_OP,
'^' => self::TYPE_BIN_OP,
'^=' => self::TYPE_BIN_OP,
'|' => self::TYPE_BIN_OP,
'|=' => self::TYPE_BIN_OP,
'||' => self::TYPE_BIN_OP,
'in' => self::TYPE_BIN_OP,
'instanceof' => self::TYPE_BIN_OP,
'+' => self::TYPE_ADD_OP,
'-' => self::TYPE_ADD_OP,
'?' => self::TYPE_HOOK,
':' => self::TYPE_COLON,
',' => self::TYPE_COMMA,
';' => self::TYPE_SEMICOLON,
'{' => self::TYPE_BRACE_OPEN,
'}' => self::TYPE_BRACE_CLOSE,
'(' => self::TYPE_PAREN_OPEN,
'[' => self::TYPE_PAREN_OPEN,
')' => self::TYPE_PAREN_CLOSE,
']' => self::TYPE_PAREN_CLOSE,
'break' => self::TYPE_RETURN,
'continue' => self::TYPE_RETURN,
'return' => self::TYPE_RETURN,
'throw' => self::TYPE_RETURN,
'catch' => self::TYPE_IF,
'for' => self::TYPE_IF,
'if' => self::TYPE_IF,
'switch' => self::TYPE_IF,
'while' => self::TYPE_IF,
'with' => self::TYPE_IF,
'case' => self::TYPE_DO,
'do' => self::TYPE_DO,
'else' => self::TYPE_DO,
'finally' => self::TYPE_DO,
'try' => self::TYPE_DO,
'var' => self::TYPE_DO,
'function' => self::TYPE_FUNC
);
// $goto : This is the main table for our state machine. For every state/token pair
// the following state is defined. When no rule exists for a given pair,
// the state is left unchanged.
$goto = array(
self::STATEMENT => array(
self::TYPE_UN_OP => self::EXPRESSION,
self::TYPE_INCR_OP => self::EXPRESSION,
self::TYPE_ADD_OP => self::EXPRESSION,
self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION,
self::TYPE_RETURN => self::EXPRESSION_NO_NL,
self::TYPE_IF => self::CONDITION,
self::TYPE_FUNC => self::CONDITION,
self::TYPE_LITERAL => self::EXPRESSION_OP
),
self::CONDITION => array(
self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION
),
self::PROPERTY_ASSIGNMENT => array(
self::TYPE_COLON => self::PROPERTY_EXPRESSION,
self::TYPE_BRACE_OPEN => self::STATEMENT
),
self::EXPRESSION => array(
self::TYPE_SEMICOLON => self::STATEMENT,
self::TYPE_BRACE_OPEN => self::PROPERTY_ASSIGNMENT,
self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION,
self::TYPE_FUNC => self::EXPRESSION_FUNC,
self::TYPE_LITERAL => self::EXPRESSION_OP
),
self::EXPRESSION_NO_NL => array(
self::TYPE_SEMICOLON => self::STATEMENT,
self::TYPE_BRACE_OPEN => self::PROPERTY_ASSIGNMENT,
self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION,
self::TYPE_FUNC => self::EXPRESSION_FUNC,
self::TYPE_LITERAL => self::EXPRESSION_OP
),
self::EXPRESSION_OP => array(
self::TYPE_BIN_OP => self::EXPRESSION,
self::TYPE_ADD_OP => self::EXPRESSION,
self::TYPE_HOOK => self::EXPRESSION_TERNARY,
self::TYPE_COLON => self::STATEMENT,
self::TYPE_COMMA => self::EXPRESSION,
self::TYPE_SEMICOLON => self::STATEMENT,
self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION
),
self::EXPRESSION_FUNC => array(
self::TYPE_BRACE_OPEN => self::STATEMENT
),
self::EXPRESSION_TERNARY => array(
self::TYPE_BRACE_OPEN => self::PROPERTY_ASSIGNMENT,
self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION,
self::TYPE_FUNC => self::EXPRESSION_TERNARY_FUNC,
self::TYPE_LITERAL => self::EXPRESSION_TERNARY_OP
),
self::EXPRESSION_TERNARY_OP => array(
self::TYPE_BIN_OP => self::EXPRESSION_TERNARY,
self::TYPE_ADD_OP => self::EXPRESSION_TERNARY,
self::TYPE_HOOK => self::EXPRESSION_TERNARY,
self::TYPE_COMMA => self::EXPRESSION_TERNARY,
self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION
),
self::EXPRESSION_TERNARY_FUNC => array(
self::TYPE_BRACE_OPEN => self::STATEMENT
),
self::PAREN_EXPRESSION => array(
self::TYPE_BRACE_OPEN => self::PROPERTY_ASSIGNMENT,
self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION,
self::TYPE_FUNC => self::PAREN_EXPRESSION_FUNC,
self::TYPE_LITERAL => self::PAREN_EXPRESSION_OP
),
self::PAREN_EXPRESSION_OP => array(
self::TYPE_BIN_OP => self::PAREN_EXPRESSION,
self::TYPE_ADD_OP => self::PAREN_EXPRESSION,
self::TYPE_HOOK => self::PAREN_EXPRESSION,
self::TYPE_COLON => self::PAREN_EXPRESSION,
self::TYPE_COMMA => self::PAREN_EXPRESSION,
self::TYPE_SEMICOLON => self::PAREN_EXPRESSION,
self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION
),
self::PAREN_EXPRESSION_FUNC => array(
self::TYPE_BRACE_OPEN => self::STATEMENT
),
self::PROPERTY_EXPRESSION => array(
self::TYPE_BRACE_OPEN => self::PROPERTY_ASSIGNMENT,
self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION,
self::TYPE_FUNC => self::PROPERTY_EXPRESSION_FUNC,
self::TYPE_LITERAL => self::PROPERTY_EXPRESSION_OP
),
self::PROPERTY_EXPRESSION_OP => array(
self::TYPE_BIN_OP => self::PROPERTY_EXPRESSION,
self::TYPE_ADD_OP => self::PROPERTY_EXPRESSION,
self::TYPE_HOOK => self::PROPERTY_EXPRESSION,
self::TYPE_COMMA => self::PROPERTY_ASSIGNMENT,
self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION
),
self::PROPERTY_EXPRESSION_FUNC => array(
self::TYPE_BRACE_OPEN => self::STATEMENT
)
);
// $push : This table contains the rules for when to push a state onto the stack.
// The pushed state is the state to return to when the corresponding
// closing token is found
$push = array(
self::STATEMENT => array(
self::TYPE_BRACE_OPEN => self::STATEMENT,
self::TYPE_PAREN_OPEN => self::EXPRESSION_OP
),
self::CONDITION => array(
self::TYPE_PAREN_OPEN => self::STATEMENT
),
self::PROPERTY_ASSIGNMENT => array(
self::TYPE_BRACE_OPEN => self::PROPERTY_ASSIGNMENT
),
self::EXPRESSION => array(
self::TYPE_BRACE_OPEN => self::EXPRESSION_OP,
self::TYPE_PAREN_OPEN => self::EXPRESSION_OP
),
self::EXPRESSION_NO_NL => array(
self::TYPE_BRACE_OPEN => self::EXPRESSION_OP,
self::TYPE_PAREN_OPEN => self::EXPRESSION_OP
),
self::EXPRESSION_OP => array(
self::TYPE_HOOK => self::EXPRESSION,
self::TYPE_PAREN_OPEN => self::EXPRESSION_OP
),
self::EXPRESSION_FUNC => array(
self::TYPE_BRACE_OPEN => self::EXPRESSION_OP
),
self::EXPRESSION_TERNARY => array(
self::TYPE_BRACE_OPEN => self::EXPRESSION_TERNARY_OP,
self::TYPE_PAREN_OPEN => self::EXPRESSION_TERNARY_OP
),
self::EXPRESSION_TERNARY_OP => array(
self::TYPE_HOOK => self::EXPRESSION_TERNARY,
self::TYPE_PAREN_OPEN => self::EXPRESSION_TERNARY_OP
),
self::EXPRESSION_TERNARY_FUNC => array(
self::TYPE_BRACE_OPEN => self::EXPRESSION_TERNARY_OP
),
self::PAREN_EXPRESSION => array(
self::TYPE_BRACE_OPEN => self::PAREN_EXPRESSION_OP,
self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION_OP
),
self::PAREN_EXPRESSION_OP => array(
self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION_OP
),
self::PAREN_EXPRESSION_FUNC => array(
self::TYPE_BRACE_OPEN => self::PAREN_EXPRESSION_OP
),
self::PROPERTY_EXPRESSION => array(
self::TYPE_BRACE_OPEN => self::PROPERTY_EXPRESSION_OP,
self::TYPE_PAREN_OPEN => self::PROPERTY_EXPRESSION_OP
),
self::PROPERTY_EXPRESSION_OP => array(
self::TYPE_PAREN_OPEN => self::PROPERTY_EXPRESSION_OP
),
self::PROPERTY_EXPRESSION_FUNC => array(
self::TYPE_BRACE_OPEN => self::PROPERTY_EXPRESSION_OP
)
);
// $pop : Rules for when to pop a state from the stack
$pop = array(
self::STATEMENT => array( self::TYPE_BRACE_CLOSE => true ),
self::PROPERTY_ASSIGNMENT => array( self::TYPE_BRACE_CLOSE => true ),
self::EXPRESSION => array( self::TYPE_BRACE_CLOSE => true ),
self::EXPRESSION_NO_NL => array( self::TYPE_BRACE_CLOSE => true ),
self::EXPRESSION_OP => array( self::TYPE_BRACE_CLOSE => true ),
self::EXPRESSION_TERNARY_OP => array( self::TYPE_COLON => true ),
self::PAREN_EXPRESSION => array( self::TYPE_PAREN_CLOSE => true ),
self::PAREN_EXPRESSION_OP => array( self::TYPE_PAREN_CLOSE => true ),
self::PROPERTY_EXPRESSION => array( self::TYPE_BRACE_CLOSE => true ),
self::PROPERTY_EXPRESSION_OP => array( self::TYPE_BRACE_CLOSE => true )
);
// $semicolon : Rules for when a semicolon insertion is appropriate
$semicolon = array(
self::EXPRESSION_NO_NL => array(
self::TYPE_UN_OP => true,
self::TYPE_INCR_OP => true,
self::TYPE_ADD_OP => true,
self::TYPE_BRACE_OPEN => true,
self::TYPE_PAREN_OPEN => true,
self::TYPE_RETURN => true,
self::TYPE_IF => true,
self::TYPE_DO => true,
self::TYPE_FUNC => true,
self::TYPE_LITERAL => true
),
self::EXPRESSION_OP => array(
self::TYPE_UN_OP => true,
self::TYPE_INCR_OP => true,
self::TYPE_BRACE_OPEN => true,
self::TYPE_RETURN => true,
self::TYPE_IF => true,
self::TYPE_DO => true,
self::TYPE_FUNC => true,
self::TYPE_LITERAL => true
)
);
// Rules for when newlines should be inserted if
// $statementsOnOwnLine is enabled.
// $newlineBefore is checked before switching state,
// $newlineAfter is checked after
$newlineBefore = array(
self::STATEMENT => array(
self::TYPE_BRACE_CLOSE => true,
),
);
$newlineAfter = array(
self::STATEMENT => array(
self::TYPE_BRACE_OPEN => true,
self::TYPE_PAREN_CLOSE => true,
self::TYPE_SEMICOLON => true,
),
);
// $divStates : Contains all states that can be followed by a division operator
$divStates = array(
self::EXPRESSION_OP => true,
self::EXPRESSION_TERNARY_OP => true,
self::PAREN_EXPRESSION_OP => true,
self::PROPERTY_EXPRESSION_OP => true
);
// Here's where the minifying takes place: Loop through the input, looking for tokens
// and output them to $out, taking actions to the above defined rules when appropriate.
$out = '';
$pos = 0;
$length = strlen( $s );
$lineLength = 0;
$newlineFound = true;
$state = self::STATEMENT;
$stack = array();
$last = ';'; // Pretend that we have seen a semicolon yet
while( $pos < $length ) {
// First, skip over any whitespace and multiline comments, recording whether we
// found any newline character
$skip = strspn( $s, " \t\n\r\xb\xc", $pos );
if( !$skip ) {
$ch = $s[$pos];
if( $ch === '/' && substr( $s, $pos, 2 ) === '/*' ) {
// Multiline comment. Search for the end token or EOT.
$end = strpos( $s, '*/', $pos + 2 );
$skip = $end === false ? $length - $pos : $end - $pos + 2;
}
}
if( $skip ) {
// The semicolon insertion mechanism needs to know whether there was a newline
// between two tokens, so record it now.
if( !$newlineFound && strcspn( $s, "\r\n", $pos, $skip ) !== $skip ) {
$newlineFound = true;
}
$pos += $skip;
continue;
}
// Handle C++-style comments and html comments, which are treated as single line
// comments by the browser, regardless of whether the end tag is on the same line.
// Handle --> the same way, but only if it's at the beginning of the line
if( ( $ch === '/' && substr( $s, $pos, 2 ) === '//' )
|| ( $ch === '<' && substr( $s, $pos, 4 ) === '<!--' )
|| ( $ch === '-' && $newlineFound && substr( $s, $pos, 3 ) === '-->' )
) {
$pos += strcspn( $s, "\r\n", $pos );
continue;
}
// Find out which kind of token we're handling. $end will point past the end of it.
$end = $pos + 1;
// Handle string literals
if( $ch === "'" || $ch === '"' ) {
// Search to the end of the string literal, skipping over backslash escapes
$search = $ch . '\\';
do{
$end += strcspn( $s, $search, $end ) + 2;
} while( $end - 2 < $length && $s[$end - 2] === '\\' );
$end--;
// We have to distinguish between regexp literals and division operators
// A division operator is only possible in certain states
} elseif( $ch === '/' && !isset( $divStates[$state] ) ) {
// Regexp literal, search to the end, skipping over backslash escapes and
// character classes
for( ; ; ) {
do{
$end += strcspn( $s, '/[\\', $end ) + 2;
} while( $end - 2 < $length && $s[$end - 2] === '\\' );
$end--;
if( $end - 1 >= $length || $s[$end - 1] === '/' ) {
break;
}
do{
$end += strcspn( $s, ']\\', $end ) + 2;
} while( $end - 2 < $length && $s[$end - 2] === '\\' );
$end--;
};
// Search past the regexp modifiers (gi)
while( $end < $length && ctype_alpha( $s[$end] ) ) {
$end++;
}
} elseif(
$ch === '0'
&& ($pos + 1 < $length) && ($s[$pos + 1] === 'x' || $s[$pos + 1] === 'X' )
) {
// Hex numeric literal
$end++; // x or X
$len = strspn( $s, '0123456789ABCDEFabcdef', $end );
if ( !$len ) {
return self::parseError($s, $pos, 'Expected a hexadecimal number but found ' . substr( $s, $pos, 5 ) . '...' );
}
$end += $len;
} elseif(
ctype_digit( $ch )
|| ( $ch === '.' && $pos + 1 < $length && ctype_digit( $s[$pos + 1] ) )
) {
$end += strspn( $s, '0123456789', $end );
$decimal = strspn( $s, '.', $end );
if ($decimal) {
if ( $decimal > 2 ) {
return self::parseError($s, $end, 'The number has too many decimal points' );
}
$end += strspn( $s, '0123456789', $end + 1 ) + $decimal;
}
$exponent = strspn( $s, 'eE', $end );
if( $exponent ) {
if ( $exponent > 1 ) {
return self::parseError($s, $end, 'Number with several E' );
}
$end++;
// + sign is optional; - sign is required.
$end += strspn( $s, '-+', $end );
$len = strspn( $s, '0123456789', $end );
if ( !$len ) {
return self::parseError($s, $pos, 'No decimal digits after e, how many zeroes should be added?' );
}
$end += $len;
}
} elseif( isset( $opChars[$ch] ) ) {
// Punctuation character. Search for the longest matching operator.
while(
$end < $length
&& isset( $tokenTypes[substr( $s, $pos, $end - $pos + 1 )] )
) {
$end++;
}
} else {
// Identifier or reserved word. Search for the end by excluding whitespace and
// punctuation.
$end += strcspn( $s, " \t\n.;,=<>+-{}()[]?:*/%'\"!&|^~\xb\xc\r", $end );
}
// Now get the token type from our type array
$token = substr( $s, $pos, $end - $pos ); // so $end - $pos == strlen( $token )
$type = isset( $tokenTypes[$token] ) ? $tokenTypes[$token] : self::TYPE_LITERAL;
if( $newlineFound && isset( $semicolon[$state][$type] ) ) {
// This token triggers the semicolon insertion mechanism of javascript. While we
// could add the ; token here ourselves, keeping the newline has a few advantages.
$out .= "\n";
$state = self::STATEMENT;
$lineLength = 0;
} elseif( $maxLineLength > 0 && $lineLength + $end - $pos > $maxLineLength &&
!isset( $semicolon[$state][$type] ) && $type !== self::TYPE_INCR_OP )
{
// This line would get too long if we added $token, so add a newline first.
// Only do this if it won't trigger semicolon insertion and if it won't
// put a postfix increment operator on its own line, which is illegal in js.
$out .= "\n";
$lineLength = 0;
// Check, whether we have to separate the token from the last one with whitespace
} elseif( !isset( $opChars[$last] ) && !isset( $opChars[$ch] ) ) {
$out .= ' ';
$lineLength++;
// Don't accidentally create ++, -- or // tokens
} elseif( $last === $ch && ( $ch === '+' || $ch === '-' || $ch === '/' ) ) {
$out .= ' ';
$lineLength++;
}
$out .= $token;
$lineLength += $end - $pos; // += strlen( $token )
$last = $s[$end - 1];
$pos = $end;
$newlineFound = false;
// Output a newline after the token if required
// This is checked before AND after switching state
$newlineAdded = false;
if ( $statementsOnOwnLine && !$newlineAdded && isset( $newlineBefore[$state][$type] ) ) {
$out .= "\n";
$lineLength = 0;
$newlineAdded = true;
}
// Now that we have output our token, transition into the new state.
if( isset( $push[$state][$type] ) && count( $stack ) < self::STACK_LIMIT ) {
$stack[] = $push[$state][$type];
}
if( $stack && isset( $pop[$state][$type] ) ) {
$state = array_pop( $stack );
} elseif( isset( $goto[$state][$type] ) ) {
$state = $goto[$state][$type];
}
// Check for newline insertion again
if ( $statementsOnOwnLine && !$newlineAdded && isset( $newlineAfter[$state][$type] ) ) {
$out .= "\n";
$lineLength = 0;
}
}
return $out;
}
static function parseError($fullJavascript, $position, $errorMsg) {
// TODO: Handle the error: trigger_error, throw exception, return false...
return false;
}
}

View File

@ -10,18 +10,22 @@ ob_start();
OCP\JSON::checkLoggedIn();
OCP\App::checkAppEnabled('calendar');
session_write_close();
$nl="\r\n";
$comps = array('VEVENT'=>true, 'VTODO'=>true, 'VJOURNAL'=>true);
$progressfile = 'import_tmp/' . md5(session_id()) . '.txt';
global $progresskey;
$progresskey = 'calendar.import-' . $_GET['progresskey'];
if (isset($_GET['progress']) && $_GET['progress']) {
echo OC_Cache::get($progresskey);
die;
}
function writeProgress($pct) {
if(is_writable('import_tmp/')){
$progressfopen = fopen($progressfile, 'w');
fwrite($progressfopen, $pct);
fclose($progressfopen);
}
global $progresskey;
OC_Cache::set($progresskey, $pct, 300);
}
writeProgress('10');
$file = OC_Filesystem::file_get_contents($_POST['path'] . '/' . $_POST['file']);
@ -114,7 +118,5 @@ foreach($uids as $uid) {
// finished import
writeProgress('100');
sleep(3);
if(is_writable('import_tmp/')){
unlink($progressfile);
}
OC_Cache::remove($progresskey);
OCP\JSON::success();

View File

@ -1,2 +0,0 @@
This folder contains static files with the percentage of the import.
Requires write permission

View File

@ -43,8 +43,8 @@ Calendar_Import={
}
$('#newcalendar').attr('readonly', 'readonly');
$('#calendar').attr('disabled', 'disabled');
var progressfile = $('#progressfile').val();
$.post(OC.filePath('calendar', 'ajax/import', 'import.php'), {method: String (method), calname: String (calname), path: String (path), file: String (filename), id: String (calid)}, function(data){
var progresskey = $('#progresskey').val();
$.post(OC.filePath('calendar', 'ajax/import', 'import.php') + '?progresskey='+progresskey, {method: String (method), calname: String (calname), path: String (path), file: String (filename), id: String (calid)}, function(data){
if(data.status == 'success'){
$('#progressbar').progressbar('option', 'value', 100);
$('#import_done').css('display', 'block');
@ -52,7 +52,7 @@ Calendar_Import={
});
$('#form_container').css('display', 'none');
$('#progressbar_container').css('display', 'block');
window.setTimeout('Calendar_Import.getimportstatus(\'' + progressfile + '\')', 500);
window.setTimeout('Calendar_Import.getimportstatus(\'' + progresskey + '\')', 500);
});
$('#calendar').change(function(){
if($('#calendar option:selected').val() == 'newcal'){
@ -62,11 +62,11 @@ Calendar_Import={
}
});
},
getimportstatus: function(progressfile){
$.get(OC.filePath('calendar', 'import_tmp', progressfile), function(percent){
getimportstatus: function(progresskey){
$.get(OC.filePath('calendar', 'ajax/import', 'import.php') + '?progress=1&progresskey=' + progresskey, function(percent){
$('#progressbar').progressbar('option', 'value', parseInt(percent));
if(percent < 100){
window.setTimeout('Calendar_Import.getimportstatus(\'' + progressfile + '\')', 500);
window.setTimeout('Calendar_Import.getimportstatus(\'' + progresskey + '\')', 500);
}else{
$('#import_done').css('display', 'block');
}

View File

@ -2,7 +2,7 @@
<div id="form_container">
<input type="hidden" id="filename" value="<?php echo $_['filename'];?>">
<input type="hidden" id="path" value="<?php echo $_['path'];?>">
<input type="hidden" id="progressfile" value="<?php echo md5(session_id()) . '.txt';?>">
<input type="hidden" id="progresskey" value="<?php echo rand() ?>">
<p style="text-align:center;"><b><?php echo $l->t('Please choose the calendar'); ?></b></p>
<select style="width:100%;" id="calendar" name="calendar">
<?php

View File

@ -10,16 +10,21 @@ ob_start();
OCP\JSON::checkLoggedIn();
OCP\App::checkAppEnabled('contacts');
session_write_close();
$nl = "\n";
$progressfile = 'import_tmp/' . md5(session_id()) . '.txt';
global $progresskey;
$progresskey = 'contacts.import-' . $_GET['progresskey'];
if (isset($_GET['progress']) && $_GET['progress']) {
echo OC_Cache::get($progresskey);
die;
}
function writeProgress($pct) {
if(is_writable('import_tmp/')){
$progressfopen = fopen($progressfile, 'w');
fwrite($progressfopen, $pct);
fclose($progressfopen);
}
global $progresskey;
OC_Cache::set($progresskey, $pct, 300);
}
writeProgress('10');
$view = $file = null;
@ -93,9 +98,7 @@ foreach($parts as $part){
//done the import
writeProgress('100');
sleep(3);
if(is_writable('import_tmp/')){
unlink($progressfile);
}
OC_Cache::remove($progresskey);
if(isset($_POST['fstype']) && $_POST['fstype'] == 'OC_FilesystemView') {
if(!$view->unlink('/' . $_POST['file'])) {
OCP\Util::writeLog('contacts','Import: Error unlinking OC_FilesystemView ' . '/' . $_POST['file'], OCP\Util::ERROR);

View File

@ -1,2 +0,0 @@
This folder contains static files with the percentage of the import.
Requires write permission

View File

@ -42,8 +42,8 @@ Contacts_Import={
}
$('#newaddressbook').attr('readonly', 'readonly');
$('#contacts').attr('disabled', 'disabled');
var progressfile = $('#progressfile').val();
$.post(OC.filePath('contacts', '', 'import.php'), {method: String (method), addressbookname: String (addressbookname), path: String (path), file: String (filename), id: String (addressbookid)}, function(jsondata){
var progresskey = $('#progresskey').val();
$.post(OC.filePath('contacts', '', 'import.php') + '?progresskey='+progresskey, {method: String (method), addressbookname: String (addressbookname), path: String (path), file: String (filename), id: String (addressbookid)}, function(jsondata){
if(jsondata.status == 'success'){
$('#progressbar').progressbar('option', 'value', 100);
$('#import_done').find('p').html(t('contacts', 'Result: ') + jsondata.data.imported + t('contacts', ' imported, ') + jsondata.data.failed + t('contacts', ' failed.'));
@ -55,7 +55,7 @@ Contacts_Import={
});
$('#form_container').css('display', 'none');
$('#progressbar_container').css('display', 'block');
window.setTimeout('Contacts_Import.getimportstatus(\'' + progressfile + '\')', 500);
window.setTimeout('Contacts_Import.getimportstatus(\'' + progresskey + '\')', 500);
});
$('#contacts').change(function(){
if($('#contacts option:selected').val() == 'newaddressbook'){
@ -65,11 +65,11 @@ Contacts_Import={
}
});
},
getimportstatus: function(progressfile){
$.get(OC.filePath('contacts', 'import_tmp', progressfile), function(percent){
getimportstatus: function(progresskey){
$.get(OC.filePath('contacts', '', 'import.php') + '?progress=1&progresskey=' + progresskey, function(percent){
$('#progressbar').progressbar('option', 'value', parseInt(percent));
if(percent < 100){
window.setTimeout('Contacts_Import.getimportstatus(\'' + progressfile + '\')', 500);
window.setTimeout('Contacts_Import.getimportstatus(\'' + progresskey + '\')', 500);
}else{
$('#import_done').css('display', 'block');
}

View File

@ -14,7 +14,7 @@ OCP\User::checkLoggedIn();
OCP\App::checkAppEnabled('contacts');
function getStandardImage(){
OCP\Response::setExpiresHeader('P10D');
//OCP\Response::setExpiresHeader('P10D');
OCP\Response::enableCaching();
OCP\Response::redirect(OCP\Util::imagePath('contacts', 'person_large.png'));
}

View File

@ -2,7 +2,7 @@
<div id="form_container">
<input type="hidden" id="filename" value="<?php echo $_['filename'];?>">
<input type="hidden" id="path" value="<?php echo $_['path'];?>">
<input type="hidden" id="progressfile" value="<?php echo md5(session_id()) . '.txt';?>">
<input type="hidden" id="progresskey" value="<?php echo rand() ?>">
<p class="bold" style="text-align:center;"><?php echo $l->t('Please choose the addressbook'); ?></p>
<select style="width:100%;" id="contacts" name="contacts">
<?php

View File

@ -53,7 +53,7 @@
</span>
</th>
<th id="headerSize"><?php echo $l->t( 'Size' ); ?></th>
<th id="headerDate"><span id="modified"><?php echo $l->t( 'Modified' ); ?></span><span class="selectedActions"><a href="" class="delete"><?php echo $l->t('Delete all')?> <img class="svg" alt="<?php echo $l->t('Delete')?>" src="<?php echo OCP\image_path("core", "actions/delete.svg"); ?>" /></a></span></th>
<th id="headerDate"><span id="modified"><?php echo $l->t( 'Modified' ); ?></span><span class="selectedActions"><a href="" class="delete"><?php echo $l->t('Delete')?> <img class="svg" alt="<?php echo $l->t('Delete')?>" src="<?php echo OCP\image_path("core", "actions/delete.svg"); ?>" /></a></span></th>
</tr>
</thead>
<tbody id="fileList" data-readonly="<?php echo $_['readonly'];?>">

View File

@ -10,7 +10,14 @@ $source = strip_tags( $source );
if( OCA_Versions\Storage::isversioned( $source ) ) {
$count=5; //show the newest revisions
$versions = OCA_Versions\Storage::getversions( $source, $count);
$versions = OCA_Versions\Storage::getVersions( $source, $count);
$versionsFormatted = array();
foreach ( $versions AS $version ) {
$versionsFormatted[] = OCP\Util::formatDate( $version );
}
$versionsSorted = array_reverse( $versions );

View File

@ -54,7 +54,7 @@ if ( isset( $_GET['path'] ) ) {
if( OCA_Versions\Storage::isversioned( $path ) ) {
$count = 999; //show the newest revisions
$versions = OCA_Versions\Storage::getversions( $path, $count );
$versions = OCA_Versions\Storage::getVersions( $path, $count);
$tmpl->assign( 'versions', array_reverse( $versions ) );

View File

@ -33,7 +33,7 @@ $(document).ready(function(){
});
function createVersionsDropdown(filename, files) {
var historyUrl = OC.linkTo('files_versions', 'history.php') + '?path='+encodeURIComponent( $( '#dir' ).val() ).replace( /%2F/g, '/' )+'/'+encodeURIComponent( filename );
var html = '<div id="dropdown" class="drop" data-file="'+files+'">';

View File

@ -22,8 +22,10 @@ if( isset( $_['message'] ) ) {
foreach ( $_['versions'] as $v ) {
echo ' ';
echo OCP\Util::formatDate( $v );
echo ' <a href="'.OCP\Util::linkTo('files_versions', 'history.php').'?path='.urlencode( $_['path'] ).'&revert='. $v .'" class="button">Revert</a><br /><br />';
echo OCP\Util::formatDate( $v['version'] );
echo ' <a href="'.OCP\Util::linkTo('files_versions', 'history.php').'?path='.urlencode( $_['path'] ).'&revert='. $v['version'] .'" class="button">Revert</a><br /><br />';
if ( $v['cur'] ) { echo ' (<b>Current</b>)'; }
echo '<br /><br />';
}

View File

@ -27,7 +27,6 @@ class Storage {
//
// todo:
// - port to oc_filesystem to enable network transparency
// - check if it works well together with encryption
// - implement expire all function. And find a place to call it ;-)
// - add transparent compression. first test if it´s worth it.
@ -35,7 +34,7 @@ class Storage {
const DEFAULTFOLDER='versions';
const DEFAULTBLACKLIST='avi mp3 mpg mp4 ctmp';
const DEFAULTMAXFILESIZE=1048576; // 10MB
const DEFAULTMININTERVAL=120; // 2 min
const DEFAULTMININTERVAL=1; // 2 min
const DEFAULTMAXVERSIONS=50;
/**
@ -76,7 +75,7 @@ class Storage {
} else {
$uid = \OCP\User::getUser();
}
$versionsfoldername=\OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);
$versionsFolderName=\OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);
$filesfoldername=\OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/files';
Storage::init();
@ -103,7 +102,7 @@ class Storage {
// check mininterval if the file is being modified by the owner (all shared files should be versioned despite mininterval)
if ($uid == \OCP\User::getUser()) {
$matches=glob($versionsfoldername.'/'.$filename.'.v*');
$matches=glob($versionsFolderName.'/'.$filename.'.v*');
sort($matches);
$parts=explode('.v',end($matches));
if((end($parts)+Storage::DEFAULTMININTERVAL)>time()){
@ -114,12 +113,12 @@ class Storage {
// create all parent folders
$info=pathinfo($filename);
if(!file_exists($versionsfoldername.'/'.$info['dirname'])) mkdir($versionsfoldername.'/'.$info['dirname'],0700,true);
if(!file_exists($versionsFolderName.'/'.$info['dirname'])) mkdir($versionsFolderName.'/'.$info['dirname'],0700,true);
// store a new version of a file
copy($filesfoldername.'/'.$filename,$versionsfoldername.'/'.$filename.'.v'.time());
copy($filesfoldername.'/'.$filename,$versionsFolderName.'/'.$filename.'.v'.time());
// expire old revisions
// expire old revisions if necessary
Storage::expire($filename);
}
}
@ -138,12 +137,12 @@ class Storage {
} else {
$uid = \OCP\User::getUser();
}
$versionsfoldername=\OCP\Config::getSystemValue('datadirectory').'/'.$uid .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);
$versionsFolderName=\OCP\Config::getSystemValue('datadirectory').'/'.$uid .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);
$filesfoldername=\OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/files';
// rollback
if ( @copy($versionsfoldername.'/'.$filename.'.v'.$revision,$filesfoldername.'/'.$filename) ) {
if ( @copy($versionsFolderName.'/'.$filename.'.v'.$revision,$filesfoldername.'/'.$filename) ) {
return true;
@ -169,10 +168,10 @@ class Storage {
} else {
$uid = \OCP\User::getUser();
}
$versionsfoldername=\OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);
$versionsFolderName=\OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);
// check for old versions
$matches=glob($versionsfoldername.'/'.$filename.'.v*');
$matches=glob($versionsFolderName.'/'.$filename.'.v*');
if(count($matches)>1){
return true;
}else{
@ -186,10 +185,15 @@ class Storage {
/**
* get a list of old versions of a file.
* @brief get a list of all available versions of a file in descending chronological order
* @param $filename file to find versions of, relative to the user files dir
* @param $count number of versions to return
* @returns array
*/
public static function getversions($filename,$count=0) {
if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
public static function getVersions( $filename, $count = 0 ) {
if( \OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true' ) {
if (\OCP\App::isEnabled('files_sharing') && $source = \OC_Share::getSource('/'.\OCP\User::getUser().'/files'.$filename)) {
$pos = strpos($source, '/files', 1);
$uid = substr($source, 1, $pos - 1);
@ -197,29 +201,65 @@ class Storage {
} else {
$uid = \OCP\User::getUser();
}
$versionsfoldername=\OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);
$versions=array();
// fetch for old versions
$matches=glob($versionsfoldername.'/'.$filename.'.v*');
sort($matches);
foreach($matches as $ma) {
$parts=explode('.v',$ma);
$versions[]=(end($parts));
$versionsFolderName = \OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);
$versions = array();
// fetch for old versions
$matches = glob( $versionsFolderName.'/'.$filename.'.v*' );
sort( $matches );
$i = 0;
foreach( $matches as $ma ) {
$i++;
$versions[$i]['cur'] = 0;
$parts = explode( '.v', $ma );
$versions[$i]['version'] = ( end( $parts ) );
// if file with modified date exists, flag it in array as currently enabled version
$curFile['fileName'] = basename( $parts[0] );
$curFile['filePath'] = \OCP\Config::getSystemValue('datadirectory').\OC_Filesystem::getRoot().'/'.$curFile['fileName'];
( \md5_file( $ma ) == \md5_file( $curFile['filePath'] ) ? $versions[$i]['fileMatch'] = 1 : $versions[$i]['fileMatch'] = 0 );
}
$versions = array_reverse( $versions );
foreach( $versions as $key => $value ) {
// flag the first matched file in array (which will have latest modification date) as current version
if ( $versions[$key]['fileMatch'] ) {
$versions[$key]['cur'] = 1;
break;
}
}
$versions = array_reverse( $versions );
// only show the newest commits
if($count<>0 and (count($versions)>$count)) {
$versions=array_slice($versions,count($versions)-$count);
if( $count != 0 and ( count( $versions )>$count ) ) {
$versions = array_slice( $versions, count( $versions ) - $count );
}
return($versions);
return( $versions );
}else{
return(array());
} else {
// if versioning isn't enabled then return an empty array
return( array() );
}
}
}
@ -228,6 +268,7 @@ class Storage {
*/
public static function expire($filename) {
if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
if (\OCP\App::isEnabled('files_sharing') && $source = \OC_Share::getSource('/'.\OCP\User::getUser().'/files'.$filename)) {
$pos = strpos($source, '/files', 1);
$uid = substr($source, 1, $pos - 1);
@ -235,28 +276,93 @@ class Storage {
} else {
$uid = \OCP\User::getUser();
}
$versionsfoldername=\OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);
$versionsFolderName=\OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);
// check for old versions
$matches=glob($versionsfoldername.'/'.$filename.'.v*');
if(count($matches)>\OCP\Config::getSystemValue('files_versionmaxversions', Storage::DEFAULTMAXVERSIONS)){
$numbertodelete=count($matches-\OCP\Config::getSystemValue('files_versionmaxversions', Storage::DEFAULTMAXVERSIONS));
$matches = glob( $versionsFolderName.'/'.$filename.'.v*' );
if( count( $matches ) > \OCP\Config::getSystemValue( 'files_versionmaxversions', Storage::DEFAULTMAXVERSIONS ) ) {
$numberToDelete = count( $matches-\OCP\Config::getSystemValue( 'files_versionmaxversions', Storage::DEFAULTMAXVERSIONS ) );
// delete old versions of a file
$deleteitems=array_slice($matches,0,$numbertodelete);
foreach($deleteitems as $de){
unlink($versionsfoldername.'/'.$filename.'.v'.$de);
$deleteItems = array_slice( $matches, 0, $numberToDelete );
foreach( $deleteItems as $de ) {
unlink( $versionsFolderName.'/'.$filename.'.v'.$de );
}
}
}
}
/**
* expire all old versions.
* @brief erase all old versions of all user files
* @return
*/
public static function expireall($filename) {
// todo this should go through all the versions directories and delete all the not needed files and not needed directories.
// useful to be included in a cleanup cronjob.
public static function expireAll() {
function deleteAll($directory, $empty = false) {
if(substr($directory,-1) == "/") {
$directory = substr($directory,0,-1);
}
if(!file_exists($directory) || !is_dir($directory)) {
return false;
} elseif(!is_readable($directory)) {
return false;
} else {
$directoryHandle = opendir($directory);
while ($contents = readdir($directoryHandle)) {
if( $contents != '.' && $contents != '..') {
$path = $directory . "/" . $contents;
if( is_dir($path) ) {
deleteAll($path);
} else {
unlink($path);
}
}
}
closedir( $directoryHandle );
if( $empty == false ) {
if(!rmdir($directory)) {
return false;
}
}
return true;
}
}
/*
// FIXME: make this path dynamic
$dir = '/home/samtuke/owncloud/git/oc5/data/admin/versions';
( deleteAll( $dir, 1 ) ? return true : return false );
*/
}

View File

@ -42,7 +42,8 @@ function handleRemove($name) {
function handleGetThumbnails($albumname) {
OCP\Response::enableCaching(3600 * 24); // 24 hour
$thumbnail = OC::$CONFIG_DATADIRECTORY.'/../gallery/'.urldecode($albumname).'.png';
$view = OCP\App::getStorage('gallery');
$thumbnail = $view->fopen(urldecode($albumname).'.png', 'r');
header('Content-Type: '.OC_Image::getMimeTypeForFile($thumbnail));
OCP\Response::sendFile($thumbnail);
}

View File

@ -80,7 +80,8 @@ function handleGetThumbnail($token, $imgpath) {
function handleGetAlbumThumbnail($token, $albumname)
{
$owner = OC_Gallery_Sharing::getTokenOwner($token);
$file = OCP\Config::getSystemValue("datadirectory").'/'. $owner .'/gallery/'.$albumname.'.png';
$view = OCP\App::getStorage('gallery');
$file = $view->fopen($albumname.'.png', 'r');
$image = new OC_Image($file);
if ($image->valid()) {
$image->centerCrop();
@ -93,7 +94,8 @@ function handleGetAlbumThumbnail($token, $albumname)
function handleGetPhoto($token, $photo) {
$owner = OC_Gallery_Sharing::getTokenOwner($token);
$file = OCP\Config::getSystemValue( "datadirectory", OC::$SERVERROOT."/data" ).'/'.$owner.'/files'.urldecode($photo);
$view = OCP\App::getStorage('files');
$file = $view->fopen(urldecode($photo), 'r');
header('Content-Type: '.OC_Image::getMimeTypeForFile($file));
OCP\Response::sendFile($file);
}

View File

@ -27,10 +27,6 @@ OCP\User::checkLoggedIn();
OCP\App::checkAppEnabled('gallery');
OCP\App::setActiveNavigationEntry( 'gallery_index' );
if (!file_exists(OCP\Config::getSystemValue("datadirectory").'/'. OCP\USER::getUser() .'/gallery')) {
mkdir(OCP\Config::getSystemValue("datadirectory").'/'. OCP\USER::getUser() .'/gallery');
}
if (!isset($_GET['view'])) {
$result = OC_Gallery_Album::find(OCP\USER::getUser());

View File

@ -78,14 +78,14 @@ function albumClickHandler(r) {
for (var i in r.photos) {
Albums.photos.push(r.photos[i]);
}
Albums.shared = r.shared;
if (Albums.shared) {
Albums.recursive = r.recursive;
Albums.token = r.token;
} else {
Albums.recursive = false;
Albums.token = '';
}
Albums.shared = r.shared;
if (Albums.shared) {
Albums.recursive = r.recursive;
Albums.token = r.token;
} else {
Albums.recursive = false;
Albums.token = '';
}
$(document).ready(function(){
var targetDiv = $('#gallery_list');
targetDiv.html('');

View File

@ -77,7 +77,7 @@ class OC_Gallery_Album {
$sql .= ' AND parent_path = ?';
$args[] = $parent;
}
$order = OCP\Config::getUserValue($owner, 'gallery', 'order', 'ASC');
$order = OCP\Config::getUserValue($owner, 'gallery', 'order', 'ASC');
$sql .= ' ORDER BY album_name ' . $order;
$stmt = OCP\DB::prepare($sql);
@ -90,25 +90,22 @@ class OC_Gallery_Album {
}
public static function changeThumbnailPath($oldname, $newname) {
$thumbpath = OC::$CONFIG_DATADIRECTORY.'/../gallery/';
rename($thumbpath.$oldname.'.png', $thumbpath.$newname.'.png');
$view = OCP\App::getStorage('gallery');
$view->rename($oldname.'.png', $newname.'.png');
}
public static function getAlbumSize($id){
$sql = 'SELECT COUNT(*) as size FROM *PREFIX*gallery_photos WHERE album_id = ?';
$stmt = OCP\DB::prepare($sql);
$result=$stmt->execute(array($id))->fetchRow();
return $result['size'];
$sql = 'SELECT COUNT(*) as size FROM *PREFIX*gallery_photos WHERE album_id = ?';
$stmt = OCP\DB::prepare($sql);
$result=$stmt->execute(array($id))->fetchRow();
return $result['size'];
}
public static function getIntermediateGallerySize($path) {
$path .= '%';
$sql = 'SELECT COUNT(*) as size FROM *PREFIX*gallery_photos photos, *PREFIX*gallery_albums albums WHERE photos.album_id = albums.album_id AND uid_owner = ? AND file_path LIKE ?';
$stmt = OCP\DB::prepare($sql);
$result = $stmt->execute(array(OCP\USER::getUser(), $path))->fetchRow();
return $result['size'];
}
public static function getIntermediateGallerySize($path) {
$path .= '%';
$sql = 'SELECT COUNT(*) as size FROM *PREFIX*gallery_photos photos, *PREFIX*gallery_albums albums WHERE photos.album_id = albums.album_id AND uid_owner = ? AND file_path LIKE ?';
$stmt = OCP\DB::prepare($sql);
$result = $stmt->execute(array(OCP\USER::getUser(), $path))->fetchRow();
return $result['size'];
}
}
?>

View File

@ -68,17 +68,17 @@ class OC_Gallery_Photo {
public static function getThumbnail($image_name, $owner = null) {
if (!$owner) $owner = OCP\USER::getUser();
$save_dir = OCP\Config::getSystemValue("datadirectory").'/'. $owner .'/gallery/';
$save_dir .= dirname($image_name). '/';
$image_path = $image_name;
$thumb_file = $save_dir . basename($image_name);
if (!is_dir($save_dir)) {
mkdir($save_dir, 0777, true);
$view = OCP\App::getStorage('gallery');
$save_dir = dirname($image_name);
if (!$view->is_dir($save_dir)) {
$view->mkdir($save_dir);
}
if (file_exists($thumb_file)) {
$image = new OC_Image($thumb_file);
$view->chroot($view->getRoot().'/'.$save_dir);
$thumb_file = basename($image_name);
if ($view->file_exists($thumb_file)) {
$image = new OC_Image($view->fopen($thumb_file, 'r'));
} else {
$image_path = OC_Filesystem::getLocalFile($image_path);
$image_path = OC_Filesystem::getLocalFile($image_name);
if(!file_exists($image_path)) {
return null;
}
@ -86,7 +86,7 @@ class OC_Gallery_Photo {
if ($image->valid()) {
$image->centerCrop(200);
$image->fixOrientation();
$image->save($thumb_file);
$image->save($view->getLocalFile($thumb_file));
}
}
if ($image->valid()) {

View File

@ -81,7 +81,8 @@ class OC_Gallery_Scanner {
$image->destroy();
}
}
imagepng($thumbnail, OCP\Config::getSystemValue("datadirectory").'/'. OCP\USER::getUser() .'/gallery/' . $albumName.'.png');
$view = OCP\App::getStorage('gallery');
imagepng($thumbnail, $view->getLocalFile($albumName.'.png'));
imagedestroy($thumbnail);
}

View File

@ -9,7 +9,7 @@
#tasks_lists .active{font-weight:bold;}
#tasks_list h1{background-color:#1D2D44;color:white;font-size:120%;padding:0 0.5em;}
.task{border-radius:0.4em;position:relative;padding:0.5em 1em;}
.task{border-radius:0.4em;position:relative;padding:0.4em 1em;}
.task:nth-child(odd){background-color:#F4F4F4;}
.task:hover {background-color:#DDDDDD;}
@ -33,7 +33,7 @@
.task .completed {position:absolute;left:3em;top:0.3em;}
.task .summary{padding-left:4em;height:2em;}
.task .summary input{position:relative;left:5px;}
.task .summary input{position:relative;left:5px;top:0.5em;}
.task.done .summary{text-decoration:line-through;}
.task .tag{border-radius:0.4em;display:inline-block;opacity:0.2;margin:0 0.2em;border:1px solid transparent;padding:0 0.4em;cursor:pointer;}
@ -42,18 +42,19 @@
.task:hover .tag{opacity:0.5}
.task:hover .tag:hover{opacity:0.8;}
.task .categories{position:absolute;right:12em;text-align:right;top:0.4em}
.task .categories{position:absolute;right:12em;text-align:right;top:0.5em}
.task .categories a{background-color:#1d2d44;color:white;}
.task .categories .tag.active{display:none;}
.task input.categories{display:none;top:0;text-align:left;}
.task .location{background-color:#442d44;color:white;position:absolute;right:0.6em;width:9.2em;text-align:left;top:0.4em}
.task .location{background-color:#442d44;color:white;position:absolute;right:0.6em;width:9.2em;text-align:left;top:0.5em}
.task input.location{display:none;top:0;text-align:left;right:0.3em;background-color:white;color:#333333;}
.task .more{display:none;margin-top:0.5em;}
.task_less{display:none;}
.task .description{position:relative;left:4em;}
.task textarea.description{width:35em;height:4em;}
.task .due{position:absolute;right:0.3em;}
.task .due .date{width:6em;}
.task .due .time{width:6em;}

View File

@ -24,7 +24,7 @@
require_once('class.openid.v3.php');
/**
* Class for user management in a SQL Database (e.g. MySQL, SQLite)
* Class for user OpenId backend
*/
class OC_USER_OPENID extends OC_User_Backend {
/**

14
core/minimizer.php Normal file
View File

@ -0,0 +1,14 @@
<?php
OC_App::loadApps();
if ($service == 'core.css'){
$minimizer = new OC_Minimizer_CSS();
$files = $minimizer->findFiles(OC_Util::$core_styles);
$minimizer->output($files);
}
else if ($service == 'core.js'){
$minimizer = new OC_Minimizer_JS();
$files = $minimizer->findFiles(OC_Util::$core_scripts);
$minimizer->output($files);
}

View File

@ -4,6 +4,9 @@
<title>ownCloud</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="shortcut icon" href="<?php echo image_path('', 'favicon.png'); ?>" /><link rel="apple-touch-icon-precomposed" href="<?php echo image_path('', 'favicon-touch.png'); ?>" />
<?php if (!defined('DEBUG') || !DEBUG): ?>
<link rel="stylesheet" href="<?php echo OC_Helper::linkToRemote('core.css', false) ?>" type="text/css" media="screen" />
<?php endif ?>
<?php foreach($_['cssfiles'] as $cssfile): ?>
<link rel="stylesheet" href="<?php echo $cssfile; ?>" type="text/css" media="screen" />
<?php endforeach; ?>
@ -11,6 +14,9 @@
var oc_webroot = '<?php echo OC::$WEBROOT; ?>';
var oc_appswebroot = '<?php echo OC::$APPSWEBROOT; ?>';
</script>
<?php if (!defined('DEBUG') || !DEBUG): ?>
<script type="text/javascript" src="<?php echo OC_Helper::linkToRemote('core.js', false) ?>"></script>
<?php endif ?>
<?php foreach($_['jsfiles'] as $jsfile): ?>
<script type="text/javascript" src="<?php echo $jsfile; ?>"></script>
<?php endforeach; ?>

View File

@ -4,6 +4,9 @@
<title><?php echo isset($_['application']) && !empty($_['application'])?$_['application'].' | ':'' ?>ownCloud <?php echo OC_User::getUser()?' ('.OC_User::getUser().') ':'' ?></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="shortcut icon" href="<?php echo image_path('', 'favicon.png'); ?>" /><link rel="apple-touch-icon-precomposed" href="<?php echo image_path('', 'favicon-touch.png'); ?>" />
<?php if (!defined('DEBUG') || !DEBUG): ?>
<link rel="stylesheet" href="<?php echo OC_Helper::linkToRemote('core.css', false) ?>" type="text/css" media="screen" />
<?php endif ?>
<?php foreach($_['cssfiles'] as $cssfile): ?>
<link rel="stylesheet" href="<?php echo $cssfile; ?>" type="text/css" media="screen" />
<?php endforeach; ?>
@ -12,6 +15,9 @@
var oc_appswebroot = '<?php echo OC::$APPSWEBROOT; ?>';
var oc_current_user = '<?php echo OC_User::getUser() ?>';
</script>
<?php if (!defined('DEBUG') || !DEBUG): ?>
<script type="text/javascript" src="<?php echo OC_Helper::linkToRemote('core.js', false) ?>"></script>
<?php endif ?>
<?php foreach($_['jsfiles'] as $jsfile): ?>
<script type="text/javascript" src="<?php echo $jsfile; ?>"></script>
<?php endforeach; ?>

View File

@ -35,6 +35,7 @@ class OC_App{
static private $personalForms = array();
static private $appInfo = array();
static private $appTypes = array();
static private $loadedApps = array();
/**
* @brief loads all apps
@ -48,24 +49,26 @@ class OC_App{
* if $types is set, only apps of those types will be loaded
*/
public static function loadApps($types=null){
// Did we already load everything?
if( self::$init ){
return true;
}
// Load the enabled apps here
$apps = self::getEnabledApps();
// prevent app.php from printing output
ob_start();
foreach( $apps as $app ){
if((is_null($types) or self::isType($app,$types))){
if((is_null($types) or self::isType($app,$types)) && !in_array($app, self::$loadedApps)){
self::loadApp($app);
self::$loadedApps[] = $app;
}
}
ob_end_clean();
self::$init = true;
if (!defined('DEBUG') || !DEBUG){
if (is_null($types)) {
OC_Util::$core_scripts = OC_Util::$scripts;
OC_Util::$scripts = array();
OC_Util::$core_styles = OC_Util::$styles;
OC_Util::$styles = array();
}
}
// return
return true;
}
@ -121,7 +124,7 @@ class OC_App{
*/
public static function setAppTypes($app){
$appData=self::getAppInfo($app);
if(isset($appData['types'])){
$appTypes=implode(',',$appData['types']);
}else{
@ -183,7 +186,7 @@ class OC_App{
if($app!==false){
// check if the app is compatible with this version of ownCloud
$info=OC_App::getAppInfo($app);
$version=OC_Util::getVersion();
$version=OC_Util::getVersion();
if(!isset($info['require']) or ($version[0]>$info['require'])){
OC_Log::write('core','App "'.$info['name'].'" can\'t be installed because it is not compatible with this version of ownCloud',OC_Log::ERROR);
return false;
@ -487,13 +490,13 @@ class OC_App{
}
}
}
// check if the current enabled apps are compatible with the current ownCloud version. disable them if not.
// this is important if you upgrade ownCloud and have non ported 3rd party apps installed
$apps =OC_App::getEnabledApps();
$version=OC_Util::getVersion();
foreach($apps as $app) {
// check if the app is compatible with this version of ownCloud
$info=OC_App::getAppInfo($app);
if(!isset($info['require']) or ($version[0]>$info['require'])){
@ -501,12 +504,12 @@ class OC_App{
OC_App::disable( $app );
}
}
}
/**

View File

@ -30,10 +30,6 @@ class OC{
* Assoziative array for autoloading. classname => filename
*/
public static $CLASSPATH = array();
/**
* $_SERVER['DOCUMENTROOT'] but without symlinks
*/
public static $DOCUMENTROOT = '';
/**
* The installation path for owncloud on the server (e.g. /srv/http/owncloud)
*/
@ -41,7 +37,7 @@ class OC{
/**
* the current request path relative to the owncloud root (e.g. files/index.php)
*/
public static $SUBURI = '';
private static $SUBURI = '';
/**
* the owncloud root path for http requests (e.g. owncloud/)
*/
@ -50,10 +46,6 @@ class OC{
* the folder that stores that data files for the filesystem of the user (e.g. /srv/http/owncloud/data/myusername/files)
*/
public static $CONFIG_DATADIRECTORY = '';
/**
* the folder that stores the data for the root filesystem (e.g. /srv/http/owncloud/data)
*/
public static $CONFIG_DATADIRECTORY_ROOT = '';
/**
* The installation path of the 3rdparty folder on the server (e.g. /srv/http/owncloud/3rdparty)
*/
@ -130,7 +122,7 @@ class OC{
public static function initPaths(){
// calculate the documentroot
OC::$DOCUMENTROOT=realpath($_SERVER['DOCUMENT_ROOT']);
$DOCUMENTROOT=realpath($_SERVER['DOCUMENT_ROOT']);
OC::$SERVERROOT=str_replace("\\",'/',substr(__FILE__,0,-13));
OC::$SUBURI=substr(realpath($_SERVER["SCRIPT_FILENAME"]),strlen(OC::$SERVERROOT));
$scriptName=$_SERVER["SCRIPT_NAME"];
@ -146,7 +138,7 @@ class OC{
}
OC::$WEBROOT=substr($scriptName,0,strlen($scriptName)-strlen(OC::$SUBURI));
// try a new way to detect the WEBROOT which is simpler and also works with the app directory outside the owncloud folder. let´s see if this works for everybody
// OC::$WEBROOT=substr(OC::$SERVERROOT,strlen(OC::$DOCUMENTROOT));
// OC::$WEBROOT=substr(OC::$SERVERROOT,strlen($DOCUMENTROOT));
if(OC::$WEBROOT!='' and OC::$WEBROOT[0]!=='/'){
@ -243,6 +235,9 @@ class OC{
OC_Config::setValue('version',implode('.',OC_Util::getVersion()));
}
OC_AppConfig::setValue('core', 'remote_core.css', '/core/minimizer.php');
OC_AppConfig::setValue('core', 'remote_core.js', '/core/minimizer.php');
OC_App::updateApps();
}
}
@ -291,18 +286,9 @@ class OC{
public static function loadfile(){
if(file_exists(OC::$APPSROOT . '/apps/' . OC::$REQUESTEDAPP . '/' . OC::$REQUESTEDFILE)){
if(substr(OC::$REQUESTEDFILE, -3) == 'css'){
$appswebroot = (string) OC::$APPSWEBROOT;
$webroot = (string) OC::$WEBROOT;
$filepath = OC::$APPSROOT . '/apps/' . OC::$REQUESTEDAPP . '/' . OC::$REQUESTEDFILE;
header('Content-Type: text/css');
OC_Response::enableCaching();
OC_Response::setLastModifiedHeader(filemtime($filepath));
$cssfile = file_get_contents($filepath);
$cssfile = str_replace('%appswebroot%', $appswebroot, $cssfile);
$cssfile = str_replace('%webroot%', $webroot, $cssfile);
OC_Response::setETagHeader(md5($cssfile));
header('Content-Length: '.strlen($cssfile));
echo $cssfile;
$file = 'apps/' . OC::$REQUESTEDAPP . '/' . OC::$REQUESTEDFILE;
$minimizer = new OC_Minimizer_CSS();
$minimizer->output(array(array(OC::$APPSROOT, OC::$APPSWEBROOT, $file)));
exit;
}elseif(substr(OC::$REQUESTEDFILE, -3) == 'php'){
require_once(OC::$APPSROOT . '/apps/' . OC::$REQUESTEDAPP . '/' . OC::$REQUESTEDFILE);

40
lib/cache.php Normal file
View File

@ -0,0 +1,40 @@
<?php
/**
* Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
class OC_Cache {
static protected $cache;
static protected function init() {
self::$cache = new OC_Cache_File();
}
static public function get($key) {
if (!self::$cache) {
self::init();
}
return self::$cache->get($key);
}
static public function set($key, $value, $ttl=0) {
if (empty($key)) {
return false;
}
if (!self::$cache) {
self::init();
}
return self::$cache->set($key, $value, $ttl);
}
static public function remove($key) {
if (!self::$cache) {
self::init();
}
return self::$cache->remove($key);
}
}

50
lib/cache/file.php vendored Normal file
View File

@ -0,0 +1,50 @@
<?php
/**
* Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
class OC_Cache_File {
protected function getStorage() {
if(OC_User::isLoggedIn()){
$subdir = 'cache';
$view = new OC_FilesystemView('/'.OC_User::getUser());
if(!$view->file_exists($subdir)) {
$view->mkdir($subdir);
}
return new OC_FilesystemView('/'.OC_User::getUser().'/'.$subdir);
}else{
OC_Log::write('core','Can\'t get cache storage, user not logged in', OC_Log::ERROR);
return false;
}
}
public function get($key) {
$storage = $this->getStorage();
if ($storage->is_file($key)) {
$mtime = $storage->filemtime($key);
if ($mtime < time()) {
$storage->unlink($key);
return false;
}
return $storage->file_get_contents($key);
}
return false;
}
public function set($key, $value, $ttl) {
$storage = $this->getStorage();
if ($storage->file_put_contents($key, $value)) {
return $storage->touch($key, time() + $ttl);
}
return false;
}
public function remove($key) {
$storage = $this->getStorage();
return $storage->unlink($key);
}
}

View File

@ -290,8 +290,10 @@ class OC_Filesystem{
}
/**
* get the fake root
* @brief get the relative path of the root data directory for the current user
* @return string
*
* Returns path like /admin/files
*/
static public function getRoot(){
return self::$defaultInstance->getRoot();

View File

@ -84,7 +84,7 @@ class OC_Group {
OC_Hook::emit( "OC_Group", "pre_createGroup", array( "run" => &$run, "gid" => $gid ));
if($run){
//create the user in the first backend that supports creating users
//create the group in the first backend that supports creating groups
foreach(self::$_usedBackends as $backend){
if(!$backend->implementsActions(OC_GROUP_BACKEND_CREATE_GROUP))
continue;
@ -141,9 +141,6 @@ class OC_Group {
*/
public static function inGroup( $uid, $gid ){
foreach(self::$_usedBackends as $backend){
if(!$backend->implementsActions(OC_GROUP_BACKEND_IN_GROUP))
continue;
if($backend->inGroup($uid,$gid)){
return true;
}
@ -228,9 +225,6 @@ class OC_Group {
public static function getUserGroups( $uid ){
$groups=array();
foreach(self::$_usedBackends as $backend){
if(!$backend->implementsActions(OC_GROUP_BACKEND_GET_USER_GROUPS))
continue;
$groups=array_merge($backend->getUserGroups($uid),$groups);
}
asort($groups);
@ -246,9 +240,6 @@ class OC_Group {
public static function getGroups(){
$groups=array();
foreach(self::$_usedBackends as $backend){
if(!$backend->implementsActions(OC_GROUP_BACKEND_GET_GROUPS))
continue;
$groups=array_merge($backend->getGroups(),$groups);
}
asort($groups);
@ -276,9 +267,6 @@ class OC_Group {
public static function usersInGroup($gid){
$users=array();
foreach(self::$_usedBackends as $backend){
if(!$backend->implementsActions(OC_GROUP_BACKEND_GET_USERS))
continue;
$users=array_merge($backend->usersInGroup($gid),$users);
}
return $users;

View File

@ -31,12 +31,8 @@ define('OC_GROUP_BACKEND_NOT_IMPLEMENTED', -501);
*/
define('OC_GROUP_BACKEND_CREATE_GROUP', 0x00000001);
define('OC_GROUP_BACKEND_DELETE_GROUP', 0x00000010);
define('OC_GROUP_BACKEND_IN_GROUP', 0x00000100);
define('OC_GROUP_BACKEND_ADD_TO_GROUP', 0x00001000);
define('OC_GROUP_BACKEND_REMOVE_FROM_GOUP', 0x00010000);
define('OC_GROUP_BACKEND_GET_USER_GROUPS', 0x00100000);
define('OC_GROUP_BACKEND_GET_USERS', 0x01000000);
define('OC_GROUP_BACKEND_GET_GROUPS', 0x10000000);
define('OC_GROUP_BACKEND_ADD_TO_GROUP', 0x00000100);
define('OC_GROUP_BACKEND_REMOVE_FROM_GOUP', 0x00001000);
/**
* Abstract base class for user management
@ -45,12 +41,8 @@ abstract class OC_Group_Backend {
protected $possibleActions = array(
OC_GROUP_BACKEND_CREATE_GROUP => 'createGroup',
OC_GROUP_BACKEND_DELETE_GROUP => 'deleteGroup',
OC_GROUP_BACKEND_IN_GROUP => 'inGroup',
OC_GROUP_BACKEND_ADD_TO_GROUP => 'addToGroup',
OC_GROUP_BACKEND_REMOVE_FROM_GOUP => 'removeFromGroup',
OC_GROUP_BACKEND_GET_USER_GROUPS => 'getUserGroups',
OC_GROUP_BACKEND_GET_USERS => 'usersInGroup',
OC_GROUP_BACKEND_GET_GROUPS => 'getGroups'
);
/**
@ -83,15 +75,55 @@ abstract class OC_Group_Backend {
return (bool)($this->getSupportedActions() & $actions);
}
/**
* @brief is user in group?
* @param $uid uid of the user
* @param $gid gid of the group
* @returns true/false
*
* Checks whether the user is member of a group or not.
*/
public static function inGroup($uid, $gid){
return in_array($gid, $this->getUserGroups($uid));
}
/**
* @brief Get all groups a user belongs to
* @param $uid Name of the user
* @returns array with group names
*
* This function fetches all groups a user belongs to. It does not check
* if the user exists at all.
*/
public static function getUserGroups($uid){
return array();
}
/**
* @brief get a list of all groups
* @returns array with group names
*
* Returns a list with all groups
*/
public static function getGroups(){
return array();
}
/**
* check if a group exists
* @param string $gid
* @return bool
*/
public function groupExists($gid){
if(!$this->implementsActions(OC_GROUP_BACKEND_GET_GROUPS)){
return false;
}
return in_array($gid, $this->getGroups());
}
/**
* @brief get a list of all users in a group
* @returns array with user ids
*/
public static function usersInGroup($gid){
return array();
}
}

View File

@ -93,6 +93,13 @@ abstract class OC_Group_Example {
*/
public static function getGroups(){}
/**
* check if a group exists
* @param string $gid
* @return bool
*/
public function groupExists($gid){}
/**
* @brief get a list of all users in a group
* @returns array with user ids

View File

@ -131,8 +131,8 @@ class OC_Helper {
*
* Returns a absolute url to the given service.
*/
public static function linkToRemote( $service ) {
return self::linkToAbsolute( '', 'remote.php') . '/' . $service . '/';
public static function linkToRemote( $service, $add_slash = true ) {
return self::linkToAbsolute( '', 'remote.php') . '/' . $service . ($add_slash?'/':'');
}
/**

40
lib/minimizer.php Normal file
View File

@ -0,0 +1,40 @@
<?php
abstract class OC_Minimizer
{
protected $files = array();
protected function appendIfExist($root, $webroot, $file) {
if (is_file($root.'/'.$file)) {
$this->files[] = array($root, $webroot, $file);
return true;
}
return false;
}
public function getLastModified($files) {
$last_modified = 0;
foreach($files as $file_info) {
$file = $file_info[0] . '/' . $file_info[2];
$filemtime = filemtime($file);
if ($filemtime > $last_modified) {
$last_modified = $filemtime;
}
}
return $last_modified;
}
abstract public function minimizeFiles($files);
public function output($files) {
header('Content-Type: '.$this->contentType);
OC_Response::enableCaching();
$last_modified = $this->getLastModified($files);
OC_Response::setLastModifiedHeader($last_modified);
$out = $this->minimizeFiles($files);
OC_Response::setETagHeader(md5($out));
header('Content-Length: '.strlen($out));
echo $out;
}
}

73
lib/minimizer/css.php Normal file
View File

@ -0,0 +1,73 @@
<?php
require_once('mediawiki/CSSMin.php');
class OC_Minimizer_CSS extends OC_Minimizer
{
protected $contentType = 'text/css';
public function findFiles($styles) {
// Read the selected theme from the config file
$theme=OC_Config::getValue( "theme" );
// Read the detected formfactor and use the right file name.
$fext = OC_Template::getFormFactorExtension();
foreach($styles as $style){
// is it in 3rdparty?
if($this->appendIfExist(OC::$THIRDPARTYROOT, OC::$THIRDPARTYWEBROOT, $style.'.css')) {
// or in apps?
}elseif($this->appendIfExist(OC::$APPSROOT, OC::$APPSWEBROOT, "apps/$style$fext.css" )) {
}elseif($this->appendIfExist(OC::$APPSROOT, OC::$APPSWEBROOT, "apps/$style.css" )) {
// or in the owncloud root?
}elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "$style$fext.css" )) {
}elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "$style.css" )) {
// or in core ?
}elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "core/$style$fext.css" )) {
}elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "core/$style.css" )) {
}else{
echo('css file not found: style:'.$style.' formfactor:'.$fext.' webroot:'.OC::$WEBROOT.' serverroot:'.OC::$SERVERROOT);
die();
}
}
// Add the theme css files. you can override the default values here
if(!empty($theme)) {
foreach($styles as $style){
if($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/apps/$style$fext.css" )) {
}elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/apps/$style.css" )) {
}elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/$style$fext.css" )) {
}elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/$style.css" )) {
}elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/core/$style$fext.css" )) {
}elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/core/$style.css" )) {
}
}
}
return $this->files;
}
public function minimizeFiles($files) {
$css_out = '';
$appswebroot = (string) OC::$APPSWEBROOT;
$webroot = (string) OC::$WEBROOT;
foreach($files as $file_info) {
$file = $file_info[0] . '/' . $file_info[2];
$css_out .= '/* ' . $file . ' */' . "\n";
$css = file_get_contents($file);
if (strpos($file, OC::$APPSROOT) == 0) {
$css = str_replace('%appswebroot%', $appswebroot, $css);
$css = str_replace('%webroot%', $webroot, $css);
}
$remote = $file_info[1];
$remote .= '../';
$remote .= dirname($file_info[2]);
$css_out .= CSSMin::remap($css, dirname($file), $remote, true);
}
$css_out = CSSMin::minify($css_out);
return $css_out;
}
}

62
lib/minimizer/js.php Normal file
View File

@ -0,0 +1,62 @@
<?php
require_once('mediawiki/JavaScriptMinifier.php');
class OC_Minimizer_JS extends OC_Minimizer
{
protected $contentType = 'application/javascript';
public function findFiles($scripts) {
// Read the selected theme from the config file
$theme=OC_Config::getValue( "theme" );
// Read the detected formfactor and use the right file name.
$fext = OC_Template::getFormFactorExtension();
// Add the core js files or the js files provided by the selected theme
foreach($scripts as $script){
// Is it in 3rd party?
if($this->appendIfExist(OC::$THIRDPARTYROOT, OC::$THIRDPARTYWEBROOT, $script.'.js')) {
// Is it in apps and overwritten by the theme?
}elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/apps/$script$fext.js" )) {
}elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/apps/$script.js" )) {
// Is it part of an app?
}elseif($this->appendIfExist(OC::$APPSROOT, OC::$APPSWEBROOT, "apps/$script$fext.js" )) {
}elseif($this->appendIfExist(OC::$APPSROOT, OC::$APPSWEBROOT, "apps/$script.js" )) {
// Is it in the owncloud root but overwritten by the theme?
}elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/$script$fext.js" )) {
}elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/$script.js" )) {
// Is it in the owncloud root ?
}elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "$script$fext.js" )) {
}elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "$script.js" )) {
// Is in core but overwritten by a theme?
}elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/core/$script$fext.js" )) {
}elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/core/$script.js" )) {
// Is it in core?
}elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "core/$script$fext.js" )) {
}elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "core/$script.js" )) {
}else{
echo('js file not found: script:'.$script.' formfactor:'.$fext.' webroot:'.OC::$WEBROOT.' serverroot:'.OC::$SERVERROOT);
die();
}
}
return $this->files;
}
public function minimizeFiles($files) {
$js_out = '';
foreach($files as $file_info) {
$file = $file_info[0] . '/' . $file_info[2];
$js_out .= '/* ' . $file . ' */' . "\n";
$js_out .= file_get_contents($file);
}
$js_out = JavaScriptMinifier::minify($js_out);
return $js_out;
}
}

View File

@ -166,7 +166,7 @@ class OC_Template{
/**
* @brief Returns the formfactor extension for current formfactor
*/
protected function getFormFactorExtension()
static public function getFormFactorExtension()
{
$formfactor=$_SESSION['formfactor'];
if($formfactor=='default') {
@ -196,7 +196,7 @@ class OC_Template{
$theme=OC_Config::getValue( "theme" );
// Read the detected formfactor and use the right file name.
$fext = $this->getFormFactorExtension();
$fext = self::getFormFactorExtension();
$app = $this->application;
// Check if it is a app template or not.
@ -379,8 +379,9 @@ class OC_Template{
$theme=OC_Config::getValue( "theme" );
// Read the detected formfactor and use the right file name.
$fext = $this->getFormFactorExtension();
$fext = self::getFormFactorExtension();
$page->assign('jsfiles', array());
// Add the core js files or the js files provided by the selected theme
foreach(OC_Util::$scripts as $script){
// Is it in 3rd party?
@ -417,6 +418,7 @@ class OC_Template{
}
}
// Add the css files
$page->assign('cssfiles', array());
foreach(OC_Util::$styles as $style){
// is it in 3rdparty?
if($page->appendIfExist('cssfiles', OC::$THIRDPARTYROOT, OC::$THIRDPARTYWEBROOT, $style.'.css')) {
@ -434,7 +436,7 @@ class OC_Template{
}elseif($page->appendIfExist('cssfiles', OC::$SERVERROOT, OC::$WEBROOT, "core/$style.css" )) {
}else{
echo('css file not found: style:'.$script.' formfactor:'.$fext.' webroot:'.OC::$WEBROOT.' serverroot:'.OC::$SERVERROOT);
echo('css file not found: style:'.$style.' formfactor:'.$fext.' webroot:'.OC::$WEBROOT.' serverroot:'.OC::$SERVERROOT);
die();
}
}

View File

@ -129,7 +129,7 @@ class OC_User {
if(trim($password) == ''){
throw new Exception('A valid password must be provided');
}
// Check if user already exists
if( self::userExists($uid) ){
throw new Exception('The username is already being used');
@ -168,9 +168,7 @@ class OC_User {
if( $run ){
//delete the user from all backends
foreach(self::$_usedBackends as $backend){
if($backend->implementsActions(OC_USER_BACKEND_DELETE_USER)){
$backend->deleteUser($uid);
}
$backend->deleteUser($uid);
}
// We have to delete the user from all groups
foreach( OC_Group::getUserGroups( $uid ) as $i ){
@ -242,12 +240,13 @@ class OC_User {
* Checks if the user is logged in
*/
public static function isLoggedIn(){
if( isset($_SESSION['user_id']) AND $_SESSION['user_id'] AND self::userExists($_SESSION['user_id']) ){
return true;
}
else{
return false;
if( isset($_SESSION['user_id']) AND $_SESSION['user_id']) {
OC_App::loadApps(array('authentication'));
if (self::userExists($_SESSION['user_id']) ){
return true;
}
}
return false;
}
/**
@ -331,11 +330,9 @@ class OC_User {
public static function getUsers(){
$users=array();
foreach(self::$_usedBackends as $backend){
if($backend->implementsActions(OC_USER_BACKEND_GET_USERS)){
$backendUsers=$backend->getUsers();
if(is_array($backendUsers)){
$users=array_merge($users,$backendUsers);
}
$backendUsers=$backend->getUsers();
if(is_array($backendUsers)){
$users=array_merge($users,$backendUsers);
}
}
asort($users);
@ -349,11 +346,9 @@ class OC_User {
*/
public static function userExists($uid){
foreach(self::$_usedBackends as $backend){
if($backend->implementsActions(OC_USER_BACKEND_USER_EXISTS)){
$result=$backend->userExists($uid);
if($result===true){
return true;
}
$result=$backend->userExists($uid);
if($result===true){
return true;
}
}
return false;

View File

@ -32,11 +32,8 @@ define('OC_USER_BACKEND_NOT_IMPLEMENTED', -501);
* actions that user backends can define
*/
define('OC_USER_BACKEND_CREATE_USER', 0x000001);
define('OC_USER_BACKEND_DELETE_USER', 0x000010);
define('OC_USER_BACKEND_SET_PASSWORD', 0x000100);
define('OC_USER_BACKEND_CHECK_PASSWORD', 0x001000);
define('OC_USER_BACKEND_GET_USERS', 0x010000);
define('OC_USER_BACKEND_USER_EXISTS', 0x100000);
define('OC_USER_BACKEND_SET_PASSWORD', 0x000010);
define('OC_USER_BACKEND_CHECK_PASSWORD', 0x000100);
/**
@ -49,11 +46,8 @@ abstract class OC_User_Backend {
protected $possibleActions = array(
OC_USER_BACKEND_CREATE_USER => 'createUser',
OC_USER_BACKEND_DELETE_USER => 'deleteUser',
OC_USER_BACKEND_SET_PASSWORD => 'setPassword',
OC_USER_BACKEND_CHECK_PASSWORD => 'checkPassword',
OC_USER_BACKEND_GET_USERS => 'getUsers',
OC_USER_BACKEND_USER_EXISTS => 'userExists'
);
/**
@ -85,4 +79,34 @@ abstract class OC_User_Backend {
public function implementsActions($actions){
return (bool)($this->getSupportedActions() & $actions);
}
/**
* @brief delete a user
* @param $uid The username of the user to delete
* @returns true/false
*
* Deletes a user
*/
public function deleteUser( $uid ){
return false;
}
/**
* @brief Get a list of all users
* @returns array with all uids
*
* Get a list of all users.
*/
public function getUsers(){
return array();
}
/**
* @brief check if a user exists
* @param string $uid the username
* @return boolean
*/
public function userExists($uid){
return false;
}
}

View File

@ -39,17 +39,6 @@ abstract class OC_User_Example extends OC_User_Backend {
return OC_USER_BACKEND_NOT_IMPLEMENTED;
}
/**
* @brief delete a user
* @param $uid The username of the user to delete
* @returns true/false
*
* Deletes a user
*/
public function deleteUser( $uid ){
return OC_USER_BACKEND_NOT_IMPLEMENTED;
}
/**
* @brief Set password
* @param $uid The username
@ -74,23 +63,4 @@ abstract class OC_User_Example extends OC_User_Backend {
public function checkPassword($uid, $password){
return OC_USER_BACKEND_NOT_IMPLEMENTED;
}
/**
* @brief Get a list of all users
* @returns array with all uids
*
* Get a list of all users.
*/
public function getUsers(){
return OC_USER_BACKEND_NOT_IMPLEMENTED;
}
/**
* @brief check if a user exists
* @param string $uid the username
* @return boolean
*/
public function userExists($uid){
return OC_USER_BACKEND_NOT_IMPLEMENTED;
}
}

View File

@ -10,6 +10,8 @@ class OC_Util {
public static $headers=array();
private static $rootMounted=false;
private static $fsSetup=false;
public static $core_styles=array();
public static $core_scripts=array();
// Can be set up
public static function setupFS( $user = "", $root = "files" ){// configure the initial filesystem based on the configuration
@ -39,7 +41,7 @@ class OC_Util {
// Create root dir.
if(!is_dir($CONFIG_DATADIRECTORY_ROOT)){
$success=@mkdir($CONFIG_DATADIRECTORY_ROOT);
if(!$success) {
if(!$success) {
$tmpl = new OC_Template( '', 'error', 'guest' );
$tmpl->assign('errors',array(1=>array('error'=>"Can't create data directory (".$CONFIG_DATADIRECTORY_ROOT.")",'hint'=>"You can usually fix this by giving the webserver write access to the ownCloud directory '".OC::$SERVERROOT."' (in a terminal, use the command 'chown -R www-data:www-data /path/to/your/owncloud/install/data' ")));
$tmpl->printPage();
@ -58,7 +60,6 @@ class OC_Util {
self::$rootMounted=true;
}
if( $user != "" ){ //if we aren't logged in, there is no use to set up the filesystem
OC::$CONFIG_DATADIRECTORY = $CONFIG_DATADIRECTORY_ROOT."/$user/$root";
if( !is_dir( OC::$CONFIG_DATADIRECTORY )){
mkdir( OC::$CONFIG_DATADIRECTORY, 0755, true );

View File

@ -11,7 +11,7 @@ if (!$pos = strpos($path_info, '/', 1)) {
$pos = strlen($path_info);
}
$service=substr($path_info, 1, $pos-1);
$file = OCP\CONFIG::getAppValue('core', 'remote_' . $service);
$file = OC_AppConfig::getValue('core', 'remote_' . $service);
if(is_null($file)){
header('HTTP/1.0 404 Not Found');
exit;

View File

@ -8,12 +8,12 @@ OC_JSON::checkLoggedIn();
$l=OC_L10N::get('core');
// Get data
if( isset( $_POST['email'] ) ){
if( isset( $_POST['email'] ) && filter_var( $_POST['email'], FILTER_VALIDATE_EMAIL) ){
$email=trim($_POST['email']);
OC_Preferences::setValue(OC_User::getUser(),'settings','email',$email);
OC_JSON::success(array("data" => array( "message" => $l->t("email Changed") )));
OC_JSON::success(array("data" => array( "message" => $l->t("Email saved") )));
}else{
OC_JSON::error(array("data" => array( "message" => $l->t("Invalid request") )));
OC_JSON::error(array("data" => array( "message" => $l->t("Invalid email") )));
}
?>

View File

@ -34,6 +34,8 @@ $(document).ready(function(){
if ( app.internal == false ) {
$('#rightcontent p.appslink').show();
$('#rightcontent a').attr('href','http://apps.owncloud.com/content/show.php?content='+app.id);
} else {
$('#rightcontent p.appslink').hide();
}
return false;
});