aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/base.php26
-rw-r--r--lib/connector/sabre/node.php16
-rw-r--r--lib/db.php72
-rw-r--r--lib/filecache.php8
-rw-r--r--lib/fileproxy/quota.php16
-rw-r--r--lib/files.php26
-rw-r--r--lib/filesystem.php4
-rw-r--r--lib/filesystemview.php7
-rw-r--r--lib/helper.php2
-rw-r--r--lib/l10n/sr.php25
-rw-r--r--lib/l10n/zh_CN.GB2312.php1
-rw-r--r--lib/migrate.php48
-rw-r--r--lib/public/constants.php38
-rw-r--r--lib/public/db.php21
-rw-r--r--lib/public/share.php21
-rw-r--r--lib/setup.php54
-rw-r--r--lib/template.php6
-rwxr-xr-xlib/util.php29
-rw-r--r--lib/vcategories.php632
19 files changed, 863 insertions, 189 deletions
diff --git a/lib/base.php b/lib/base.php
index d4eeac82daa..c97700b3dbf 100644
--- a/lib/base.php
+++ b/lib/base.php
@@ -20,6 +20,8 @@
*
*/
+require_once 'public/constants.php';
+
/**
* Class that is a namespace for all global OC variables
* No, we can not put this class in its own file because it is used by
@@ -225,12 +227,10 @@ class OC{
if (isset($_SERVER['SERVER_SOFTWARE']) && strstr($_SERVER['SERVER_SOFTWARE'], 'Apache')) {
if(!OC_Util::ishtaccessworking()) {
if(!file_exists(OC::$SERVERROOT.'/data/.htaccess')) {
- $content = "deny from all\n";
- $content.= "IndexIgnore *";
- file_put_contents(OC_Config::getValue('datadirectory', OC::$SERVERROOT.'/data').'/.htaccess', $content);
+ OC_Setup::protectDataDirectory();
}
}
- }
+ }
OC_Log::write('core', 'starting upgrade from '.$installedVersion.' to '.$currentVersion, OC_Log::DEBUG);
$result=OC_DB::updateDbFromStructure(OC::$SERVERROOT.'/db_structure.xml');
if(!$result) {
@@ -288,7 +288,7 @@ class OC{
// (re)-initialize session
session_start();
-
+
// regenerate session id periodically to avoid session fixation
if (!isset($_SESSION['SID_CREATED'])) {
$_SESSION['SID_CREATED'] = time();
@@ -356,6 +356,10 @@ class OC{
//try to set the session lifetime to 60min
@ini_set('gc_maxlifetime', '3600');
+ //copy http auth headers for apache+php-fcgid work around
+ if (isset($_SERVER['HTTP_XAUTHORIZATION']) && !isset($_SERVER['HTTP_AUTHORIZATION'])) {
+ $_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['HTTP_XAUTHORIZATION'];
+ }
//set http auth headers for apache+php-cgi work around
if (isset($_SERVER['HTTP_AUTHORIZATION']) && preg_match('/Basic\s+(.*)$/i', $_SERVER['HTTP_AUTHORIZATION'], $matches)) {
@@ -475,17 +479,7 @@ class OC{
*/
public static function handleRequest() {
if (!OC_Config::getValue('installed', false)) {
- // Check for autosetup:
- $autosetup_file = OC::$SERVERROOT."/config/autoconfig.php";
- if( file_exists( $autosetup_file )) {
- OC_Log::write('core', 'Autoconfig file found, setting up owncloud...', OC_Log::INFO);
- include $autosetup_file;
- $_POST['install'] = 'true';
- $_POST = array_merge ($_POST, $AUTOCONFIG);
- unlink($autosetup_file);
- }
- OC_Util::addScript('setup');
- require_once 'setup.php';
+ require_once 'core/setup.php';
exit();
}
// Handle WebDAV
diff --git a/lib/connector/sabre/node.php b/lib/connector/sabre/node.php
index 5fc106b85ed..9fffa108d2a 100644
--- a/lib/connector/sabre/node.php
+++ b/lib/connector/sabre/node.php
@@ -26,6 +26,13 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
const LASTMODIFIED_PROPERTYNAME = '{DAV:}lastmodified';
/**
+ * Allow configuring the method used to generate Etags
+ *
+ * @var array(class_name, function_name)
+ */
+ public static $ETagFunction = null;
+
+ /**
* The path to the current node
*
* @var string
@@ -178,7 +185,7 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
* If the array is empty, all properties should be returned
*
* @param array $properties
- * @return void
+ * @return array
*/
public function getProperties($properties) {
if (is_null($this->property_cache)) {
@@ -209,7 +216,12 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
* @return string|null Returns null if the ETag can not effectively be determined
*/
static protected function createETag($path) {
- return uniqid('', true);
+ if(self::$ETagFunction) {
+ $hash = call_user_func(self::$ETagFunction, $path);
+ return $hash;
+ }else{
+ return uniqid('', true);
+ }
}
/**
diff --git a/lib/db.php b/lib/db.php
index fba2687967f..de42626563d 100644
--- a/lib/db.php
+++ b/lib/db.php
@@ -542,6 +542,78 @@ class OC_DB {
}
/**
+ * @brief Insert a row if a matching row doesn't exists.
+ * @param string $table. The table to insert into in the form '*PREFIX*tableName'
+ * @param array $input. An array of fieldname/value pairs
+ * @returns The return value from PDOStatementWrapper->execute()
+ */
+ public static function insertIfNotExist($table, $input) {
+ self::connect();
+ $prefix = OC_Config::getValue( "dbtableprefix", "oc_" );
+ $table = str_replace( '*PREFIX*', $prefix, $table );
+
+ if(is_null(self::$type)) {
+ self::$type=OC_Config::getValue( "dbtype", "sqlite" );
+ }
+ $type = self::$type;
+
+ $query = '';
+ // differences in escaping of table names ('`' for mysql) and getting the current timestamp
+ if( $type == 'sqlite' || $type == 'sqlite3' ) {
+ // NOTE: For SQLite we have to use this clumsy approach
+ // otherwise all fieldnames used must have a unique key.
+ $query = 'SELECT * FROM "' . $table . '" WHERE ';
+ foreach($input as $key => $value) {
+ $query .= $key . " = '" . $value . '\' AND ';
+ }
+ $query = substr($query, 0, strlen($query) - 5);
+ try {
+ $stmt = self::prepare($query);
+ $result = $stmt->execute();
+ } catch(PDOException $e) {
+ $entry = 'DB Error: "'.$e->getMessage() . '"<br />';
+ $entry .= 'Offending command was: ' . $query . '<br />';
+ OC_Log::write('core', $entry, OC_Log::FATAL);
+ error_log('DB error: '.$entry);
+ die( $entry );
+ }
+
+ if($result->numRows() == 0) {
+ $query = 'INSERT INTO "' . $table . '" ("'
+ . implode('","', array_keys($input)) . '") VALUES("'
+ . implode('","', array_values($input)) . '")';
+ } else {
+ return true;
+ }
+ } elseif( $type == 'pgsql' || $type == 'oci' || $type == 'mysql') {
+ $query = 'INSERT INTO `' .$table . '` ('
+ . implode(',', array_keys($input)) . ') SELECT \''
+ . implode('\',\'', array_values($input)) . '\' FROM ' . $table . ' WHERE ';
+
+ foreach($input as $key => $value) {
+ $query .= $key . " = '" . $value . '\' AND ';
+ }
+ $query = substr($query, 0, strlen($query) - 5);
+ $query .= ' HAVING COUNT(*) = 0';
+ }
+
+ // TODO: oci should be use " (quote) instead of ` (backtick).
+ //OC_Log::write('core', __METHOD__ . ', type: ' . $type . ', query: ' . $query, OC_Log::DEBUG);
+
+ try {
+ $result = self::prepare($query);
+ } catch(PDOException $e) {
+ $entry = 'DB Error: "'.$e->getMessage() . '"<br />';
+ $entry .= 'Offending command was: ' . $query.'<br />';
+ OC_Log::write('core', $entry, OC_Log::FATAL);
+ error_log('DB error: ' . $entry);
+ die( $entry );
+ }
+
+ return $result->execute();
+ }
+
+ /**
* @brief does minor changes to query
* @param string $query Query string
* @return string corrected query string
diff --git a/lib/filecache.php b/lib/filecache.php
index 6263e03fc64..4a7dbd0250d 100644
--- a/lib/filecache.php
+++ b/lib/filecache.php
@@ -502,11 +502,11 @@ class OC_FileCache{
*/
public static function triggerUpdate($user='') {
if($user) {
- $query=OC_DB::prepare('UPDATE `*PREFIX*fscache` SET `mtime`=0 WHERE `user`=? AND `mimetype`="httpd/unix-directory"');
- $query->execute(array($user));
+ $query=OC_DB::prepare('UPDATE `*PREFIX*fscache` SET `mtime`=0 WHERE `user`=? AND `mimetype`= ? ');
+ $query->execute(array($user,'httpd/unix-directory'));
}else{
- $query=OC_DB::prepare('UPDATE `*PREFIX*fscache` SET `mtime`=0 AND `mimetype`="httpd/unix-directory"');
- $query->execute();
+ $query=OC_DB::prepare('UPDATE `*PREFIX*fscache` SET `mtime`=0 AND `mimetype`= ? ');
+ $query->execute(array('httpd/unix-directory'));
}
}
}
diff --git a/lib/fileproxy/quota.php b/lib/fileproxy/quota.php
index 46bc8dc16d8..742e02d471b 100644
--- a/lib/fileproxy/quota.php
+++ b/lib/fileproxy/quota.php
@@ -43,7 +43,7 @@ class OC_FileProxy_Quota extends OC_FileProxy{
$userQuota=OC_AppConfig::getValue('files', 'default_quota', 'none');
}
if($userQuota=='none') {
- $this->userQuota[$user]=0;
+ $this->userQuota[$user]=-1;
}else{
$this->userQuota[$user]=OC_Helper::computerFileSize($userQuota);
}
@@ -61,8 +61,8 @@ class OC_FileProxy_Quota extends OC_FileProxy{
$owner=$storage->getOwner($path);
$totalSpace=$this->getQuota($owner);
- if($totalSpace==0) {
- return 0;
+ if($totalSpace==-1) {
+ return -1;
}
$rootInfo=OC_FileCache::get('', "/".$owner."/files");
@@ -79,7 +79,7 @@ class OC_FileProxy_Quota extends OC_FileProxy{
public function postFree_space($path, $space) {
$free=$this->getFreeSpace($path);
- if($free==0) {
+ if($free==-1) {
return $space;
}
return min($free, $space);
@@ -89,21 +89,21 @@ class OC_FileProxy_Quota extends OC_FileProxy{
if (is_resource($data)) {
$data = '';//TODO: find a way to get the length of the stream without emptying it
}
- return (strlen($data)<$this->getFreeSpace($path) or $this->getFreeSpace($path)==0);
+ return (strlen($data)<$this->getFreeSpace($path) or $this->getFreeSpace($path)==-1);
}
public function preCopy($path1, $path2) {
if(!self::$rootView) {
self::$rootView = new OC_FilesystemView('');
}
- return (self::$rootView->filesize($path1)<$this->getFreeSpace($path2) or $this->getFreeSpace($path2)==0);
+ return (self::$rootView->filesize($path1)<$this->getFreeSpace($path2) or $this->getFreeSpace($path2)==-1);
}
public function preFromTmpFile($tmpfile, $path) {
- return (filesize($tmpfile)<$this->getFreeSpace($path) or $this->getFreeSpace($path)==0);
+ return (filesize($tmpfile)<$this->getFreeSpace($path) or $this->getFreeSpace($path)==-1);
}
public function preFromUploadedFile($tmpfile, $path) {
- return (filesize($tmpfile)<$this->getFreeSpace($path) or $this->getFreeSpace($path)==0);
+ return (filesize($tmpfile)<$this->getFreeSpace($path) or $this->getFreeSpace($path)==-1);
}
}
diff --git a/lib/files.php b/lib/files.php
index 5a14083c285..e5bf78d032f 100644
--- a/lib/files.php
+++ b/lib/files.php
@@ -42,16 +42,20 @@ class OC_Files {
* - versioned
*/
public static function getFileInfo($path) {
+ $path = OC_Filesystem::normalizePath($path);
if (($path == '/Shared' || substr($path, 0, 8) == '/Shared/') && OC_App::isEnabled('files_sharing')) {
if ($path == '/Shared') {
list($info) = OCP\Share::getItemsSharedWith('file', OC_Share_Backend_File::FORMAT_FILE_APP_ROOT);
- }else{
- $info['size'] = OC_Filesystem::filesize($path);
- $info['mtime'] = OC_Filesystem::filemtime($path);
- $info['ctime'] = OC_Filesystem::filectime($path);
- $info['mimetype'] = OC_Filesystem::getMimeType($path);
- $info['encrypted'] = false;
- $info['versioned'] = false;
+ } else {
+ $info = array();
+ if (OC_Filesystem::file_exists($path)) {
+ $info['size'] = OC_Filesystem::filesize($path);
+ $info['mtime'] = OC_Filesystem::filemtime($path);
+ $info['ctime'] = OC_Filesystem::filectime($path);
+ $info['mimetype'] = OC_Filesystem::getMimeType($path);
+ $info['encrypted'] = false;
+ $info['versioned'] = false;
+ }
}
} else {
$info = OC_FileCache::get($path);
@@ -87,16 +91,16 @@ class OC_Files {
foreach ($files as &$file) {
$file['directory'] = $directory;
$file['type'] = ($file['mimetype'] == 'httpd/unix-directory') ? 'dir' : 'file';
- $permissions = OCP\Share::PERMISSION_READ;
+ $permissions = OCP\PERMISSION_READ;
// NOTE: Remove check when new encryption is merged
if (!$file['encrypted']) {
- $permissions |= OCP\Share::PERMISSION_SHARE;
+ $permissions |= OCP\PERMISSION_SHARE;
}
if ($file['type'] == 'dir' && $file['writable']) {
- $permissions |= OCP\Share::PERMISSION_CREATE;
+ $permissions |= OCP\PERMISSION_CREATE;
}
if ($file['writable']) {
- $permissions |= OCP\Share::PERMISSION_UPDATE | OCP\Share::PERMISSION_DELETE;
+ $permissions |= OCP\PERMISSION_UPDATE | OCP\PERMISSION_DELETE;
}
$file['permissions'] = $permissions;
}
diff --git a/lib/filesystem.php b/lib/filesystem.php
index 4635f8b4f30..aa03593908d 100644
--- a/lib/filesystem.php
+++ b/lib/filesystem.php
@@ -232,8 +232,8 @@ class OC_Filesystem{
}
if(isset($mountConfig['user'])) {
- foreach($mountConfig['user'] as $user=>$mounts) {
- if($user==='all' or strtolower($user)===strtolower($user)) {
+ foreach($mountConfig['user'] as $mountUser=>$mounts) {
+ if($user==='all' or strtolower($mountUser)===strtolower($user)) {
foreach($mounts as $mountPoint=>$options) {
$mountPoint=self::setUserVars($mountPoint, $user);
foreach($options as &$option) {
diff --git a/lib/filesystemview.php b/lib/filesystemview.php
index 936e1feb412..0229213ebcb 100644
--- a/lib/filesystemview.php
+++ b/lib/filesystemview.php
@@ -47,11 +47,8 @@ class OC_FilesystemView {
$this->fakeRoot=$root;
}
- public function getAbsolutePath($path) {
- if(!$path) {
- $path='/';
- }
- if($path[0]!=='/') {
+ public function getAbsolutePath($path = '/') {
+ if(!$path || $path[0]!=='/') {
$path='/'.$path;
}
return $this->fakeRoot.$path;
diff --git a/lib/helper.php b/lib/helper.php
index ed459dab624..ccceb58cd4c 100644
--- a/lib/helper.php
+++ b/lib/helper.php
@@ -319,7 +319,7 @@ class OC_Helper {
self::copyr("$src/$file", "$dest/$file");
}
}
- }elseif(file_exists($src)) {
+ }elseif(file_exists($src) && !OC_Filesystem::isFileBlacklisted($src)) {
copy($src, $dest);
}
}
diff --git a/lib/l10n/sr.php b/lib/l10n/sr.php
index cec7ea703fb..a48830551bd 100644
--- a/lib/l10n/sr.php
+++ b/lib/l10n/sr.php
@@ -3,6 +3,29 @@
"Personal" => "Лично",
"Settings" => "Подешавања",
"Users" => "Корисници",
+"Apps" => "Апликације",
+"Admin" => "Администрација",
+"ZIP download is turned off." => "Преузимање ЗИПа је искључено.",
+"Files need to be downloaded one by one." => "Преузимање морате радити једану по једану.",
+"Back to Files" => "Назад на датотеке",
+"Selected files too large to generate zip file." => "Изабране датотеке су превелике да бисте правили зип датотеку.",
+"Application is not enabled" => "Апликација није укључена",
"Authentication error" => "Грешка при аутентификацији",
-"Text" => "Текст"
+"Token expired. Please reload page." => "Токен је истекао. Поново учитајте страну.",
+"Files" => "Датотеке",
+"Text" => "Текст",
+"Images" => "Слике",
+"seconds ago" => "пре неколико секунди",
+"1 minute ago" => "пре 1 минута",
+"%d minutes ago" => "%d минута раније",
+"today" => "данас",
+"yesterday" => "јуче",
+"%d days ago" => "%d дана раније",
+"last month" => "прошлог месеца",
+"months ago" => "месеци раније",
+"last year" => "прошле године",
+"years ago" => "година раније",
+"%s is available. Get <a href=\"%s\">more information</a>" => "%s је доступна. Погледајте <a href=\"%s\">више информација</a>",
+"up to date" => "је ажурна",
+"updates check is disabled" => "провера ажурирања је искључена"
);
diff --git a/lib/l10n/zh_CN.GB2312.php b/lib/l10n/zh_CN.GB2312.php
index adc5c3bc6a9..4fbdb66ff22 100644
--- a/lib/l10n/zh_CN.GB2312.php
+++ b/lib/l10n/zh_CN.GB2312.php
@@ -14,6 +14,7 @@
"Token expired. Please reload page." => "会话过期。请刷新页面。",
"Files" => "文件",
"Text" => "文本",
+"Images" => "图片",
"seconds ago" => "秒前",
"1 minute ago" => "1 分钟前",
"%d minutes ago" => "%d 分钟前",
diff --git a/lib/migrate.php b/lib/migrate.php
index 96f5a0001f7..2cc0a3067b8 100644
--- a/lib/migrate.php
+++ b/lib/migrate.php
@@ -200,7 +200,7 @@ class OC_Migrate{
$scan = scandir( $extractpath );
// Check for export_info.json
if( !in_array( 'export_info.json', $scan ) ) {
- OC_Log::write( 'migration', 'Invalid import file, export_info.json note found', OC_Log::ERROR );
+ OC_Log::write( 'migration', 'Invalid import file, export_info.json not found', OC_Log::ERROR );
return json_encode( array( 'success' => false ) );
}
$json = json_decode( file_get_contents( $extractpath . 'export_info.json' ) );
@@ -235,12 +235,19 @@ class OC_Migrate{
return json_encode( array( 'success' => false ) );
}
// Copy data
- if( !self::copy_r( $extractpath . $json->exporteduser, $datadir . '/' . self::$uid ) ) {
- return json_encode( array( 'success' => false ) );
+ $userfolder = $extractpath . $json->exporteduser;
+ $newuserfolder = $datadir . '/' . self::$uid;
+ foreach(scandir($userfolder) as $file){
+ if($file !== '.' && $file !== '..' && is_dir($file)) {
+ // Then copy the folder over
+ OC_Helper::copyr($userfolder.'/'.$file, $newuserfolder.'/'.$file);
+ }
}
// Import user app data
- if( !$appsimported = self::importAppData( $extractpath . $json->exporteduser . '/migration.db', $json, self::$uid ) ) {
- return json_encode( array( 'success' => false ) );
+ if(file_exists($extractpath . $json->exporteduser . '/migration.db')) {
+ if( !$appsimported = self::importAppData( $extractpath . $json->exporteduser . '/migration.db', $json, self::$uid ) ) {
+ return json_encode( array( 'success' => false ) );
+ }
}
// All done!
if( !self::unlink_r( $extractpath ) ) {
@@ -305,37 +312,6 @@ class OC_Migrate{
}
/**
- * @brief copies recursively
- * @param $path string path to source folder
- * @param $dest string path to destination
- * @return bool
- */
- private static function copy_r( $path, $dest ) {
- if( is_dir($path) ) {
- @mkdir( $dest );
- $objects = scandir( $path );
- if( sizeof( $objects ) > 0 ) {
- foreach( $objects as $file ) {
- if( $file == "." || $file == ".." || $file == ".htaccess")
- continue;
- // go on
- if( is_dir( $path . '/' . $file ) ) {
- self::copy_r( $path .'/' . $file, $dest . '/' . $file );
- } else {
- copy( $path . '/' . $file, $dest . '/' . $file );
- }
- }
- }
- return true;
- }
- elseif( is_file( $path ) ) {
- return copy( $path, $dest );
- } else {
- return false;
- }
- }
-
- /**
* @brief tries to extract the import zip
* @param $path string path to the zip
* @return string path to extract location (with a trailing slash) or false on failure
diff --git a/lib/public/constants.php b/lib/public/constants.php
new file mode 100644
index 00000000000..bc979c9031f
--- /dev/null
+++ b/lib/public/constants.php
@@ -0,0 +1,38 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Thomas Tanghus
+ * @copyright 2012 Thomas Tanghus (thomas@tanghus.net)
+ *
+ * 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/>.
+ *
+ */
+
+/**
+ * This file defines common constants used in ownCloud
+ */
+
+namespace OCP;
+
+/**
+ * CRUDS permissions.
+ */
+const PERMISSION_CREATE = 4;
+const PERMISSION_READ = 1;
+const PERMISSION_UPDATE = 2;
+const PERMISSION_DELETE = 8;
+const PERMISSION_SHARE = 16;
+const PERMISSION_ALL = 31;
+
diff --git a/lib/public/db.php b/lib/public/db.php
index d2484b6eb83..92ff8f93a22 100644
--- a/lib/public/db.php
+++ b/lib/public/db.php
@@ -46,6 +46,27 @@ class DB {
}
/**
+ * @brief Insert a row if a matching row doesn't exists.
+ * @param $table string The table name (will replace *PREFIX*) to perform the replace on.
+ * @param $input array
+ *
+ * The input array if in the form:
+ *
+ * array ( 'id' => array ( 'value' => 6,
+ * 'key' => true
+ * ),
+ * 'name' => array ('value' => 'Stoyan'),
+ * 'family' => array ('value' => 'Stefanov'),
+ * 'birth_date' => array ('value' => '1975-06-20')
+ * );
+ * @returns true/false
+ *
+ */
+ public static function insertIfNotExist($table, $input) {
+ return(\OC_DB::insertIfNotExist($table, $input));
+ }
+
+ /**
* @brief gets last value of autoincrement
* @param $table string The optional table name (will replace *PREFIX*) and add sequence suffix
* @returns id
diff --git a/lib/public/share.php b/lib/public/share.php
index 071304ec249..dcb1b5c278e 100644
--- a/lib/public/share.php
+++ b/lib/public/share.php
@@ -46,12 +46,8 @@ class Share {
* Check if permission is granted with And (&) e.g. Check if delete is granted: if ($permissions & PERMISSION_DELETE)
* Remove permissions with And (&) and Not (~) e.g. Remove the update permission: $permissions &= ~PERMISSION_UPDATE
* Apps are required to handle permissions on their own, this class only stores and manages the permissions of shares
+ * @see lib/public/constants.php
*/
- const PERMISSION_CREATE = 4;
- const PERMISSION_READ = 1;
- const PERMISSION_UPDATE = 2;
- const PERMISSION_DELETE = 8;
- const PERMISSION_SHARE = 16;
const FORMAT_NONE = -1;
const FORMAT_STATUSES = -2;
@@ -402,7 +398,7 @@ class Share {
// Check if permissions were removed
if ($item['permissions'] & ~$permissions) {
// If share permission is removed all reshares must be deleted
- if (($item['permissions'] & self::PERMISSION_SHARE) && (~$permissions & self::PERMISSION_SHARE)) {
+ if (($item['permissions'] & PERMISSION_SHARE) && (~$permissions & PERMISSION_SHARE)) {
self::delete($item['id'], true);
} else {
$ids = array();
@@ -552,7 +548,7 @@ class Share {
$itemTypes = $collectionTypes;
}
$placeholders = join(',', array_fill(0, count($itemTypes), '?'));
- $where .= ' WHERE item_type IN ('.$placeholders.'))';
+ $where .= ' WHERE `item_type` IN ('.$placeholders.'))';
$queryArgs = $itemTypes;
} else {
$where = ' WHERE `item_type` = ?';
@@ -629,7 +625,7 @@ class Share {
$queryArgs[] = $item;
if ($includeCollections && $collectionTypes) {
$placeholders = join(',', array_fill(0, count($collectionTypes), '?'));
- $where .= ' OR item_type IN ('.$placeholders.'))';
+ $where .= ' OR `item_type` IN ('.$placeholders.'))';
$queryArgs = array_merge($queryArgs, $collectionTypes);
}
}
@@ -677,6 +673,9 @@ class Share {
$root = strlen($root);
$query = \OC_DB::prepare('SELECT '.$select.' FROM `*PREFIX*share` '.$where, $queryLimit);
$result = $query->execute($queryArgs);
+ if (\OC_DB::isError($result)) {
+ \OC_Log::write('OCP\Share', \OC_DB::getErrorMessage($result) . ', select=' . $select . ' where=' . $where, \OC_Log::ERROR);
+ }
$items = array();
$targets = array();
while ($row = $result->fetchRow()) {
@@ -701,7 +700,7 @@ class Share {
$items[$id]['share_with'] = $row['share_with'];
}
// Switch ids if sharing permission is granted on only one share to ensure correct parent is used if resharing
- if (~(int)$items[$id]['permissions'] & self::PERMISSION_SHARE && (int)$row['permissions'] & self::PERMISSION_SHARE) {
+ if (~(int)$items[$id]['permissions'] & PERMISSION_SHARE && (int)$row['permissions'] & PERMISSION_SHARE) {
$items[$row['id']] = $items[$id];
unset($items[$id]);
$id = $row['id'];
@@ -847,7 +846,7 @@ class Share {
throw new \Exception($message);
}
// Check if share permissions is granted
- if ((int)$checkReshare['permissions'] & self::PERMISSION_SHARE) {
+ if ((int)$checkReshare['permissions'] & PERMISSION_SHARE) {
if (~(int)$checkReshare['permissions'] & $permissions) {
$message = 'Sharing '.$itemSource.' failed, because the permissions exceed permissions granted to '.$uidOwner;
\OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
@@ -1133,7 +1132,7 @@ class Share {
$duplicateParent = $query->execute(array($item['item_type'], $item['item_target'], self::SHARE_TYPE_USER, self::SHARE_TYPE_GROUP, self::$shareTypeGroupUserUnique, $item['uid_owner'], $item['parent']))->fetchRow();
if ($duplicateParent) {
// Change the parent to the other item id if share permission is granted
- if ($duplicateParent['permissions'] & self::PERMISSION_SHARE) {
+ if ($duplicateParent['permissions'] & PERMISSION_SHARE) {
$query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `parent` = ? WHERE `id` = ?');
$query->execute(array($duplicateParent['id'], $item['id']));
continue;
diff --git a/lib/setup.php b/lib/setup.php
index 726b3352d50..264cd55795e 100644
--- a/lib/setup.php
+++ b/lib/setup.php
@@ -1,45 +1,5 @@
<?php
-$hasSQLite = (is_callable('sqlite_open') or class_exists('SQLite3'));
-$hasMySQL = is_callable('mysql_connect');
-$hasPostgreSQL = is_callable('pg_connect');
-$hasOracle = is_callable('oci_connect');
-$datadir = OC_Config::getValue('datadirectory', OC::$SERVERROOT.'/data');
-
-// Test if .htaccess is working
-$content = "deny from all";
-file_put_contents(OC::$SERVERROOT.'/data/.htaccess', $content);
-
-$opts = array(
- 'hasSQLite' => $hasSQLite,
- 'hasMySQL' => $hasMySQL,
- 'hasPostgreSQL' => $hasPostgreSQL,
- 'hasOracle' => $hasOracle,
- 'directory' => $datadir,
- 'secureRNG' => OC_Util::secureRNG_available(),
- 'htaccessWorking' => OC_Util::ishtaccessworking(),
- 'errors' => array(),
-);
-
-if(isset($_POST['install']) AND $_POST['install']=='true') {
- // We have to launch the installation process :
- $e = OC_Setup::install($_POST);
- $errors = array('errors' => $e);
-
- if(count($e) > 0) {
- //OC_Template::printGuestPage("", "error", array("errors" => $errors));
- $options = array_merge($_POST, $opts, $errors);
- OC_Template::printGuestPage("", "installation", $options);
- }
- else {
- header("Location: ".OC::$WEBROOT.'/');
- exit();
- }
-}
-else {
- OC_Template::printGuestPage("", "installation", $opts);
-}
-
class OC_Setup {
public static function install($options) {
$error = array();
@@ -573,7 +533,15 @@ class OC_Setup {
* create .htaccess files for apache hosts
*/
private static function createHtaccess() {
- $content = "ErrorDocument 403 ".OC::$WEBROOT."/core/templates/403.php\n";//custom 403 error page
+ $content = "<IfModule mod_fcgid.c>\n";
+ $content.= "<IfModule mod_setenvif.c>\n";
+ $content.= "<IfModule mod_headers.c>\n";
+ $content.= "SetEnvIfNoCase ^Authorization$ \"(.+)\" XAUTHORIZATION=$1\n";
+ $content.= "RequestHeader set XAuthorization %{XAUTHORIZATION}e env=XAUTHORIZATION\n";
+ $content.= "</IfModule>\n";
+ $content.= "</IfModule>\n";
+ $content.= "</IfModule>\n";
+ $content.= "ErrorDocument 403 ".OC::$WEBROOT."/core/templates/403.php\n";//custom 403 error page
$content.= "ErrorDocument 404 ".OC::$WEBROOT."/core/templates/404.php\n";//custom 404 error page
$content.= "<IfModule mod_php5.c>\n";
$content.= "php_value upload_max_filesize 512M\n";//upload limit
@@ -599,6 +567,10 @@ class OC_Setup {
$content.= "Options -Indexes\n";
@file_put_contents(OC::$SERVERROOT.'/.htaccess', $content); //supress errors in case we don't have permissions for it
+ self::protectDataDirectory();
+ }
+
+ public static function protectDataDirectory() {
$content = "deny from all\n";
$content.= "IndexIgnore *";
file_put_contents(OC_Config::getValue('datadirectory', OC::$SERVERROOT.'/data').'/.htaccess', $content);
diff --git a/lib/template.php b/lib/template.php
index 3d3589abd1e..a10cabf5931 100644
--- a/lib/template.php
+++ b/lib/template.php
@@ -103,13 +103,13 @@ function relative_modified_date($timestamp) {
if($timediff < 60) { return $l->t('seconds ago'); }
else if($timediff < 120) { return $l->t('1 minute ago'); }
else if($timediff < 3600) { return $l->t('%d minutes ago', $diffminutes); }
- //else if($timediff < 7200) { return '1 hour ago'; }
- //else if($timediff < 86400) { return $diffhours.' hours ago'; }
+ else if($timediff < 7200) { return $l->t('1 hour ago'); }
+ else if($timediff < 86400) { return $l->t('%d hours ago', $diffhours); }
else if((date('G')-$diffhours) > 0) { return $l->t('today'); }
else if((date('G')-$diffhours) > -24) { return $l->t('yesterday'); }
else if($timediff < 2678400) { return $l->t('%d days ago', $diffdays); }
else if($timediff < 5184000) { return $l->t('last month'); }
- else if((date('n')-$diffmonths) > 0) { return $l->t('months ago'); }
+ else if((date('n')-$diffmonths) > 0) { return $l->t('%d months ago', $diffmonths); }
else if($timediff < 63113852) { return $l->t('last year'); }
else { return $l->t('years ago'); }
}
diff --git a/lib/util.php b/lib/util.php
index 40b44bf9d6e..da57b226ba0 100755
--- a/lib/util.php
+++ b/lib/util.php
@@ -95,7 +95,7 @@ class OC_Util {
*/
public static function getVersion() {
// hint: We only can count up. So the internal version number of ownCloud 4.5 will be 4.90.0. This is not visible to the user
- return array(4, 91, 00);
+ return array(4, 91, 01);
}
/**
@@ -584,6 +584,33 @@ class OC_Util {
}
}
+
+ /**
+ * Check if the ownCloud server can connect to the internet
+ */
+ public static function isinternetconnectionworking() {
+
+ // try to connect to owncloud.org to see if http connections to the internet are possible.
+ $connected = @fsockopen("www.owncloud.org", 80);
+ if ($connected) {
+ fclose($connected);
+ return true;
+ }else{
+
+ // second try in case one server is down
+ $connected = @fsockopen("apps.owncloud.com", 80);
+ if ($connected) {
+ fclose($connected);
+ return true;
+ }else{
+ return false;
+ }
+
+ }
+
+ }
+
+
/**
* @brief Generates a cryptographical secure pseudorandom string
* @param Int with the length of the random string
diff --git a/lib/vcategories.php b/lib/vcategories.php
index 46256def9c4..406a4eb1074 100644
--- a/lib/vcategories.php
+++ b/lib/vcategories.php
@@ -21,6 +21,7 @@
*
*/
+OC_Hook::connect('OC_User', 'post_deleteUser', 'OC_VCategories', 'post_deleteUser');
/**
* Class for easy access to categories in VCARD, VEVENT, VTODO and VJOURNAL.
@@ -28,50 +29,261 @@
* anything else that is either parsed from a vobject or that the user chooses
* to add.
* Category names are not case-sensitive, but will be saved with the case they
- * are entered in. If a user already has a category 'family' for an app, and
+ * are entered in. If a user already has a category 'family' for a type, and
* tries to add a category named 'Family' it will be silently ignored.
- * NOTE: There is a limitation in that the the configvalue field in the
- * preferences table is a varchar(255).
*/
class OC_VCategories {
- const PREF_CATEGORIES_LABEL = 'extra_categories';
+
/**
* Categories
*/
private $categories = array();
- private $app = null;
+ /**
+ * Used for storing objectid/categoryname pairs while rescanning.
+ */
+ private static $relations = array();
+
+ private $type = null;
private $user = null;
+ const CATEGORY_TABLE = '*PREFIX*vcategory';
+ const RELATION_TABLE = '*PREFIX*vcategory_to_object';
+
+ const CATEGORY_FAVORITE = '_$!<Favorite>!$_';
+
+ const FORMAT_LIST = 0;
+ const FORMAT_MAP = 1;
+
/**
* @brief Constructor.
- * @param $app The application identifier e.g. 'contacts' or 'calendar'.
+ * @param $type The type identifier e.g. 'contact' or 'event'.
* @param $user The user whos data the object will operate on. This
* parameter should normally be omitted but to make an app able to
* update categories for all users it is made possible to provide it.
* @param $defcategories An array of default categories to be used if none is stored.
*/
- public function __construct($app, $user=null, $defcategories=array()) {
- $this->app = $app;
+ public function __construct($type, $user=null, $defcategories=array()) {
+ $this->type = $type;
$this->user = is_null($user) ? OC_User::getUser() : $user;
- $categories = trim(OC_Preferences::getValue($this->user, $app, self::PREF_CATEGORIES_LABEL, ''));
- if ($categories) {
- $categories = @unserialize($categories);
+
+ $this->loadCategories();
+ OCP\Util::writeLog('core', __METHOD__ . ', categories: '
+ . print_r($this->categories, true),
+ OCP\Util::DEBUG
+ );
+
+ if($defcategories && count($this->categories) === 0) {
+ $this->addMulti($defcategories, true);
+ }
+ }
+
+ /**
+ * @brief Load categories from db.
+ */
+ private function loadCategories() {
+ $this->categories = array();
+ $result = null;
+ $sql = 'SELECT `id`, `category` FROM `' . self::CATEGORY_TABLE . '` '
+ . 'WHERE `uid` = ? AND `type` = ? ORDER BY `category`';
+ try {
+ $stmt = OCP\DB::prepare($sql);
+ $result = $stmt->execute(array($this->user, $this->type));
+ if (OC_DB::isError($result)) {
+ OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR);
+ }
+ } catch(Exception $e) {
+ OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
+ OCP\Util::ERROR);
+ }
+
+ if(!is_null($result)) {
+ while( $row = $result->fetchRow()) {
+ // The keys are prefixed because array_search wouldn't work otherwise :-/
+ $this->categories[$row['id']] = $row['category'];
+ }
+ }
+ OCP\Util::writeLog('core', __METHOD__.', categories: ' . print_r($this->categories, true),
+ OCP\Util::DEBUG);
+ }
+
+
+ /**
+ * @brief Check if any categories are saved for this type and user.
+ * @returns boolean.
+ * @param $type The type identifier e.g. 'contact' or 'event'.
+ * @param $user The user whos categories will be checked. If not set current user will be used.
+ */
+ public static function isEmpty($type, $user = null) {
+ $user = is_null($user) ? OC_User::getUser() : $user;
+ $sql = 'SELECT COUNT(*) FROM `' . self::CATEGORY_TABLE . '` '
+ . 'WHERE `uid` = ? AND `type` = ?';
+ try {
+ $stmt = OCP\DB::prepare($sql);
+ $result = $stmt->execute(array($user, $type));
+ if (OC_DB::isError($result)) {
+ OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR);
+ return false;
+ }
+ return ($result->numRows() == 0);
+ } catch(Exception $e) {
+ OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
+ OCP\Util::ERROR);
+ return false;
}
- $this->categories = is_array($categories) ? $categories : $defcategories;
}
/**
* @brief Get the categories for a specific user.
+ * @param
* @returns array containing the categories as strings.
*/
- public function categories() {
- //OC_Log::write('core', 'OC_VCategories::categories: '.print_r($this->categories, true), OC_Log::DEBUG);
+ public function categories($format = null) {
if(!$this->categories) {
return array();
}
- usort($this->categories, 'strnatcasecmp'); // usort to also renumber the keys
- return $this->categories;
+ $categories = array_values($this->categories);
+ uasort($categories, 'strnatcasecmp');
+ if($format == self::FORMAT_MAP) {
+ $catmap = array();
+ foreach($categories as $category) {
+ if($category !== self::CATEGORY_FAVORITE) {
+ $catmap[] = array(
+ 'id' => $this->array_searchi($category, $this->categories),
+ 'name' => $category
+ );
+ }
+ }
+ return $catmap;
+ }
+
+ // Don't add favorites to normal categories.
+ $favpos = array_search(self::CATEGORY_FAVORITE, $categories);
+ if($favpos !== false) {
+ return array_splice($categories, $favpos);
+ } else {
+ return $categories;
+ }
+ }
+
+ /**
+ * Get the a list if items belonging to $category.
+ *
+ * Throws an exception if the category could not be found.
+ *
+ * @param string|integer $category Category id or name.
+ * @returns array An array of object ids or false on error.
+ */
+ public function idsForCategory($category) {
+ $result = null;
+ if(is_numeric($category)) {
+ $catid = $category;
+ } elseif(is_string($category)) {
+ $catid = $this->array_searchi($category, $this->categories);
+ }
+ OCP\Util::writeLog('core', __METHOD__.', category: '.$catid.' '.$category, OCP\Util::DEBUG);
+ if($catid === false) {
+ $l10n = OC_L10N::get('core');
+ throw new Exception(
+ $l10n->t('Could not find category "%s"', $category)
+ );
+ }
+
+ $ids = array();
+ $sql = 'SELECT `objid` FROM `' . self::RELATION_TABLE
+ . '` WHERE `categoryid` = ?';
+
+ try {
+ $stmt = OCP\DB::prepare($sql);
+ $result = $stmt->execute(array($catid));
+ if (OC_DB::isError($result)) {
+ OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR);
+ return false;
+ }
+ } catch(Exception $e) {
+ OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
+ OCP\Util::ERROR);
+ return false;
+ }
+
+ if(!is_null($result)) {
+ while( $row = $result->fetchRow()) {
+ $ids[] = (int)$row['objid'];
+ }
+ }
+
+ return $ids;
+ }
+
+ /**
+ * Get the a list if items belonging to $category.
+ *
+ * Throws an exception if the category could not be found.
+ *
+ * @param string|integer $category Category id or name.
+ * @param array $tableinfo Array in the form {'tablename' => table, 'fields' => ['field1', 'field2']}
+ * @param int $limit
+ * @param int $offset
+ *
+ * This generic method queries a table assuming that the id
+ * field is called 'id' and the table name provided is in
+ * the form '*PREFIX*table_name'.
+ *
+ * If the category name cannot be resolved an exception is thrown.
+ *
+ * TODO: Maybe add the getting permissions for objects?
+ *
+ * @returns array containing the resulting items or false on error.
+ */
+ public function itemsForCategory($category, $tableinfo, $limit = null, $offset = null) {
+ $result = null;
+ if(is_numeric($category)) {
+ $catid = $category;
+ } elseif(is_string($category)) {
+ $catid = $this->array_searchi($category, $this->categories);
+ }
+ OCP\Util::writeLog('core', __METHOD__.', category: '.$catid.' '.$category, OCP\Util::DEBUG);
+ if($catid === false) {
+ $l10n = OC_L10N::get('core');
+ throw new Exception(
+ $l10n->t('Could not find category "%s"', $category)
+ );
+ }
+ $fields = '';
+ foreach($tableinfo['fields'] as $field) {
+ $fields .= '`' . $tableinfo['tablename'] . '`.`' . $field . '`,';
+ }
+ $fields = substr($fields, 0, -1);
+
+ $items = array();
+ $sql = 'SELECT `' . self::RELATION_TABLE . '`.`categoryid`, ' . $fields
+ . ' FROM `' . $tableinfo['tablename'] . '` JOIN `'
+ . self::RELATION_TABLE . '` ON `' . $tableinfo['tablename']
+ . '`.`id` = `' . self::RELATION_TABLE . '`.`objid` WHERE `'
+ . self::RELATION_TABLE . '`.`categoryid` = ?';
+
+ try {
+ $stmt = OCP\DB::prepare($sql, $limit, $offset);
+ $result = $stmt->execute(array($catid));
+ if (OC_DB::isError($result)) {
+ OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR);
+ return false;
+ }
+ } catch(Exception $e) {
+ OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
+ OCP\Util::ERROR);
+ return false;
+ }
+
+ if(!is_null($result)) {
+ while( $row = $result->fetchRow()) {
+ $items[] = $row;
+ }
+ }
+ //OCP\Util::writeLog('core', __METHOD__.', count: ' . count($items), OCP\Util::DEBUG);
+ //OCP\Util::writeLog('core', __METHOD__.', sql: ' . $sql, OCP\Util::DEBUG);
+
+ return $items;
}
/**
@@ -84,22 +296,51 @@ class OC_VCategories {
}
/**
- * @brief Add a new category name.
+ * @brief Add a new category.
+ * @param $name A string with a name of the category
+ * @returns int the id of the added category or false if it already exists.
+ */
+ public function add($name) {
+ OCP\Util::writeLog('core', __METHOD__.', name: ' . $name, OCP\Util::DEBUG);
+ if($this->hasCategory($name)) {
+ OCP\Util::writeLog('core', __METHOD__.', name: ' . $name. ' exists already', OCP\Util::DEBUG);
+ return false;
+ }
+ OCP\DB::insertIfNotExist(self::CATEGORY_TABLE,
+ array(
+ 'uid' => $this->user,
+ 'type' => $this->type,
+ 'category' => $name,
+ ));
+ $id = OCP\DB::insertid(self::CATEGORY_TABLE);
+ OCP\Util::writeLog('core', __METHOD__.', id: ' . $id, OCP\Util::DEBUG);
+ $this->categories[$id] = $name;
+ return $id;
+ }
+
+ /**
+ * @brief Add a new category.
* @param $names A string with a name or an array of strings containing
* the name(s) of the categor(y|ies) to add.
* @param $sync bool When true, save the categories
+ * @param $id int Optional object id to add to this|these categor(y|ies)
* @returns bool Returns false on error.
*/
- public function add($names, $sync=false) {
+ public function addMulti($names, $sync=false, $id = null) {
if(!is_array($names)) {
$names = array($names);
}
$names = array_map('trim', $names);
$newones = array();
foreach($names as $name) {
- if(($this->in_arrayi($name, $this->categories) == false) && $name != '') {
+ if(($this->in_arrayi(
+ $name, $this->categories) == false) && $name != '') {
$newones[] = $name;
}
+ if(!is_null($id) ) {
+ // Insert $objectid, $categoryid pairs if not exist.
+ self::$relations[] = array('objid' => $id, 'category' => $name);
+ }
}
if(count($newones) > 0) {
$this->categories = array_merge($this->categories, $newones);
@@ -114,8 +355,8 @@ class OC_VCategories {
* @brief Extracts categories from a vobject and add the ones not already present.
* @param $vobject The instance of OC_VObject to load the categories from.
*/
- public function loadFromVObject($vobject, $sync=false) {
- $this->add($vobject->getAsArray('CATEGORIES'), $sync);
+ public function loadFromVObject($id, $vobject, $sync=false) {
+ $this->addMulti($vobject->getAsArray('CATEGORIES'), $sync, $id);
}
/**
@@ -128,23 +369,62 @@ class OC_VCategories {
* $result = $stmt->execute();
* $objects = array();
* if(!is_null($result)) {
- * while( $row = $result->fetchRow()) {
- * $objects[] = $row['carddata'];
+ * while( $row = $result->fetchRow()){
+ * $objects[] = array($row['id'], $row['carddata']);
* }
* }
* $categories->rescan($objects);
*/
public function rescan($objects, $sync=true, $reset=true) {
+
if($reset === true) {
+ $result = null;
+ // Find all objectid/categoryid pairs.
+ try {
+ $stmt = OCP\DB::prepare('SELECT `id` FROM `' . self::CATEGORY_TABLE . '` '
+ . 'WHERE `uid` = ? AND `type` = ?');
+ $result = $stmt->execute(array($this->user, $this->type));
+ if (OC_DB::isError($result)) {
+ OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR);
+ return false;
+ }
+ } catch(Exception $e) {
+ OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
+ OCP\Util::ERROR);
+ }
+
+ // And delete them.
+ if(!is_null($result)) {
+ $stmt = OCP\DB::prepare('DELETE FROM `' . self::RELATION_TABLE . '` '
+ . 'WHERE `categoryid` = ? AND `type`= ?');
+ while( $row = $result->fetchRow()) {
+ $stmt->execute(array($row['id'], $this->type));
+ }
+ }
+ try {
+ $stmt = OCP\DB::prepare('DELETE FROM `' . self::CATEGORY_TABLE . '` '
+ . 'WHERE `uid` = ? AND `type` = ?');
+ $result = $stmt->execute(array($this->user, $this->type));
+ if (OC_DB::isError($result)) {
+ OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR);
+ return;
+ }
+ } catch(Exception $e) {
+ OCP\Util::writeLog('core', __METHOD__ . ', exception: '
+ . $e->getMessage(), OCP\Util::ERROR);
+ return;
+ }
$this->categories = array();
}
+ // Parse all the VObjects
foreach($objects as $object) {
- //OC_Log::write('core', 'OC_VCategories::rescan: '.substr($object, 0, 100).'(...)', OC_Log::DEBUG);
- $vobject = OC_VObject::parse($object);
+ $vobject = OC_VObject::parse($object[1]);
if(!is_null($vobject)) {
- $this->loadFromVObject($vobject, $sync);
+ // Load the categories
+ $this->loadFromVObject($object[0], $vobject, $sync);
} else {
- OC_Log::write('core', 'OC_VCategories::rescan, unable to parse. ID: '.', '.substr($object, 0, 100).'(...)', OC_Log::DEBUG);
+ OC_Log::write('core', __METHOD__ . ', unable to parse. ID: ' . ', '
+ . substr($object, 0, 100) . '(...)', OC_Log::DEBUG);
}
}
$this->save();
@@ -155,16 +435,224 @@ class OC_VCategories {
*/
private function save() {
if(is_array($this->categories)) {
- usort($this->categories, 'strnatcasecmp'); // usort to also renumber the keys
- $escaped_categories = serialize($this->categories);
- OC_Preferences::setValue($this->user, $this->app, self::PREF_CATEGORIES_LABEL, $escaped_categories);
- OC_Log::write('core', 'OC_VCategories::save: '.print_r($this->categories, true), OC_Log::DEBUG);
+ foreach($this->categories as $category) {
+ OCP\DB::insertIfNotExist(self::CATEGORY_TABLE,
+ array(
+ 'uid' => $this->user,
+ 'type' => $this->type,
+ 'category' => $category,
+ ));
+ }
+ // reload categories to get the proper ids.
+ $this->loadCategories();
+ // Loop through temporarily cached objectid/categoryname pairs
+ // and save relations.
+ $categories = $this->categories;
+ // For some reason this is needed or array_search(i) will return 0..?
+ ksort($categories);
+ foreach(self::$relations as $relation) {
+ $catid = $this->array_searchi($relation['category'], $categories);
+ OC_Log::write('core', __METHOD__ . 'catid, ' . $relation['category'] . ' ' . $catid, OC_Log::DEBUG);
+ if($catid) {
+ OCP\DB::insertIfNotExist(self::RELATION_TABLE,
+ array(
+ 'objid' => $relation['objid'],
+ 'categoryid' => $catid,
+ 'type' => $this->type,
+ ));
+ }
+ }
+ self::$relations = array(); // reset
} else {
- OC_Log::write('core', 'OC_VCategories::save: $this->categories is not an array! '.print_r($this->categories, true), OC_Log::ERROR);
+ OC_Log::write('core', __METHOD__.', $this->categories is not an array! '
+ . print_r($this->categories, true), OC_Log::ERROR);
}
}
/**
+ * @brief Delete categories and category/object relations for a user.
+ * For hooking up on post_deleteUser
+ * @param string $uid The user id for which entries should be purged.
+ */
+ public static function post_deleteUser($arguments) {
+ // Find all objectid/categoryid pairs.
+ $result = null;
+ try {
+ $stmt = OCP\DB::prepare('SELECT `id` FROM `' . self::CATEGORY_TABLE . '` '
+ . 'WHERE `uid` = ?');
+ $result = $stmt->execute(array($arguments['uid']));
+ if (OC_DB::isError($result)) {
+ OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR);
+ }
+ } catch(Exception $e) {
+ OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
+ OCP\Util::ERROR);
+ }
+
+ if(!is_null($result)) {
+ try {
+ $stmt = OCP\DB::prepare('DELETE FROM `' . self::RELATION_TABLE . '` '
+ . 'WHERE `categoryid` = ?');
+ while( $row = $result->fetchRow()) {
+ try {
+ $stmt->execute(array($row['id']));
+ } catch(Exception $e) {
+ OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
+ OCP\Util::ERROR);
+ }
+ }
+ } catch(Exception $e) {
+ OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
+ OCP\Util::ERROR);
+ }
+ }
+ try {
+ $stmt = OCP\DB::prepare('DELETE FROM `' . self::CATEGORY_TABLE . '` '
+ . 'WHERE `uid` = ? AND');
+ $result = $stmt->execute(array($arguments['uid']));
+ if (OC_DB::isError($result)) {
+ OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR);
+ }
+ } catch(Exception $e) {
+ OCP\Util::writeLog('core', __METHOD__ . ', exception: '
+ . $e->getMessage(), OCP\Util::ERROR);
+ }
+ }
+
+ /**
+ * @brief Delete category/object relations from the db
+ * @param int $id The id of the object
+ * @param string $type The type of object (event/contact/task/journal).
+ * Defaults to the type set in the instance
+ * @returns boolean Returns false on error.
+ */
+ public function purgeObject($id, $type = null) {
+ $type = is_null($type) ? $this->type : $type;
+ try {
+ $stmt = OCP\DB::prepare('DELETE FROM `' . self::RELATION_TABLE . '` '
+ . 'WHERE `objid` = ? AND `type`= ?');
+ $result = $stmt->execute(array($id, $type));
+ if (OC_DB::isError($result)) {
+ OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR);
+ return false;
+ }
+ } catch(Exception $e) {
+ OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
+ OCP\Util::ERROR);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Get favorites for an object type
+ *
+ * @param string $type The type of object (event/contact/task/journal).
+ * Defaults to the type set in the instance
+ * @returns array An array of object ids.
+ */
+ public function getFavorites($type = null) {
+ $type = is_null($type) ? $this->type : $type;
+
+ try {
+ return $this->idsForCategory(self::CATEGORY_FAVORITE);
+ } catch(Exception $e) {
+ // No favorites
+ return array();
+ }
+ }
+
+ /**
+ * Add an object to favorites
+ *
+ * @param int $objid The id of the object
+ * @param string $type The type of object (event/contact/task/journal).
+ * Defaults to the type set in the instance
+ * @returns boolean
+ */
+ public function addToFavorites($objid, $type = null) {
+ $type = is_null($type) ? $this->type : $type;
+ if(!$this->hasCategory(self::CATEGORY_FAVORITE)) {
+ $this->add(self::CATEGORY_FAVORITE, true);
+ }
+ return $this->addToCategory($objid, self::CATEGORY_FAVORITE, $type);
+ }
+
+ /**
+ * Remove an object from favorites
+ *
+ * @param int $objid The id of the object
+ * @param string $type The type of object (event/contact/task/journal).
+ * Defaults to the type set in the instance
+ * @returns boolean
+ */
+ public function removeFromFavorites($objid, $type = null) {
+ $type = is_null($type) ? $this->type : $type;
+ return $this->removeFromCategory($objid, self::CATEGORY_FAVORITE, $type);
+ }
+
+ /**
+ * @brief Creates a category/object relation.
+ * @param int $objid The id of the object
+ * @param int|string $category The id or name of the category
+ * @param string $type The type of object (event/contact/task/journal).
+ * Defaults to the type set in the instance
+ * @returns boolean Returns false on database error.
+ */
+ public function addToCategory($objid, $category, $type = null) {
+ $type = is_null($type) ? $this->type : $type;
+ if(is_string($category) && !is_numeric($category)) {
+ if(!$this->hasCategory($category)) {
+ $this->add($category, true);
+ }
+ $categoryid = $this->array_searchi($category, $this->categories);
+ } else {
+ $categoryid = $category;
+ }
+ try {
+ OCP\DB::insertIfNotExist(self::RELATION_TABLE,
+ array(
+ 'objid' => $objid,
+ 'categoryid' => $categoryid,
+ 'type' => $type,
+ ));
+ } catch(Exception $e) {
+ OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
+ OCP\Util::ERROR);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @brief Delete single category/object relation from the db
+ * @param int $objid The id of the object
+ * @param int|string $category The id or name of the category
+ * @param string $type The type of object (event/contact/task/journal).
+ * Defaults to the type set in the instance
+ * @returns boolean
+ */
+ public function removeFromCategory($objid, $category, $type = null) {
+ $type = is_null($type) ? $this->type : $type;
+ $categoryid = (is_string($category) && !is_numeric($category))
+ ? $this->array_searchi($category, $this->categories)
+ : $category;
+ try {
+ $sql = 'DELETE FROM `' . self::RELATION_TABLE . '` '
+ . 'WHERE `objid` = ? AND `categoryid` = ? AND `type` = ?';
+ OCP\Util::writeLog('core', __METHOD__.', sql: ' . $objid . ' ' . $categoryid . ' ' . $type,
+ OCP\Util::DEBUG);
+ $stmt = OCP\DB::prepare($sql);
+ $stmt->execute(array($objid, $categoryid, $type));
+ } catch(Exception $e) {
+ OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
+ OCP\Util::ERROR);
+ return false;
+ }
+ return true;
+ }
+
+ /**
* @brief Delete categories from the db and from all the vobject supplied
* @param $names An array of categories to delete
* @param $objects An array of arrays with [id,vobject] (as text) pairs suitable for updating the apps object table.
@@ -173,37 +661,87 @@ class OC_VCategories {
if(!is_array($names)) {
$names = array($names);
}
- OC_Log::write('core', 'OC_VCategories::delete, before: '.print_r($this->categories, true), OC_Log::DEBUG);
+
+ OC_Log::write('core', __METHOD__ . ', before: '
+ . print_r($this->categories, true), OC_Log::DEBUG);
foreach($names as $name) {
- OC_Log::write('core', 'OC_VCategories::delete: '.$name, OC_Log::DEBUG);
+ $id = null;
+ OC_Log::write('core', __METHOD__.', '.$name, OC_Log::DEBUG);
if($this->hasCategory($name)) {
- //OC_Log::write('core', 'OC_VCategories::delete: '.$name.' got it', OC_Log::DEBUG);
- unset($this->categories[$this->array_searchi($name, $this->categories)]);
+ $id = $this->array_searchi($name, $this->categories);
+ unset($this->categories[$id]);
+ }
+ try {
+ $stmt = OCP\DB::prepare('DELETE FROM `' . self::CATEGORY_TABLE . '` WHERE '
+ . '`uid` = ? AND `type` = ? AND `category` = ?');
+ $result = $stmt->execute(array($this->user, $this->type, $name));
+ if (OC_DB::isError($result)) {
+ OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR);
+ }
+ } catch(Exception $e) {
+ OCP\Util::writeLog('core', __METHOD__ . ', exception: '
+ . $e->getMessage(), OCP\Util::ERROR);
+ }
+ if(!is_null($id) && $id !== false) {
+ try {
+ $sql = 'DELETE FROM `' . self::RELATION_TABLE . '` '
+ . 'WHERE `categoryid` = ?';
+ $stmt = OCP\DB::prepare($sql);
+ $result = $stmt->execute(array($id));
+ if (OC_DB::isError($result)) {
+ OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR);
+ }
+ } catch(Exception $e) {
+ OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
+ OCP\Util::ERROR);
+ return false;
+ }
}
}
- $this->save();
- OC_Log::write('core', 'OC_VCategories::delete, after: '.print_r($this->categories, true), OC_Log::DEBUG);
+ OC_Log::write('core', __METHOD__.', after: '
+ . print_r($this->categories, true), OC_Log::DEBUG);
if(!is_null($objects)) {
foreach($objects as $key=>&$value) {
$vobject = OC_VObject::parse($value[1]);
if(!is_null($vobject)) {
- $categories = $vobject->getAsArray('CATEGORIES');
- //OC_Log::write('core', 'OC_VCategories::delete, before: '.$key.': '.print_r($categories, true), OC_Log::DEBUG);
+ $object = null;
+ $componentname = '';
+ if (isset($vobject->VEVENT)) {
+ $object = $vobject->VEVENT;
+ $componentname = 'VEVENT';
+ } else
+ if (isset($vobject->VTODO)) {
+ $object = $vobject->VTODO;
+ $componentname = 'VTODO';
+ } else
+ if (isset($vobject->VJOURNAL)) {
+ $object = $vobject->VJOURNAL;
+ $componentname = 'VJOURNAL';
+ } else {
+ $object = $vobject;
+ }
+ $categories = $object->getAsArray('CATEGORIES');
foreach($names as $name) {
$idx = $this->array_searchi($name, $categories);
- //OC_Log::write('core', 'OC_VCategories::delete, loop: '.$name.', '.print_r($idx, true), OC_Log::DEBUG);
if($idx !== false) {
- OC_Log::write('core', 'OC_VCategories::delete, unsetting: '.$categories[$this->array_searchi($name, $categories)], OC_Log::DEBUG);
+ OC_Log::write('core', __METHOD__
+ .', unsetting: '
+ . $categories[$this->array_searchi($name, $categories)],
+ OC_Log::DEBUG);
unset($categories[$this->array_searchi($name, $categories)]);
- //unset($categories[$idx]);
}
}
- //OC_Log::write('core', 'OC_VCategories::delete, after: '.$key.': '.print_r($categories, true), OC_Log::DEBUG);
- $vobject->setString('CATEGORIES', implode(',', $categories));
+
+ $object->setString('CATEGORIES', implode(',', $categories));
+ if($vobject !== $object) {
+ $vobject[$componentname] = $object;
+ }
$value[1] = $vobject->serialize();
$objects[$key] = $value;
} else {
- OC_Log::write('core', 'OC_VCategories::delete, unable to parse. ID: '.$value[0].', '.substr($value[1], 0, 50).'(...)', OC_Log::DEBUG);
+ OC_Log::write('core', __METHOD__
+ .', unable to parse. ID: ' . $value[0] . ', '
+ . substr($value[1], 0, 50) . '(...)', OC_Log::DEBUG);
}
}
}
@@ -224,5 +762,5 @@ class OC_VCategories {
}
return array_search(strtolower($needle), array_map('strtolower', $haystack));
}
-
}
+