mirror of
https://github.com/nextcloud/server.git
synced 2026-04-20 22:00:39 -04:00
fix merge conflicts
This commit is contained in:
commit
f2dcab50b5
128 changed files with 4072 additions and 931 deletions
2
3rdparty/MDB2/Driver/mysql.php
vendored
2
3rdparty/MDB2/Driver/mysql.php
vendored
|
|
@ -794,7 +794,7 @@ class MDB2_Driver_mysql extends MDB2_Driver_Common
|
|||
? 'mysql_query' : 'mysql_unbuffered_query';
|
||||
$result = @$function($query, $connection);
|
||||
if (!$result) {
|
||||
$err =& $this->raiseError(null, null, null,
|
||||
$err =$this->raiseError(null, null, null,
|
||||
'Could not execute statement', __FUNCTION__);
|
||||
return $err;
|
||||
}
|
||||
|
|
|
|||
253
3rdparty/phpass/PasswordHash.php
vendored
Normal file
253
3rdparty/phpass/PasswordHash.php
vendored
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
<?php
|
||||
#
|
||||
# Portable PHP password hashing framework.
|
||||
#
|
||||
# Version 0.3 / genuine.
|
||||
#
|
||||
# Written by Solar Designer <solar at openwall.com> in 2004-2006 and placed in
|
||||
# the public domain. Revised in subsequent years, still public domain.
|
||||
#
|
||||
# There's absolutely no warranty.
|
||||
#
|
||||
# The homepage URL for this framework is:
|
||||
#
|
||||
# http://www.openwall.com/phpass/
|
||||
#
|
||||
# Please be sure to update the Version line if you edit this file in any way.
|
||||
# It is suggested that you leave the main version number intact, but indicate
|
||||
# your project name (after the slash) and add your own revision information.
|
||||
#
|
||||
# Please do not change the "private" password hashing method implemented in
|
||||
# here, thereby making your hashes incompatible. However, if you must, please
|
||||
# change the hash type identifier (the "$P$") to something different.
|
||||
#
|
||||
# Obviously, since this code is in the public domain, the above are not
|
||||
# requirements (there can be none), but merely suggestions.
|
||||
#
|
||||
class PasswordHash {
|
||||
var $itoa64;
|
||||
var $iteration_count_log2;
|
||||
var $portable_hashes;
|
||||
var $random_state;
|
||||
|
||||
function PasswordHash($iteration_count_log2, $portable_hashes)
|
||||
{
|
||||
$this->itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
|
||||
|
||||
if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31)
|
||||
$iteration_count_log2 = 8;
|
||||
$this->iteration_count_log2 = $iteration_count_log2;
|
||||
|
||||
$this->portable_hashes = $portable_hashes;
|
||||
|
||||
$this->random_state = microtime();
|
||||
if (function_exists('getmypid'))
|
||||
$this->random_state .= getmypid();
|
||||
}
|
||||
|
||||
function get_random_bytes($count)
|
||||
{
|
||||
$output = '';
|
||||
if (is_readable('/dev/urandom') &&
|
||||
($fh = @fopen('/dev/urandom', 'rb'))) {
|
||||
$output = fread($fh, $count);
|
||||
fclose($fh);
|
||||
}
|
||||
|
||||
if (strlen($output) < $count) {
|
||||
$output = '';
|
||||
for ($i = 0; $i < $count; $i += 16) {
|
||||
$this->random_state =
|
||||
md5(microtime() . $this->random_state);
|
||||
$output .=
|
||||
pack('H*', md5($this->random_state));
|
||||
}
|
||||
$output = substr($output, 0, $count);
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
function encode64($input, $count)
|
||||
{
|
||||
$output = '';
|
||||
$i = 0;
|
||||
do {
|
||||
$value = ord($input[$i++]);
|
||||
$output .= $this->itoa64[$value & 0x3f];
|
||||
if ($i < $count)
|
||||
$value |= ord($input[$i]) << 8;
|
||||
$output .= $this->itoa64[($value >> 6) & 0x3f];
|
||||
if ($i++ >= $count)
|
||||
break;
|
||||
if ($i < $count)
|
||||
$value |= ord($input[$i]) << 16;
|
||||
$output .= $this->itoa64[($value >> 12) & 0x3f];
|
||||
if ($i++ >= $count)
|
||||
break;
|
||||
$output .= $this->itoa64[($value >> 18) & 0x3f];
|
||||
} while ($i < $count);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
function gensalt_private($input)
|
||||
{
|
||||
$output = '$P$';
|
||||
$output .= $this->itoa64[min($this->iteration_count_log2 +
|
||||
((PHP_VERSION >= '5') ? 5 : 3), 30)];
|
||||
$output .= $this->encode64($input, 6);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
function crypt_private($password, $setting)
|
||||
{
|
||||
$output = '*0';
|
||||
if (substr($setting, 0, 2) == $output)
|
||||
$output = '*1';
|
||||
|
||||
$id = substr($setting, 0, 3);
|
||||
# We use "$P$", phpBB3 uses "$H$" for the same thing
|
||||
if ($id != '$P$' && $id != '$H$')
|
||||
return $output;
|
||||
|
||||
$count_log2 = strpos($this->itoa64, $setting[3]);
|
||||
if ($count_log2 < 7 || $count_log2 > 30)
|
||||
return $output;
|
||||
|
||||
$count = 1 << $count_log2;
|
||||
|
||||
$salt = substr($setting, 4, 8);
|
||||
if (strlen($salt) != 8)
|
||||
return $output;
|
||||
|
||||
# We're kind of forced to use MD5 here since it's the only
|
||||
# cryptographic primitive available in all versions of PHP
|
||||
# currently in use. To implement our own low-level crypto
|
||||
# in PHP would result in much worse performance and
|
||||
# consequently in lower iteration counts and hashes that are
|
||||
# quicker to crack (by non-PHP code).
|
||||
if (PHP_VERSION >= '5') {
|
||||
$hash = md5($salt . $password, TRUE);
|
||||
do {
|
||||
$hash = md5($hash . $password, TRUE);
|
||||
} while (--$count);
|
||||
} else {
|
||||
$hash = pack('H*', md5($salt . $password));
|
||||
do {
|
||||
$hash = pack('H*', md5($hash . $password));
|
||||
} while (--$count);
|
||||
}
|
||||
|
||||
$output = substr($setting, 0, 12);
|
||||
$output .= $this->encode64($hash, 16);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
function gensalt_extended($input)
|
||||
{
|
||||
$count_log2 = min($this->iteration_count_log2 + 8, 24);
|
||||
# This should be odd to not reveal weak DES keys, and the
|
||||
# maximum valid value is (2**24 - 1) which is odd anyway.
|
||||
$count = (1 << $count_log2) - 1;
|
||||
|
||||
$output = '_';
|
||||
$output .= $this->itoa64[$count & 0x3f];
|
||||
$output .= $this->itoa64[($count >> 6) & 0x3f];
|
||||
$output .= $this->itoa64[($count >> 12) & 0x3f];
|
||||
$output .= $this->itoa64[($count >> 18) & 0x3f];
|
||||
|
||||
$output .= $this->encode64($input, 3);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
function gensalt_blowfish($input)
|
||||
{
|
||||
# This one needs to use a different order of characters and a
|
||||
# different encoding scheme from the one in encode64() above.
|
||||
# We care because the last character in our encoded string will
|
||||
# only represent 2 bits. While two known implementations of
|
||||
# bcrypt will happily accept and correct a salt string which
|
||||
# has the 4 unused bits set to non-zero, we do not want to take
|
||||
# chances and we also do not want to waste an additional byte
|
||||
# of entropy.
|
||||
$itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
|
||||
$output = '$2a$';
|
||||
$output .= chr(ord('0') + $this->iteration_count_log2 / 10);
|
||||
$output .= chr(ord('0') + $this->iteration_count_log2 % 10);
|
||||
$output .= '$';
|
||||
|
||||
$i = 0;
|
||||
do {
|
||||
$c1 = ord($input[$i++]);
|
||||
$output .= $itoa64[$c1 >> 2];
|
||||
$c1 = ($c1 & 0x03) << 4;
|
||||
if ($i >= 16) {
|
||||
$output .= $itoa64[$c1];
|
||||
break;
|
||||
}
|
||||
|
||||
$c2 = ord($input[$i++]);
|
||||
$c1 |= $c2 >> 4;
|
||||
$output .= $itoa64[$c1];
|
||||
$c1 = ($c2 & 0x0f) << 2;
|
||||
|
||||
$c2 = ord($input[$i++]);
|
||||
$c1 |= $c2 >> 6;
|
||||
$output .= $itoa64[$c1];
|
||||
$output .= $itoa64[$c2 & 0x3f];
|
||||
} while (1);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
function HashPassword($password)
|
||||
{
|
||||
$random = '';
|
||||
|
||||
if (CRYPT_BLOWFISH == 1 && !$this->portable_hashes) {
|
||||
$random = $this->get_random_bytes(16);
|
||||
$hash =
|
||||
crypt($password, $this->gensalt_blowfish($random));
|
||||
if (strlen($hash) == 60)
|
||||
return $hash;
|
||||
}
|
||||
|
||||
if (CRYPT_EXT_DES == 1 && !$this->portable_hashes) {
|
||||
if (strlen($random) < 3)
|
||||
$random = $this->get_random_bytes(3);
|
||||
$hash =
|
||||
crypt($password, $this->gensalt_extended($random));
|
||||
if (strlen($hash) == 20)
|
||||
return $hash;
|
||||
}
|
||||
|
||||
if (strlen($random) < 6)
|
||||
$random = $this->get_random_bytes(6);
|
||||
$hash =
|
||||
$this->crypt_private($password,
|
||||
$this->gensalt_private($random));
|
||||
if (strlen($hash) == 34)
|
||||
return $hash;
|
||||
|
||||
# Returning '*' on error is safe here, but would _not_ be safe
|
||||
# in a crypt(3)-like function used _both_ for generating new
|
||||
# hashes and for validating passwords against existing hashes.
|
||||
return '*';
|
||||
}
|
||||
|
||||
function CheckPassword($password, $stored_hash)
|
||||
{
|
||||
$hash = $this->crypt_private($password, $stored_hash);
|
||||
if ($hash[0] == '*')
|
||||
$hash = crypt($password, $stored_hash);
|
||||
|
||||
return $hash == $stored_hash;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
21
3rdparty/phpass/c/Makefile
vendored
Normal file
21
3rdparty/phpass/c/Makefile
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#
|
||||
# Written by Solar Designer and placed in the public domain.
|
||||
# See crypt_private.c for more information.
|
||||
#
|
||||
CC = gcc
|
||||
LD = $(CC)
|
||||
RM = rm -f
|
||||
CFLAGS = -Wall -O2 -fomit-frame-pointer -funroll-loops
|
||||
LDFLAGS = -s
|
||||
LIBS = -lcrypto
|
||||
|
||||
all: crypt_private-test
|
||||
|
||||
crypt_private-test: crypt_private-test.o
|
||||
$(LD) $(LDFLAGS) $(LIBS) crypt_private-test.o -o $@
|
||||
|
||||
crypt_private-test.o: crypt_private.c
|
||||
$(CC) -c $(CFLAGS) crypt_private.c -DTEST -o $@
|
||||
|
||||
clean:
|
||||
$(RM) crypt_private-test*
|
||||
106
3rdparty/phpass/c/crypt_private.c
vendored
Normal file
106
3rdparty/phpass/c/crypt_private.c
vendored
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* This code exists for the sole purpose to serve as another implementation
|
||||
* of the "private" password hashing method implemened in PasswordHash.php
|
||||
* and thus to confirm that these password hashes are indeed calculated as
|
||||
* intended.
|
||||
*
|
||||
* Other uses of this code are discouraged. There are much better password
|
||||
* hashing algorithms available to C programmers; one of those is bcrypt:
|
||||
*
|
||||
* http://www.openwall.com/crypt/
|
||||
*
|
||||
* Written by Solar Designer <solar at openwall.com> in 2005 and placed in
|
||||
* the public domain.
|
||||
*
|
||||
* There's absolutely no warranty.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/md5.h>
|
||||
|
||||
#ifdef TEST
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
static char *itoa64 =
|
||||
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
static void encode64(char *dst, char *src, int count)
|
||||
{
|
||||
int i, value;
|
||||
|
||||
i = 0;
|
||||
do {
|
||||
value = (unsigned char)src[i++];
|
||||
*dst++ = itoa64[value & 0x3f];
|
||||
if (i < count)
|
||||
value |= (unsigned char)src[i] << 8;
|
||||
*dst++ = itoa64[(value >> 6) & 0x3f];
|
||||
if (i++ >= count)
|
||||
break;
|
||||
if (i < count)
|
||||
value |= (unsigned char)src[i] << 16;
|
||||
*dst++ = itoa64[(value >> 12) & 0x3f];
|
||||
if (i++ >= count)
|
||||
break;
|
||||
*dst++ = itoa64[(value >> 18) & 0x3f];
|
||||
} while (i < count);
|
||||
}
|
||||
|
||||
char *crypt_private(char *password, char *setting)
|
||||
{
|
||||
static char output[35];
|
||||
MD5_CTX ctx;
|
||||
char hash[MD5_DIGEST_LENGTH];
|
||||
char *p, *salt;
|
||||
int count_log2, length, count;
|
||||
|
||||
strcpy(output, "*0");
|
||||
if (!strncmp(setting, output, 2))
|
||||
output[1] = '1';
|
||||
|
||||
if (strncmp(setting, "$P$", 3))
|
||||
return output;
|
||||
|
||||
p = strchr(itoa64, setting[3]);
|
||||
if (!p)
|
||||
return output;
|
||||
count_log2 = p - itoa64;
|
||||
if (count_log2 < 7 || count_log2 > 30)
|
||||
return output;
|
||||
|
||||
salt = setting + 4;
|
||||
if (strlen(salt) < 8)
|
||||
return output;
|
||||
|
||||
length = strlen(password);
|
||||
|
||||
MD5_Init(&ctx);
|
||||
MD5_Update(&ctx, salt, 8);
|
||||
MD5_Update(&ctx, password, length);
|
||||
MD5_Final(hash, &ctx);
|
||||
|
||||
count = 1 << count_log2;
|
||||
do {
|
||||
MD5_Init(&ctx);
|
||||
MD5_Update(&ctx, hash, MD5_DIGEST_LENGTH);
|
||||
MD5_Update(&ctx, password, length);
|
||||
MD5_Final(hash, &ctx);
|
||||
} while (--count);
|
||||
|
||||
memcpy(output, setting, 12);
|
||||
encode64(&output[12], hash, MD5_DIGEST_LENGTH);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 3) return 1;
|
||||
|
||||
puts(crypt_private(argv[1], argv[2]));
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
72
3rdparty/phpass/test.php
vendored
Normal file
72
3rdparty/phpass/test.php
vendored
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
#
|
||||
# This is a test program for the portable PHP password hashing framework.
|
||||
#
|
||||
# Written by Solar Designer and placed in the public domain.
|
||||
# See PasswordHash.php for more information.
|
||||
#
|
||||
|
||||
require 'PasswordHash.php';
|
||||
|
||||
header('Content-type: text/plain');
|
||||
|
||||
$ok = 0;
|
||||
|
||||
# Try to use stronger but system-specific hashes, with a possible fallback to
|
||||
# the weaker portable hashes.
|
||||
$t_hasher = new PasswordHash(8, FALSE);
|
||||
|
||||
$correct = 'test12345';
|
||||
$hash = $t_hasher->HashPassword($correct);
|
||||
|
||||
print 'Hash: ' . $hash . "\n";
|
||||
|
||||
$check = $t_hasher->CheckPassword($correct, $hash);
|
||||
if ($check) $ok++;
|
||||
print "Check correct: '" . $check . "' (should be '1')\n";
|
||||
|
||||
$wrong = 'test12346';
|
||||
$check = $t_hasher->CheckPassword($wrong, $hash);
|
||||
if (!$check) $ok++;
|
||||
print "Check wrong: '" . $check . "' (should be '0' or '')\n";
|
||||
|
||||
unset($t_hasher);
|
||||
|
||||
# Force the use of weaker portable hashes.
|
||||
$t_hasher = new PasswordHash(8, TRUE);
|
||||
|
||||
$hash = $t_hasher->HashPassword($correct);
|
||||
|
||||
print 'Hash: ' . $hash . "\n";
|
||||
|
||||
$check = $t_hasher->CheckPassword($correct, $hash);
|
||||
if ($check) $ok++;
|
||||
print "Check correct: '" . $check . "' (should be '1')\n";
|
||||
|
||||
$check = $t_hasher->CheckPassword($wrong, $hash);
|
||||
if (!$check) $ok++;
|
||||
print "Check wrong: '" . $check . "' (should be '0' or '')\n";
|
||||
|
||||
# A correct portable hash for 'test12345'.
|
||||
# Please note the use of single quotes to ensure that the dollar signs will
|
||||
# be interpreted literally. Of course, a real application making use of the
|
||||
# framework won't store password hashes within a PHP source file anyway.
|
||||
# We only do this for testing.
|
||||
$hash = '$P$9IQRaTwmfeRo7ud9Fh4E2PdI0S3r.L0';
|
||||
|
||||
print 'Hash: ' . $hash . "\n";
|
||||
|
||||
$check = $t_hasher->CheckPassword($correct, $hash);
|
||||
if ($check) $ok++;
|
||||
print "Check correct: '" . $check . "' (should be '1')\n";
|
||||
|
||||
$check = $t_hasher->CheckPassword($wrong, $hash);
|
||||
if (!$check) $ok++;
|
||||
print "Check wrong: '" . $check . "' (should be '0' or '')\n";
|
||||
|
||||
if ($ok == 6)
|
||||
print "All tests have PASSED\n";
|
||||
else
|
||||
print "Some tests have FAILED\n";
|
||||
|
||||
?>
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
*/
|
||||
|
||||
OC::$CLASSPATH['OC_Bookmarks_Bookmarks'] = 'apps/bookmarks/lib/bookmarks.php';
|
||||
OC::$CLASSPATH['OC_Search_Provider_Bookmarks'] = 'apps/bookmarks/lib/search.php';
|
||||
|
||||
OC_App::register( array( 'order' => 70, 'id' => 'bookmark', 'name' => 'Bookmarks' ));
|
||||
|
||||
|
|
@ -15,5 +16,5 @@ $l = new OC_l10n('bookmarks');
|
|||
OC_App::addNavigationEntry( array( 'id' => 'bookmarks_index', 'order' => 70, 'href' => OC_Helper::linkTo( 'bookmarks', 'index.php' ), 'icon' => OC_Helper::imagePath( 'bookmarks', 'bookmarks.png' ), 'name' => $l->t('Bookmarks')));
|
||||
|
||||
OC_App::registerPersonal('bookmarks', 'settings');
|
||||
require_once('apps/bookmarks/lib/search.php');
|
||||
OC_Util::addScript('bookmarks','bookmarksearch');
|
||||
OC_Search::registerProvider('OC_Search_Provider_Bookmarks');
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@
|
|||
}
|
||||
|
||||
.bookmarks_list {
|
||||
margin-top: 36px;
|
||||
overflow: auto;
|
||||
position: fixed;
|
||||
top: 6.5em;
|
||||
}
|
||||
|
||||
.bookmarks_addBml {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,11 @@ var bookmarks_sorting = 'bookmarks_sorting_recent';
|
|||
|
||||
$(document).ready(function() {
|
||||
$('#bookmark_add_submit').click(addOrEditBookmark);
|
||||
$(window).scroll(updateOnBottom);
|
||||
$(window).resize(function () {
|
||||
fillWindow($('.bookmarks_list'));
|
||||
});
|
||||
$(window).resize();
|
||||
$($('.bookmarks_list')).scroll(updateOnBottom);
|
||||
|
||||
$('.bookmarks_list').empty();
|
||||
getBookmarks();
|
||||
|
|
@ -21,7 +25,9 @@ function getBookmarks() {
|
|||
url: 'ajax/updateList.php',
|
||||
data: 'tag=' + encodeURI($('#bookmarkFilterTag').val()) + '&page=' + bookmarks_page + '&sort=' + bookmarks_sorting,
|
||||
success: function(bookmarks){
|
||||
bookmarks_page += 1;
|
||||
if (bookmarks.data.length) {
|
||||
bookmarks_page += 1;
|
||||
}
|
||||
$('.bookmark_link').unbind('click', recordClick);
|
||||
$('.bookmark_delete').unbind('click', delBookmark);
|
||||
$('.bookmark_edit').unbind('click', showBookmark);
|
||||
|
|
@ -39,6 +45,9 @@ function getBookmarks() {
|
|||
$('.bookmark_edit').click(showBookmark);
|
||||
|
||||
bookmarks_loading = false;
|
||||
if (bookmarks.data.length) {
|
||||
updateOnBottom()
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -146,7 +155,11 @@ function updateBookmarksList(bookmark) {
|
|||
|
||||
function updateOnBottom() {
|
||||
//check wether user is on bottom of the page
|
||||
if ($('body').height() <= ($(window).height() + $(window).scrollTop())) {
|
||||
var top = $('.bookmarks_list>:last-child').position().top;
|
||||
var height = $('.bookmarks_list').height();
|
||||
// use a bit of margin to begin loading before we are really at the
|
||||
// bottom
|
||||
if (top < height * 1.2) {
|
||||
getBookmarks();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
class OC_Search_Provider_Bookmarks extends OC_Search_Provider{
|
||||
function search($query){
|
||||
class OC_Search_Provider_Bookmarks implements OC_Search_Provider{
|
||||
static function search($query){
|
||||
$results=array();
|
||||
|
||||
$offset = 0;
|
||||
|
|
@ -45,6 +45,3 @@ class OC_Search_Provider_Bookmarks extends OC_Search_Provider{
|
|||
return $results;
|
||||
}
|
||||
}
|
||||
new OC_Search_Provider_Bookmarks();
|
||||
|
||||
?>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,6 @@
|
|||
function createBookmarklet() {
|
||||
$l = new OC_L10N('bookmarks');
|
||||
echo '<small>' . $l->t('Drag this to your browser bookmarks and click it, when you want to bookmark a webpage quickly:') . '</small>'
|
||||
. '<a class="button" href="javascript:(function(){var a=window,b=document,c=encodeURIComponent,d=a.open(\'' . OC_Helper::linkToAbsolute('bookmarks', 'addBm.php') . '?output=popup&url=\'+c(b.location),\'bkmk_popup\',\'left=\'+((a.screenX||a.screenLeft)+10)+\',top=\'+((a.screenY||a.screenTop)+10)+\',height=230px,width=230px,resizable=1,alwaysRaised=1\');a.setTimeout(function(){d.focus()},300);})();">'
|
||||
. '<a class="bookmarklet" href="javascript:(function(){var a=window,b=document,c=encodeURIComponent,d=a.open(\'' . OC_Helper::linkToAbsolute('bookmarks', 'addBm.php') . '?output=popup&url=\'+c(b.location),\'bkmk_popup\',\'left=\'+((a.screenX||a.screenLeft)+10)+\',top=\'+((a.screenY||a.screenTop)+10)+\',height=230px,width=230px,resizable=1,alwaysRaised=1\');a.setTimeout(function(){d.focus()},300);})();">'
|
||||
. $l->t('Read later') . '</a>';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,13 @@ require_once('../../../3rdparty/when/When.php');
|
|||
OC_JSON::checkLoggedIn();
|
||||
OC_JSON::checkAppEnabled('calendar');
|
||||
|
||||
$start = DateTime::createFromFormat('U', $_GET['start']);
|
||||
$end = DateTime::createFromFormat('U', $_GET['end']);
|
||||
if(version_compare(PHP_VERSION, '5.3.0', '>=')){
|
||||
$start = DateTime::createFromFormat('U', $_GET['start']);
|
||||
$end = DateTime::createFromFormat('U', $_GET['end']);
|
||||
}else{
|
||||
$start = new DateTime('@' . $_GET['start']);
|
||||
$end = new DateTime('@' . $_GET['end']);
|
||||
}
|
||||
|
||||
if($_GET['calendar_id'] == 'shared_rw' || $_GET['calendar_id'] == 'shared_r'){
|
||||
$calendars = OC_Calendar_Share::allSharedwithuser(OC_USER::getUser(), OC_Calendar_Share::CALENDAR, 1, ($_GET['calendar_id'] == 'shared_rw')?'rw':'r');
|
||||
|
|
@ -23,28 +28,33 @@ if($_GET['calendar_id'] == 'shared_rw' || $_GET['calendar_id'] == 'shared_r'){
|
|||
$events = array_merge($events, $calendarevents);
|
||||
}
|
||||
}else{
|
||||
$calendar = OC_Calendar_Calendar::find($_GET['calendar_id']);
|
||||
if($calendar['userid'] != OC_User::getUser()){
|
||||
OC_JSON::error();
|
||||
exit;
|
||||
$calendar_id = $_GET['calendar_id'];
|
||||
if (is_numeric($calendar_id)) {
|
||||
$calendar = OC_Calendar_App::getCalendar($calendar_id);
|
||||
OC_Response::enableCaching(0);
|
||||
OC_Response::setETagHeader($calendar['ctag']);
|
||||
$events = OC_Calendar_Object::allInPeriod($calendar_id, $start, $end);
|
||||
} else {
|
||||
$events = array();
|
||||
OC_Hook::emit('OC_Calendar', 'getEvents', array('calendar_id' => $calendar_id, 'events' => &$events));
|
||||
}
|
||||
$events = OC_Calendar_Object::allInPeriod($_GET['calendar_id'], $start, $end);
|
||||
OC_Response::enableCaching(0);
|
||||
OC_Response::setETagHeader($calendar['ctag']);
|
||||
}
|
||||
|
||||
$events = OC_Calendar_Object::allInPeriod($_GET['calendar_id'], $start, $end);
|
||||
$user_timezone = OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone', date_default_timezone_get());
|
||||
$return = array();
|
||||
foreach($events as $event){
|
||||
$object = OC_VObject::parse($event['calendardata']);
|
||||
$vevent = $object->VEVENT;
|
||||
if (isset($event['calendardata'])) {
|
||||
$object = OC_VObject::parse($event['calendardata']);
|
||||
$vevent = $object->VEVENT;
|
||||
} else {
|
||||
$vevent = $event['vevent'];
|
||||
}
|
||||
|
||||
$return_event = OC_Calendar_App::prepareForOutput($event, $vevent);
|
||||
|
||||
$dtstart = $vevent->DTSTART;
|
||||
$dtend = OC_Calendar_Object::getDTEndFromVEvent($vevent);
|
||||
$start_dt = $dtstart->getDateTime();
|
||||
$dtend = OC_Calendar_Object::getDTEndFromVEvent($vevent);
|
||||
$end_dt = $dtend->getDateTime();
|
||||
if ($dtstart->getDateType() == Sabre_VObject_Element_DateTime::DATE){
|
||||
$return_event['allDay'] = true;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ require_once('../../../../lib/base.php');
|
|||
OC_JSON::checkLoggedIn();
|
||||
OC_Util::checkAppEnabled('calendar');
|
||||
$nl = "\n";
|
||||
$progressfile = OC::$SERVERROOT . '/apps/calendar/import_tmp/' . md5(session_id()) . '.txt';
|
||||
$progressfile = OC::$APPSROOT . '/apps/calendar/import_tmp/' . md5(session_id()) . '.txt';
|
||||
if(is_writable('import_tmp/')){
|
||||
$progressfopen = fopen($progressfile, 'w');
|
||||
fwrite($progressfopen, '10');
|
||||
|
|
@ -117,4 +117,4 @@ sleep(3);
|
|||
if(is_writable('import_tmp/')){
|
||||
unlink($progressfile);
|
||||
}
|
||||
OC_JSON::success();
|
||||
OC_JSON::success();
|
||||
|
|
|
|||
12
apps/calendar/ajax/settings/getfirstday.php
Normal file
12
apps/calendar/ajax/settings/getfirstday.php
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Georg Ehrke <ownclouddev at georgswebsite dot de>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
require_once('../../../../lib/base.php');
|
||||
OC_JSON::checkLoggedIn();
|
||||
$firstday = OC_Preferences::getValue( OC_User::getUser(), 'calendar', 'firstday', 'mo');
|
||||
OC_JSON::encodedPrint(array('firstday' => $firstday));
|
||||
?>
|
||||
|
|
@ -5,44 +5,23 @@
|
|||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
function make_array_out_of_xml ($xml){
|
||||
$returnarray = array();
|
||||
$xml = (array)$xml ;
|
||||
foreach ($xml as $property => $value){
|
||||
$value = (array)$value;
|
||||
if(!isset($value[0])){
|
||||
$returnarray[$property] = make_array_out_of_xml($value);
|
||||
}else{
|
||||
$returnarray[$property] = trim($value[0]);
|
||||
}
|
||||
}
|
||||
return $returnarray;
|
||||
}
|
||||
require_once('../../../../lib/base.php');
|
||||
|
||||
OC_JSON::checkLoggedIn();
|
||||
OC_JSON::checkAppEnabled('calendar');
|
||||
$l = new OC_L10N('calendar');
|
||||
$lat = $_GET['lat'];
|
||||
$long = $_GET['long'];
|
||||
if(OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'position') == $lat . '-' . $long && OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone') != null){
|
||||
OC_JSON::success();
|
||||
exit;
|
||||
}
|
||||
OC_Preferences::setValue(OC_USER::getUser(), 'calendar', 'position', $lat . '-' . $long);
|
||||
$geolocation = file_get_contents('http://ws.geonames.org/timezone?lat=' . $lat . '&lng=' . $long);
|
||||
//Information are by Geonames (http://www.geonames.org) and licensed under the Creative Commons Attribution 3.0 License
|
||||
$geoxml = simplexml_load_string($geolocation);
|
||||
$geoarray = make_array_out_of_xml($geoxml);
|
||||
if($geoarray['timezone']['timezoneId'] == OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone')){
|
||||
OC_JSON::success();
|
||||
exit;
|
||||
}
|
||||
if(in_array($geoarray['timezone']['timezoneId'], DateTimeZone::listIdentifiers())){
|
||||
OC_Preferences::setValue(OC_USER::getUser(), 'calendar', 'timezone', $geoarray['timezone']['timezoneId']);
|
||||
$message = array('message'=> $l->t('New Timezone:') . $geoarray['timezone']['timezoneId']);
|
||||
OC_JSON::success($message);
|
||||
}else{
|
||||
OC_JSON::error();
|
||||
}
|
||||
|
||||
?>
|
||||
$l = new OC_L10N('calendar');
|
||||
|
||||
$lat = $_GET['lat'];
|
||||
$lng = $_GET['long'];
|
||||
|
||||
$timezone = OC_Geo::timezone($lat, $lng);
|
||||
|
||||
if($timezone == OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone')){
|
||||
OC_JSON::success();
|
||||
exit;
|
||||
}
|
||||
OC_Preferences::setValue(OC_USER::getUser(), 'calendar', 'timezone', $timezone);
|
||||
$message = array('message'=> $l->t('New Timezone:') . $timezone);
|
||||
OC_JSON::success($message);
|
||||
?>
|
||||
17
apps/calendar/ajax/settings/setfirstday.php
Normal file
17
apps/calendar/ajax/settings/setfirstday.php
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Georg Ehrke <ownclouddev at georgswebsite dot de>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
require_once('../../../../lib/base.php');
|
||||
OC_JSON::checkLoggedIn();
|
||||
if(isset($_POST["firstday"])){
|
||||
OC_Preferences::setValue(OC_User::getUser(), 'calendar', 'firstday', $_POST["firstday"]);
|
||||
OC_JSON::success();
|
||||
}else{
|
||||
OC_JSON::error();
|
||||
}
|
||||
?>
|
||||
|
||||
|
|
@ -1,26 +1,25 @@
|
|||
<?php
|
||||
if(version_compare(PHP_VERSION, '5.3.0', '>=')){
|
||||
$l=new OC_L10N('calendar');
|
||||
OC::$CLASSPATH['OC_Calendar_App'] = 'apps/calendar/lib/app.php';
|
||||
OC::$CLASSPATH['OC_Calendar_Calendar'] = 'apps/calendar/lib/calendar.php';
|
||||
OC::$CLASSPATH['OC_Calendar_Object'] = 'apps/calendar/lib/object.php';
|
||||
OC::$CLASSPATH['OC_Calendar_Hooks'] = 'apps/calendar/lib/hooks.php';
|
||||
OC::$CLASSPATH['OC_Connector_Sabre_CalDAV'] = 'apps/calendar/lib/connector_sabre.php';
|
||||
OC::$CLASSPATH['OC_Calendar_Share'] = 'apps/calendar/lib/share.php';
|
||||
OC_HOOK::connect('OC_User', 'post_deleteUser', 'OC_Calendar_Hooks', 'deleteUser');
|
||||
OC_Util::addScript('calendar','loader');
|
||||
OC_Util::addScript('3rdparty', 'chosen/chosen.jquery.min');
|
||||
OC_Util::addStyle('3rdparty', 'chosen/chosen');
|
||||
OC_App::register( array(
|
||||
'order' => 10,
|
||||
'id' => 'calendar',
|
||||
'name' => 'Calendar' ));
|
||||
OC_App::addNavigationEntry( array(
|
||||
'id' => 'calendar_index',
|
||||
'order' => 10,
|
||||
'href' => OC_Helper::linkTo( 'calendar', 'index.php' ),
|
||||
'icon' => OC_Helper::imagePath( 'calendar', 'icon.svg' ),
|
||||
'name' => $l->t('Calendar')));
|
||||
OC_App::registerPersonal('calendar', 'settings');
|
||||
require_once('apps/calendar/lib/search.php');
|
||||
}
|
||||
$l=new OC_L10N('calendar');
|
||||
OC::$CLASSPATH['OC_Calendar_App'] = 'apps/calendar/lib/app.php';
|
||||
OC::$CLASSPATH['OC_Calendar_Calendar'] = 'apps/calendar/lib/calendar.php';
|
||||
OC::$CLASSPATH['OC_Calendar_Object'] = 'apps/calendar/lib/object.php';
|
||||
OC::$CLASSPATH['OC_Calendar_Hooks'] = 'apps/calendar/lib/hooks.php';
|
||||
OC::$CLASSPATH['OC_Connector_Sabre_CalDAV'] = 'apps/calendar/lib/connector_sabre.php';
|
||||
OC::$CLASSPATH['OC_Calendar_Share'] = 'apps/calendar/lib/share.php';
|
||||
OC::$CLASSPATH['OC_Search_Provider_Calendar'] = 'apps/calendar/lib/search.php';
|
||||
OC_HOOK::connect('OC_User', 'post_deleteUser', 'OC_Calendar_Hooks', 'deleteUser');
|
||||
OC_Hook::connect('OC_DAV', 'initialize', 'OC_Calendar_Hooks', 'initializeCalDAV');
|
||||
OC_Util::addScript('calendar','loader');
|
||||
OC_App::register( array(
|
||||
'order' => 10,
|
||||
'id' => 'calendar',
|
||||
'name' => 'Calendar' ));
|
||||
OC_App::addNavigationEntry( array(
|
||||
'id' => 'calendar_index',
|
||||
'order' => 10,
|
||||
'href' => OC_Helper::linkTo( 'calendar', 'index.php' ),
|
||||
'icon' => OC_Helper::imagePath( 'calendar', 'icon.svg' ),
|
||||
'name' => $l->t('Calendar')));
|
||||
OC_App::registerPersonal('calendar', 'settings');
|
||||
OC_Search::registerProvider('OC_Search_Provider_Calendar');
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ $nodes = array(
|
|||
|
||||
// Fire up server
|
||||
$server = new Sabre_DAV_Server($nodes);
|
||||
$server->setBaseUri(OC::$WEBROOT.'/apps/calendar/caldav.php');
|
||||
$server->setBaseUri(OC::$APPSWEBROOT.'/apps/calendar/caldav.php');
|
||||
// Add plugins
|
||||
$server->addPlugin(new Sabre_DAV_Auth_Plugin($authBackend,'ownCloud'));
|
||||
$server->addPlugin(new Sabre_CalDAV_Plugin());
|
||||
|
|
|
|||
|
|
@ -9,18 +9,24 @@
|
|||
require_once ('../../lib/base.php');
|
||||
OC_Util::checkLoggedIn();
|
||||
OC_Util::checkAppEnabled('calendar');
|
||||
|
||||
// Create default calendar ...
|
||||
$calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser(), 1);
|
||||
if( count($calendars) == 0){
|
||||
OC_Calendar_Calendar::addCalendar(OC_User::getUser(),'Default calendar');
|
||||
$calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser(), 1);
|
||||
}
|
||||
|
||||
$eventSources = array();
|
||||
foreach($calendars as $calendar){
|
||||
$eventSources[] = OC_Calendar_Calendar::getEventSourceInfo($calendar);
|
||||
}
|
||||
|
||||
$eventSources[] = array('url' => 'ajax/events.php?calendar_id=shared_rw', 'backgroundColor' => '#1D2D44', 'borderColor' => '#888', 'textColor' => 'white', 'editable'=>'true');
|
||||
$eventSources[] = array('url' => 'ajax/events.php?calendar_id=shared_r', 'backgroundColor' => '#1D2D44', 'borderColor' => '#888', 'textColor' => 'white', 'editable' => 'false');
|
||||
|
||||
OC_Hook::emit('OC_Calendar', 'getSources', array('sources' => &$eventSources));
|
||||
|
||||
//Fix currentview for fullcalendar
|
||||
if(OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'currentview', 'month') == "oneweekview"){
|
||||
OC_Preferences::setValue(OC_USER::getUser(), "calendar", "currentview", "agendaWeek");
|
||||
|
|
|
|||
|
|
@ -74,6 +74,9 @@ Calendar={
|
|||
}
|
||||
},
|
||||
editEvent:function(calEvent, jsEvent, view){
|
||||
if (calEvent.editable == false || calEvent.source.editable == false) {
|
||||
return;
|
||||
}
|
||||
var id = calEvent.id;
|
||||
if($('#event').dialog('isOpen') == true){
|
||||
// TODO: save event
|
||||
|
|
@ -215,7 +218,7 @@ Calendar={
|
|||
},
|
||||
initScroll:function(){
|
||||
if(window.addEventListener)
|
||||
document.addEventListener('DOMMouseScroll', Calendar.UI.scrollCalendar);
|
||||
document.addEventListener('DOMMouseScroll', Calendar.UI.scrollCalendar, false);
|
||||
//}else{
|
||||
document.onmousewheel = Calendar.UI.scrollCalendar;
|
||||
//}
|
||||
|
|
@ -764,7 +767,7 @@ $(document).ready(function(){
|
|||
Calendar.UI.initScroll();
|
||||
$('#calendar_holder').fullCalendar({
|
||||
header: false,
|
||||
firstDay: 1,
|
||||
firstDay: firstDay,
|
||||
editable: true,
|
||||
defaultView: defaultView,
|
||||
timeFormat: {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ if (navigator.geolocation) {
|
|||
function(data){
|
||||
if (data.status == 'success' && typeof(data.message) != 'undefined'){
|
||||
$('#notification').html(data.message);
|
||||
$('#notification').attr('title', 'CC BY 3.0 by Geonames.org');
|
||||
$('#notification').slideDown();
|
||||
window.setTimeout(function(){$('#notification').slideUp();}, 5000);
|
||||
}else{
|
||||
|
|
|
|||
|
|
@ -17,6 +17,14 @@ $(document).ready(function(){
|
|||
}
|
||||
});
|
||||
});
|
||||
$('#firstday').change( function(){
|
||||
var data = $('#firstday').serialize();
|
||||
$.post( OC.filePath('calendar', 'ajax/settings', 'setfirstday.php'), data, function(data){
|
||||
if(data == 'error'){
|
||||
console.log('saving firstday failed');
|
||||
}
|
||||
});
|
||||
});
|
||||
$('#timezonedetection').change( function(){
|
||||
var post = $('#timezonedetection').serialize();
|
||||
$.post( OC.filePath('calendar', 'ajax/settings', 'timezonedetection.php'), post, function(data){
|
||||
|
|
@ -32,4 +40,8 @@ $(document).ready(function(){
|
|||
$('#timezonedetection').attr('checked', 'checked');
|
||||
}
|
||||
});
|
||||
$.getJSON(OC.filePath('calendar', 'ajax/settings', 'getfirstday.php'), function(jsondata, status) {
|
||||
$('#' + jsondata.firstday).attr('selected',true);
|
||||
$('#firstday').chosen();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -240,9 +240,10 @@ class OC_Calendar_Calendar{
|
|||
'#9fc6e7', // "light blue"
|
||||
);
|
||||
}
|
||||
|
||||
public static function getEventSourceInfo($calendar){
|
||||
return array(
|
||||
'url' => 'ajax/events.php?calendar_id='.$calendar['id'],
|
||||
'url' => OC_Helper::linkTo('calendar', 'ajax/events.php').'?calendar_id='.$calendar['id'],
|
||||
'backgroundColor' => $calendar['calendarcolor'],
|
||||
'borderColor' => '#888',
|
||||
'textColor' => 'black',
|
||||
|
|
|
|||
|
|
@ -17,11 +17,24 @@ class OC_Calendar_Hooks{
|
|||
*/
|
||||
public static function deleteUser($parameters) {
|
||||
$calendars = OC_Calendar_Calendar::allCalendars($parameters['uid']);
|
||||
|
||||
|
||||
foreach($calendars as $calendar) {
|
||||
OC_Calendar_Calendar::deleteCalendar($calendar['id']);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds the CardDAV resource to the DAV server
|
||||
* @param paramters parameters from initialize-Hook
|
||||
* @return array
|
||||
*/
|
||||
public static function initializeCalDAV($parameters){
|
||||
// We need a backend, the root node and the caldav plugin
|
||||
$parameters['backends']['caldav'] = new OC_Connector_Sabre_CalDAV();
|
||||
$parameters['nodes'][] = new Sabre_CalDAV_CalendarRootNode($parameters['backends']['principal'], $parameters['backends']['caldav']);
|
||||
$parameters['plugins'][] = new Sabre_CalDAV_Plugin();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -309,6 +309,8 @@ class OC_Calendar_Object{
|
|||
$dtend = $vevent->DTEND;
|
||||
}else{
|
||||
$dtend = clone $vevent->DTSTART;
|
||||
// clone creates a shallow copy, also clone DateTime
|
||||
$dtend->setDateTime(clone $dtend->getDateTime(), $dtend->getDateType());
|
||||
if ($vevent->DURATION){
|
||||
$duration = strval($vevent->DURATION);
|
||||
$invert = 0;
|
||||
|
|
@ -817,9 +819,10 @@ class OC_Calendar_Object{
|
|||
|
||||
return $vcalendar;
|
||||
}
|
||||
|
||||
public static function getowner($id){
|
||||
$event = self::find($id);
|
||||
$cal = OC_Calendar_Calendar::find($event['calendarid']);
|
||||
return $cal['userid'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
class OC_Search_Provider_Calendar extends OC_Search_Provider{
|
||||
function search($query){
|
||||
class OC_Search_Provider_Calendar implements OC_Search_Provider{
|
||||
static function search($query){
|
||||
$calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser(), 1);
|
||||
if(count($calendars)==0 || !OC_App::isEnabled('calendar')){
|
||||
//return false;
|
||||
|
|
@ -44,4 +44,3 @@ class OC_Search_Provider_Calendar extends OC_Search_Provider{
|
|||
return $results;
|
||||
}
|
||||
}
|
||||
new OC_Search_Provider_Calendar();
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
var missing_field_startsbeforeends = '<?php echo addslashes($l->t('The event ends before it starts')) ?>';
|
||||
var missing_field_dberror = '<?php echo addslashes($l->t('There was a database fail')) ?>';
|
||||
var totalurl = '<?php echo OC_Helper::linkToAbsolute('calendar', 'caldav.php'); ?>/calendars';
|
||||
var firstDay = '<?php echo (OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'firstday', 'mo') == 'mo' ? '1' : '0'); ?>';
|
||||
$(document).ready(function() {
|
||||
<?php
|
||||
if(array_key_exists('showevent', $_)){
|
||||
|
|
|
|||
|
|
@ -37,6 +37,13 @@
|
|||
</select>
|
||||
</td></tr>
|
||||
|
||||
<tr><td><label for="firstday" class="bold"><?php echo $l->t('First day of the week');?></label></td><td>
|
||||
<select style="display: none;" id="firstday" title="<?php echo "First day"; ?>" name="firstday">
|
||||
<option value="mo" id="mo"><?php echo $l->t("Monday"); ?></option>
|
||||
<option value="su" id="su"><?php echo $l->t("Sunday"); ?></option>
|
||||
</select>
|
||||
</td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
<?php echo $l->t('Calendar CalDAV syncing address:');?>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,11 @@ OC::$CLASSPATH['OC_Contacts_Addressbook'] = 'apps/contacts/lib/addressbook.php';
|
|||
OC::$CLASSPATH['OC_Contacts_VCard'] = 'apps/contacts/lib/vcard.php';
|
||||
OC::$CLASSPATH['OC_Contacts_Hooks'] = 'apps/contacts/lib/hooks.php';
|
||||
OC::$CLASSPATH['OC_Connector_Sabre_CardDAV'] = 'apps/contacts/lib/connector_sabre.php';
|
||||
OC::$CLASSPATH['OC_Search_Provider_Contacts'] = 'apps/contacts/lib/search.php';
|
||||
OC_HOOK::connect('OC_User', 'post_deleteUser', 'OC_Contacts_Hooks', 'deleteUser');
|
||||
OC_HOOK::connect('OC_Calendar', 'getEvents', 'OC_Contacts_Hooks', 'getBirthdayEvents');
|
||||
OC_HOOK::connect('OC_Calendar', 'getSources', 'OC_Contacts_Hooks', 'getCalenderSources');
|
||||
OC_Hook::connect('OC_DAV', 'initialize', 'OC_Contacts_Hooks', 'initializeCardDAV');
|
||||
|
||||
OC_App::register( array(
|
||||
'order' => 10,
|
||||
|
|
@ -21,4 +25,4 @@ OC_App::addNavigationEntry( array(
|
|||
|
||||
OC_APP::registerPersonal('contacts','settings');
|
||||
OC_UTIL::addScript('contacts', 'loader');
|
||||
require_once('apps/contacts/lib/search.php');
|
||||
OC_Search::registerProvider('OC_Search_Provider_Contacts');
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ $nodes = array(
|
|||
|
||||
// Fire up server
|
||||
$server = new Sabre_DAV_Server($nodes);
|
||||
$server->setBaseUri(OC::$WEBROOT.'/apps/contacts/carddav.php');
|
||||
$server->setBaseUri(OC::$APPSWEBROOT.'/apps/contacts/carddav.php');
|
||||
// Add plugins
|
||||
$server->addPlugin(new Sabre_DAV_Auth_Plugin($authBackend,'ownCloud'));
|
||||
$server->addPlugin(new Sabre_CardDAV_Plugin());
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ class OC_Contacts_App {
|
|||
$vcard = OC_VObject::parse($card['carddata']);
|
||||
// Try to fix cards with missing 'N' field from pre ownCloud 4. Hot damn, this is ugly...
|
||||
if(!is_null($vcard) && !$vcard->__isset('N')) {
|
||||
$appinfo = $info=OC_App::getAppInfo('contacts');
|
||||
$appinfo = OC_App::getAppInfo('contacts');
|
||||
if($appinfo['version'] >= 5) {
|
||||
OC_Log::write('contacts','OC_Contacts_App::getContactVCard. Deprecated check for missing N field', OC_Log::DEBUG);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class OC_Contacts_Hooks{
|
|||
* @param paramters parameters from postDeleteUser-Hook
|
||||
* @return array
|
||||
*/
|
||||
public function deleteUser($parameters) {
|
||||
static public function deleteUser($parameters) {
|
||||
$addressbooks = OC_Contacts_Addressbook::all($parameters['uid']);
|
||||
|
||||
foreach($addressbooks as $addressbook) {
|
||||
|
|
@ -38,4 +38,62 @@ class OC_Contacts_Hooks{
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds the CardDAV resource to the DAV server
|
||||
* @param paramters parameters from initialize-Hook
|
||||
* @return array
|
||||
*/
|
||||
static public function initializeCardDAV($parameters){
|
||||
// We need a backend, the root node and the carddav plugin
|
||||
$parameters['backends']['carddav'] = new OC_Connector_Sabre_CardDAV();
|
||||
$parameters['nodes'][] = new Sabre_CardDAV_AddressBookRoot($parameters['backends']['principal'], $parameters['backends']['carddav']);
|
||||
$parameters['plugins'][] = new Sabre_CardDAV_Plugin();
|
||||
return true;
|
||||
}
|
||||
|
||||
static public function getCalenderSources($parameters) {
|
||||
$base_url = OC_Helper::linkTo('calendar', 'ajax/events.php').'?calendar_id=';
|
||||
foreach(OC_Contacts_Addressbook::all(OC_User::getUser()) as $addressbook) {
|
||||
$parameters['sources'][] =
|
||||
array(
|
||||
'url' => $base_url.'birthday_'. $addressbook['id'],
|
||||
'backgroundColor' => '#cccccc',
|
||||
'borderColor' => '#888',
|
||||
'textColor' => 'black',
|
||||
'cache' => true,
|
||||
'editable' => false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static public function getBirthdayEvents($parameters) {
|
||||
$name = $parameters['calendar_id'];
|
||||
if (strpos('birthday_', $name) != 0) {
|
||||
return;
|
||||
}
|
||||
$info = explode('_', $name);
|
||||
$aid = $info[1];
|
||||
OC_Contacts_App::getAddressbook($aid);
|
||||
foreach(OC_Contacts_VCard::all($aid) as $card){
|
||||
$vcard = OC_VObject::parse($card['carddata']);
|
||||
$birthday = $vcard->BDAY;
|
||||
if ($birthday) {
|
||||
$date = new DateTime($birthday);
|
||||
$vevent = new OC_VObject('VEVENT');
|
||||
$vevent->setDateTime('LAST-MODIFIED', new DateTime($vcard->REV));
|
||||
$vevent->setDateTime('DTSTART', $date, Sabre_VObject_Element_DateTime::DATE);
|
||||
$vevent->setString('DURATION', 'P1D');
|
||||
// DESCRIPTION?
|
||||
$vevent->setString('RRULE', 'FREQ=YEARLY');
|
||||
$title = str_replace('{name}', $vcard->getAsString('FN'), OC_Contacts_App::$l10n->t('{name}\'s Birthday'));
|
||||
$parameters['events'][] = array(
|
||||
'id' => 0,//$card['id'],
|
||||
'vevent' => $vevent,
|
||||
'repeating' => true,
|
||||
'summary' => $title,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
class OC_Search_Provider_Contacts extends OC_Search_Provider{
|
||||
function search($query){
|
||||
class OC_Search_Provider_Contacts implements OC_Search_Provider{
|
||||
static function search($query){
|
||||
$addressbooks = OC_Contacts_Addressbook::all(OC_User::getUser(), 1);
|
||||
// if(count($calendars)==0 || !OC_App::isEnabled('contacts')){
|
||||
// //return false;
|
||||
|
|
@ -26,4 +26,3 @@ class OC_Search_Provider_Contacts extends OC_Search_Provider{
|
|||
return $results;
|
||||
}
|
||||
}
|
||||
new OC_Search_Provider_Contacts();
|
||||
|
|
|
|||
14
apps/files_archive/appinfo/app.php
Normal file
14
apps/files_archive/appinfo/app.php
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
OC::$CLASSPATH['OC_Archive'] = 'apps/files_archive/lib/archive.php';
|
||||
foreach(array('ZIP') as $type){
|
||||
OC::$CLASSPATH['OC_Archive_'.$type] = 'apps/files_archive/lib/'.strtolower($type).'.php';
|
||||
}
|
||||
|
||||
OC::$CLASSPATH['OC_Filestorage_Archive']='apps/files_archive/lib/storage.php';
|
||||
10
apps/files_archive/appinfo/info.xml
Normal file
10
apps/files_archive/appinfo/info.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0"?>
|
||||
<info>
|
||||
<id>files_archive</id>
|
||||
<name>Archive support</name>
|
||||
<description>Transparent opening of archives</description>
|
||||
<version>0.1</version>
|
||||
<licence>AGPL</licence>
|
||||
<author>Robin Appelman</author>
|
||||
<require>3</require>
|
||||
</info>
|
||||
99
apps/files_archive/lib/archive.php
Normal file
99
apps/files_archive/lib/archive.php
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
abstract class OC_Archive{
|
||||
/**
|
||||
* open any of the supporeted archive types
|
||||
* @param string path
|
||||
* @return OC_Archive
|
||||
*/
|
||||
public static function open($path){
|
||||
$ext=substr($path,strrpos($path,'.'));
|
||||
switch($ext){
|
||||
case '.zip':
|
||||
return new OC_Archive_ZIP($path);
|
||||
}
|
||||
}
|
||||
|
||||
abstract function __construct($source);
|
||||
/**
|
||||
* add an empty folder to the archive
|
||||
* @param string path
|
||||
* @return bool
|
||||
*/
|
||||
abstract function addFolder($path);
|
||||
/**
|
||||
* add a file to the archive
|
||||
* @param string path
|
||||
* @param string source either a local file or string data
|
||||
* @return bool
|
||||
*/
|
||||
abstract function addFile($path,$source='');
|
||||
/**
|
||||
* rename a file or folder in the archive
|
||||
* @param string source
|
||||
* @param string dest
|
||||
* @return bool
|
||||
*/
|
||||
abstract function rename($source,$dest);
|
||||
/**
|
||||
* get the uncompressed size of a file in the archive
|
||||
* @param string path
|
||||
* @return int
|
||||
*/
|
||||
abstract function filesize($path);
|
||||
/**
|
||||
* get the last modified time of a file in the archive
|
||||
* @param string path
|
||||
* @return int
|
||||
*/
|
||||
abstract function mtime($path);
|
||||
/**
|
||||
* get the files in a folder
|
||||
* @param path
|
||||
* @return array
|
||||
*/
|
||||
abstract function getFolder($path);
|
||||
/**
|
||||
*get all files in the archive
|
||||
* @return array
|
||||
*/
|
||||
abstract function getFiles();
|
||||
/**
|
||||
* get the content of a file
|
||||
* @param string path
|
||||
* @return string
|
||||
*/
|
||||
abstract function getFile($path);
|
||||
/**
|
||||
* extract a single file from the archive
|
||||
* @param string path
|
||||
* @param string dest
|
||||
* @return bool
|
||||
*/
|
||||
abstract function extractFile($path,$dest);
|
||||
/**
|
||||
* check if a file or folder exists in the archive
|
||||
* @param string path
|
||||
* @return bool
|
||||
*/
|
||||
abstract function fileExists($path);
|
||||
/**
|
||||
* remove a file or folder from the archive
|
||||
* @param string path
|
||||
* @return bool
|
||||
*/
|
||||
abstract function remove($path);
|
||||
/**
|
||||
* get a file handler
|
||||
* @param string path
|
||||
* @param string mode
|
||||
* @return resource
|
||||
*/
|
||||
abstract function getStream($path,$mode);
|
||||
}
|
||||
102
apps/files_archive/lib/storage.php
Normal file
102
apps/files_archive/lib/storage.php
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
class OC_Filestorage_Archive extends OC_Filestorage_Common{
|
||||
/**
|
||||
* underlying local storage used for missing functions
|
||||
* @var OC_Archive
|
||||
*/
|
||||
private $archive;
|
||||
private $path;
|
||||
|
||||
private function stripPath($path){//files should never start with /
|
||||
if(substr($path,0,1)=='/'){
|
||||
return substr($path,1);
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
|
||||
public function __construct($params){
|
||||
$this->archive=OC_Archive::open($params['archive']);
|
||||
$this->path=$params['archive'];
|
||||
}
|
||||
|
||||
public function mkdir($path){
|
||||
$path=$this->stripPath($path);
|
||||
return $this->archive->addFolder($path);
|
||||
}
|
||||
public function rmdir($path){
|
||||
$path=$this->stripPath($path);
|
||||
return $this->archive->remove($path.'/');
|
||||
}
|
||||
public function opendir($path){
|
||||
$path=$this->stripPath($path);
|
||||
$content=$this->archive->getFolder($path);
|
||||
foreach($content as &$file){
|
||||
if(substr($file,-1)=='/'){
|
||||
$file=substr($file,0,-1);
|
||||
}
|
||||
}
|
||||
$id=md5($this->path.$path);
|
||||
OC_FakeDirStream::$dirs[$id]=$content;
|
||||
return opendir('fakedir://'.$id);
|
||||
}
|
||||
public function stat($path){
|
||||
$ctime=filectime($this->path);
|
||||
$path=$this->stripPath($path);
|
||||
if($path==''){
|
||||
$stat=stat($this->path);
|
||||
}else{
|
||||
$stat=array();
|
||||
$stat['mtime']=$this->archive->mtime($path);
|
||||
$stat['size']=$this->archive->filesize($path);
|
||||
}
|
||||
$stat['ctime']=$ctime;
|
||||
return $stat;
|
||||
}
|
||||
public function filetype($path){
|
||||
$path=$this->stripPath($path);
|
||||
if($path==''){
|
||||
return 'dir';
|
||||
}
|
||||
return $this->archive->fileExists($path.'/')?'dir':'file';
|
||||
}
|
||||
public function is_readable($path){
|
||||
return is_readable($this->path);
|
||||
}
|
||||
public function is_writable($path){
|
||||
return is_writable($this->path);
|
||||
}
|
||||
public function file_exists($path){
|
||||
$path=$this->stripPath($path);
|
||||
if($path==''){
|
||||
return file_exists($this->path);
|
||||
}
|
||||
return $this->archive->fileExists($path) or $this->archive->fileExists($path.'/');
|
||||
}
|
||||
public function unlink($path){
|
||||
$path=$this->stripPath($path);
|
||||
return $this->archive->remove($path);
|
||||
}
|
||||
public function fopen($path,$mode){
|
||||
$path=$this->stripPath($path);
|
||||
return $this->archive->getStream($path,$mode);
|
||||
}
|
||||
public function free_space($path){
|
||||
return 0;
|
||||
}
|
||||
public function touch($path, $mtime=null){
|
||||
if(is_null($mtime)){
|
||||
$tmpFile=OC_Helper::tmpFile();
|
||||
$this->archive->extractFile($path,$tmpFile);
|
||||
$this->archive->addfile($path,$tmpFile);
|
||||
}else{
|
||||
return false;//not supported
|
||||
}
|
||||
}
|
||||
}
|
||||
182
apps/files_archive/lib/zip.php
Normal file
182
apps/files_archive/lib/zip.php
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
class OC_Archive_ZIP extends OC_Archive{
|
||||
/**
|
||||
* @var ZipArchive zip
|
||||
*/
|
||||
private $zip=null;
|
||||
private $contents=array();
|
||||
private $success=false;
|
||||
private $path;
|
||||
|
||||
function __construct($source){
|
||||
$this->path=$source;
|
||||
$this->zip=new ZipArchive();
|
||||
if($this->zip->open($source,ZipArchive::CREATE)){
|
||||
}else{
|
||||
OC_LOG::write('files_archive','Error while opening archive '.$source,OC_Log::WARN);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* add an empty folder to the archive
|
||||
* @param string path
|
||||
* @return bool
|
||||
*/
|
||||
function addFolder($path){
|
||||
return $this->zip->addEmptyDir($path);
|
||||
}
|
||||
/**
|
||||
* add a file to the archive
|
||||
* @param string path
|
||||
* @param string source either a local file or string data
|
||||
* @return bool
|
||||
*/
|
||||
function addFile($path,$source=''){
|
||||
if(file_exists($source)){
|
||||
$result=$this->zip->addFile($source,$path);
|
||||
}else{
|
||||
$result=$this->zip->addFromString($path,$source);
|
||||
}
|
||||
if($result){
|
||||
$this->zip->close();//close and reopen to save the zip
|
||||
$this->zip->open($this->path);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
/**
|
||||
* rename a file or folder in the archive
|
||||
* @param string source
|
||||
* @param string dest
|
||||
* @return bool
|
||||
*/
|
||||
function rename($source,$dest){
|
||||
return $this->zip->renameName($source,$dest);
|
||||
}
|
||||
/**
|
||||
* get the uncompressed size of a file in the archive
|
||||
* @param string path
|
||||
* @return int
|
||||
*/
|
||||
function filesize($path){
|
||||
$stat=$this->zip->statName($path);
|
||||
return $stat['size'];
|
||||
}
|
||||
/**
|
||||
* get the last modified time of a file in the archive
|
||||
* @param string path
|
||||
* @return int
|
||||
*/
|
||||
function mtime($path){
|
||||
$stat=$this->zip->statName($path);
|
||||
return $stat['mtime'];
|
||||
}
|
||||
/**
|
||||
* get the files in a folder
|
||||
* @param path
|
||||
* @return array
|
||||
*/
|
||||
function getFolder($path){
|
||||
$files=$this->getFiles();
|
||||
$folderContent=array();
|
||||
$pathLength=strlen($path);
|
||||
foreach($files as $file){
|
||||
if(substr($file,0,$pathLength)==$path and $file!=$path){
|
||||
if(strrpos(substr($file,0,-1),'/')<=$pathLength){
|
||||
$folderContent[]=substr($file,$pathLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $folderContent;
|
||||
}
|
||||
/**
|
||||
*get all files in the archive
|
||||
* @return array
|
||||
*/
|
||||
function getFiles(){
|
||||
if(count($this->contents)){
|
||||
return $this->contents;
|
||||
}
|
||||
$fileCount=$this->zip->numFiles;
|
||||
$files=array();
|
||||
for($i=0;$i<$fileCount;$i++){
|
||||
$files[]=$this->zip->getNameIndex($i);
|
||||
}
|
||||
$this->contents=$files;
|
||||
return $files;
|
||||
}
|
||||
/**
|
||||
* get the content of a file
|
||||
* @param string path
|
||||
* @return string
|
||||
*/
|
||||
function getFile($path){
|
||||
return $this->zip->getFromName($path);
|
||||
}
|
||||
/**
|
||||
* extract a single file from the archive
|
||||
* @param string path
|
||||
* @param string dest
|
||||
* @return bool
|
||||
*/
|
||||
function extractFile($path,$dest){
|
||||
$fp = $this->zip->getStream($path);
|
||||
file_put_contents($dest,$fp);
|
||||
}
|
||||
/**
|
||||
* check if a file or folder exists in the archive
|
||||
* @param string path
|
||||
* @return bool
|
||||
*/
|
||||
function fileExists($path){
|
||||
return $this->zip->locateName($path)!==false;
|
||||
}
|
||||
/**
|
||||
* remove a file or folder from the archive
|
||||
* @param string path
|
||||
* @return bool
|
||||
*/
|
||||
function remove($path){
|
||||
return $this->zip->deleteName($path);
|
||||
}
|
||||
/**
|
||||
* get a file handler
|
||||
* @param string path
|
||||
* @param string mode
|
||||
* @return resource
|
||||
*/
|
||||
function getStream($path,$mode){
|
||||
if($mode=='r' or $mode=='rb'){
|
||||
return $this->zip->getStream($path);
|
||||
}else{//since we cant directly get a writable stream, make a temp copy of the file and put it back in the archive when the stream is closed
|
||||
if(strrpos($path,'.')!==false){
|
||||
$ext=substr($path,strrpos($path,'.'));
|
||||
}else{
|
||||
$ext='';
|
||||
}
|
||||
$tmpFile=OC_Helper::tmpFile($ext);
|
||||
OC_CloseStreamWrapper::$callBacks[$tmpFile]=array($this,'writeBack');
|
||||
if($this->fileExists($path)){
|
||||
$this->extractFile($path,$tmpFile);
|
||||
}
|
||||
self::$tempFiles[$tmpFile]=$path;
|
||||
return fopen('close://'.$tmpFile,$mode);
|
||||
}
|
||||
}
|
||||
|
||||
private static $tempFiles=array();
|
||||
/**
|
||||
* write back temporary files
|
||||
*/
|
||||
function writeBack($tmpFile){
|
||||
if(isset(self::$tempFiles[$tmpFile])){
|
||||
$this->addFile(self::$tempFiles[$tmpFile],$tmpFile);
|
||||
unlink($tmpFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
97
apps/files_archive/tests/archive.php
Normal file
97
apps/files_archive/tests/archive.php
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
abstract class Test_Archive extends UnitTestCase {
|
||||
/**
|
||||
* @var OC_Archive
|
||||
*/
|
||||
protected $instance;
|
||||
|
||||
/**
|
||||
* get the existing test archive
|
||||
* @return OC_Archive
|
||||
*/
|
||||
abstract protected function getExisting();
|
||||
/**
|
||||
* get a new archive for write testing
|
||||
* @return OC_Archive
|
||||
*/
|
||||
abstract protected function getNew();
|
||||
|
||||
public function testGetFiles(){
|
||||
$this->instance=$this->getExisting();
|
||||
$allFiles=$this->instance->getFiles();
|
||||
$expected=array('lorem.txt','logo-wide.png','dir/','dir/lorem.txt');
|
||||
$this->assertEqual(4,count($allFiles));
|
||||
foreach($expected as $file){
|
||||
$this->assertNotIdentical(false,array_search($file,$allFiles),'cant find '.$file.' in archive');
|
||||
$this->assertTrue($this->instance->fileExists($file));
|
||||
}
|
||||
$this->assertFalse($this->instance->fileExists('non/existing/file'));
|
||||
|
||||
$rootContent=$this->instance->getFolder('');
|
||||
$expected=array('lorem.txt','logo-wide.png','dir/');
|
||||
$this->assertEqual(3,count($rootContent));
|
||||
foreach($expected as $file){
|
||||
$this->assertNotIdentical(false,array_search($file,$rootContent),'cant find '.$file.' in archive');
|
||||
}
|
||||
|
||||
$dirContent=$this->instance->getFolder('dir/');
|
||||
$expected=array('lorem.txt');
|
||||
$this->assertEqual(1,count($dirContent));
|
||||
foreach($expected as $file){
|
||||
$this->assertNotIdentical(false,array_search($file,$dirContent),'cant find '.$file.' in archive');
|
||||
}
|
||||
}
|
||||
|
||||
public function testContent(){
|
||||
$this->instance=$this->getExisting();
|
||||
$dir=OC::$SERVERROOT.'/apps/files_archive/tests/data';
|
||||
$textFile=$dir.'/lorem.txt';
|
||||
$this->assertEqual(file_get_contents($textFile),$this->instance->getFile('lorem.txt'));
|
||||
|
||||
$tmpFile=OC_Helper::tmpFile('.txt');
|
||||
$this->instance->extractFile('lorem.txt',$tmpFile);
|
||||
$this->assertEqual(file_get_contents($textFile),file_get_contents($tmpFile));
|
||||
}
|
||||
|
||||
public function testWrite(){
|
||||
$dir=OC::$SERVERROOT.'/apps/files_archive/tests/data';
|
||||
$textFile=$dir.'/lorem.txt';
|
||||
$this->instance=$this->getNew();
|
||||
$this->assertEqual(0,count($this->instance->getFiles()));
|
||||
$this->instance->addFile('lorem.txt',$textFile);
|
||||
$this->assertEqual(1,count($this->instance->getFiles()));
|
||||
$this->assertTrue($this->instance->fileExists('lorem.txt'));
|
||||
|
||||
$this->assertEqual(file_get_contents($textFile),$this->instance->getFile('lorem.txt'));
|
||||
$this->instance->addFile('lorem.txt','foobar');
|
||||
$this->assertEqual('foobar',$this->instance->getFile('lorem.txt'));
|
||||
}
|
||||
|
||||
public function testReadStream(){
|
||||
$dir=OC::$SERVERROOT.'/apps/files_archive/tests/data';
|
||||
$this->instance=$this->getExisting();
|
||||
$fh=$this->instance->getStream('lorem.txt','r');
|
||||
$this->assertTrue($fh);
|
||||
$content=fread($fh,$this->instance->filesize('lorem.txt'));
|
||||
fclose($fh);
|
||||
$this->assertEqual(file_get_contents($dir.'/lorem.txt'),$content);
|
||||
}
|
||||
public function testWriteStream(){
|
||||
$dir=OC::$SERVERROOT.'/apps/files_archive/tests/data';
|
||||
$this->instance=$this->getNew();
|
||||
$fh=$this->instance->getStream('lorem.txt','w');
|
||||
$source=fopen($dir.'/lorem.txt','r');
|
||||
OC_Helper::streamCopy($source,$fh);
|
||||
fclose($source);
|
||||
fclose($fh);
|
||||
$this->assertTrue($this->instance->fileExists('lorem.txt'));
|
||||
$this->assertEqual(file_get_contents($dir.'/lorem.txt'),$this->instance->getFile('lorem.txt'));
|
||||
}
|
||||
}
|
||||
25
apps/files_archive/tests/storage.php
Normal file
25
apps/files_archive/tests/storage.php
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
class Test_Filestorage_Archive_Zip extends Test_FileStorage {
|
||||
/**
|
||||
* @var string tmpDir
|
||||
*/
|
||||
private $tmpFile;
|
||||
|
||||
public function setUp(){
|
||||
$this->tmpFile=OC_Helper::tmpFile('.zip');
|
||||
$this->instance=new OC_Filestorage_Archive(array('archive'=>$this->tmpFile));
|
||||
}
|
||||
|
||||
public function tearDown(){
|
||||
unlink($this->tmpFile);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
20
apps/files_archive/tests/zip.php
Normal file
20
apps/files_archive/tests/zip.php
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
require_once('archive.php');
|
||||
|
||||
class Test_Archive_ZIP extends Test_Archive{
|
||||
protected function getExisting(){
|
||||
$dir=OC::$SERVERROOT.'/apps/files_archive/tests/data';
|
||||
return new OC_Archive_ZIP($dir.'/data.zip');
|
||||
}
|
||||
|
||||
protected function getNew(){
|
||||
return new OC_Archive_ZIP(OC_Helper::tmpFile('.zip'));
|
||||
}
|
||||
}
|
||||
19
apps/files_encryption/appinfo/app.php
Normal file
19
apps/files_encryption/appinfo/app.php
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
OC::$CLASSPATH['OC_Crypt'] = 'apps/files_encryption/lib/crypt.php';
|
||||
OC::$CLASSPATH['OC_CryptStream'] = 'apps/files_encryption/lib/cryptstream.php';
|
||||
OC::$CLASSPATH['OC_FileProxy_Encryption'] = 'apps/files_encryption/lib/proxy.php';
|
||||
|
||||
OC_FileProxy::register(new OC_FileProxy_Encryption());
|
||||
|
||||
OC_Hook::connect('OC_User','post_login','OC_Crypt','loginListener');
|
||||
|
||||
stream_wrapper_register('crypt','OC_CryptStream');
|
||||
|
||||
if(!isset($_SESSION['enckey']) and OC_User::isLoggedIn()){//force the user to re-loggin if the encryption key isn't unlocked (happens when a user is logged in before the encryption app is enabled)
|
||||
OC_User::logout();
|
||||
header("Location: ".OC::$WEBROOT.'/');
|
||||
exit();
|
||||
}
|
||||
|
||||
OC_App::registerAdmin('files_encryption', 'settings');
|
||||
10
apps/files_encryption/appinfo/info.xml
Normal file
10
apps/files_encryption/appinfo/info.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0"?>
|
||||
<info>
|
||||
<id>files_encryption</id>
|
||||
<name>Encryption</name>
|
||||
<description>Server side encryption of files</description>
|
||||
<version>0.1</version>
|
||||
<licence>AGPL</licence>
|
||||
<author>Robin Appelman</author>
|
||||
<require>3</require>
|
||||
</info>
|
||||
19
apps/files_encryption/js/settings.js
Normal file
19
apps/files_encryption/js/settings.js
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* Copyright (c) 2011, Robin Appelman <icewind1991@gmail.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
|
||||
$(document).ready(function(){
|
||||
$('#encryption_blacklist').multiSelect({
|
||||
oncheck:blackListChange,
|
||||
onuncheck:blackListChange,
|
||||
createText:'...',
|
||||
});
|
||||
|
||||
function blackListChange(){
|
||||
var blackList=$('#encryption_blacklist').val().join(',');
|
||||
OC.AppConfig.setValue('files_encryption','type_blacklist',blackList);
|
||||
}
|
||||
})
|
||||
|
|
@ -37,90 +37,111 @@ require_once('Crypt_Blowfish/Blowfish.php');
|
|||
* This class is for crypting and decrypting
|
||||
*/
|
||||
class OC_Crypt {
|
||||
static private $bf = null;
|
||||
|
||||
static $encription_extension='.encrypted';
|
||||
public static function loginListener($params){
|
||||
self::init($params['uid'],$params['password']);
|
||||
}
|
||||
|
||||
public static function init($login,$password) {
|
||||
$_SESSION['user_password'] = $password; // save the password as passcode for the encryption
|
||||
if(OC_User::isLoggedIn()){
|
||||
// does key exist?
|
||||
if(!file_exists(OC_Config::getValue( "datadirectory").'/'.$login.'/encryption.key')){
|
||||
OC_Crypt::createkey($_SESSION['user_password']);
|
||||
$view=new OC_FilesystemView('/'.$login);
|
||||
OC_FileProxy::$enabled=false;
|
||||
if(!$view->file_exists('/encryption.key')){// does key exist?
|
||||
OC_Crypt::createkey($login,$password);
|
||||
}
|
||||
$key=$view->file_get_contents('/encryption.key');
|
||||
OC_FileProxy::$enabled=true;
|
||||
$_SESSION['enckey']=OC_Crypt::decrypt($key, $password);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the blowfish encryption handeler for a key
|
||||
* @param string $key (optional)
|
||||
* @return Crypt_Blowfish
|
||||
*
|
||||
* if the key is left out, the default handeler will be used
|
||||
*/
|
||||
public static function getBlowfish($key=''){
|
||||
if($key){
|
||||
return new Crypt_Blowfish($key);
|
||||
}else{
|
||||
if(!isset($_SESSION['enckey'])){
|
||||
return false;
|
||||
}
|
||||
if(!self::$bf){
|
||||
self::$bf=new Crypt_Blowfish($_SESSION['enckey']);
|
||||
}
|
||||
return self::$bf;
|
||||
}
|
||||
}
|
||||
|
||||
public static function createkey($username,$passcode) {
|
||||
// generate a random key
|
||||
$key=mt_rand(10000,99999).mt_rand(10000,99999).mt_rand(10000,99999).mt_rand(10000,99999);
|
||||
|
||||
// encrypt the key with the passcode of the user
|
||||
$enckey=OC_Crypt::encrypt($key,$passcode);
|
||||
|
||||
public static function createkey($passcode) {
|
||||
if(OC_User::isLoggedIn()){
|
||||
// generate a random key
|
||||
$key=mt_rand(10000,99999).mt_rand(10000,99999).mt_rand(10000,99999).mt_rand(10000,99999);
|
||||
|
||||
// encrypt the key with the passcode of the user
|
||||
$enckey=OC_Crypt::encrypt($key,$passcode);
|
||||
|
||||
// Write the file
|
||||
$username=OC_USER::getUser();
|
||||
@file_put_contents(OC_Config::getValue( "datadirectory").'/'.$username.'/encryption.key', $enckey );
|
||||
}
|
||||
// Write the file
|
||||
$proxyEnabled=OC_FileProxy::$enabled;
|
||||
OC_FileProxy::$enabled=false;
|
||||
$view=new OC_FilesystemView('/'.$username);
|
||||
$view->file_put_contents('/encryption.key',$enckey);
|
||||
OC_FileProxy::$enabled=$proxyEnabled;
|
||||
}
|
||||
|
||||
public static function changekeypasscode( $newpasscode) {
|
||||
public static function changekeypasscode($oldPassword, $newPassword) {
|
||||
if(OC_User::isLoggedIn()){
|
||||
$username=OC_USER::getUser();
|
||||
$username=OC_USER::getUser();
|
||||
$view=new OC_FilesystemView('/'.$username);
|
||||
|
||||
// read old key
|
||||
$key=file_get_contents(OC_Config::getValue( "datadirectory").'/'.$username.'/encryption.key');
|
||||
$key=$view->file_get_contents('/encryption.key');
|
||||
|
||||
// decrypt key with old passcode
|
||||
$key=OC_Crypt::decrypt($key, $_SESSION['user_password']);
|
||||
$key=OC_Crypt::decrypt($key, $oldPassword);
|
||||
|
||||
// encrypt again with new passcode
|
||||
$key=OC_Crypt::encrypt($key,$newpassword);
|
||||
$key=OC_Crypt::encrypt($key, $newPassword);
|
||||
|
||||
// store the new key
|
||||
file_put_contents(OC_Config::getValue( "datadirectory").'/'.$username.'/encryption.key', $key );
|
||||
|
||||
$_SESSION['user_password']=$newpasscode;
|
||||
$view->file_put_contents('/encryption.key', $key );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief encrypts an content
|
||||
* @param $content the cleartext message you want to encrypt
|
||||
* @param $key the encryption key
|
||||
* @param $key the encryption key (optional)
|
||||
* @returns encrypted content
|
||||
*
|
||||
* This function encrypts an content
|
||||
*/
|
||||
public static function encrypt( $content, $key) {
|
||||
$bf = new Crypt_Blowfish($key);
|
||||
public static function encrypt( $content, $key='') {
|
||||
$bf = self::getBlowfish($key);
|
||||
return($bf->encrypt($content));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief decryption of an content
|
||||
* @param $content the cleartext message you want to decrypt
|
||||
* @param $key the encryption key (optional)
|
||||
* @returns cleartext content
|
||||
*
|
||||
* This function decrypts an content
|
||||
*/
|
||||
public static function decrypt( $content, $key='') {
|
||||
$bf = self::getBlowfish($key);
|
||||
return($bf->decrypt($content));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief decryption of an content
|
||||
* @param $content the cleartext message you want to decrypt
|
||||
* @param $key the encryption key
|
||||
* @returns cleartext content
|
||||
*
|
||||
* This function decrypts an content
|
||||
*/
|
||||
public static function decrypt( $content, $key) {
|
||||
$bf = new Crypt_Blowfish($key);
|
||||
return($bf->encrypt($contents));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief encryption of a file
|
||||
* @param $filename
|
||||
* @param $key the encryption key
|
||||
*
|
||||
* This function encrypts a file
|
||||
*/
|
||||
/**
|
||||
* @brief encryption of a file
|
||||
* @param $filename
|
||||
* @param $key the encryption key
|
||||
*
|
||||
* This function encrypts a file
|
||||
*/
|
||||
public static function encryptfile( $filename, $key) {
|
||||
$handleread = fopen($filename, "rb");
|
||||
if($handleread<>FALSE) {
|
||||
|
|
@ -158,8 +179,28 @@ class OC_Crypt {
|
|||
}
|
||||
fclose($handleread);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* encrypt data in 8192b sized blocks
|
||||
*/
|
||||
public static function blockEncrypt($data){
|
||||
$result='';
|
||||
while(strlen($data)){
|
||||
$result=self::encrypt(substr($data,0,8192));
|
||||
$data=substr($data,8192);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* decrypt data in 8192b sized blocks
|
||||
*/
|
||||
public static function blockDecrypt($data){
|
||||
$result='';
|
||||
while(strlen($data)){
|
||||
$result=self::decrypt(substr($data,0,8192));
|
||||
$data=substr($data,8192);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
153
apps/files_encryption/lib/cryptstream.php
Normal file
153
apps/files_encryption/lib/cryptstream.php
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
<?php
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Robin Appelman
|
||||
* @copyright 2011 Robin Appelman icewind1991@gmail.com
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* transparently encrypted filestream
|
||||
*
|
||||
* you can use it as wrapper around an existing stream by setting OC_CryptStream::$sourceStreams['foo']=array('path'=>$path,'stream'=>$stream)
|
||||
* and then fopen('crypt://streams/foo');
|
||||
*/
|
||||
|
||||
class OC_CryptStream{
|
||||
public static $sourceStreams=array();
|
||||
private $source;
|
||||
private $path;
|
||||
private $readBuffer;//for streams that dont support seeking
|
||||
private $meta=array();//header/meta for source stream
|
||||
|
||||
public function stream_open($path, $mode, $options, &$opened_path){
|
||||
$path=str_replace('crypt://','',$path);
|
||||
if(dirname($path)=='streams' and isset(self::$sourceStreams[basename($path)])){
|
||||
$this->source=self::$sourceStreams[basename($path)]['stream'];
|
||||
$this->path=self::$sourceStreams[basename($path)]['path'];
|
||||
}else{
|
||||
$this->path=$path;
|
||||
OC_Log::write('files_encryption','open encrypted '.$path. ' in '.$mode,OC_Log::DEBUG);
|
||||
OC_FileProxy::$enabled=false;//disable fileproxies so we can open the source file
|
||||
$this->source=OC_FileSystem::fopen($path,$mode);
|
||||
OC_FileProxy::$enabled=true;
|
||||
if(!is_resource($this->source)){
|
||||
OC_Log::write('files_encryption','failed to open '.$path,OC_Log::ERROR);
|
||||
}
|
||||
}
|
||||
if(is_resource($this->source)){
|
||||
$this->meta=stream_get_meta_data($this->source);
|
||||
}
|
||||
return is_resource($this->source);
|
||||
}
|
||||
|
||||
public function stream_seek($offset, $whence=SEEK_SET){
|
||||
fseek($this->source,$offset,$whence);
|
||||
}
|
||||
|
||||
public function stream_tell(){
|
||||
return ftell($this->source);
|
||||
}
|
||||
|
||||
public function stream_read($count){
|
||||
$pos=0;
|
||||
$currentPos=ftell($this->source);
|
||||
$offset=$currentPos%8192;
|
||||
$result='';
|
||||
if($offset>0){
|
||||
if($this->meta['seekable']){
|
||||
fseek($this->source,-$offset,SEEK_CUR);//if seeking isnt supported the internal read buffer will be used
|
||||
}else{
|
||||
$pos=strlen($this->readBuffer);
|
||||
$result=$this->readBuffer;
|
||||
}
|
||||
}
|
||||
while($count>$pos){
|
||||
$data=fread($this->source,8192);
|
||||
$pos+=8192;
|
||||
if(strlen($data)){
|
||||
$result.=OC_Crypt::decrypt($data);
|
||||
}
|
||||
}
|
||||
if(!$this->meta['seekable']){
|
||||
$this->readBuffer=substr($result,$count);
|
||||
}
|
||||
return substr($result,0,$count);
|
||||
}
|
||||
|
||||
public function stream_write($data){
|
||||
$length=strlen($data);
|
||||
$written=0;
|
||||
$currentPos=ftell($this->source);
|
||||
if($currentPos%8192!=0){
|
||||
//make sure we always start on a block start
|
||||
fseek($this->source,-($currentPos%8192),SEEK_CUR);
|
||||
$encryptedBlock=fread($this->source,8192);
|
||||
fseek($this->source,-($currentPos%8192),SEEK_CUR);
|
||||
$block=OC_Crypt::decrypt($encryptedBlock);
|
||||
$data=substr($block,0,$currentPos%8192).$data;
|
||||
}
|
||||
while(strlen($data)>0){
|
||||
if(strlen($data)<8192){
|
||||
//fetch the current data in that block and append it to the input so we always write entire blocks
|
||||
$oldPos=ftell($this->source);
|
||||
$encryptedBlock=fread($this->source,8192);
|
||||
fseek($this->source,$oldPos);
|
||||
$block=OC_Crypt::decrypt($encryptedBlock);
|
||||
$data.=substr($block,strlen($data));
|
||||
}
|
||||
$encrypted=OC_Crypt::encrypt(substr($data,0,8192));
|
||||
fwrite($this->source,$encrypted);
|
||||
$data=substr($data,8192);
|
||||
}
|
||||
return $length;
|
||||
}
|
||||
|
||||
public function stream_set_option($option,$arg1,$arg2){
|
||||
switch($option){
|
||||
case STREAM_OPTION_BLOCKING:
|
||||
stream_set_blocking($this->source,$arg1);
|
||||
break;
|
||||
case STREAM_OPTION_READ_TIMEOUT:
|
||||
stream_set_timeout($this->source,$arg1,$arg2);
|
||||
break;
|
||||
case STREAM_OPTION_WRITE_BUFFER:
|
||||
stream_set_write_buffer($this->source,$arg1,$arg2);
|
||||
}
|
||||
}
|
||||
|
||||
public function stream_stat(){
|
||||
return fstat($this->source);
|
||||
}
|
||||
|
||||
public function stream_lock($mode){
|
||||
flock($this->source,$mode);
|
||||
}
|
||||
|
||||
public function stream_flush(){
|
||||
return fflush($this->source);
|
||||
}
|
||||
|
||||
public function stream_eof(){
|
||||
return feof($this->source);
|
||||
}
|
||||
|
||||
public function stream_close(){
|
||||
OC_FileCache::put($this->path,array('encrypted'=>true));
|
||||
return fclose($this->source);
|
||||
}
|
||||
}
|
||||
115
apps/files_encryption/lib/proxy.php
Normal file
115
apps/files_encryption/lib/proxy.php
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Robin Appelman
|
||||
* @copyright 2011 Robin Appelman icewind1991@gmail.com
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* transparent encryption
|
||||
*/
|
||||
|
||||
class OC_FileProxy_Encryption extends OC_FileProxy{
|
||||
private static $blackList=null; //mimetypes blacklisted from encryption
|
||||
private static $metaData=array(); //metadata cache
|
||||
|
||||
/**
|
||||
* check if a file should be encrypted during write
|
||||
* @param string $path
|
||||
* @return bool
|
||||
*/
|
||||
private static function shouldEncrypt($path){
|
||||
if(is_null(self::$blackList)){
|
||||
self::$blackList=explode(',',OC_Appconfig::getValue('files_encryption','type_blacklist','jpg,png,jpeg,avi,mpg,mpeg,mkv,mp3,oga,ogv,ogg'));
|
||||
}
|
||||
if(self::isEncrypted($path)){
|
||||
return true;
|
||||
}
|
||||
$extention=substr($path,strrpos($path,'.')+1);
|
||||
if(array_search($extention,self::$blackList)===false){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* check if a file is encrypted
|
||||
* @param string $path
|
||||
* @return bool
|
||||
*/
|
||||
private static function isEncrypted($path){
|
||||
if(isset(self::$metaData[$path])){
|
||||
$metadata=self::$metaData[$path];
|
||||
}else{
|
||||
$metadata=OC_FileCache::getCached($path);
|
||||
self::$metaData[$path]=$metadata;
|
||||
}
|
||||
return (bool)$metadata['encrypted'];
|
||||
}
|
||||
|
||||
public function preFile_put_contents($path,&$data){
|
||||
if(self::shouldEncrypt($path)){
|
||||
if (!is_resource($data)) {//stream put contents should have been converter to fopen
|
||||
$data=OC_Crypt::blockEncrypt($data);
|
||||
OC_FileCache::put($path,array('encrypted'=>true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function postFile_get_contents($path,$data){
|
||||
if(self::isEncrypted($path)){
|
||||
$data=OC_Crypt::blockDecrypt($data);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function postFopen($path,&$result){
|
||||
if(!$result){
|
||||
return $result;
|
||||
}
|
||||
$meta=stream_get_meta_data($result);
|
||||
if(self::isEncrypted($path)){
|
||||
fclose($result);
|
||||
$result=fopen('crypt://'.$path,$meta['mode']);
|
||||
}elseif(self::shouldEncrypt($path) and $meta['mode']!='r' and $meta['mode']!='rb'){
|
||||
if(OC_Filesystem::file_exists($path) and OC_Filesystem::filesize($path)>0){
|
||||
//first encrypt the target file so we don't end up with a half encrypted file
|
||||
OC_Log::write('files_encryption','Decrypting '.$path.' before writing',OC_Log::DEBUG);
|
||||
$tmp=fopen('php://temp');
|
||||
while(!feof($result)){
|
||||
$chunk=fread($result,8192);
|
||||
if($chunk){
|
||||
fwrite($tmp,$chunk);
|
||||
}
|
||||
}
|
||||
fclose($result);
|
||||
OC_Filesystem::file_put_contents($path,$tmp);
|
||||
fclose($tmp);
|
||||
}
|
||||
$result=fopen('crypt://'.$path,$meta['mode']);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function postGetMimeType($path,$mime){
|
||||
if(self::isEncrypted($path)){
|
||||
$mime=OC_Helper::getMimeType('crypt://'.$path,'w');
|
||||
}
|
||||
return $mime;
|
||||
}
|
||||
}
|
||||
16
apps/files_encryption/settings.php
Normal file
16
apps/files_encryption/settings.php
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2011 Robin Appelman <icewind@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
$tmpl = new OC_Template( 'files_encryption', 'settings');
|
||||
$blackList=explode(',',OC_Appconfig::getValue('files_encryption','type_blacklist','jpg,png,jpeg,avi,mpg,mpeg,mkv,mp3,oga,ogv,ogg'));
|
||||
$tmpl->assign('blacklist',$blackList);
|
||||
|
||||
OC_Util::addScript('files_encryption','settings');
|
||||
OC_Util::addScript('core','multiselect');
|
||||
|
||||
return $tmpl->fetchPage();
|
||||
11
apps/files_encryption/templates/settings.php
Normal file
11
apps/files_encryption/templates/settings.php
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<form id="calendar">
|
||||
<fieldset class="personalblock">
|
||||
<strong><?php echo $l->t('Encryption'); ?></strong>
|
||||
<?php echo $l->t("Exclude the following file types from encryption"); ?>
|
||||
<select id='encryption_blacklist' title="<?php echo $l->t('None')?>" multiple="multiple">
|
||||
<?php foreach($_["blacklist"] as $type): ?>
|
||||
<option selected="selected" value="<?php echo $type;?>"><?php echo $type;?></option>
|
||||
<?php endforeach;?>
|
||||
</select>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
|
@ -58,7 +58,7 @@ class OC_Filestorage_Shared extends OC_Filestorage {
|
|||
}
|
||||
|
||||
public function mkdir($path) {
|
||||
if ($path == "" || $path == "/" || !$this->is_writeable($path)) {
|
||||
if ($path == "" || $path == "/" || !$this->is_writable($path)) {
|
||||
return false;
|
||||
} else {
|
||||
$source = $this->getSource($path);
|
||||
|
|
@ -79,7 +79,6 @@ class OC_Filestorage_Shared extends OC_Filestorage {
|
|||
if ($path == "" || $path == "/") {
|
||||
$path = $this->datadir.$path;
|
||||
$sharedItems = OC_Share::getItemsInFolder($path);
|
||||
global $FAKEDIRS;
|
||||
$files = array();
|
||||
foreach ($sharedItems as $item) {
|
||||
// If item is in the root of the shared storage provider and the item exists add it to the fakedirs
|
||||
|
|
@ -87,7 +86,7 @@ class OC_Filestorage_Shared extends OC_Filestorage {
|
|||
$files[] = basename($item['target']);
|
||||
}
|
||||
}
|
||||
$FAKEDIRS['shared'] = $files;
|
||||
OC_FakeDirStream::$dirs['shared']=$files;
|
||||
return opendir('fakedir://shared');
|
||||
} else {
|
||||
$source = $this->getSource($path);
|
||||
|
|
@ -281,14 +280,6 @@ class OC_Filestorage_Shared extends OC_Filestorage {
|
|||
}
|
||||
}
|
||||
|
||||
public function readfile($path) {
|
||||
$source = $this->getSource($path);
|
||||
if ($source) {
|
||||
$storage = OC_Filesystem::getStorage($source);
|
||||
return $storage->readfile($this->getInternalPath($source));
|
||||
}
|
||||
}
|
||||
|
||||
public function filectime($path) {
|
||||
if ($path == "" || $path == "/") {
|
||||
$ctime = 0;
|
||||
|
|
@ -514,7 +505,13 @@ class OC_Filestorage_Shared extends OC_Filestorage {
|
|||
return $storage->getLocalFile($this->getInternalPath($source));
|
||||
}
|
||||
}
|
||||
|
||||
public function touch($path, $mtime=null){
|
||||
$source = $this->getSource($path);
|
||||
if ($source) {
|
||||
$storage = OC_Filesystem::getStorage($source);
|
||||
return $storage->touch($this->getInternalPath($source),$time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ function handleRemove($name) {
|
|||
|
||||
function handleGetThumbnails($albumname) {
|
||||
OC_Response::enableCaching(3600 * 24); // 24 hour
|
||||
$thumbnail = OC::$CONFIG_DATADIRECTORY.'/../gallery/'.$albumname.'.png';
|
||||
error_log(htmlentities($albumname));
|
||||
$thumbnail = OC::$CONFIG_DATADIRECTORY.'/../gallery/'.urldecode($albumname).'.png';
|
||||
header('Content-Type: '.OC_Image::getMimeTypeForFile($thumbnail));
|
||||
OC_Response::sendFile($thumbnail);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ while ($r = $result->fetchRow()) {
|
|||
$album_name = $r['album_name'];
|
||||
$tmp_res = OC_Gallery_Photo::find($r['album_id']);
|
||||
|
||||
$a[] = array('name' => $album_name, 'numOfItems' => min($tmp_res->numRows(), 10), 'bgPath' => OC::$WEBROOT.'/data/'.OC_User::getUser().'/gallery/'.$album_name.'.png');
|
||||
$a[] = array('name' => utf8_encode($album_name), 'numOfItems' => min($tmp_res->numRows(), 10), 'bgPath' => OC::$WEBROOT.'/data/'.OC_User::getUser().'/gallery/'.$album_name.'.png');
|
||||
}
|
||||
|
||||
OC_JSON::success(array('albums'=>$a));
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ OC_App::addNavigationEntry( array(
|
|||
'icon' => OC_Helper::imagePath('core', 'places/picture.svg'),
|
||||
'name' => $l->t('Gallery')));
|
||||
|
||||
class OC_GallerySearchProvider extends OC_Search_Provider{
|
||||
function search($query){
|
||||
class OC_GallerySearchProvider implements OC_Search_Provider{
|
||||
static function search($query){
|
||||
$stmt = OC_DB::prepare('SELECT * FROM *PREFIX*gallery_albums WHERE uid_owner = ? AND album_name LIKE ?');
|
||||
$result = $stmt->execute(array(OC_User::getUser(),'%'.$query.'%'));
|
||||
$results=array();
|
||||
|
|
@ -52,7 +52,7 @@ OC_App::addNavigationEntry( array(
|
|||
}
|
||||
}
|
||||
|
||||
new OC_GallerySearchProvider();
|
||||
OC_Search::registerProvider('OC_GallerySearchProvider');
|
||||
|
||||
require_once('apps/gallery/lib/hooks_handlers.php');
|
||||
?>
|
||||
|
|
|
|||
|
|
@ -54,9 +54,9 @@ Albums={
|
|||
event.preventDefault();
|
||||
galleryRemove(event.data.name);
|
||||
});
|
||||
$("a.view", local).attr('href','?view='+escape(a.name));
|
||||
$('h1',local).text(a.name);
|
||||
$(".gallery_album_cover", local).attr('title',a.name);
|
||||
$("a.view", local).attr('href','?view='+decodeURIComponent(escape(a.name)));
|
||||
$('h1',local).text(decodeURIComponent(escape(a.name)));
|
||||
$(".gallery_album_cover", local).attr('title',decodeURIComponent(escape(a.name)));
|
||||
$(".gallery_album_cover", local).css('background-repeat', 'no-repeat');
|
||||
$(".gallery_album_cover", local).css('background-position', '0');
|
||||
$(".gallery_album_cover", local).css('background-image','url("ajax/galleryOp.php?operation=get_covers&albumname='+escape(a.name)+'")');
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ OC_Util::addScript('gallery', 'album_cover');
|
|||
$l = new OC_L10N('gallery');
|
||||
?>
|
||||
|
||||
<div id="notification"><div id="gallery_notification_text">Creating thumbnails</div></div>
|
||||
<div id="controls">
|
||||
<div id="scan">
|
||||
<div id="scanprogressbar"></div>
|
||||
|
|
|
|||
|
|
@ -120,7 +120,10 @@ if($arguments['action']){
|
|||
OC_Filesystem::readfile($arguments['path']);
|
||||
exit;
|
||||
case 'find_music':
|
||||
OC_JSON::encodedPrint(OC_FileCache::searchByMime('audio'));
|
||||
$music=OC_FileCache::searchByMime('audio');
|
||||
$ogg=OC_FileCache::searchByMime('application','ogg');
|
||||
$music=array_merge($music,$ogg);
|
||||
OC_JSON::encodedPrint($music);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,4 +30,5 @@ OC_APP::registerPersonal('media','settings');
|
|||
OC_App::register( array( 'order' => 3, 'id' => 'media', 'name' => 'Media' ));
|
||||
|
||||
OC_App::addNavigationEntry(array('id' => 'media_index', 'order' => 2, 'href' => OC_Helper::linkTo('media', 'index.php'), 'icon' => OC_Helper::imagePath('core', 'places/music.svg'), 'name' => $l->t('Music')));
|
||||
?>
|
||||
|
||||
OC_Search::registerProvider('OC_MediaSearchProvider');
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ class OC_MEDIA{
|
|||
*/
|
||||
public static function updateFile($params){
|
||||
$path=$params['path'];
|
||||
if(!$path) return;
|
||||
require_once 'lib_scanner.php';
|
||||
require_once 'lib_collection.php';
|
||||
//fix a bug where there were multiply '/' in front of the path, it should only be one
|
||||
|
|
@ -81,8 +82,8 @@ class OC_MEDIA{
|
|||
}
|
||||
}
|
||||
|
||||
class OC_MediaSearchProvider extends OC_Search_Provider{
|
||||
function search($query){
|
||||
class OC_MediaSearchProvider implements OC_Search_Provider{
|
||||
static function search($query){
|
||||
require_once('lib_collection.php');
|
||||
$artists=OC_MEDIA_COLLECTION::getArtists($query);
|
||||
$albums=OC_MEDIA_COLLECTION::getAlbums(0,$query);
|
||||
|
|
@ -106,5 +107,3 @@ class OC_MediaSearchProvider extends OC_Search_Provider{
|
|||
}
|
||||
}
|
||||
|
||||
new OC_MediaSearchProvider();
|
||||
?>
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ class OC_MEDIA_SCANNER{
|
|||
*/
|
||||
public static function scanCollection($eventSource=null){
|
||||
$music=OC_FileCache::searchByMime('audio');
|
||||
$ogg=OC_FileCache::searchByMime('application','ogg');
|
||||
$music=array_merge($music,$ogg);
|
||||
$eventSource->send('count',count($music));
|
||||
$songs=0;
|
||||
foreach($music as $file){
|
||||
|
|
|
|||
61
apps/remoteStorage/BearerAuth.php
Normal file
61
apps/remoteStorage/BearerAuth.php
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* HTTP Bearer Authentication handler
|
||||
*
|
||||
* Use this class for easy http authentication setup
|
||||
*
|
||||
* @package Sabre
|
||||
* @subpackage HTTP
|
||||
* @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
|
||||
* @author Evert Pot (http://www.rooftopsolutions.nl/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
class Sabre_HTTP_BearerAuth extends Sabre_HTTP_AbstractAuth {
|
||||
|
||||
/**
|
||||
* Returns the supplied username and password.
|
||||
*
|
||||
* The returned array has two values:
|
||||
* * 0 - username
|
||||
* * 1 - password
|
||||
*
|
||||
* If nothing was supplied, 'false' will be returned
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getUserPass() {
|
||||
|
||||
// Apache and mod_php
|
||||
if (($user = $this->httpRequest->getRawServerValue('PHP_AUTH_USER')) && ($pass = $this->httpRequest->getRawServerValue('PHP_AUTH_PW'))) {
|
||||
|
||||
return array($user,$pass);
|
||||
|
||||
}
|
||||
|
||||
// Most other webservers
|
||||
$auth = $this->httpRequest->getHeader('Authorization');
|
||||
|
||||
if (!$auth) return false;
|
||||
|
||||
if (strpos(strtolower($auth),'bearer')!==0) return false;
|
||||
|
||||
return explode(':', base64_decode(substr($auth, 7)));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an HTTP 401 header, forcing login
|
||||
*
|
||||
* This should be called when username and password are incorrect, or not supplied at all
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function requireLogin() {
|
||||
|
||||
$this->httpResponse->setHeader('WWW-Authenticate','Basic realm="' . $this->realm . '"');
|
||||
$this->httpResponse->sendStatus(401);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -33,6 +33,7 @@ require_once('../../lib/base.php');
|
|||
OC_Util::checkAppEnabled('remoteStorage');
|
||||
require_once('Sabre/autoload.php');
|
||||
require_once('lib_remoteStorage.php');
|
||||
require_once('BearerAuth.php');
|
||||
require_once('oauth_ro_auth.php');
|
||||
|
||||
ini_set('default_charset', 'UTF-8');
|
||||
|
|
@ -68,7 +69,10 @@ if(count($pathParts) >= 3 && $pathParts[0] == '') {
|
|||
$server->setBaseUri(OC::$WEBROOT."/apps/remoteStorage/WebDAV.php/$ownCloudUser");
|
||||
|
||||
// Auth backend
|
||||
$authBackend = new OC_Connector_Sabre_Auth_ro_oauth(OC_remoteStorage::getValidTokens($ownCloudUser, $category));
|
||||
$authBackend = new OC_Connector_Sabre_Auth_ro_oauth(
|
||||
OC_remoteStorage::getValidTokens($ownCloudUser, $category),
|
||||
$category
|
||||
);
|
||||
|
||||
$authPlugin = new Sabre_DAV_Auth_Plugin($authBackend,'ownCloud');//should use $validTokens here
|
||||
$server->addPlugin($authPlugin);
|
||||
|
|
@ -81,5 +85,6 @@ if(count($pathParts) >= 3 && $pathParts[0] == '') {
|
|||
// And off we go!
|
||||
$server->exec();
|
||||
} else {
|
||||
die('not the right address format '.var_export($pathParts, true));
|
||||
//die('not the right address format '.var_export($pathParts, true));
|
||||
die('not the right address format');
|
||||
}
|
||||
|
|
|
|||
41
apps/remoteStorage/ajax/revokeToken.php
Normal file
41
apps/remoteStorage/ajax/revokeToken.php
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* Original:
|
||||
* @author Frank Karlitschek
|
||||
* @copyright 2010 Frank Karlitschek karlitschek@kde.org
|
||||
*
|
||||
* Adapted:
|
||||
* @author Michiel de Jong, 2012
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// Do not load FS ...
|
||||
$RUNTIME_NOSETUPFS = true;
|
||||
|
||||
require_once('../../../lib/base.php');
|
||||
OC_Util::checkAppEnabled('remoteStorage');
|
||||
require_once('Sabre/autoload.php');
|
||||
require_once('../lib_remoteStorage.php');
|
||||
|
||||
ini_set('default_charset', 'UTF-8');
|
||||
#ini_set('error_reporting', '');
|
||||
@ob_clean();
|
||||
|
||||
echo OC_remoteStorage::deleteToken(file_get_contents("php://input"));
|
||||
|
|
@ -3,3 +3,4 @@ OC_App::register( array(
|
|||
'order' => 10,
|
||||
'id' => 'remoteStorage',
|
||||
'name' => 'remoteStorage compatibility' ));
|
||||
OC_APP::registerPersonal('remoteStorage','settings');
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
<id>remoteStorage</id>
|
||||
<name>remoteStorage compatibility</name>
|
||||
<description>Enables your users to use ownCloud as their remote storage for unhosted applications.</description>
|
||||
<version>0.2</version>
|
||||
<licence>AGPL</licence>
|
||||
<version>0.5</version>
|
||||
<licence>AGPL or MIT</licence>
|
||||
<author>Michiel de Jong</author>
|
||||
<require>2</require>
|
||||
</info>
|
||||
|
|
|
|||
8
apps/remoteStorage/auth.css
Normal file
8
apps/remoteStorage/auth.css
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
h2 { font-size:2em; font-weight:bold; margin-bottom:1em; white-space:nowrap; }
|
||||
ul.scopes { list-style:disc; }
|
||||
ul.scopes li { white-space:nowrap; }
|
||||
h2 img { width: 50% }
|
||||
#oauth { margin:4em auto 2em; width:20em; }
|
||||
#allow-auth { background-color:#5c3; text-shadow:#5e3 0 1px 0; color:#fff;
|
||||
-webkit-box-shadow:0 1px 1px #fff, 0 1px 1px #5f3 inset; -moz-box-shadow:0 1px 1px #fff, 0 1px 1px #5f3 inset; box-shadow:0 1px 1px #fff, 0 1px 1px #5f3 inset; }
|
||||
#deny-auth { padding:0; margin:.7em; border:0; background:none; font-size:1.2em; -moz-box-shadow: 0 0 0 #fff, 0 0 0 #fff inset; -webkit-box-shadow: 0 0 0 #fff, 0 0 0 #fff inset; box-shadow: 0 0 0 #fff, 0 0 0 #fff inset; }
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
* @copyright 2010 Frank Karlitschek karlitschek@kde.org
|
||||
*
|
||||
* Adapted:
|
||||
* @author Michiel de Jong, 2011
|
||||
* @author Michiel de Jong, 2012
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
|
|
@ -17,11 +17,11 @@
|
|||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -39,24 +39,8 @@ ini_set('default_charset', 'UTF-8');
|
|||
#ini_set('error_reporting', '');
|
||||
@ob_clean();
|
||||
|
||||
//allow use as remote storage for other websites
|
||||
if(isset($_SERVER['HTTP_ORIGIN'])) {
|
||||
header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
|
||||
header('Access-Control-Max-Age: 3600');
|
||||
header('Access-Control-Allow-Methods: OPTIONS, GET, PUT, DELETE, PROPFIND');
|
||||
header('Access-Control-Allow-Headers: Authorization, Content-Type');
|
||||
} else {
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
}
|
||||
|
||||
$path = substr($_SERVER["REQUEST_URI"], strlen($_SERVER["SCRIPT_NAME"]));
|
||||
$pathParts = explode('/', $path);
|
||||
// for webdav:
|
||||
// 0/ 1 / 2 / 3 / 4 / 5 / 6 / 7
|
||||
// /$ownCloudUser/remoteStorage/webdav/$userHost/$userName/$dataScope/$key
|
||||
// for oauth:
|
||||
// 0/ 1 / 2 / 3 / 4
|
||||
// /$ownCloudUser/remoteStorage/oauth/auth
|
||||
$pathParts = explode('/', $path);
|
||||
|
||||
if(count($pathParts) == 2 && $pathParts[0] == '') {
|
||||
//TODO: input checking. these explodes may fail to produces the desired arrays:
|
||||
|
|
@ -66,19 +50,69 @@ if(count($pathParts) == 2 && $pathParts[0] == '') {
|
|||
if($k=='user_address'){
|
||||
$userAddress=$v;
|
||||
} else if($k=='redirect_uri'){
|
||||
$appUrl=$v;
|
||||
$appUrlParts=explode('/', $v);
|
||||
$appUrl = $appUrlParts[2];//bit dodgy i guess
|
||||
} else if($k=='scope'){
|
||||
$category=$v;
|
||||
$categories=$v;
|
||||
}
|
||||
}
|
||||
$currUser = OC_User::getUser();
|
||||
if($currUser == $ownCloudUser) {
|
||||
if(isset($_POST['allow'])) {
|
||||
//TODO: check if this can be faked by editing the cookie in firebug!
|
||||
$token=OC_remoteStorage::createCategory($appUrl, $category);
|
||||
$token=OC_remoteStorage::createCategories($appUrl, $categories);
|
||||
header('Location: '.$_GET['redirect_uri'].'#access_token='.$token.'&token_type=bearer');
|
||||
} else {
|
||||
echo '<form method="POST"><input name="allow" type="submit" value="Allow this web app to store stuff on your owncloud."></form>';
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>ownCloud</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<link rel="shortcut icon" href="../../../core/img/favicon.png" /><link rel="apple-touch-icon-precomposed" href="../../../core/img/favicon-touch.png" />
|
||||
<link rel="stylesheet" href="../../../core/css/styles.css" type="text/css" media="screen" />
|
||||
<link rel="stylesheet" href="../auth.css" type="text/css" media="screen" />
|
||||
</head>
|
||||
<body id="body-login">
|
||||
<div id="login">
|
||||
<header>
|
||||
<div id="header">
|
||||
<img src="../../../core/img/owncloud-logo-medium-white.png" alt="ownCloud" />
|
||||
</div>
|
||||
</header>
|
||||
<section id="main">
|
||||
<div id="oauth">
|
||||
<h2><img src="../remoteStorage-big.png" alt="remoteStorage" /></h2>
|
||||
<p><strong><?php $appUrlParts = explode('/', $_GET['redirect_uri']); echo htmlentities($appUrlParts[2]); ?></strong>
|
||||
requests read & write access to your
|
||||
<?php
|
||||
$categories = explode(',', htmlentities($_GET['scope']));
|
||||
if(!count($categories)) {
|
||||
echo htmlentities($_GET['scope']);
|
||||
} else {
|
||||
echo '<em>'.$categories[0].'</em>';
|
||||
if(count($categories)==2) {
|
||||
echo ' and <em>'.$categories[1].'</em>';
|
||||
} else if(count($categories)>2) {
|
||||
for($i=1; $i<count($categories)-1; $i++) {
|
||||
echo ', <em>'.$categories[$i].'</em>';
|
||||
}
|
||||
echo ', and <em>'.$categories[$i].'</em>';
|
||||
}
|
||||
}
|
||||
?>.
|
||||
</p>
|
||||
<form accept-charset="UTF-8" method="post">
|
||||
<input id="allow-auth" name="allow" type="submit" value="Allow" />
|
||||
<input id="deny-auth" name="deny" type="submit" value="Deny" />
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<footer><p class="info"><a href="http://owncloud.org/">ownCloud</a> – web services under your control</p></footer>
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
}
|
||||
} else {
|
||||
if((isset($_SERVER['HTTPS'])) && ($_SERVER['HTTPS'])) {
|
||||
|
|
@ -88,13 +122,13 @@ if(count($pathParts) == 2 && $pathParts[0] == '') {
|
|||
}
|
||||
$url .= $_SERVER['SERVER_NAME'];
|
||||
$url .= substr($_SERVER['SCRIPT_NAME'], 0, -strlen('apps/remoteStorage/compat.php'));
|
||||
die('You are '.($currUser?'logged in as '.$currUser.' instead of '.$ownCloudUser:'not logged in').'. Please '
|
||||
.'<input type="submit" onclick="'
|
||||
."window.open('$url','Close me!','height=600,width=300');"
|
||||
.'" value="log in">'
|
||||
.', close the pop-up, and '
|
||||
.'<form method="POST"><input name="allow" type="submit" value="Click here"></form>');
|
||||
if($currUser) {
|
||||
die('You are logged in as '.$currUser.' instead of '.$ownCloudUser);
|
||||
} else {
|
||||
header('Location: /?redirect_url='.urlencode('/apps/remoteStorage/auth.php'.$_SERVER['PATH_INFO'].'?'.$_SERVER['QUERY_STRING']));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
die('please use auth.php/username?params. '.var_export($pathParts, true));
|
||||
//die('please use auth.php/username?params. '.var_export($pathParts, true));
|
||||
die('please use auth.php/username?params.');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,11 +2,13 @@
|
|||
|
||||
class OC_remoteStorage {
|
||||
public static function getValidTokens($ownCloudUser, $category) {
|
||||
$query=OC_DB::prepare("SELECT token,appUrl FROM *PREFIX*authtoken WHERE user=? AND category=? LIMIT 100");
|
||||
$result=$query->execute(array($ownCloudUser,$category));
|
||||
$query=OC_DB::prepare("SELECT token,appUrl,category FROM *PREFIX*authtoken WHERE user=? LIMIT 100");
|
||||
$result=$query->execute(array($ownCloudUser));
|
||||
$ret = array();
|
||||
while($row=$result->fetchRow()){
|
||||
$ret[$row['token']]=true;
|
||||
if(in_array($category, explode(',', $row['category']))) {
|
||||
$ret[$row['token']]=true;
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
|
@ -18,8 +20,8 @@ class OC_remoteStorage {
|
|||
$ret = array();
|
||||
while($row=$result->fetchRow()){
|
||||
$ret[$row['token']] = array(
|
||||
'appUrl' => $row['appurl'],
|
||||
'category' => $row['category'],
|
||||
'appUrl' => $row['appUrl'],
|
||||
'categories' => $row['category'],
|
||||
);
|
||||
}
|
||||
return $ret;
|
||||
|
|
@ -29,22 +31,25 @@ class OC_remoteStorage {
|
|||
$user=OC_User::getUser();
|
||||
$query=OC_DB::prepare("DELETE FROM *PREFIX*authtoken WHERE token=? AND user=?");
|
||||
$result=$query->execute(array($token,$user));
|
||||
return 'unknown';//how can we see if any rows were affected?
|
||||
}
|
||||
private static function addToken($token, $appUrl, $category){
|
||||
private static function addToken($token, $appUrl, $categories){
|
||||
$user=OC_User::getUser();
|
||||
$query=OC_DB::prepare("INSERT INTO *PREFIX*authtoken (`token`,`appUrl`,`user`,`category`) VALUES(?,?,?,?)");
|
||||
$result=$query->execute(array($token,$appUrl,$user,$category));
|
||||
$result=$query->execute(array($token,$appUrl,$user,$categories));
|
||||
}
|
||||
public static function createCategory($appUrl, $category) {
|
||||
public static function createCategories($appUrl, $categories) {
|
||||
$token=uniqid();
|
||||
self::addToken($token, $appUrl, $category);
|
||||
//TODO: input checking on $category
|
||||
OC_Util::setupFS(OC_User::getUser());
|
||||
$scopePathParts = array('remoteStorage', $category);
|
||||
for($i=0;$i<=count($scopePathParts);$i++){
|
||||
$thisPath = '/'.implode('/', array_slice($scopePathParts, 0, $i));
|
||||
if(!OC_Filesystem::file_exists($thisPath)) {
|
||||
OC_Filesystem::mkdir($thisPath);
|
||||
self::addToken($token, $appUrl, $categories);
|
||||
foreach(explode(',', $categories) as $category) {
|
||||
//TODO: input checking on $category
|
||||
$scopePathParts = array('remoteStorage', $category);
|
||||
for($i=0;$i<=count($scopePathParts);$i++){
|
||||
$thisPath = '/'.implode('/', array_slice($scopePathParts, 0, $i));
|
||||
if(!OC_Filesystem::file_exists($thisPath)) {
|
||||
OC_Filesystem::mkdir($thisPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
return base64_encode('remoteStorage:'.$token);
|
||||
|
|
|
|||
|
|
@ -16,9 +16,10 @@
|
|||
|
||||
class OC_Connector_Sabre_Auth_ro_oauth extends Sabre_DAV_Auth_Backend_AbstractBasic {
|
||||
private $validTokens;
|
||||
|
||||
public function __construct($validTokensArg) {
|
||||
private $category;
|
||||
public function __construct($validTokensArg, $categoryArg) {
|
||||
$this->validTokens = $validTokensArg;
|
||||
$this->category = $categoryArg;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -31,29 +32,31 @@ class OC_Connector_Sabre_Auth_ro_oauth extends Sabre_DAV_Auth_Backend_AbstractBa
|
|||
*/
|
||||
protected function validateUserPass($username, $password){
|
||||
//always give read-only:
|
||||
if(in_array($_SERVER['REQUEST_METHOD'], array('GET', 'HEAD', 'OPTIONS'))) {
|
||||
OC_Util::setUpFS();
|
||||
return true;
|
||||
} else if(isset($this->validTokens[$password]) && $this->validTokens[$password] == $username) {
|
||||
if(($_SERVER['REQUEST_METHOD'] == 'OPTIONS')
|
||||
|| (isset($this->validTokens[$password]))
|
||||
|| (($_SERVER['REQUEST_METHOD'] == 'GET') && ($this->category == 'public'))
|
||||
) {
|
||||
OC_Util::setUpFS();
|
||||
return true;
|
||||
} else {
|
||||
var_export($_SERVER);
|
||||
var_export($this->validTokens);
|
||||
die('not getting in with "'.$username.'"/"'.$password.'"!');
|
||||
//var_export($_SERVER);
|
||||
//var_export($this->validTokens);
|
||||
//die('not getting in with "'.$username.'"/"'.$password.'"!');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//overwriting this to make it not automatically fail if no auth header is found:
|
||||
public function authenticate(Sabre_DAV_Server $server,$realm) {
|
||||
$auth = new Sabre_HTTP_BasicAuth();
|
||||
$auth = new Sabre_HTTP_BearerAuth();
|
||||
$auth->setHTTPRequest($server->httpRequest);
|
||||
$auth->setHTTPResponse($server->httpResponse);
|
||||
$auth->setRealm($realm);
|
||||
$userpass = $auth->getUserPass();
|
||||
if (!$userpass) {
|
||||
if(in_array($_SERVER['REQUEST_METHOD'], array('OPTIONS'))) {
|
||||
if(($_SERVER['REQUEST_METHOD'] == 'OPTIONS')
|
||||
||(($_SERVER['REQUEST_METHOD'] == 'GET') && ($this->category == 'public'))
|
||||
) {
|
||||
$userpass = array('', '');
|
||||
} else {
|
||||
$auth->requireLogin();
|
||||
|
|
|
|||
BIN
apps/remoteStorage/remoteStorage-big.png
Normal file
BIN
apps/remoteStorage/remoteStorage-big.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.5 KiB |
BIN
apps/remoteStorage/remoteStorage.png
Normal file
BIN
apps/remoteStorage/remoteStorage.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
7
apps/remoteStorage/settings.php
Normal file
7
apps/remoteStorage/settings.php
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
require_once('lib_remoteStorage.php');
|
||||
$tmpl = new OC_Template( 'remoteStorage', 'settings');
|
||||
|
||||
return $tmpl->fetchPage();
|
||||
?>
|
||||
28
apps/remoteStorage/templates/settings.php
Normal file
28
apps/remoteStorage/templates/settings.php
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<fieldset class="personalblock">
|
||||
<?php
|
||||
echo '<img src="/apps/remoteStorage/remoteStorage.png" style="width:16px"> '
|
||||
.'<strong>'.$l->t('remoteStorage').'</strong> user address: '
|
||||
.OC_User::getUser().'@'.$_SERVER['SERVER_NAME']
|
||||
.' (<a href="http://unhosted.org/">more info</a>)';
|
||||
?>
|
||||
<p><em>Apps that currently have access to your ownCloud:</em></p>
|
||||
<script>
|
||||
function revokeToken(token) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', '/apps/remoteStorage/ajax/revokeToken.php', true);
|
||||
xhr.send(token);
|
||||
}
|
||||
</script>
|
||||
<ul>
|
||||
<?php
|
||||
foreach(OC_remoteStorage::getAllTokens() as $token => $details) {
|
||||
echo '<li onmouseover="'
|
||||
.'document.getElementById(\'revoke_'.$token.'\').style.display=\'inline\';"'
|
||||
.'onmouseout="document.getElementById(\'revoke_'.$token.'\').style.display=\'none\';"'
|
||||
.'> <strong>'.$details['appUrl'].'</strong>: '.$details['categories']
|
||||
.' <a href="#" title="Revoke" class="action" style="display:none" id="revoke_'.$token.'" onclick="'
|
||||
.'revokeToken(\''.$token.'\');this.parentNode.style.display=\'none\';"'
|
||||
.'><img src="/core/img/actions/delete.svg"></a></li>'."\n";
|
||||
}
|
||||
?></ul>
|
||||
</fieldset>
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
$params = array('ldap_host', 'ldap_port', 'ldap_dn', 'ldap_password', 'ldap_base', 'ldap_filter', 'ldap_display_name', 'ldap_tls', 'ldap_nocase');
|
||||
$params = array('ldap_host', 'ldap_port', 'ldap_dn', 'ldap_password', 'ldap_base', 'ldap_userlist_filter', 'ldap_login_filter', 'ldap_display_name', 'ldap_tls', 'ldap_nocase'. 'ldap_quota_def', 'ldap_quota_attr', 'ldap_email_attr');
|
||||
|
||||
if ($_POST) {
|
||||
foreach($params as $param){
|
||||
|
|
@ -29,12 +29,12 @@ if ($_POST) {
|
|||
}
|
||||
elseif('ldap_tls' == $param) {
|
||||
// unchecked checkboxes are not included in the post paramters
|
||||
OC_Appconfig::setValue('user_ldap', $param, 0);
|
||||
OC_Appconfig::setValue('user_ldap', $param, 0);
|
||||
}
|
||||
elseif('ldap_nocase' == $param) {
|
||||
OC_Appconfig::setValue('user_ldap', $param, 0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,15 +6,16 @@
|
|||
<p><label for="ldap_dn"><?php echo $l->t('Name');?></label><input type="text" id="ldap_dn" name="ldap_dn" value="<?php echo $_['ldap_dn']; ?>" />
|
||||
<label for="ldap_password"><?php echo $l->t('Password');?></label><input type="password" id="ldap_password" name="ldap_password" value="<?php echo $_['ldap_password']; ?>" />
|
||||
<small><?php echo $l->t('Leave both empty for anonymous bind for search, then bind with users credentials.');?></small></p>
|
||||
<p><label for="ldap_base"><?php echo $l->t('Base');?></label><input type="text" id="ldap_base" name="ldap_base" value="<?php echo $_['ldap_base']; ?>" />
|
||||
<label for="ldap_filter"><?php echo $l->t('Filter (use %%uid placeholder)');?></label><input type="text" id="ldap_filter" name="ldap_filter" value="<?php echo $_['ldap_filter']; ?>" /></p>
|
||||
<p><label for="ldap_base"><?php echo $l->t('Base');?></label><input type="text" id="ldap_base" name="ldap_base" value="<?php echo $_['ldap_base']; ?>" /></p>
|
||||
<p><label for="ldap_login_filter"><?php echo $l->t('User Login Filter');?></label><input type="text" id="ldap_login_filter" name="ldap_login_filter" value="<?php echo $_['ldap_login_filter']; ?>" /><small><?php echo $l->t('use %%uid placeholder, e.g. uid=%%uid');?></small></p>
|
||||
<p><label for="ldap_userlist_filter"><?php echo $l->t('User List Filter');?></label><input type="text" id="ldap_userlist_filter" name="ldap_userlist_filter" value="<?php echo $_['ldap_userlist_filter']; ?>" /><small><?php echo $l->t('without any placeholder, e.g. "objectClass=person".');?> </p>
|
||||
<p><label for="ldap_display_name"><?php echo $l->t('Display Name Field');?></label><input type="text" id="ldap_display_name" name="ldap_display_name" value="<?php echo $_['ldap_display_name']; ?>" />
|
||||
<small><?php echo $l->t('Currently the display name field needs to be the same you matched %%uid against in the filter above, because ownCloud doesn\'t distinguish between user id and user name.');?></small></p>
|
||||
<p><input type="checkbox" id="ldap_tls" name="ldap_tls" value="1"<?php if ($_['ldap_tls']) echo ' checked'; ?>><label for="ldap_tls"><?php echo $l->t('Use TLS');?></label></p>
|
||||
<p><input type="checkbox" id="ldap_nocase" name="ldap_nocase" value="1"<?php if ($_['ldap_nocase']) echo ' checked'; ?>><label for="ldap_nocase"><?php echo $l->t('Case insensitve LDAP server (Windows)');?></label></p>
|
||||
<p><label for="ldap_quota">Quota Attribute</label><input type="text" id="ldap_quota" name="ldap_quota" value="<?php echo $_['ldap_quota']; ?>" />
|
||||
<p><label for="ldap_quota_attr">Quota Attribute</label><input type="text" id="ldap_quota_attr" name="ldap_quota_attr" value="<?php echo $_['ldap_quota_attr']; ?>" />
|
||||
<label for="ldap_quota_def">Quota Default</label><input type="text" id="ldap_quota_def" name="ldap_quota_def" value="<?php echo $_['ldap_quota_def']; ?>" />bytes</p>
|
||||
<p><label for="ldap_email">Email Attribute</label><input type="text" id="ldap_email" name="ldap_email" value="<?php echo $_['ldap_email']; ?>" /></p>
|
||||
<p><label for="ldap_email_attr">Email Attribute</label><input type="text" id="ldap_email_attr" name="ldap_email_attr" value="<?php echo $_['ldap_email_attr']; ?>" /></p>
|
||||
<input type="submit" value="Save" />
|
||||
</fieldset>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -32,7 +32,8 @@ class OC_USER_LDAP extends OC_User_Backend {
|
|||
protected $ldap_dn;
|
||||
protected $ldap_password;
|
||||
protected $ldap_base;
|
||||
protected $ldap_filter;
|
||||
protected $ldap_login_filter;
|
||||
protected $ldap_userlist_filter;
|
||||
protected $ldap_tls;
|
||||
protected $ldap_nocase;
|
||||
protected $ldap_display_name;
|
||||
|
|
@ -49,7 +50,8 @@ class OC_USER_LDAP extends OC_User_Backend {
|
|||
$this->ldap_dn = OC_Appconfig::getValue('user_ldap', 'ldap_dn','');
|
||||
$this->ldap_password = OC_Appconfig::getValue('user_ldap', 'ldap_password','');
|
||||
$this->ldap_base = OC_Appconfig::getValue('user_ldap', 'ldap_base','');
|
||||
$this->ldap_filter = OC_Appconfig::getValue('user_ldap', 'ldap_filter','');
|
||||
$this->ldap_login_filter = OC_Appconfig::getValue('user_ldap', 'ldap_login_filter','');
|
||||
$this->ldap_userlist_filter = OC_Appconfig::getValue('user_ldap', 'ldap_userlist_filter','objectClass=person');
|
||||
$this->ldap_tls = OC_Appconfig::getValue('user_ldap', 'ldap_tls', 0);
|
||||
$this->ldap_nocase = OC_Appconfig::getValue('user_ldap', 'ldap_nocase', 0);
|
||||
$this->ldap_display_name = OC_Appconfig::getValue('user_ldap', 'ldap_display_name', OC_USER_BACKEND_LDAP_DEFAULT_DISPLAY_NAME);
|
||||
|
|
@ -61,7 +63,7 @@ class OC_USER_LDAP extends OC_User_Backend {
|
|||
&& !empty($this->ldap_port)
|
||||
&& ((!empty($this->ldap_dn) && !empty($this->ldap_password)) || (empty($this->ldap_dn) && empty($this->ldap_password)))
|
||||
&& !empty($this->ldap_base)
|
||||
&& !empty($this->ldap_filter)
|
||||
&& !empty($this->ldap_login_filter)
|
||||
&& !empty($this->ldap_display_name)
|
||||
)
|
||||
{
|
||||
|
|
@ -79,9 +81,13 @@ class OC_USER_LDAP extends OC_User_Backend {
|
|||
if( !$this->ldap_dc )
|
||||
return false;
|
||||
|
||||
$quota = $this->ldap_dc[$this->ldap_quota_attr][0];
|
||||
if(!empty($this->ldap_quota_attr)) {
|
||||
$quota = $this->ldap_dc[strtolower($this->ldap_quota_attr)][0];
|
||||
} else {
|
||||
$quota = false;
|
||||
}
|
||||
$quota = $quota != -1 ? $quota : $this->ldap_quota_def;
|
||||
OC_Preferences::setValue($uid, 'files', 'quota', $quota);
|
||||
OC_Preferences::setValue($uid, 'files', 'quota', OC_Helper::computerFileSize($quota));
|
||||
}
|
||||
|
||||
private function setEmail( $uid ) {
|
||||
|
|
@ -127,7 +133,7 @@ class OC_USER_LDAP extends OC_User_Backend {
|
|||
return false;
|
||||
|
||||
// get dn
|
||||
$filter = str_replace('%uid', $uid, $this->ldap_filter);
|
||||
$filter = str_replace('%uid', $uid, $this->ldap_login_filter);
|
||||
$sr = ldap_search( $this->getDs(), $this->ldap_base, $filter );
|
||||
$entries = ldap_get_entries( $this->getDs(), $sr );
|
||||
|
||||
|
|
@ -152,7 +158,7 @@ class OC_USER_LDAP extends OC_User_Backend {
|
|||
return false;
|
||||
}
|
||||
|
||||
if(!empty($this->ldap_quota) && !empty($this->ldap_quota_def)) {
|
||||
if(!empty($this->ldap_quota_attr) || !empty($this->ldap_quota_def)) {
|
||||
$this->setQuota($uid);
|
||||
}
|
||||
|
||||
|
|
@ -161,7 +167,7 @@ class OC_USER_LDAP extends OC_User_Backend {
|
|||
}
|
||||
|
||||
if($this->ldap_nocase) {
|
||||
$filter = str_replace('%uid', $uid, $this->ldap_filter);
|
||||
$filter = str_replace('%uid', $uid, $this->ldap_login_filter);
|
||||
$sr = ldap_search( $this->getDs(), $this->ldap_base, $filter );
|
||||
$entries = ldap_get_entries( $this->getDs(), $sr );
|
||||
if( $entries['count'] == 1 ) {
|
||||
|
|
@ -187,7 +193,7 @@ class OC_USER_LDAP extends OC_User_Backend {
|
|||
if(!$this->configured){
|
||||
return false;
|
||||
}
|
||||
$dn = $this->getDn($uid);
|
||||
$dn = $this->getDc($uid);
|
||||
return !empty($dn);
|
||||
}
|
||||
|
||||
|
|
@ -202,8 +208,7 @@ class OC_USER_LDAP extends OC_User_Backend {
|
|||
return false;
|
||||
|
||||
// get users
|
||||
$filter = 'objectClass=person';
|
||||
$sr = ldap_search( $this->getDs(), $this->ldap_base, $filter );
|
||||
$sr = ldap_search( $this->getDs(), $this->ldap_base, $this->ldap_userlist_filter );
|
||||
$entries = ldap_get_entries( $this->getDs(), $sr );
|
||||
if( $entries['count'] == 0 )
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
<id>user_webfinger</id>
|
||||
<name>Webfinger</name>
|
||||
<description>Provide WebFinger for all users so they get a user address like user@owncloudinstance which can be used for unhosted applications. If you don't run ownCloud in the root of your domain, for instance if you run it on example.com/owncloud/, then make sure you link example.com/.well-known/ to example.com/owncloud/apps/user_webfinger/ - by running something like "ln -s /var/www/owncloud/apps/user_webfinger /var/www/.well-known". Only enable this app if you run this ownCloud installation on a public web address, not if you run it on an intranet or on localhost.</description>
|
||||
<version>0.1</version>
|
||||
<licence>AGPL</licence>
|
||||
<version>0.2</version>
|
||||
<licence>AGPL or MIT</licence>
|
||||
<author>Michiel de Jong</author>
|
||||
<require>2</require>
|
||||
</info>
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ if($_SERVER['SCRIPT_NAME'] == '/.well-known/host-meta.php') {
|
|||
} else {
|
||||
header('Please-first: activate');
|
||||
}
|
||||
header("Content-Type: application/xml+xrd");
|
||||
header("Content-Type: application/xrd+xml");
|
||||
echo "<";
|
||||
?>
|
||||
?xml version="1.0" encoding="UTF-8"?>
|
||||
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0" xmlns:hm="http://host-meta.net/xrd/1.0">
|
||||
<hm:Host xmlns="http://host-meta.net/xrd/1.0"><?php echo $_SERVER['SERVER_NAME'] ?></hm:Host>
|
||||
<Link rel="lrdd" template="http<?php echo ($_SERVER['HTTPS']?'s':''); ?>://<?php echo $_SERVER['SERVER_NAME'] ?>/.well-known/webfinger.php?q={uri}">
|
||||
<Link rel="lrdd" template="http<?php echo (isset($_SERVER['HTTPS'])?'s':''); ?>://<?php echo $_SERVER['SERVER_NAME'] ?>/.well-known/webfinger.php?q={uri}">
|
||||
</Link>
|
||||
</XRD>
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ if($_SERVER['SCRIPT_NAME'] == '/.well-known/webfinger.php') {
|
|||
} else {
|
||||
header('Please-first: activate');
|
||||
}
|
||||
// header("Content-Type: application/xml+xrd");
|
||||
header("Content-Type: application/xrd+xml");
|
||||
|
||||
// calculate the documentroot
|
||||
// modified version of the one in lib/base.php that takes the .well-known symlink into account
|
||||
|
|
@ -22,7 +22,7 @@ if($_GET['q']) {
|
|||
if(substr($userName, 0, 5) == 'acct:') {
|
||||
$userName = substr($userName, 5);
|
||||
}
|
||||
if($_SERVER['HTTPS']) {
|
||||
if(isset($_SERVER['HTTPS'])) {
|
||||
$baseAddress = 'https://'.$_SERVER['SERVER_NAME'].'/apps/remoteStorage/';
|
||||
} else {
|
||||
$baseAddress = 'http://'.$_SERVER['SERVER_NAME'].'/apps/remoteStorage/';
|
||||
|
|
|
|||
35
core/ajax/appconfig.php
Normal file
35
core/ajax/appconfig.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2011, Robin Appelman <icewind1991@gmail.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
require_once ("../../lib/base.php");
|
||||
OC_JSON::checkLoggedIn();
|
||||
$action=isset($_POST['action'])?$_POST['action']:$_GET['action'];
|
||||
$result=false;
|
||||
switch($action){
|
||||
case 'getValue':
|
||||
$result=OC_Appconfig::getValue($_GET['app'],$_GET['key'],$_GET['default']);
|
||||
break;
|
||||
case 'setValue':
|
||||
$result=OC_Appconfig::setValue($_POST['app'],$_POST['key'],$_POST['value']);
|
||||
break;
|
||||
case 'getApps':
|
||||
$result=OC_Appconfig::getApps();
|
||||
break;
|
||||
case 'getKeys':
|
||||
$result=OC_Appconfig::getKeys($_GET['app']);
|
||||
break;
|
||||
case 'hasKey':
|
||||
$result=OC_Appconfig::hasKey($_GET['app'],$_GET['key']);
|
||||
break;
|
||||
case 'deleteKey':
|
||||
$result=OC_Appconfig::deleteKey($_POST['app'],$_POST['key']);
|
||||
break;
|
||||
case 'deleteApp':
|
||||
$result=OC_Appconfig::deleteApp($_POST['app']);
|
||||
break;
|
||||
}
|
||||
OC_JSON::success(array('data'=>$result));
|
||||
|
|
@ -128,4 +128,6 @@ div.jp-play-bar, div.jp-seek-bar { padding:0; }
|
|||
li.error { width:640px; margin:4em auto; padding:1em 1em 1em 4em; background:#ffe .8em .8em no-repeat; color: #FF3B3B; border:1px solid #ccc; -moz-border-radius:10px; -webkit-border-radius:10px; border-radius:10px; }
|
||||
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { overflow: hidden; text-overflow: ellipsis; }
|
||||
.hint { background-image: url('/core/img/actions/info.png'); background-repeat:no-repeat; color: #777777; padding-left: 25px; background-position: 0 0.3em;}
|
||||
.separator { display: inline; border-left: 1px solid #d3d3d3; border-right: 1px solid #fff; height: 10px; width:0px; margin: 4px; }
|
||||
.separator { display: inline; border-left: 1px solid #d3d3d3; border-right: 1px solid #fff; height: 10px; width:0px; margin: 4px; }
|
||||
|
||||
a.bookmarklet { background-color: #ddd; border:1px solid #ccc; padding: 5px;padding-top: 0px;padding-bottom: 2px; text-decoration: none; margin-top: 5px }
|
||||
|
|
|
|||
55
core/js/config.js
Normal file
55
core/js/config.js
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
* Copyright (c) 2011, Robin Appelman <icewind1991@gmail.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
OC.AppConfig={
|
||||
url:OC.filePath('core','ajax','appconfig.php'),
|
||||
getCall:function(action,data,callback){
|
||||
data.action=action;
|
||||
$.getJSON(OC.AppConfig.url,data,function(result){
|
||||
if(result.status='success'){
|
||||
if(callback){
|
||||
callback(result.data);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
postCall:function(action,data,callback){
|
||||
data.action=action;
|
||||
$.post(OC.AppConfig.url,data,function(result){
|
||||
if(result.status='success'){
|
||||
if(callback){
|
||||
callback(result.data);
|
||||
}
|
||||
}
|
||||
},'json');
|
||||
},
|
||||
getValue:function(app,key,defaultValue,callback){
|
||||
if(typeof defaultValue=='function'){
|
||||
callback=defaultValue;
|
||||
defaultValue=null;
|
||||
}
|
||||
OC.AppConfig.getCall('getValue',{app:app,key:key,default:defaultValue},callback);
|
||||
},
|
||||
setValue:function(app,key,value){
|
||||
OC.AppConfig.postCall('setValue',{app:app,key:key,value:value});
|
||||
},
|
||||
getApps:function(callback){
|
||||
OC.AppConfig.getCall('getApps',{},callback);
|
||||
},
|
||||
getKeys:function(app,callback){
|
||||
OC.AppConfig.getCall('getKeys',{app:app},callback);
|
||||
},
|
||||
hasKey:function(app,key,callback){
|
||||
OC.AppConfig.getCall('hasKey',{app:app,key:key},callback);
|
||||
},
|
||||
deleteKey:function(app,key){
|
||||
OC.AppConfig.postCall('deleteKey',{app:app,key:key});
|
||||
},
|
||||
deleteApp:function(app){
|
||||
OC.AppConfig.postCall('deleteApp',{app:app});
|
||||
},
|
||||
}
|
||||
//TODO OC.Preferences
|
||||
|
|
@ -125,7 +125,8 @@ OC={
|
|||
OC.search.showResults(results);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
dialogs:OCdialogs
|
||||
};
|
||||
OC.search.customResults={};
|
||||
OC.search.currentResult=-1;
|
||||
|
|
@ -252,16 +253,22 @@ function replaceSVG(){
|
|||
$('.svg').each(function(index,element){
|
||||
element=$(element);
|
||||
var background=element.css('background-image');
|
||||
if(background && background!='none'){
|
||||
background=background.substr(0,background.length-4)+'png)';
|
||||
element.css('background-image',background);
|
||||
if(background){
|
||||
var i=background.lastIndexOf('.svg');
|
||||
if(i>=0){
|
||||
background=background.substr(0,i)+'.png'+background.substr(i+4);
|
||||
element.css('background-image',background);
|
||||
}
|
||||
}
|
||||
element.find('*').each(function(index,element) {
|
||||
element=$(element);
|
||||
var background=element.css('background-image');
|
||||
if(background && background!='none'){
|
||||
background=background.substr(0,background.length-4)+'png)';
|
||||
element.css('background-image',background);
|
||||
if(background){
|
||||
var i=background.lastIndexOf('.svg');
|
||||
if(i>=0){
|
||||
background=background.substr(0,i)+'.png'+background.substr(i+4);
|
||||
element.css('background-image',background);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -444,4 +451,33 @@ $.fn.filterAttr = function(attr_name, attr_value) {
|
|||
return this.filter(function() { return $(this).attr(attr_name) === attr_value; });
|
||||
};
|
||||
|
||||
function humanFileSize(size) {
|
||||
humanList = ['B', 'kB', 'MB', 'GB', 'TB'];
|
||||
// Calculate Log with base 1024: size = 1024 ** order
|
||||
order = Math.floor(Math.log(size) / Math.log(1024));
|
||||
// Stay in range of the byte sizes that are defined
|
||||
order = Math.min(humanList.length - 1, order);
|
||||
readableFormat = humanList[order];
|
||||
relativeSize = (size / Math.pow(1024, order)).toFixed(1);
|
||||
if(relativeSize.substr(relativeSize.length-2,2)=='.0'){
|
||||
relativeSize=relativeSize.substr(0,relativeSize.length-2);
|
||||
}
|
||||
return relativeSize + ' ' + readableFormat;
|
||||
}
|
||||
|
||||
function simpleFileSize(bytes) {
|
||||
mbytes = Math.round(bytes/(1024*1024/10))/10;
|
||||
if(bytes == 0) { return '0'; }
|
||||
else if(mbytes < 0.1) { return '< 0.1'; }
|
||||
else if(mbytes > 1000) { return '> 1000'; }
|
||||
else { return mbytes.toFixed(1); }
|
||||
}
|
||||
|
||||
function formatDate(date){
|
||||
if(typeof date=='number'){
|
||||
date=new Date(date);
|
||||
}
|
||||
var monthNames = [ t('files','January'), t('files','February'), t('files','March'), t('files','April'), t('files','May'), t('files','June'),
|
||||
t('files','July'), t('files','August'), t('files','September'), t('files','October'), t('files','November'), t('files','December') ];
|
||||
return monthNames[date.getMonth()]+' '+date.getDate()+', '+date.getFullYear()+', '+((date.getHours()<10)?'0':'')+date.getHours()+':'+date.getMinutes();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,11 @@
|
|||
'minWidth': 'default;',
|
||||
};
|
||||
$.extend(settings,options);
|
||||
$.each(this.children(),function(i,option){
|
||||
if($(option).attr('selected') && settings.checked.indexOf($(option).val())==-1){
|
||||
settings.checked.push($(option).val());
|
||||
}
|
||||
});
|
||||
var button=$('<div class="multiselect button"><span>'+settings.title+'</span><span>▾</span></div>');
|
||||
var span=$('<span/>');
|
||||
span.append(button);
|
||||
|
|
@ -46,9 +51,11 @@
|
|||
});
|
||||
button.addClass('active');
|
||||
event.stopPropagation();
|
||||
var options=$(this).parent().next().children().map(function(){return $(this).val();});
|
||||
var options=$(this).parent().next().children();
|
||||
var list=$('<ul class="multiselectoptions"/>').hide().appendTo($(this).parent());
|
||||
function createItem(item,checked){
|
||||
function createItem(element,checked){
|
||||
element=$(element);
|
||||
var item=element.val();
|
||||
var id='ms'+multiSelectId+'-option-'+item;
|
||||
var input=$('<input id="'+id+'" type="checkbox"/>');
|
||||
var label=$('<label for="'+id+'">'+item+'</label>');
|
||||
|
|
@ -61,6 +68,7 @@
|
|||
input.change(function(){
|
||||
var groupname=$(this).next().text();
|
||||
if($(this).is(':checked')){
|
||||
element.attr('selected','selected');
|
||||
if(settings.oncheck){
|
||||
if(settings.oncheck(groupname)===false){
|
||||
$(this).attr('checked', false);
|
||||
|
|
@ -70,6 +78,7 @@
|
|||
settings.checked.push(groupname);
|
||||
}else{
|
||||
var index=settings.checked.indexOf(groupname);
|
||||
element.attr('selected',null);
|
||||
if(settings.onuncheck){
|
||||
if(settings.onuncheck(groupname)===false){
|
||||
$(this).attr('checked',true);
|
||||
|
|
@ -119,11 +128,11 @@
|
|||
var li=$(this).parent();
|
||||
$(this).remove();
|
||||
li.text('+ '+settings.createText);
|
||||
li.before(createItem($(this).val()));
|
||||
li.before(createItem(this));
|
||||
var select=button.parent().next();
|
||||
select.append($('<option selected="selected" value="'+$(this).val()+'">'+$(this).val()+'</option>'));
|
||||
li.prev().children('input').trigger('click');
|
||||
button.parent().data('preventHide',false);
|
||||
var select=button.parent().next();
|
||||
select.append($('<option value="'+$(this).val()+'">'+$(this).val()+'</option>'));
|
||||
if(settings.createCallback){
|
||||
settings.createCallback();
|
||||
}
|
||||
|
|
|
|||
145
core/js/oc-dialogs.js
Normal file
145
core/js/oc-dialogs.js
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Bartek Przybylski
|
||||
* @copyright 2012 Bartek Przybylski bart.p.pl@gmail.com
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* todo(bartek): add select option in form
|
||||
*/
|
||||
|
||||
/**
|
||||
* this class ease usage of jquery dialogs
|
||||
*/
|
||||
OCdialogs = {
|
||||
/**
|
||||
* displays alert dialog
|
||||
* @param text content of dialog
|
||||
* @param title dialog title
|
||||
* @param callback which will be triggered when user press OK
|
||||
*/
|
||||
alert:function(text, title, callback) {
|
||||
var content = '<p><span class="ui-icon ui-icon-alert"></span>'+text+'</p>';
|
||||
OCdialogs.message(content, title, OCdialogs.ALERT_DIALOG, OCdialogs.OK_BUTTON, callback);
|
||||
},
|
||||
/**
|
||||
* displays info dialog
|
||||
* @param text content of dialog
|
||||
* @param title dialog title
|
||||
* @param callback which will be triggered when user press OK
|
||||
*/
|
||||
info:function(text, title, callback) {
|
||||
var content = '<p><span class="ui-icon ui-icon-info"></span>'+text+'</p>';
|
||||
OCdialogs.message(content, title, OCdialogs.ALERT_DIALOG, OCdialogs.OK_BUTTON, callback);
|
||||
},
|
||||
/**
|
||||
* displays confirmation dialog
|
||||
* @param text content of dialog
|
||||
* @param title dialog title
|
||||
* @param callback which will be triggered when user press YES or NO (true or false would be passed to callback respectively)
|
||||
*/
|
||||
confirm:function(text, title, callback) {
|
||||
var content = '<p><span class="ui-icon ui-icon-notice"></span>'+text+'</p>';
|
||||
OCdialogs.message(content, title, OCdialogs.ALERT_DIALOG, OCdialogs.YES_NO_BUTTON, callback);
|
||||
},
|
||||
/**
|
||||
* prompt for user input
|
||||
* @param text content of dialog
|
||||
* @param title dialog title
|
||||
* @param callback which will be triggered when user press OK (input text will be passed to callback)
|
||||
*/
|
||||
prompt:function(text, title, callback) {
|
||||
var content = '<p><span class="ui-icon ui-icon-pencil"></span>'+text+':<br/><input type="text" id="oc-dialog-prompt-input" style="width:90%"></p>';
|
||||
OCdialogs.message(content, title, OCdialogs.PROMPT_DIALOG, OCdialogs.OK_CANCEL_BUTTONS, callback);
|
||||
},
|
||||
/**
|
||||
* prompt user for input with custom form
|
||||
* fields should be passed in following format: [{text:'prompt text', name:'return name', type:'input type'},...]
|
||||
* @param fields to display
|
||||
* @param title dialog title
|
||||
* @param callback which will be triggered when user press OK (user answers will be passed to callback in following format: [{name:'return name', value: 'user value'},...])
|
||||
*/
|
||||
form:function(fields, title, callback) {
|
||||
var content = '<table>';
|
||||
for (var a in fields) {
|
||||
content += '<tr><td>'+fields[a].text+'</td><td>';
|
||||
var type=fields[a].type;
|
||||
if (type == 'text' || type == 'checkbox' || type == 'password')
|
||||
content += '<input type="'+type+'" name="'+fields[a].name+'">';
|
||||
content += "</td></tr>"
|
||||
}
|
||||
content += "</table>";
|
||||
OCdialogs.message(content, title, OCdialogs.FORM_DIALOG, OCdialogs.OK_CANCEL_BUTTONS, callback);
|
||||
},
|
||||
message:function(content, title, dialog_type, buttons, callback) {
|
||||
var c_name = 'oc-dialog-'+OCdialogs.dialogs_counter+'-content';
|
||||
var c_id = '#'+c_name;
|
||||
var d = '<div id="'+c_name+'" title="'+title+'">'+content+'</div>';
|
||||
$('body').append(d);
|
||||
var b = [];
|
||||
switch (buttons) {
|
||||
case OCdialogs.YES_NO_BUTTONS:
|
||||
b[1] = {text: t('dialogs', 'No'), click: function(){ if (callback != undefined) callback(false); $(c_id).dialog('close'); }};
|
||||
b[0] = {text: t('dialogs', 'Yes'), click: function(){ if (callback != undefined) callback(true); $(c_id).dialog('close');}};
|
||||
break;
|
||||
case OCdialogs.OK_CANCEL_BUTTONS:
|
||||
b[1] = {text: t('dialogs', 'Cancel'), click: function(){$(c_id).dialog('close'); }};
|
||||
case OCdialogs.OK_BUTTON: // fallthrough
|
||||
var f;
|
||||
switch(dialog_type) {
|
||||
case OCdialogs.ALERT_DIALOG:
|
||||
f = function(){$(c_id).dialog('close'); };
|
||||
break;
|
||||
case OCdialogs.PROMPT_DIALOG:
|
||||
f = function(){OCdialogs.prompt_ok_handler(callback, c_id)};
|
||||
break;
|
||||
case OCdialogs.FORM_DIALOG:
|
||||
f = function(){OCdialogs.form_ok_handler(callback, c_id)};
|
||||
break;
|
||||
}
|
||||
b[0] = {text: t('dialogs', 'Ok'), click: f};
|
||||
break;
|
||||
}
|
||||
$(c_id).dialog({width: 4*$(document).width()/9, height: $(d).height() + 150, modal: false, buttons: b});
|
||||
OCdialogs.dialogs_counter++;
|
||||
},
|
||||
// dialogs buttons types
|
||||
YES_NO_BUTTONS: 70,
|
||||
OK_BUTTONS: 71,
|
||||
OK_CANCEL_BUTTONS: 72,
|
||||
// dialogs types
|
||||
ALERT_DIALOG: 80,
|
||||
INFO_DIALOG: 81,
|
||||
PROMPT_DIALOG: 82,
|
||||
FORM_DIALOG: 83,
|
||||
dialogs_counter: 0,
|
||||
determineValue: function(element) {
|
||||
switch ($(element).attr('type')) {
|
||||
case 'checkbox': return $(element).attr('checked') != undefined;
|
||||
}
|
||||
return $(element).val();
|
||||
},
|
||||
prompt_ok_handler: function(callback, c_id){callback(true, $(c_id + " input#oc-dialog-prompt-input").val()); $(c_id).dialog('close');},
|
||||
form_ok_handler: function(callback, c_id) {
|
||||
var r = [];
|
||||
var c = 0;
|
||||
$(c_id + ' input').each(function(i, elem) {
|
||||
r[c] = {name: $(elem).attr('name'), value: OCdialogs.determineValue(elem)};
|
||||
c++;
|
||||
});
|
||||
$(c_id).dialog('close');
|
||||
callback(r);
|
||||
}
|
||||
};
|
||||
77
dav.php
Normal file
77
dav.php
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Jakob Sack
|
||||
* @copyright 2012 Jakob Sack owncloud@jakobsack.de
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
require_once('lib/base.php');
|
||||
|
||||
// Backends we always need (auth, principal and files)
|
||||
$backends = array(
|
||||
'auth' => new OC_Connector_Sabre_Auth(),
|
||||
'principal' => new OC_Connector_Sabre_Principal()
|
||||
);
|
||||
|
||||
// Root nodes
|
||||
$nodes = array(
|
||||
new Sabre_CalDAV_Principal_Collection($backends['principal'])
|
||||
);
|
||||
|
||||
// Plugins
|
||||
$plugins = array(
|
||||
new Sabre_DAV_Auth_Plugin($backends['auth'],'ownCloud'),
|
||||
new Sabre_DAVACL_Plugin(),
|
||||
new Sabre_DAV_Browser_Plugin(false) // Show something in the Browser, but no upload
|
||||
);
|
||||
|
||||
// Load the plugins etc we need for usual file sharing
|
||||
$backends['lock'] = new OC_Connector_Sabre_Locks();
|
||||
$plugins[] = new Sabre_DAV_Locks_Plugin($backends['lock']);
|
||||
// Add a RESTful user directory
|
||||
// /files/$username/
|
||||
if( OC_User::isLoggedIn()){
|
||||
$currentuser = OC_User::getUser();
|
||||
$files = new Sabre_DAV_SimpleCollection('files');
|
||||
foreach( OC_User::getUsers() as $username ){
|
||||
if( $username == $currentuser ){
|
||||
$public = new OC_Connector_Sabre_Directory('.');
|
||||
$files->addChild( new Sabre_DAV_SimpleCollection( $username, $public->getChildren()));
|
||||
}
|
||||
else{
|
||||
$files->addChild(new Sabre_DAV_SimpleCollection( $username ));
|
||||
}
|
||||
}
|
||||
$nodes[] = $files;
|
||||
}
|
||||
|
||||
// Get the other plugins and nodes
|
||||
OC_Hook::emit( 'OC_DAV', 'initialize', array( 'backends' => &$backends, 'nodes' => &$nodes, 'plugins' => &$plugins ));
|
||||
|
||||
// Fire up server
|
||||
$server = new Sabre_DAV_Server($nodes);
|
||||
$server->setBaseUri(OC::$WEBROOT.'/dav.php');
|
||||
|
||||
// Load additional plugins
|
||||
foreach( $plugins as &$plugin ){
|
||||
$server->addPlugin( $plugin );
|
||||
} unset( $plugin ); // Always do this after foreach with references!
|
||||
|
||||
// And off we go!
|
||||
$server->exec();
|
||||
106
db_structure.xml
106
db_structure.xml
|
|
@ -70,7 +70,7 @@
|
|||
<default>
|
||||
</default>
|
||||
<notnull>true</notnull>
|
||||
<length>4</length>
|
||||
<length>8</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
|
|
@ -96,7 +96,7 @@
|
|||
<type>integer</type>
|
||||
<default></default>
|
||||
<notnull>true</notnull>
|
||||
<length>4</length>
|
||||
<length>8</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
|
|
@ -105,7 +105,7 @@
|
|||
<default>
|
||||
</default>
|
||||
<notnull>true</notnull>
|
||||
<length>4</length>
|
||||
<length>8</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
|
|
@ -114,7 +114,7 @@
|
|||
<default>
|
||||
</default>
|
||||
<notnull>true</notnull>
|
||||
<length>4</length>
|
||||
<length>8</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
|
|
@ -291,7 +291,7 @@
|
|||
<type>integer</type>
|
||||
<default></default>
|
||||
<notnull>false</notnull>
|
||||
<length>4</length>
|
||||
<length>8</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
|
|
@ -427,102 +427,6 @@
|
|||
|
||||
</table>
|
||||
|
||||
<table>
|
||||
|
||||
<name>*dbprefix*principalgroups</name>
|
||||
|
||||
<declaration>
|
||||
|
||||
<field>
|
||||
<name>id</name>
|
||||
<type>integer</type>
|
||||
<default>0</default>
|
||||
<notnull>true</notnull>
|
||||
<autoincrement>1</autoincrement>
|
||||
<unsigned>true</unsigned>
|
||||
<length>4</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>principal_id</name>
|
||||
<type>integer</type>
|
||||
<default></default>
|
||||
<notnull>true</notnull>
|
||||
<unsigned>true</unsigned>
|
||||
<length>4</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>member_id</name>
|
||||
<type>integer</type>
|
||||
<default></default>
|
||||
<notnull>true</notnull>
|
||||
<unsigned>true</unsigned>
|
||||
<length>4</length>
|
||||
</field>
|
||||
|
||||
<index>
|
||||
<name>principals_members_index</name>
|
||||
<unique>true</unique>
|
||||
<field>
|
||||
<name>principal_id</name>
|
||||
<sorting>ascending</sorting>
|
||||
</field>
|
||||
<field>
|
||||
<name>member_id</name>
|
||||
<sorting>ascending</sorting>
|
||||
</field>
|
||||
</index>
|
||||
|
||||
</declaration>
|
||||
|
||||
</table>
|
||||
|
||||
<table>
|
||||
|
||||
<name>*dbprefix*principals</name>
|
||||
|
||||
<declaration>
|
||||
|
||||
<field>
|
||||
<name>id</name>
|
||||
<type>integer</type>
|
||||
<default>0</default>
|
||||
<notnull>true</notnull>
|
||||
<autoincrement>1</autoincrement>
|
||||
<unsigned>true</unsigned>
|
||||
<length>4</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>uri</name>
|
||||
<type>text</type>
|
||||
<default></default>
|
||||
<notnull>false</notnull>
|
||||
<length>255</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>displayname</name>
|
||||
<type>text</type>
|
||||
<default></default>
|
||||
<notnull>false</notnull>
|
||||
<length>255</length>
|
||||
</field>
|
||||
|
||||
<index>
|
||||
<name>uri</name>
|
||||
<unique>true</unique>
|
||||
<field>
|
||||
<name>uri</name>
|
||||
<sorting>ascending</sorting>
|
||||
</field>
|
||||
</index>
|
||||
|
||||
</declaration>
|
||||
|
||||
</table>
|
||||
|
||||
<table>
|
||||
|
||||
<name>*dbprefix*properties</name>
|
||||
|
|
|
|||
|
|
@ -16,12 +16,13 @@ foreach ($_FILES['files']['error'] as $error) {
|
|||
if ($error != 0) {
|
||||
$l=new OC_L10N('files');
|
||||
$errors = array(
|
||||
0=>$l->t("There is no error, the file uploaded with success"),
|
||||
1=>$l->t("The uploaded file exceeds the upload_max_filesize directive in php.ini").ini_get('upload_max_filesize'),
|
||||
2=>$l->t("The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form"),
|
||||
3=>$l->t("The uploaded file was only partially uploaded"),
|
||||
4=>$l->t("No file was uploaded"),
|
||||
6=>$l->t("Missing a temporary folder")
|
||||
UPLOAD_ERR_OK=>$l->t("There is no error, the file uploaded with success"),
|
||||
UPLOAD_ERR_INI_SIZE=>$l->t("The uploaded file exceeds the upload_max_filesize directive in php.ini").ini_get('upload_max_filesize'),
|
||||
UPLOAD_ERR_FORM_SIZE=>$l->t("The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form"),
|
||||
UPLOAD_ERR_PARTIAL=>$l->t("The uploaded file was only partially uploaded"),
|
||||
UPLOAD_ERR_NO_FILE=>$l->t("No file was uploaded"),
|
||||
UPLOAD_ERR_NO_TMP_DIR=>$l->t("Missing a temporary folder"),
|
||||
UPLOAD_ERR_CANT_WRITE=>$l->t('Failed to write to disk'),
|
||||
);
|
||||
OC_JSON::error(array("data" => array( "message" => $errors[$error] )));
|
||||
exit();
|
||||
|
|
@ -48,7 +49,8 @@ if(strpos($dir,'..') === false){
|
|||
for($i=0;$i<$fileCount;$i++){
|
||||
$target=stripslashes($dir) . $files['name'][$i];
|
||||
if(is_uploaded_file($files['tmp_name'][$i]) and OC_Filesystem::fromTmpFile($files['tmp_name'][$i],$target)){
|
||||
$result[]=array( "status" => "success", 'mime'=>OC_Filesystem::getMimeType($target),'size'=>OC_Filesystem::filesize($target),'name'=>$files['name'][$i]);
|
||||
$meta=OC_FileCache::getCached($target);
|
||||
$result[]=array( "status" => "success", 'mime'=>$meta['mimetype'],'size'=>$meta['size'],'name'=>$files['name'][$i]);
|
||||
}
|
||||
}
|
||||
OC_JSON::encodedPrint($result);
|
||||
|
|
|
|||
|
|
@ -7,4 +7,4 @@ OC_App::register( array( "order" => 2, "id" => "files", "name" => "Files" ));
|
|||
|
||||
OC_App::addNavigationEntry( array( "id" => "files_index", "order" => 1, "href" => OC_Helper::linkTo( "files", "index.php" ), "icon" => OC_Helper::imagePath( "core", "places/home.svg" ), "name" => $l->t("Files") ));
|
||||
|
||||
?>
|
||||
OC_Search::registerProvider('OC_Search_Provider_File');
|
||||
|
|
|
|||
|
|
@ -387,39 +387,6 @@ function updateBreadcrumb(breadcrumbHtml) {
|
|||
$('p.nav').empty().html(breadcrumbHtml);
|
||||
}
|
||||
|
||||
function humanFileSize(bytes){
|
||||
if( bytes < 1024 ){
|
||||
return bytes+' B';
|
||||
}
|
||||
bytes = Math.round(bytes / 1024, 1 );
|
||||
if( bytes < 1024 ){
|
||||
return bytes+' kB';
|
||||
}
|
||||
bytes = Math.round( bytes / 1024, 1 );
|
||||
if( bytes < 1024 ){
|
||||
return bytes+' MB';
|
||||
}
|
||||
|
||||
// Wow, heavy duty for owncloud
|
||||
bytes = Math.round( bytes / 1024, 1 );
|
||||
return bytes+' GB';
|
||||
}
|
||||
|
||||
function simpleFileSize(bytes) {
|
||||
mbytes = Math.round(bytes/(1024*1024/10))/10;
|
||||
if(bytes == 0) { return '0'; }
|
||||
else if(mbytes < 0.1) { return '< 0.1'; }
|
||||
else if(mbytes > 1000) { return '> 1000'; }
|
||||
else { return mbytes.toFixed(1); }
|
||||
}
|
||||
|
||||
function formatDate(date){
|
||||
var monthNames = [ t('files','January'), t('files','February'), t('files','March'), t('files','April'), t('files','May'), t('files','June'),
|
||||
t('files','July'), t('files','August'), t('files','September'), t('files','October'), t('files','November'), t('files','December') ];
|
||||
return monthNames[date.getMonth()]+' '+date.getDate()+', '+date.getFullYear()+', '+((date.getHours()<10)?'0':'')+date.getHours()+':'+date.getMinutes();
|
||||
}
|
||||
|
||||
|
||||
//options for file drag/dropp
|
||||
var dragOptions={
|
||||
distance: 20, revert: 'invalid', opacity: 0.7,
|
||||
|
|
|
|||
18
lib/app.php
18
lib/app.php
|
|
@ -58,8 +58,8 @@ class OC_App{
|
|||
$apps = OC_Appconfig::getApps();
|
||||
foreach( $apps as $app ){
|
||||
if( self::isEnabled( $app )){
|
||||
if(is_file(OC::$SERVERROOT.'/apps/'.$app.'/appinfo/app.php')){
|
||||
require( 'apps/'.$app.'/appinfo/app.php' );
|
||||
if(is_file(OC::$APPSROOT.'/apps/'.$app.'/appinfo/app.php')){
|
||||
require( $app.'/appinfo/app.php' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -268,7 +268,7 @@ class OC_App{
|
|||
if(is_file($appid)){
|
||||
$file=$appid;
|
||||
}else{
|
||||
$file=OC::$SERVERROOT.'/apps/'.$appid.'/appinfo/info.xml';
|
||||
$file=OC::$APPSROOT.'/apps/'.$appid.'/appinfo/info.xml';
|
||||
if(!is_file($file)){
|
||||
return array();
|
||||
}
|
||||
|
|
@ -363,9 +363,9 @@ class OC_App{
|
|||
*/
|
||||
public static function getAllApps(){
|
||||
$apps=array();
|
||||
$dh=opendir(OC::$SERVERROOT.'/apps');
|
||||
$dh=opendir(OC::$APPSROOT.'/apps');
|
||||
while($file=readdir($dh)){
|
||||
if(is_file(OC::$SERVERROOT.'/apps/'.$file.'/appinfo/app.php')){
|
||||
if(substr($file,0,1)!='.' and is_file(OC::$APPSROOT.'/apps/'.$file.'/appinfo/app.php')){
|
||||
$apps[]=$file;
|
||||
}
|
||||
}
|
||||
|
|
@ -396,11 +396,11 @@ class OC_App{
|
|||
* @param string appid
|
||||
*/
|
||||
public static function updateApp($appid){
|
||||
if(file_exists(OC::$SERVERROOT.'/apps/'.$appid.'/appinfo/database.xml')){
|
||||
OC_DB::updateDbFromStructure(OC::$SERVERROOT.'/apps/'.$appid.'/appinfo/database.xml');
|
||||
if(file_exists(OC::$APPSROOT.'/apps/'.$appid.'/appinfo/database.xml')){
|
||||
OC_DB::updateDbFromStructure(OC::$APPSROOT.'/apps/'.$appid.'/appinfo/database.xml');
|
||||
}
|
||||
if(file_exists(OC::$SERVERROOT.'/apps/'.$appid.'/appinfo/update.php')){
|
||||
include OC::$SERVERROOT.'/apps/'.$appid.'/appinfo/update.php';
|
||||
if(file_exists(OC::$APPSROOT.'/apps/'.$appid.'/appinfo/update.php')){
|
||||
include OC::$APPSROOT.'/apps/'.$appid.'/appinfo/update.php';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
73
lib/base.php
73
lib/base.php
|
|
@ -62,6 +62,14 @@ class OC{
|
|||
* the root path of the 3rdparty folder for http requests (e.g. owncloud/3rdparty)
|
||||
*/
|
||||
public static $THIRDPARTYWEBROOT = '';
|
||||
/**
|
||||
* The installation path of the apps folder on the server (e.g. /srv/http/owncloud)
|
||||
*/
|
||||
public static $APPSROOT = '';
|
||||
/**
|
||||
* the root path of the apps folder for http requests (e.g. owncloud)
|
||||
*/
|
||||
public static $APPSWEBROOT = '';
|
||||
|
||||
/**
|
||||
* SPL autoload
|
||||
|
|
@ -136,6 +144,12 @@ class OC{
|
|||
$_SERVER['PHP_AUTH_PW'] = strip_tags($password);
|
||||
}
|
||||
|
||||
// register the stream wrappers
|
||||
require_once('streamwrappers.php');
|
||||
stream_wrapper_register("fakedir", "OC_FakeDirStream");
|
||||
stream_wrapper_register('static', 'OC_StaticStreamWrapper');
|
||||
stream_wrapper_register('close', 'OC_CloseStreamWrapper');
|
||||
|
||||
// calculate the documentroot
|
||||
OC::$DOCUMENTROOT=realpath($_SERVER['DOCUMENT_ROOT']);
|
||||
OC::$SERVERROOT=str_replace("\\",'/',substr(__FILE__,0,-13));
|
||||
|
|
@ -143,8 +157,17 @@ class OC{
|
|||
$scriptName=$_SERVER["SCRIPT_NAME"];
|
||||
if(substr($scriptName,-1)=='/'){
|
||||
$scriptName.='index.php';
|
||||
//make sure suburi follows the same rules as scriptName
|
||||
if(substr(OC::$SUBURI,-9)!='index.php'){
|
||||
if(substr(OC::$SUBURI,-1)!='/'){
|
||||
OC::$SUBURI=OC::$SUBURI.'/';
|
||||
}
|
||||
OC::$SUBURI=OC::$SUBURI.'index.php';
|
||||
}
|
||||
}
|
||||
OC::$WEBROOT=substr($scriptName,0,strlen($scriptName)-strlen(OC::$SUBURI));
|
||||
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));
|
||||
|
||||
|
||||
if(OC::$WEBROOT!='' and OC::$WEBROOT[0]!=='/'){
|
||||
|
|
@ -159,22 +182,35 @@ class OC{
|
|||
OC::$THIRDPARTYROOT=OC::$SERVERROOT;
|
||||
OC::$THIRDPARTYWEBROOT=OC::$WEBROOT;
|
||||
}elseif(file_exists(OC::$SERVERROOT.'/../3rdparty')){
|
||||
$url_tmp=explode('/',OC::$WEBROOT);
|
||||
$length=count($url_tmp);
|
||||
unset($url_tmp[$length-1]);
|
||||
OC::$THIRDPARTYWEBROOT=implode('/',$url_tmp);
|
||||
$root_tmp=explode('/',OC::$SERVERROOT);
|
||||
$length=count($root_tmp);
|
||||
unset($root_tmp[$length-1]);
|
||||
OC::$THIRDPARTYROOT=implode('/',$root_tmp);
|
||||
OC::$THIRDPARTYWEBROOT=rtrim(dirname(OC::$WEBROOT), '/');
|
||||
OC::$THIRDPARTYROOT=rtrim(dirname(OC::$SERVERROOT), '/');
|
||||
}else{
|
||||
echo("3rdparty directory not found! Please put the ownCloud 3rdparty folder in the ownCloud folder or the folder above. You can also configure the location in the config.php file.");
|
||||
exit;
|
||||
}
|
||||
|
||||
// search the apps folder
|
||||
if(file_exists(OC::$SERVERROOT.'/apps')){
|
||||
OC::$APPSROOT=OC::$SERVERROOT;
|
||||
OC::$APPSWEBROOT=OC::$WEBROOT;
|
||||
}elseif(file_exists(OC::$SERVERROOT.'/../apps')){
|
||||
OC::$APPSWEBROOT=rtrim(dirname(OC::$WEBROOT), '/');
|
||||
OC::$APPSROOT=rtrim(dirname(OC::$SERVERROOT), '/');
|
||||
}else{
|
||||
echo("apps directory not found! Please put the ownCloud apps folder in the ownCloud folder or the folder above. You can also configure the location in the config.php file.");
|
||||
exit;
|
||||
}
|
||||
|
||||
// set the right include path
|
||||
set_include_path(OC::$SERVERROOT.'/lib'.PATH_SEPARATOR.OC::$SERVERROOT.'/config'.PATH_SEPARATOR.OC::$THIRDPARTYROOT.'/3rdparty'.PATH_SEPARATOR.get_include_path().PATH_SEPARATOR.OC::$SERVERROOT);
|
||||
set_include_path(
|
||||
OC::$SERVERROOT.'/lib'.PATH_SEPARATOR.
|
||||
OC::$SERVERROOT.'/config'.PATH_SEPARATOR.
|
||||
OC::$THIRDPARTYROOT.'/3rdparty'.PATH_SEPARATOR.
|
||||
OC::$APPSROOT.PATH_SEPARATOR.
|
||||
OC::$APPSROOT.'/apps'.PATH_SEPARATOR.
|
||||
get_include_path().PATH_SEPARATOR.
|
||||
OC::$SERVERROOT
|
||||
);
|
||||
|
||||
// Redirect to installer if not installed
|
||||
if (!OC_Config::getValue('installed', false) && OC::$SUBURI != '/index.php') {
|
||||
|
|
@ -234,8 +270,10 @@ class OC{
|
|||
OC_Util::addScript( "jquery-showpassword" );
|
||||
OC_Util::addScript( "jquery.infieldlabel.min" );
|
||||
OC_Util::addScript( "jquery-tipsy" );
|
||||
OC_Util::addScript( "oc-dialogs" );
|
||||
OC_Util::addScript( "js" );
|
||||
OC_Util::addScript( "eventsource" );
|
||||
OC_Util::addScript( "config" );
|
||||
//OC_Util::addScript( "multiselect" );
|
||||
OC_Util::addScript('search','result');
|
||||
OC_Util::addStyle( "styles" );
|
||||
|
|
@ -261,6 +299,7 @@ class OC{
|
|||
$_SESSION['user_id'] = '';
|
||||
}
|
||||
|
||||
|
||||
OC_User::useBackend( OC_Config::getValue( "userbackend", "database" ));
|
||||
OC_Group::setBackend( OC_Config::getValue( "groupbackend", "database" ));
|
||||
|
||||
|
|
@ -277,9 +316,8 @@ class OC{
|
|||
OC_App::loadApps();
|
||||
}
|
||||
|
||||
// Last part: connect some hooks
|
||||
OC_HOOK::connect('OC_User', 'post_createUser', 'OC_Connector_Sabre_Principal', 'addPrincipal');
|
||||
OC_HOOK::connect('OC_User', 'post_deleteUser', 'OC_Connector_Sabre_Principal', 'deletePrincipal');
|
||||
//make sure temporary files are cleaned up
|
||||
register_shutdown_function(array('OC_Helper','cleanTmp'));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -302,15 +340,10 @@ if(!function_exists('get_temp_dir')) {
|
|||
unlink($temp);
|
||||
return dirname($temp);
|
||||
}
|
||||
if( $temp=sys_get_temp_dir()) return $temp;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
OC::init();
|
||||
|
||||
require_once('fakedirstream.php');
|
||||
|
||||
|
||||
|
||||
// FROM search.php
|
||||
new OC_Search_Provider_File();
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ class OC_Connector_Sabre_Auth extends Sabre_DAV_Auth_Backend_AbstractBasic {
|
|||
* @return bool
|
||||
*/
|
||||
protected function validateUserPass($username, $password){
|
||||
OC_Util::setUpFS();//login hooks may need early access to the filesystem
|
||||
if(OC_User::login($username,$password)){
|
||||
OC_Util::setUpFS();
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -8,50 +8,6 @@
|
|||
*/
|
||||
|
||||
class OC_Connector_Sabre_Principal implements Sabre_DAVACL_IPrincipalBackend {
|
||||
/**
|
||||
* TODO: write doc
|
||||
*/
|
||||
public static function addPrincipal($params){
|
||||
// Add the user
|
||||
$uri = 'principals/'.$params['uid'];
|
||||
$displayname = $params['uid'];
|
||||
$query = OC_DB::prepare('INSERT INTO *PREFIX*principals (uri,displayname) VALUES(?,?)');
|
||||
$query->execute(array($uri,$displayname));
|
||||
|
||||
// Add calendar and addressbook read and write support (sharing calendars)
|
||||
$uri = 'principals/'.$params['uid'].'/calendar-proxy-read';
|
||||
$displayname = null;
|
||||
$query->execute(array($uri,$displayname));
|
||||
$uri = 'principals/'.$params['uid'].'/calendar-proxy-write';
|
||||
$query->execute(array($uri,$displayname));
|
||||
$uri = 'principals/'.$params['uid'].'/addressbook-proxy-read';
|
||||
$query->execute(array($uri,$displayname));
|
||||
$uri = 'principals/'.$params['uid'].'/addressbook-proxy-write';
|
||||
$query->execute(array($uri,$displayname));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: write doc
|
||||
*/
|
||||
public static function deletePrincipal($params){
|
||||
$query = OC_DB::prepare('SELECT * FROM *PREFIX*principals');
|
||||
$result = $query->execute();
|
||||
|
||||
$deleteprincipal = OC_DB::prepare('DELETE FROM *PREFIX*principals WHERE id = ?');
|
||||
$deletegroup = OC_DB::prepare('DELETE FROM *PREFIX*principalgroups WHERE principal_id = ? OR member_id = ?');
|
||||
// We have to delete the principals and relations! Principals include
|
||||
while($row = $result->fetchRow()){
|
||||
// Checking if the principal is in the prefix
|
||||
$array = explode('/',$row['uri']);
|
||||
if ($array[1] != $params['uid']) continue;
|
||||
$deleteprincipal->execute(array($row['id']));
|
||||
$deletegroup->execute(array($row['id'],$row['id']));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of principals based on a prefix.
|
||||
*
|
||||
|
|
|
|||
37
lib/db.php
37
lib/db.php
|
|
@ -316,8 +316,8 @@ class OC_DB {
|
|||
// read file
|
||||
$content = file_get_contents( $file );
|
||||
|
||||
// Make changes and save them to a temporary file
|
||||
$file2 = tempnam( get_temp_dir(), 'oc_db_scheme_' );
|
||||
// Make changes and save them to an in-memory file
|
||||
$file2 = 'static://db_scheme';
|
||||
if($file2 == ''){
|
||||
die('could not create tempfile in get_temp_dir() - aborting');
|
||||
}
|
||||
|
|
@ -331,7 +331,7 @@ class OC_DB {
|
|||
// Try to create tables
|
||||
$definition = self::$schema->parseDatabaseDefinitionFile( $file2 );
|
||||
|
||||
// Delete our temporary file
|
||||
//clean up memory
|
||||
unlink( $file2 );
|
||||
|
||||
// Die in case something went wrong
|
||||
|
|
@ -371,8 +371,8 @@ class OC_DB {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Make changes and save them to a temporary file
|
||||
$file2 = tempnam( get_temp_dir(), 'oc_db_scheme_' );
|
||||
// Make changes and save them to an in-memory file
|
||||
$file2 = 'static://db_scheme';
|
||||
$content = str_replace( '*dbname*', $previousSchema['name'], $content );
|
||||
$content = str_replace( '*dbprefix*', $CONFIG_DBTABLEPREFIX, $content );
|
||||
if( $CONFIG_DBTYPE == 'pgsql' ){ //mysql support it too but sqlite doesn't
|
||||
|
|
@ -381,7 +381,7 @@ class OC_DB {
|
|||
file_put_contents( $file2, $content );
|
||||
$op = self::$schema->updateDatabase($file2, $previousSchema, array(), false);
|
||||
|
||||
// Delete our temporary file
|
||||
//clean up memory
|
||||
unlink( $file2 );
|
||||
|
||||
if (PEAR::isError($op)) {
|
||||
|
|
@ -508,6 +508,21 @@ class OC_DB {
|
|||
self::$connection->commit();
|
||||
self::$inTransaction=false;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if a result is an error, works with MDB2 and PDOException
|
||||
* @param mixed $result
|
||||
* @return bool
|
||||
*/
|
||||
public static function isError($result){
|
||||
if(!$result){
|
||||
return true;
|
||||
}elseif(self::$backend==self::BACKEND_MDB2 and PEAR::isError($result)){
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -527,11 +542,15 @@ class PDOStatementWrapper{
|
|||
public function execute($input=array()){
|
||||
$this->lastArguments=$input;
|
||||
if(count($input)>0){
|
||||
$this->statement->execute($input);
|
||||
$result=$this->statement->execute($input);
|
||||
}else{
|
||||
$this->statement->execute();
|
||||
$result=$this->statement->execute();
|
||||
}
|
||||
if($result){
|
||||
return $this;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,45 +0,0 @@
|
|||
<?php
|
||||
global $FAKEDIRS;
|
||||
$FAKEDIRS=array();
|
||||
|
||||
class fakeDirStream{
|
||||
private $name;
|
||||
private $data;
|
||||
private $index;
|
||||
|
||||
public function dir_opendir($path,$options){
|
||||
global $FAKEDIRS;
|
||||
$url=parse_url($path);
|
||||
$this->name=substr($path,strlen('fakedir://'));
|
||||
$this->index=0;
|
||||
if(isset($FAKEDIRS[$this->name])){
|
||||
$this->data=$FAKEDIRS[$this->name];
|
||||
}else{
|
||||
$this->data=array();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function dir_readdir(){
|
||||
if($this->index>=count($this->data)){
|
||||
return false;
|
||||
}
|
||||
$filename=$this->data[$this->index];
|
||||
$this->index++;
|
||||
return $filename;
|
||||
}
|
||||
|
||||
public function dir_closedir() {
|
||||
$this->data=false;
|
||||
$this->name='';
|
||||
return true;
|
||||
}
|
||||
|
||||
public function dir_rewinddir() {
|
||||
$this->index=0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
stream_wrapper_register("fakedir", "fakeDirStream");
|
||||
|
||||
|
|
@ -28,6 +28,8 @@
|
|||
* It will try to keep the data up to date but changes from outside ownCloud can invalidate the cache
|
||||
*/
|
||||
class OC_FileCache{
|
||||
private static $savedData=array();
|
||||
|
||||
/**
|
||||
* get the filesystem info from the cache
|
||||
* @param string path
|
||||
|
|
@ -93,6 +95,14 @@ class OC_FileCache{
|
|||
self::update($id,$data);
|
||||
return;
|
||||
}
|
||||
if(isset(self::$savedData[$path])){
|
||||
$data=array_merge($data,self::$savedData[$path]);
|
||||
unset(self::$savedData[$path]);
|
||||
}
|
||||
if(!isset($data['size']) or !isset($data['mtime'])){//save incomplete data for the next time we write it
|
||||
self::$savedData[$path]=$data;
|
||||
return;
|
||||
}
|
||||
if(!isset($data['encrypted'])){
|
||||
$data['encrypted']=false;
|
||||
}
|
||||
|
|
@ -101,9 +111,11 @@ class OC_FileCache{
|
|||
}
|
||||
$mimePart=dirname($data['mimetype']);
|
||||
$user=OC_User::getUser();
|
||||
$query=OC_DB::prepare('INSERT INTO *PREFIX*fscache(parent, name, path, size, mtime, ctime, mimetype, mimepart,user,writable) VALUES(?,?,?,?,?,?,?,?,?,?)');
|
||||
$query->execute(array($parent,basename($path),$path,$data['size'],$data['mtime'],$data['ctime'],$data['mimetype'],$mimePart,$user,$data['writable']));
|
||||
|
||||
$query=OC_DB::prepare('INSERT INTO *PREFIX*fscache(parent, name, path, size, mtime, ctime, mimetype, mimepart,user,writable,encrypted,versioned) VALUES(?,?,?,?,?,?,?,?,?,?,?,?)');
|
||||
$result=$query->execute(array($parent,basename($path),$path,$data['size'],$data['mtime'],$data['ctime'],$data['mimetype'],$mimePart,$user,$data['writable'],$data['encrypted'],$data['versioned']));
|
||||
if(OC_DB::isError($result)){
|
||||
OC_Log::write('files','error while writing file('.$path.') to cache',OC_Log::ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -128,7 +140,10 @@ class OC_FileCache{
|
|||
|
||||
$sql = 'UPDATE *PREFIX*fscache SET '.implode(' , ',$queryParts).' WHERE id=?';
|
||||
$query=OC_DB::prepare($sql);
|
||||
$query->execute($arguments);
|
||||
$result=$query->execute($arguments);
|
||||
if(OC_DB::isError($result)){
|
||||
OC_Log::write('files','error while updating file('.$path.') in cache',OC_Log::ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -262,11 +277,20 @@ class OC_FileCache{
|
|||
*/
|
||||
private static function getFileId($path){
|
||||
$query=OC_DB::prepare('SELECT id FROM *PREFIX*fscache WHERE path=?');
|
||||
$result=$query->execute(array($path))->fetchRow();
|
||||
if(OC_DB::isError($query)){
|
||||
OC_Log::write('files','error while getting file id of '.$path,OC_Log::ERROR);
|
||||
return -1;
|
||||
}
|
||||
$result=$query->execute(array($path));
|
||||
if(OC_DB::isError($result)){
|
||||
OC_Log::write('files','error while getting file id of '.$path,OC_Log::ERROR);
|
||||
return -1;
|
||||
}
|
||||
$result=$result->fetchRow();
|
||||
if(is_array($result)){
|
||||
return $result['id'];
|
||||
}else{
|
||||
OC_Log::write('getFileId(): file not found in cache ('.$path.')','core',OC_Log::DEBUG);
|
||||
OC_Log::write('getFileId(): file not found in cache ('.$path.')','core',OC_Log::DEBUG);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
@ -323,7 +347,29 @@ class OC_FileCache{
|
|||
}
|
||||
self::increaseSize(dirname($fullPath),$size-$cachedSize);
|
||||
}
|
||||
|
||||
|
||||
public static function getCached($path,$root=''){
|
||||
if(!$root){
|
||||
$root=OC_Filesystem::getRoot();
|
||||
}else{
|
||||
if($root=='/'){
|
||||
$root='';
|
||||
}
|
||||
}
|
||||
$path=$root.$path;
|
||||
$query=OC_DB::prepare('SELECT ctime,mtime,mimetype,size,encrypted,versioned,writable FROM *PREFIX*fscache WHERE path=?');
|
||||
$result=$query->execute(array($path))->fetchRow();
|
||||
if(is_array($result)){
|
||||
if(isset(self::$savedData[$path])){
|
||||
$result=array_merge($result,self::$savedData[$path]);
|
||||
}
|
||||
return $result;
|
||||
}else{
|
||||
OC_Log::write('get(): file not found in cache ('.$path.')','core',OC_Log::DEBUG);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static function getCachedSize($path,$root){
|
||||
if(!$root){
|
||||
$root=OC_Filesystem::getRoot();
|
||||
|
|
@ -332,6 +378,7 @@ class OC_FileCache{
|
|||
$root='';
|
||||
}
|
||||
}
|
||||
$path=$root.$path;
|
||||
$query=OC_DB::prepare('SELECT size FROM *PREFIX*fscache WHERE path=?');
|
||||
$result=$query->execute(array($path));
|
||||
if($row=$result->fetchRow()){
|
||||
|
|
@ -515,6 +562,9 @@ class OC_FileCache{
|
|||
}
|
||||
$view=new OC_FilesystemView($root);
|
||||
}
|
||||
if(!$view->file_exists($path)){
|
||||
return false;
|
||||
}
|
||||
$mtime=$view->filemtime($path);
|
||||
$isDir=$view->is_dir($path);
|
||||
$path=$root.$path;
|
||||
|
|
|
|||
|
|
@ -34,11 +34,12 @@
|
|||
* A post-proxy recieves 2 arguments, the filepath and the result of the operation.
|
||||
* The return calue of the post-proxy will be used as the new result of the operation
|
||||
* The operations that have a post-proxy are
|
||||
* file_get_contents, is_file, is_dir, file_exists, stat, is_readable, is_writable, filemtime, filectime, file_get_contents, getMimeType, hash, free_space and search
|
||||
* file_get_contents, is_file, is_dir, file_exists, stat, is_readable, is_writable, fileatime, filemtime, filectime, file_get_contents, getMimeType, hash, fopen, free_space and search
|
||||
*/
|
||||
|
||||
class OC_FileProxy{
|
||||
private static $proxies=array();
|
||||
public static $enabled=true;
|
||||
|
||||
/**
|
||||
* check if this proxy implments a specific proxy operation
|
||||
|
|
@ -83,16 +84,19 @@ class OC_FileProxy{
|
|||
return $proxies;
|
||||
}
|
||||
|
||||
public static function runPreProxies($operation,$filepath,$filepath2=null){
|
||||
public static function runPreProxies($operation,&$filepath,&$filepath2=null){
|
||||
if(!self::$enabled){
|
||||
return true;
|
||||
}
|
||||
$proxies=self::getProxies($operation,false);
|
||||
$operation='pre'.$operation;
|
||||
foreach($proxies as $proxy){
|
||||
if($filepath2){
|
||||
if(!$proxy->$operation($filepath,$filepath2)){
|
||||
if(!is_null($filepath2)){
|
||||
if($proxy->$operation($filepath,$filepath2)===false){
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
if(!$proxy->$operation($filepath)){
|
||||
if($proxy->$operation($filepath)===false){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -101,6 +105,9 @@ class OC_FileProxy{
|
|||
}
|
||||
|
||||
public static function runPostProxies($operation,$path,$result){
|
||||
if(!self::$enabled){
|
||||
return $result;
|
||||
}
|
||||
$proxies=self::getProxies($operation,true);
|
||||
$operation='post'.$operation;
|
||||
foreach($proxies as $proxy){
|
||||
|
|
|
|||
|
|
@ -23,33 +23,31 @@
|
|||
/**
|
||||
* Privde a common interface to all different storage options
|
||||
*/
|
||||
class OC_Filestorage{
|
||||
abstract class OC_Filestorage{
|
||||
public function __construct($parameters){}
|
||||
public function mkdir($path){}
|
||||
public function rmdir($path){}
|
||||
public function opendir($path){}
|
||||
public function is_dir($path){}
|
||||
public function is_file($path){}
|
||||
public function stat($path){}
|
||||
public function filetype($path){}
|
||||
public function filesize($path){}
|
||||
public function is_readable($path){}
|
||||
public function is_writable($path){}
|
||||
public function file_exists($path){}
|
||||
public function readfile($path){}
|
||||
public function filectime($path){}
|
||||
public function filemtime($path){}
|
||||
public function file_get_contents($path){}
|
||||
public function file_put_contents($path,$data){}
|
||||
public function unlink($path){}
|
||||
public function rename($path1,$path2){}
|
||||
public function copy($path1,$path2){}
|
||||
public function fopen($path,$mode){}
|
||||
public function toTmpFile($path){}//copy the file to a temporary file, used for cross-storage file actions
|
||||
public function fromTmpFile($tmpPath,$path){}//copy a file from a temporary file, used for cross-storage file actions
|
||||
public function getMimeType($path){}
|
||||
public function hash($type,$path,$raw){}
|
||||
public function free_space($path){}
|
||||
public function search($query){}
|
||||
public function getLocalFile($path){}// get a path to a local version of the file, whether the original file is local or remote
|
||||
abstract public function mkdir($path);
|
||||
abstract public function rmdir($path);
|
||||
abstract public function opendir($path);
|
||||
abstract public function is_dir($path);
|
||||
abstract public function is_file($path);
|
||||
abstract public function stat($path);
|
||||
abstract public function filetype($path);
|
||||
abstract public function filesize($path);
|
||||
abstract public function is_readable($path);
|
||||
abstract public function is_writable($path);
|
||||
abstract public function file_exists($path);
|
||||
abstract public function filectime($path);
|
||||
abstract public function filemtime($path);
|
||||
abstract public function file_get_contents($path);
|
||||
abstract public function file_put_contents($path,$data);
|
||||
abstract public function unlink($path);
|
||||
abstract public function rename($path1,$path2);
|
||||
abstract public function copy($path1,$path2);
|
||||
abstract public function fopen($path,$mode);
|
||||
abstract public function getMimeType($path);
|
||||
abstract public function hash($type,$path,$raw);
|
||||
abstract public function free_space($path);
|
||||
abstract public function search($query);
|
||||
abstract public function touch($path, $mtime=null);
|
||||
abstract public function getLocalFile($path);// get a path to a local version of the file, whether the original file is local or remote
|
||||
}
|
||||
|
|
|
|||
151
lib/filestorage/common.php
Normal file
151
lib/filestorage/common.php
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Michael Gapczynski
|
||||
* @copyright 2012 Michael Gapczynski GapczynskiM@gmail.com
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
abstract class OC_Filestorage_Common extends OC_Filestorage {
|
||||
|
||||
public function __construct($parameters){}
|
||||
// abstract public function mkdir($path);
|
||||
// abstract public function rmdir($path);
|
||||
// abstract public function opendir($path);
|
||||
public function is_dir($path){
|
||||
return $this->filetype($path)=='dir';
|
||||
}
|
||||
public function is_file($path){
|
||||
return $this->filetype($path)=='file';
|
||||
}
|
||||
// abstract public function stat($path);
|
||||
// abstract public function filetype($path);
|
||||
public function filesize($path) {
|
||||
if($this->is_dir($path)){
|
||||
return 0;//by definition
|
||||
}else{
|
||||
$stat = $this->stat($path);
|
||||
return $stat['size'];
|
||||
}
|
||||
}
|
||||
// abstract public function is_readable($path);
|
||||
// abstract public function is_writable($path);
|
||||
// abstract public function file_exists($path);
|
||||
public function filectime($path) {
|
||||
$stat = $this->stat($path);
|
||||
return $stat['ctime'];
|
||||
}
|
||||
public function filemtime($path) {
|
||||
$stat = $this->stat($path);
|
||||
return $stat['mtime'];
|
||||
}
|
||||
public function fileatime($path) {
|
||||
$stat = $this->stat($path);
|
||||
return $stat['atime'];
|
||||
}
|
||||
public function file_get_contents($path) {
|
||||
$handle = $this->fopen($path, "r");
|
||||
if(!$handle){
|
||||
return false;
|
||||
}
|
||||
$size=$this->filesize($path);
|
||||
if($size==0){
|
||||
return '';
|
||||
}
|
||||
return fread($handle, $size);
|
||||
}
|
||||
public function file_put_contents($path,$data) {
|
||||
$handle = $this->fopen($path, "w");
|
||||
return fwrite($handle, $data);
|
||||
}
|
||||
// abstract public function unlink($path);
|
||||
public function rename($path1,$path2){
|
||||
if($this->copy($path1,$path2)){
|
||||
return $this->unlink($path1);
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public function copy($path1,$path2) {
|
||||
$source=$this->fopen($path1,'r');
|
||||
$target=$this->fopen($path2,'w');
|
||||
$count=OC_Helper::streamCopy($source,$target);
|
||||
return $count>0;
|
||||
}
|
||||
// abstract public function fopen($path,$mode);
|
||||
public function getMimeType($path){
|
||||
if(!$this->file_exists($path)){
|
||||
return false;
|
||||
}
|
||||
if($this->is_dir($path)){
|
||||
return 'httpd/unix-directory';
|
||||
}
|
||||
$source=$this->fopen($path,'r');
|
||||
if(!$source){
|
||||
return false;
|
||||
}
|
||||
$head=fread($source,8192);//8kb should suffice to determine a mimetype
|
||||
$extention=substr($path,strrpos($path,'.'));
|
||||
$tmpFile=OC_Helper::tmpFile($extention);
|
||||
file_put_contents($tmpFile,$head);
|
||||
$mime=OC_Helper::getMimeType($tmpFile);
|
||||
unlink($tmpFile);
|
||||
return $mime;
|
||||
}
|
||||
public function hash($type,$path,$raw){
|
||||
$tmpFile=$this->getLocalFile();
|
||||
$hash=hash($type,$tmpFile,$raw);
|
||||
unlink($tmpFile);
|
||||
return $hash;
|
||||
}
|
||||
// abstract public function free_space($path);
|
||||
public function search($query){
|
||||
return $this->searchInDir($query);
|
||||
}
|
||||
public function getLocalFile($path){
|
||||
return $this->toTmpFile($path);
|
||||
}
|
||||
private function toTmpFile($path){//no longer in the storage api, still usefull here
|
||||
$source=$this->fopen($path,'r');
|
||||
if(!$source){
|
||||
return false;
|
||||
}
|
||||
$extention=substr($path,strrpos($path,'.'));
|
||||
$tmpFile=OC_Helper::tmpFile($extention);
|
||||
$target=fopen($tmpFile,'w');
|
||||
$count=OC_Helper::streamCopy($source,$target);
|
||||
return $tmpFile;
|
||||
}
|
||||
// abstract public function touch($path, $mtime=null);
|
||||
|
||||
protected function searchInDir($query,$dir=''){
|
||||
$files=array();
|
||||
$dh=$this->opendir($dir);
|
||||
if($dh){
|
||||
while($item=readdir($dh)){
|
||||
if ($item == '.' || $item == '..') continue;
|
||||
if(strstr(strtolower($item),strtolower($query))!==false){
|
||||
$files[]=$dir.'/'.$item;
|
||||
}
|
||||
if($this->is_dir($dir.'/'.$item)){
|
||||
$files=array_merge($files,$this->searchInDir($query,$dir.'/'.$item));
|
||||
}
|
||||
}
|
||||
}
|
||||
return $files;
|
||||
}
|
||||
}
|
||||
75
lib/filestorage/commontest.php
Normal file
75
lib/filestorage/commontest.php
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Robin Appelman
|
||||
* @copyright 2012 Robin Appelman icewind@owncloud.com
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* test implementation for OC_FileStorage_Common with OC_FileStorage_Local
|
||||
*/
|
||||
|
||||
class OC_Filestorage_CommonTest extends OC_Filestorage_Common{
|
||||
/**
|
||||
* underlying local storage used for missing functions
|
||||
* @var OC_FileStorage_Local
|
||||
*/
|
||||
private $storage;
|
||||
|
||||
public function __construct($params){
|
||||
$this->storage=new OC_Filestorage_Local($params);
|
||||
}
|
||||
|
||||
public function mkdir($path){
|
||||
return $this->storage->mkdir($path);
|
||||
}
|
||||
public function rmdir($path){
|
||||
return $this->storage->rmdir($path);
|
||||
}
|
||||
public function opendir($path){
|
||||
return $this->storage->opendir($path);
|
||||
}
|
||||
public function stat($path){
|
||||
return $this->storage->stat($path);
|
||||
}
|
||||
public function filetype($path){
|
||||
return $this->storage->filetype($path);
|
||||
}
|
||||
public function is_readable($path){
|
||||
return $this->storage->is_readable($path);
|
||||
}
|
||||
public function is_writable($path){
|
||||
return $this->storage->is_writable($path);
|
||||
}
|
||||
public function file_exists($path){
|
||||
return $this->storage->file_exists($path);
|
||||
}
|
||||
public function unlink($path){
|
||||
return $this->storage->unlink($path);
|
||||
}
|
||||
public function fopen($path,$mode){
|
||||
return $this->storage->fopen($path,$mode);
|
||||
}
|
||||
public function free_space($path){
|
||||
return $this->storage->free_space($path);
|
||||
}
|
||||
public function touch($path, $mtime=null){
|
||||
return $this->storage->touch($path,$mtime);
|
||||
}
|
||||
}
|
||||
|
|
@ -20,36 +20,322 @@
|
|||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
class OC_Filestorage_Google extends OC_Filestorage_Common {
|
||||
|
||||
private $auth;
|
||||
require_once 'common.inc.php';
|
||||
|
||||
public function __construct($parameters) {
|
||||
class OC_Filestorage_Google extends OC_Filestorage_Common {
|
||||
|
||||
private $datadir;
|
||||
private $consumer;
|
||||
private $oauth_token;
|
||||
private $sig_method;
|
||||
private $entries;
|
||||
|
||||
public function __construct($arguments) {
|
||||
$this->datadir = $arguments['datadir'];
|
||||
$consumer_key = isset($arguments['consumer_key']) ? $arguments['consumer_key'] : 'anonymous';
|
||||
$consumer_secret = isset($arguments['consumer_secret']) ? $arguments['consumer_secret'] : 'anonymous';
|
||||
$this->consumer = new OAuthConsumer($consumer_key, $consumer_secret);
|
||||
$this->oauth_token = new OAuthToken($arguments['token'], $arguments['token_secret']);
|
||||
$this->sig_method = new OAuthSignatureMethod_HMAC_SHA1();
|
||||
$this->entries = array();
|
||||
}
|
||||
|
||||
private function sendRequest($feedUri, $http_method, $postData = null) {
|
||||
$feedUri = trim($feedUri);
|
||||
// create an associative array from each key/value url query param pair.
|
||||
$params = array();
|
||||
$pieces = explode('?', $feedUri);
|
||||
if (isset($pieces[1])) {
|
||||
$params = explode_assoc('=', '&', $pieces[1]);
|
||||
}
|
||||
// urlencode each url parameter key/value pair
|
||||
$tempStr = $pieces[0];
|
||||
foreach ($params as $key => $value) {
|
||||
$tempStr .= '&' . urlencode($key) . '=' . urlencode($value);
|
||||
}
|
||||
$feedUri = preg_replace('/&/', '?', $tempStr, 1);
|
||||
$req = OAuthRequest::from_consumer_and_token($this->consumer, $this->oauth_token, $http_method, $feedUri, $params);
|
||||
$req->sign_request($this->sig_method, $this->consumer, $this->oauth_token);
|
||||
$auth_header = $req->to_header();
|
||||
$result = send_signed_request($http_method, $feedUri, array($auth_header, 'Content-Type: application/atom+xml', 'GData-Version: 3.0'), $postData);
|
||||
// TODO Return false if error is received
|
||||
if (!$result) {
|
||||
return false;
|
||||
}
|
||||
$result = explode('<', $result, 2);
|
||||
$result = isset($result[1]) ? '<'.$result[1] : $result[0];
|
||||
$dom = new DOMDocument();
|
||||
$dom->loadXML($result);
|
||||
return $dom;
|
||||
}
|
||||
|
||||
private function getResource($path) {
|
||||
if (array_key_exists($path, $this->entries)) {
|
||||
return $this->entries[$path];
|
||||
} else {
|
||||
$title = basename($path);
|
||||
$dom = $this->sendRequest('https://docs.google.com/feeds/default/private/full?showfolders=true&title='.$title, 'GET');
|
||||
// Check if request was successful and entry exists
|
||||
if ($dom && $entry = $dom->getElementsByTagName('entry')->item(0)) {
|
||||
$this->entries[$path] = $entry;
|
||||
return $entry;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private function getExtension($entry) {
|
||||
$mimetype = $this->getMimeType('', $entry);
|
||||
switch($mimetype) {
|
||||
case 'httpd/unix-directory':
|
||||
return '';
|
||||
case 'application/vnd.oasis.opendocument.text':
|
||||
return 'odt';
|
||||
case 'application/vnd.oasis.opendocument.spreadsheet':
|
||||
return 'ods';
|
||||
case 'application/vnd.oasis.opendocument.presentation':
|
||||
return 'pptx';
|
||||
case 'text/html':
|
||||
return 'html';
|
||||
default:
|
||||
return 'html';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function mkdir($path) {
|
||||
$dir = dirname($path);
|
||||
// Check if path parent is root directory
|
||||
if ($dir == '/' || $dir == '\.' || $dir == '.') {
|
||||
$feedUri = 'https://docs.google.com/feeds/default/private/full';
|
||||
// Get parent content link
|
||||
} else if ($dom = $this->getResource(basename($dir))) {
|
||||
$feedUri = $dom->getElementsByTagName('content')->item(0)->getAttribute('src');
|
||||
}
|
||||
if (isset($feedUri)) {
|
||||
$title = basename($path);
|
||||
// Construct post data
|
||||
$postData = '<?xml version="1.0" encoding="UTF-8"?>';
|
||||
$postData .= '<entry xmlns="http://www.w3.org/2005/Atom">';
|
||||
$postData .= '<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/docs/2007#folder"/>';
|
||||
$postData .= '<title>'.$title.'</title>';
|
||||
$postData .= '</entry>';
|
||||
if ($dom = $this->sendRequest($feedUri, 'POST', $postData)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function rmdir($path) {
|
||||
return $this->unlink($path);
|
||||
}
|
||||
|
||||
public function opendir($path) {
|
||||
if ($path == '' || $path == '/') {
|
||||
$next = 'https://docs.google.com/feeds/default/private/full/folder%3Aroot/contents';
|
||||
} else {
|
||||
if ($entry = $this->getResource($path)) {
|
||||
$next = $entry->getElementsByTagName('content')->item(0)->getAttribute('src');
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$files = array();
|
||||
while ($next) {
|
||||
$dom = $this->sendRequest($next, 'GET');
|
||||
$links = $dom->getElementsByTagName('link');
|
||||
foreach ($links as $link) {
|
||||
if ($link->getAttribute('rel') == 'next') {
|
||||
$next = $link->getAttribute('src');
|
||||
break;
|
||||
} else {
|
||||
$next = false;
|
||||
}
|
||||
}
|
||||
$entries = $dom->getElementsByTagName('entry');
|
||||
foreach ($entries as $entry) {
|
||||
$name = $entry->getElementsByTagName('title')->item(0)->nodeValue;
|
||||
// Google Docs resources don't always include extensions in title
|
||||
if (!strpos($name, '.')) {
|
||||
$name .= '.'.$this->getExtension($entry);
|
||||
}
|
||||
$files[] = $name;
|
||||
// Cache entry for future use
|
||||
$this->entries[$name] = $entry;
|
||||
}
|
||||
}
|
||||
OC_FakeDirStream::$dirs['google'] = $files;
|
||||
return opendir('fakedir://google');
|
||||
}
|
||||
|
||||
public function stat($path) {
|
||||
if ($path == '' || $path == '/') {
|
||||
$stat['size'] = $this->free_space($path);
|
||||
$stat['atime'] = time();
|
||||
$stat['mtime'] = time();
|
||||
$stat['ctime'] = time();
|
||||
} else if ($entry = $this->getResource($path)) {
|
||||
// NOTE: Native resources don't have a file size
|
||||
$stat['size'] = $entry->getElementsByTagNameNS('http://schemas.google.com/g/2005', 'quotaBytesUsed')->item(0)->nodeValue;
|
||||
$stat['atime'] = strtotime($entry->getElementsByTagNameNS('http://schemas.google.com/g/2005', 'lastViewed')->item(0)->nodeValue);
|
||||
$stat['mtime'] = strtotime($entry->getElementsByTagName('updated')->item(0)->nodeValue);
|
||||
$stat['ctime'] = strtotime($entry->getElementsByTagName('published')->item(0)->nodeValue);
|
||||
}
|
||||
return $stat;
|
||||
}
|
||||
|
||||
public function filetype($path) {
|
||||
if ($path == '' || $path == '/') {
|
||||
return 'dir';
|
||||
} else if ($entry = $this->getResource($path)) {
|
||||
$categories = $entry->getElementsByTagName('category');
|
||||
foreach ($categories as $category) {
|
||||
if ($category->getAttribute('scheme') == 'http://schemas.google.com/g/2005#kind') {
|
||||
$type = $category->getAttribute('label');
|
||||
if (strlen(strstr($type, 'folder')) > 0) {
|
||||
return 'dir';
|
||||
} else {
|
||||
return 'file';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function is_readable($path) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function is_writable($path) {
|
||||
if ($path == '' || $path == '/') {
|
||||
return true;
|
||||
} else if ($entry = $this->getResource($path)) {
|
||||
// Check if edit or edit-media links exist
|
||||
$links = $entry->getElementsByTagName('link');
|
||||
foreach ($links as $link) {
|
||||
if ($link->getAttribute('rel') == 'edit') {
|
||||
return true;
|
||||
} else if ($link->getAttribute('rel') == 'edit-media') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function file_exists($path) {
|
||||
if ($path == '' || $path == '/') {
|
||||
return true;
|
||||
} else if ($this->getResource($path)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function unlink($path) {
|
||||
// Get resource self link to trash resource
|
||||
if ($entry = $this->getResource($path)) {
|
||||
$links = $entry->getElementsByTagName('link');
|
||||
foreach ($links as $link) {
|
||||
if ($link->getAttribute('rel') == 'self') {
|
||||
$feedUri = $link->getAttribute('href');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($feedUri)) {
|
||||
$this->sendRequest($feedUri, 'DELETE');
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function rename($path1, $path2) {
|
||||
// TODO Add support for moving to different collections
|
||||
// Get resource edit link to rename resource
|
||||
if ($entry = $this->getResource($path1)) {
|
||||
$etag = $entry->getElementsByTagName('entry')->item(0)->getAttribute('gd:etag');
|
||||
$links = $entry->getElementsByTagName('link');
|
||||
foreach ($links as $link) {
|
||||
if ($link->getAttribute('rel') == 'edit') {
|
||||
$feedUri = $link->getAttribute('href');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($etag) && isset($feedUri)) {
|
||||
$title = basename($path2);
|
||||
// Construct post data
|
||||
$postData = '<?xml version="1.0" encoding="UTF-8"?>';
|
||||
$postData .= '<entry xmlns="http://www.w3.org/2005/Atom" xmlns:docs="http://schemas.google.com/docs/2007" xmlns:gd="http://schemas.google.com/g/2005" gd:etag='.$etag.'>';
|
||||
$postData .= '<title>'.$title.'</title>';
|
||||
$postData .= '</entry>';
|
||||
$this->sendRequest($feedUri, 'PUT', $postData);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function fopen($path, $mode) {
|
||||
if ($entry = $this->getResource($path)) {
|
||||
$extension = $this->getExtension($path);
|
||||
$downloadUri = $entry->getElementsByTagName('content')->item(0)->getAttribute('src');
|
||||
// TODO Non-native documents don't need these additional parameters
|
||||
$downloadUri .= '&exportFormat='.$extension.'&format='.$extension;
|
||||
}
|
||||
}
|
||||
|
||||
public function getMimeType($path, $entry = null) {
|
||||
if ($entry == null) {
|
||||
if ($path == '' || $path == '/') {
|
||||
return 'httpd/unix-directory';
|
||||
} else {
|
||||
$entry = $this->getResource($path);
|
||||
}
|
||||
}
|
||||
if ($entry) {
|
||||
$mimetype = $entry->getElementsByTagName('content')->item(0)->getAttribute('type');
|
||||
// Native Google Docs resources often default to text/html, but it may be more useful to default to a corresponding ODF mimetype
|
||||
// Collections get reported as application/atom+xml, make sure it actually is a folder and fix the mimetype
|
||||
if ($mimetype == 'text/html' || $mimetype == 'application/atom+xml') {
|
||||
$categories = $entry->getElementsByTagName('category');
|
||||
foreach ($categories as $category) {
|
||||
if ($category->getAttribute('scheme') == 'http://schemas.google.com/g/2005#kind') {
|
||||
$type = $category->getAttribute('label');
|
||||
if (strlen(strstr($type, 'folder')) > 0) {
|
||||
return 'httpd/unix-directory';
|
||||
} else if (strlen(strstr($type, 'document')) > 0) {
|
||||
return 'application/vnd.oasis.opendocument.text';
|
||||
} else if (strlen(strstr($type, 'spreadsheet')) > 0) {
|
||||
return 'application/vnd.oasis.opendocument.spreadsheet';
|
||||
} else if (strlen(strstr($type, 'presentation')) > 0) {
|
||||
return 'application/vnd.oasis.opendocument.presentation';
|
||||
} else if (strlen(strstr($type, 'drawing')) > 0) {
|
||||
return 'application/vnd.oasis.opendocument.graphics';
|
||||
} else {
|
||||
// If nothing matches return text/html, all native Google Docs resources can be exported as text/html
|
||||
return 'text/html';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $mimetype;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function free_space($path) {
|
||||
if ($dom = $this->sendRequest('https://docs.google.com/feeds/metadata/default', 'GET')) {
|
||||
// NOTE: Native Google Docs resources don't count towards quota
|
||||
$total = $dom->getElementsByTagNameNS('http://schemas.google.com/g/2005', 'quotaBytesTotal')->item(0)->nodeValue;
|
||||
$used = $dom->getElementsByTagNameNS('http://schemas.google.com/g/2005', 'quotaBytesUsed')->item(0)->nodeValue;
|
||||
return $total - $used;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function search($query) {
|
||||
|
||||
}
|
||||
|
||||
private function connect() {
|
||||
|
||||
}
|
||||
public function mkdir($path){}
|
||||
public function rmdir($path){}
|
||||
public function opendir($path){}
|
||||
public function is_dir($path){}
|
||||
public function is_file($path){}
|
||||
public function stat($path){}
|
||||
public function filetype($path){}
|
||||
public function is_readable($path){}
|
||||
public function is_writable($path){}
|
||||
public function file_exists($path){}
|
||||
public function unlink($path){}
|
||||
public function rename($path1,$path2){}
|
||||
public function fopen($path,$mode){}
|
||||
public function toTmpFile($path){}
|
||||
public function fromTmpFile($tmpPath,$path){}
|
||||
public function fromUploadedFile($tmpPath,$path){}
|
||||
public function getMimeType($path){}
|
||||
public function hash($type,$path,$raw){}
|
||||
public function free_space($path){}
|
||||
public function search($query){}
|
||||
public function getLocalFile($path){}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue