summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/base.php33
-rw-r--r--lib/l10n/ar.php4
-rw-r--r--lib/l10n/ast.php26
-rw-r--r--lib/l10n/az.php10
-rw-r--r--lib/l10n/ca.php5
-rw-r--r--lib/l10n/cs_CZ.php5
-rw-r--r--lib/l10n/da.php4
-rw-r--r--lib/l10n/de.php6
-rw-r--r--lib/l10n/de_CH.php4
-rw-r--r--lib/l10n/de_DE.php6
-rw-r--r--lib/l10n/el.php6
-rw-r--r--lib/l10n/en_GB.php6
-rw-r--r--lib/l10n/es.php6
-rw-r--r--lib/l10n/es_AR.php4
-rw-r--r--lib/l10n/es_MX.php4
-rw-r--r--lib/l10n/et_EE.php11
-rw-r--r--lib/l10n/eu.php5
-rw-r--r--lib/l10n/fa.php4
-rw-r--r--lib/l10n/fi_FI.php6
-rw-r--r--lib/l10n/fr.php6
-rw-r--r--lib/l10n/gl.php6
-rw-r--r--lib/l10n/he.php4
-rw-r--r--lib/l10n/hu_HU.php5
-rw-r--r--lib/l10n/id.php4
-rw-r--r--lib/l10n/it.php6
-rw-r--r--lib/l10n/ja.php5
-rw-r--r--lib/l10n/jv.php8
-rw-r--r--lib/l10n/ka_GE.php4
-rw-r--r--lib/l10n/km.php4
-rw-r--r--lib/l10n/ko.php4
-rw-r--r--lib/l10n/lt_LT.php4
-rw-r--r--lib/l10n/lv.php5
-rw-r--r--lib/l10n/mk.php4
-rw-r--r--lib/l10n/nb_NO.php4
-rw-r--r--lib/l10n/nl.php6
-rw-r--r--lib/l10n/nn_NO.php4
-rw-r--r--lib/l10n/pl.php6
-rw-r--r--lib/l10n/pl_PL.php5
-rw-r--r--lib/l10n/pt_BR.php6
-rw-r--r--lib/l10n/pt_PT.php4
-rw-r--r--lib/l10n/ro.php4
-rw-r--r--lib/l10n/ru.php4
-rw-r--r--lib/l10n/sk_SK.php5
-rw-r--r--lib/l10n/sl.php4
-rw-r--r--lib/l10n/sq.php4
-rw-r--r--lib/l10n/sr.php4
-rw-r--r--lib/l10n/sv.php12
-rw-r--r--lib/l10n/tr.php24
-rw-r--r--lib/l10n/ug.php4
-rw-r--r--lib/l10n/uk.php4
-rw-r--r--lib/l10n/zh_CN.php4
-rw-r--r--lib/l10n/zh_TW.php4
-rw-r--r--lib/private/appconfig.php6
-rw-r--r--lib/private/appframework/dependencyinjection/dicontainer.php10
-rw-r--r--lib/private/appframework/http/request.php87
-rw-r--r--lib/private/appframework/routing/routeconfig.php10
-rw-r--r--lib/private/cache.php2
-rw-r--r--lib/private/cache/file.php20
-rw-r--r--lib/private/config.php2
-rw-r--r--lib/private/connector/sabre/node.php9
-rw-r--r--lib/private/connector/sabre/quotaplugin.php11
-rw-r--r--lib/private/contactsmanager.php4
-rw-r--r--lib/private/davclient.php13
-rw-r--r--lib/private/db.php5
-rw-r--r--lib/private/db/statementwrapper.php14
-rw-r--r--lib/private/defaults.php4
-rw-r--r--lib/private/filechunking.php40
-rw-r--r--lib/private/files.php3
-rw-r--r--lib/private/files/cache/cache.php18
-rw-r--r--lib/private/files/filesystem.php25
-rw-r--r--lib/private/files/storage/common.php21
-rw-r--r--lib/private/files/storage/local.php2
-rw-r--r--lib/private/files/storage/mappedlocal.php2
-rw-r--r--lib/private/files/view.php22
-rw-r--r--lib/private/forbiddenexception.php16
-rw-r--r--lib/private/group/backend.php2
-rw-r--r--lib/private/group/database.php14
-rw-r--r--lib/private/group/dummy.php10
-rw-r--r--lib/private/group/group.php21
-rw-r--r--lib/private/helper.php12
-rw-r--r--lib/private/image.php2
-rw-r--r--lib/private/l10n.php5
-rw-r--r--lib/private/legacy/appconfig.php2
-rw-r--r--lib/private/legacy/config.php6
-rw-r--r--lib/private/mail.php3
-rw-r--r--lib/private/ocs/cloud.php27
-rw-r--r--lib/private/ocs/result.php2
-rwxr-xr-xlib/private/preview.php236
-rwxr-xr-xlib/private/request.php5
-rw-r--r--lib/private/route/router.php14
-rw-r--r--lib/private/server.php11
-rw-r--r--lib/private/share/constants.php44
-rw-r--r--lib/private/share/helper.php202
-rw-r--r--lib/private/share/hooks.php108
-rw-r--r--lib/private/share/mailnotifications.php1
-rw-r--r--lib/private/share/share.php1629
-rw-r--r--lib/private/template/base.php2
-rw-r--r--lib/private/template/functions.php9
-rw-r--r--lib/private/urlgenerator.php10
-rw-r--r--lib/private/user.php2
-rw-r--r--lib/private/user/manager.php11
-rwxr-xr-xlib/private/util.php66
-rw-r--r--lib/public/appframework/controller.php14
-rw-r--r--lib/public/appframework/http/jsonresponse.php3
-rw-r--r--lib/public/appframework/http/response.php13
-rw-r--r--lib/public/appframework/http/templateresponse.php6
-rw-r--r--lib/public/appframework/iappcontainer.php4
-rw-r--r--lib/public/config.php6
-rw-r--r--lib/public/contacts/imanager.php4
-rw-r--r--lib/public/iappconfig.php5
-rw-r--r--lib/public/il10n.php12
-rw-r--r--lib/public/iservercontainer.php2
-rw-r--r--lib/public/share.php1746
113 files changed, 2859 insertions, 2094 deletions
diff --git a/lib/base.php b/lib/base.php
index 2515b9657cb..6ea77aa7a58 100644
--- a/lib/base.php
+++ b/lib/base.php
@@ -305,6 +305,7 @@ class OC {
OC_Util::addScript("jquery.placeholder");
OC_Util::addScript("jquery-tipsy");
OC_Util::addScript("compatibility");
+ OC_Util::addScript("underscore");
OC_Util::addScript("jquery.ocdialog");
OC_Util::addScript("oc-dialogs");
OC_Util::addScript("js");
@@ -549,16 +550,10 @@ class OC {
OC_User::logout();
}
- // Load Apps
- // This includes plugins for users and filesystems as well
- global $RUNTIME_NOAPPS;
- global $RUNTIME_APPTYPES;
- if (!$RUNTIME_NOAPPS && !self::checkUpgrade(false)) {
- if ($RUNTIME_APPTYPES) {
- OC_App::loadApps($RUNTIME_APPTYPES);
- } else {
- OC_App::loadApps();
- }
+ // Load minimum set of apps - which is filesystem, authentication and logging
+ if (!self::checkUpgrade(false)) {
+ OC_App::loadApps(array('authentication'));
+ OC_App::loadApps(array('filesystem', 'logging'));
}
//setup extra user backends
@@ -659,10 +654,10 @@ class OC {
*/
public static function registerShareHooks() {
if (\OC_Config::getValue('installed')) {
- OC_Hook::connect('OC_User', 'post_deleteUser', 'OCP\Share', 'post_deleteUser');
- OC_Hook::connect('OC_User', 'post_addToGroup', 'OCP\Share', 'post_addToGroup');
- OC_Hook::connect('OC_User', 'post_removeFromGroup', 'OCP\Share', 'post_removeFromGroup');
- OC_Hook::connect('OC_User', 'post_deleteGroup', 'OCP\Share', 'post_deleteGroup');
+ OC_Hook::connect('OC_User', 'post_deleteUser', 'OC\Share\Hooks', 'post_deleteUser');
+ OC_Hook::connect('OC_User', 'post_addToGroup', 'OC\Share\Hooks', 'post_addToGroup');
+ OC_Hook::connect('OC_User', 'post_removeFromGroup', 'OC\Share\Hooks', 'post_removeFromGroup');
+ OC_Hook::connect('OC_User', 'post_deleteGroup', 'OC\Share\Hooks', 'post_deleteGroup');
}
}
@@ -851,7 +846,7 @@ class OC {
) {
return false;
}
- OC_App::loadApps(array('authentication'));
+
if (defined("DEBUG") && DEBUG) {
OC_Log::write('core', 'Trying to login from cookie', OC_Log::DEBUG);
}
@@ -923,7 +918,7 @@ class OC {
) {
return false;
}
- OC_App::loadApps(array('authentication'));
+
if (OC_User::login($_SERVER["PHP_AUTH_USER"], $_SERVER["PHP_AUTH_PW"])) {
//OC_Log::write('core',"Logged in with HTTP Authentication", OC_Log::DEBUG);
OC_User::unsetMagicInCookie();
@@ -934,11 +929,6 @@ class OC {
}
-// define runtime variables - unless this already has been done
-if (!isset($RUNTIME_NOAPPS)) {
- $RUNTIME_NOAPPS = false;
-}
-
if (!function_exists('get_temp_dir')) {
function get_temp_dir() {
if ($temp = ini_get('upload_tmp_dir')) return $temp;
@@ -957,4 +947,3 @@ if (!function_exists('get_temp_dir')) {
}
OC::init();
-
diff --git a/lib/l10n/ar.php b/lib/l10n/ar.php
index 6287a53d619..c8b51a3bb7e 100644
--- a/lib/l10n/ar.php
+++ b/lib/l10n/ar.php
@@ -56,6 +56,8 @@ $TRANSLATIONS = array(
"last month" => "الشهر الماضي",
"_%n month ago_::_%n months ago_" => array("","","","","",""),
"last year" => "السنةالماضية",
-"years ago" => "سنة مضت"
+"years ago" => "سنة مضت",
+"A valid username must be provided" => "يجب ادخال اسم مستخدم صحيح",
+"A valid password must be provided" => "يجب ادخال كلمة مرور صحيحة"
);
$PLURAL_FORMS = "nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;";
diff --git a/lib/l10n/ast.php b/lib/l10n/ast.php
new file mode 100644
index 00000000000..93a20beb5d4
--- /dev/null
+++ b/lib/l10n/ast.php
@@ -0,0 +1,26 @@
+<?php
+$TRANSLATIONS = array(
+"Personal" => "Personal",
+"Settings" => "Axustes",
+"Users" => "Usuarios",
+"Failed to upgrade \"%s\"." => "Fallu al anovar \"%s\".",
+"Invalid image" => "Imaxe inválida",
+"Application is not enabled" => "L'aplicación nun ta habilitada",
+"Files" => "Ficheros",
+"Text" => "Testu",
+"Images" => "Imaxes",
+"Set an admin username." => "Afitar nome d'usuariu p'almin",
+"Set an admin password." => "Afitar contraseña p'almin",
+"Could not find category \"%s\"" => "Nun pudo alcontrase la estaya \"%s.\"",
+"seconds ago" => "fai segundos",
+"_%n minute ago_::_%n minutes ago_" => array("","fai %n minutos"),
+"_%n hour ago_::_%n hours ago_" => array("","fai %n hores"),
+"today" => "güei",
+"yesterday" => "ayeri",
+"_%n day go_::_%n days ago_" => array("","fai %n díes"),
+"last month" => "mes caberu",
+"_%n month ago_::_%n months ago_" => array("","fai %n meses"),
+"last year" => "añu caberu",
+"years ago" => "fai años"
+);
+$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/az.php b/lib/l10n/az.php
index e7b09649a24..15f78e0bce6 100644
--- a/lib/l10n/az.php
+++ b/lib/l10n/az.php
@@ -1,8 +1,8 @@
<?php
$TRANSLATIONS = array(
-"_%n minute ago_::_%n minutes ago_" => array(""),
-"_%n hour ago_::_%n hours ago_" => array(""),
-"_%n day go_::_%n days ago_" => array(""),
-"_%n month ago_::_%n months ago_" => array("")
+"_%n minute ago_::_%n minutes ago_" => array("",""),
+"_%n hour ago_::_%n hours ago_" => array("",""),
+"_%n day go_::_%n days ago_" => array("",""),
+"_%n month ago_::_%n months ago_" => array("","")
);
-$PLURAL_FORMS = "nplurals=1; plural=0;";
+$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/ca.php b/lib/l10n/ca.php
index 88bb8ec9eee..477cdf2925b 100644
--- a/lib/l10n/ca.php
+++ b/lib/l10n/ca.php
@@ -66,6 +66,9 @@ $TRANSLATIONS = array(
"last month" => "el mes passat",
"_%n month ago_::_%n months ago_" => array("fa %n mes","fa %n mesos"),
"last year" => "l'any passat",
-"years ago" => "anys enrere"
+"years ago" => "anys enrere",
+"A valid username must be provided" => "Heu de facilitar un nom d'usuari vàlid",
+"A valid password must be provided" => "Heu de facilitar una contrasenya vàlida",
+"The username is already being used" => "El nom d'usuari ja està en ús"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/cs_CZ.php b/lib/l10n/cs_CZ.php
index 6b5c8441ca1..d535b97f631 100644
--- a/lib/l10n/cs_CZ.php
+++ b/lib/l10n/cs_CZ.php
@@ -66,6 +66,9 @@ $TRANSLATIONS = array(
"last month" => "minulý měsíc",
"_%n month ago_::_%n months ago_" => array("před %n měsícem","před %n měsíci","před %n měsíci"),
"last year" => "minulý rok",
-"years ago" => "před lety"
+"years ago" => "před lety",
+"A valid username must be provided" => "Musíte zadat platné uživatelské jméno",
+"A valid password must be provided" => "Musíte zadat platné heslo",
+"The username is already being used" => "Uživatelské jméno je již využíváno"
);
$PLURAL_FORMS = "nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;";
diff --git a/lib/l10n/da.php b/lib/l10n/da.php
index c3166000727..3be45001030 100644
--- a/lib/l10n/da.php
+++ b/lib/l10n/da.php
@@ -66,6 +66,8 @@ $TRANSLATIONS = array(
"last month" => "sidste måned",
"_%n month ago_::_%n months ago_" => array("%n måned siden","%n måneder siden"),
"last year" => "sidste år",
-"years ago" => "år siden"
+"years ago" => "år siden",
+"A valid username must be provided" => "Et gyldigt brugernavn skal angives",
+"A valid password must be provided" => "En gyldig adgangskode skal angives"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/de.php b/lib/l10n/de.php
index d644582b91e..297cc57bde7 100644
--- a/lib/l10n/de.php
+++ b/lib/l10n/de.php
@@ -66,6 +66,10 @@ $TRANSLATIONS = array(
"last month" => "Letzten Monat",
"_%n month ago_::_%n months ago_" => array("Vor %n Monat","Vor %n Monaten"),
"last year" => "Letztes Jahr",
-"years ago" => "Vor Jahren"
+"years ago" => "Vor Jahren",
+"Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-\"" => "Folgende Zeichen sind im Benutzernamen erlaubt: \"a-z\", \"A-Z\", \"0-9\" und \"_.@-\"",
+"A valid username must be provided" => "Es muss ein gültiger Benutzername angegeben werden",
+"A valid password must be provided" => "Es muss ein gültiges Passwort angegeben werden",
+"The username is already being used" => "Dieser Benutzername existiert bereits"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/de_CH.php b/lib/l10n/de_CH.php
index fe1a519ccf7..e034cc3c209 100644
--- a/lib/l10n/de_CH.php
+++ b/lib/l10n/de_CH.php
@@ -47,6 +47,8 @@ $TRANSLATIONS = array(
"last month" => "Letzten Monat",
"_%n month ago_::_%n months ago_" => array("","Vor %n Monaten"),
"last year" => "Letztes Jahr",
-"years ago" => "Vor Jahren"
+"years ago" => "Vor Jahren",
+"A valid username must be provided" => "Es muss ein gültiger Benutzername angegeben werden",
+"A valid password must be provided" => "Es muss ein gültiges Passwort angegeben werden"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/de_DE.php b/lib/l10n/de_DE.php
index 85ed7e5c80a..d0a4a9b1c6e 100644
--- a/lib/l10n/de_DE.php
+++ b/lib/l10n/de_DE.php
@@ -66,6 +66,10 @@ $TRANSLATIONS = array(
"last month" => "Letzten Monat",
"_%n month ago_::_%n months ago_" => array("Vor %n Monat","Vor %n Monaten"),
"last year" => "Letztes Jahr",
-"years ago" => "Vor Jahren"
+"years ago" => "Vor Jahren",
+"Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-\"" => "Folgende Zeichen sind im Benutzernamen erlaubt: \"a-z\", \"A-Z\", \"0-9\" und \"_.@-\"",
+"A valid username must be provided" => "Es muss ein gültiger Benutzername angegeben werden",
+"A valid password must be provided" => "Es muss ein gültiges Passwort angegeben werden",
+"The username is already being used" => "Der Benutzername existiert bereits"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/el.php b/lib/l10n/el.php
index 148b7fc1fe5..244cc50b847 100644
--- a/lib/l10n/el.php
+++ b/lib/l10n/el.php
@@ -44,7 +44,9 @@ $TRANSLATIONS = array(
"DB Error: \"%s\"" => "Σφάλμα Βάσης Δεδομένων: \"%s\"",
"Offending command was: \"%s\"" => "Η εντολη παραβατικοτητας ηταν: \"%s\"",
"MySQL/MariaDB user '%s'@'localhost' exists already." => "Υπάρχει ήδη ο χρήστης '%s'@'localhost' της MySQL/MariaDB",
+"Drop this user from MySQL/MariaDB" => "Κατάργηση του χρήστη από MySQL/MariaDB",
"MySQL/MariaDB user '%s'@'%%' already exists" => "Υπάρχει ήδη ο χρήστης '%s'@'%%' της MySQL/MariaDB",
+"Drop this user from MySQL/MariaDB." => "Κατάργηση του χρήστη από MySQL/MariaDB.",
"Oracle connection could not be established" => "Αδυναμία σύνδεσης Oracle",
"Oracle username and/or password not valid" => "Μη έγκυρος χρήστης και/ή συνθηματικό της Oracle",
"Offending command was: \"%s\", name: %s, password: %s" => "Η εντολη παραβατικοτητας ηταν: \"%s\", ονομα: %s, κωδικος: %s",
@@ -64,6 +66,8 @@ $TRANSLATIONS = array(
"last month" => "τελευταίο μήνα",
"_%n month ago_::_%n months ago_" => array("","%n μήνες πριν"),
"last year" => "τελευταίο χρόνο",
-"years ago" => "χρόνια πριν"
+"years ago" => "χρόνια πριν",
+"A valid username must be provided" => "Πρέπει να δοθεί έγκυρο όνομα χρήστη",
+"A valid password must be provided" => "Πρέπει να δοθεί έγκυρο συνθηματικό"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/en_GB.php b/lib/l10n/en_GB.php
index 7d2246eb66b..e1c49392bd8 100644
--- a/lib/l10n/en_GB.php
+++ b/lib/l10n/en_GB.php
@@ -66,6 +66,10 @@ $TRANSLATIONS = array(
"last month" => "last month",
"_%n month ago_::_%n months ago_" => array("%n month ago","%n months ago"),
"last year" => "last year",
-"years ago" => "years ago"
+"years ago" => "years ago",
+"Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-\"" => "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-\"",
+"A valid username must be provided" => "A valid username must be provided",
+"A valid password must be provided" => "A valid password must be provided",
+"The username is already being used" => "The username is already being used"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/es.php b/lib/l10n/es.php
index 14d6435c891..c01239cca7a 100644
--- a/lib/l10n/es.php
+++ b/lib/l10n/es.php
@@ -66,6 +66,10 @@ $TRANSLATIONS = array(
"last month" => "mes pasado",
"_%n month ago_::_%n months ago_" => array("Hace %n mes","Hace %n meses"),
"last year" => "año pasado",
-"years ago" => "hace años"
+"years ago" => "hace años",
+"Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-\"" => "Solo los siguientes caracteres están permitidos en un nombre de usuario: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-\"",
+"A valid username must be provided" => "Se debe proporcionar un nombre de usuario válido",
+"A valid password must be provided" => "Se debe proporcionar una contraseña válida",
+"The username is already being used" => "El nombre de usuario ya está en uso"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/es_AR.php b/lib/l10n/es_AR.php
index a925e22ba88..34775b16b22 100644
--- a/lib/l10n/es_AR.php
+++ b/lib/l10n/es_AR.php
@@ -60,6 +60,8 @@ $TRANSLATIONS = array(
"last month" => "el mes pasado",
"_%n month ago_::_%n months ago_" => array("Hace %n mes","Hace %n meses"),
"last year" => "el año pasado",
-"years ago" => "años atrás"
+"years ago" => "años atrás",
+"A valid username must be provided" => "Debe ingresar un nombre de usuario válido",
+"A valid password must be provided" => "Debe ingresar una contraseña válida"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/es_MX.php b/lib/l10n/es_MX.php
index 2f0ed33f6b3..befb076b7de 100644
--- a/lib/l10n/es_MX.php
+++ b/lib/l10n/es_MX.php
@@ -60,6 +60,8 @@ $TRANSLATIONS = array(
"last month" => "mes pasado",
"_%n month ago_::_%n months ago_" => array("Hace %n mes","Hace %n meses"),
"last year" => "año pasado",
-"years ago" => "hace años"
+"years ago" => "hace años",
+"A valid username must be provided" => "Se debe proporcionar un nombre de usuario válido",
+"A valid password must be provided" => "Se debe proporcionar una contraseña válida"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/et_EE.php b/lib/l10n/et_EE.php
index f6435320c6c..883c7323c0c 100644
--- a/lib/l10n/et_EE.php
+++ b/lib/l10n/et_EE.php
@@ -31,6 +31,7 @@ $TRANSLATIONS = array(
"Application is not enabled" => "Rakendus pole sisse lülitatud",
"Authentication error" => "Autentimise viga",
"Token expired. Please reload page." => "Kontrollkood aegus. Paelun lae leht uuesti.",
+"Unknown user" => "Tundmatu kasutaja",
"Files" => "Failid",
"Text" => "Tekst",
"Images" => "Pildid",
@@ -39,8 +40,13 @@ $TRANSLATIONS = array(
"%s you may not use dots in the database name" => "%s punktide kasutamine andmebaasi nimes pole lubatud",
"MS SQL username and/or password not valid: %s" => "MS SQL kasutajatunnus ja/või parool pole õiged: %s",
"You need to enter either an existing account or the administrator." => "Sisesta kas juba olemasolev konto või administrator.",
+"MySQL/MariaDB username and/or password not valid" => "MySQL/MariaDB kasutajatunnus ja/või parool pole õiged",
"DB Error: \"%s\"" => "Andmebaasi viga: \"%s\"",
"Offending command was: \"%s\"" => "Tõrkuv käsk oli: \"%s\"",
+"MySQL/MariaDB user '%s'@'localhost' exists already." => "MySQL/MariaDB kasutaja '%s'@'localhost' on juba olemas.",
+"Drop this user from MySQL/MariaDB" => "Kustuta see MySQL/MariaDB kasutaja",
+"MySQL/MariaDB user '%s'@'%%' already exists" => "MySQL/MariaDB user '%s'@'%%' on juba olemas",
+"Drop this user from MySQL/MariaDB." => "Kustuta see MySQL/MariaDB kasutaja.",
"Oracle connection could not be established" => "Ei suuda luua ühendust Oracle baasiga",
"Oracle username and/or password not valid" => "Oracle kasutajatunnus ja/või parool pole õiged",
"Offending command was: \"%s\", name: %s, password: %s" => "Tõrkuv käsk oli: \"%s\", nimi: %s, parool: %s",
@@ -60,6 +66,9 @@ $TRANSLATIONS = array(
"last month" => "viimasel kuul",
"_%n month ago_::_%n months ago_" => array("","%n kuud tagasi"),
"last year" => "viimasel aastal",
-"years ago" => "aastat tagasi"
+"years ago" => "aastat tagasi",
+"A valid username must be provided" => "Sisesta nõuetele vastav kasutajatunnus",
+"A valid password must be provided" => "Sisesta nõuetele vastav parool",
+"The username is already being used" => "Kasutajanimi on juba kasutuses"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/eu.php b/lib/l10n/eu.php
index 58c198cff14..7a8a11f5b32 100644
--- a/lib/l10n/eu.php
+++ b/lib/l10n/eu.php
@@ -60,6 +60,9 @@ $TRANSLATIONS = array(
"last month" => "joan den hilabetean",
"_%n month ago_::_%n months ago_" => array("orain dela hilabete %n","orain dela %n hilabete"),
"last year" => "joan den urtean",
-"years ago" => "urte"
+"years ago" => "urte",
+"A valid username must be provided" => "Baliozko erabiltzaile izena eman behar da",
+"A valid password must be provided" => "Baliozko pasahitza eman behar da",
+"The username is already being used" => "Erabiltzaile izena dagoeneko erabiltzen ari da"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/fa.php b/lib/l10n/fa.php
index 7323ffe1918..c1c16cf94b4 100644
--- a/lib/l10n/fa.php
+++ b/lib/l10n/fa.php
@@ -42,6 +42,8 @@ $TRANSLATIONS = array(
"last month" => "ماه قبل",
"_%n month ago_::_%n months ago_" => array(""),
"last year" => "سال قبل",
-"years ago" => "سال‌های قبل"
+"years ago" => "سال‌های قبل",
+"A valid username must be provided" => "نام کاربری صحیح باید وارد شود",
+"A valid password must be provided" => "رمز عبور صحیح باید وارد شود"
);
$PLURAL_FORMS = "nplurals=1; plural=0;";
diff --git a/lib/l10n/fi_FI.php b/lib/l10n/fi_FI.php
index 018e4c04c4f..13e97e1b677 100644
--- a/lib/l10n/fi_FI.php
+++ b/lib/l10n/fi_FI.php
@@ -59,6 +59,10 @@ $TRANSLATIONS = array(
"last month" => "viime kuussa",
"_%n month ago_::_%n months ago_" => array("%n kuukausi sitten","%n kuukautta sitten"),
"last year" => "viime vuonna",
-"years ago" => "vuotta sitten"
+"years ago" => "vuotta sitten",
+"Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-\"" => "Vain seuraavat merkit ovat sallittuja käyttäjätunnuksessa: \"a-z\", \"A-Z\", \"0-9\" ja \"_.@-\"",
+"A valid username must be provided" => "Anna kelvollinen käyttäjätunnus",
+"A valid password must be provided" => "Anna kelvollinen salasana",
+"The username is already being used" => "Käyttäjätunnus on jo käytössä"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/fr.php b/lib/l10n/fr.php
index d866fb664ee..b13970c610d 100644
--- a/lib/l10n/fr.php
+++ b/lib/l10n/fr.php
@@ -66,6 +66,10 @@ $TRANSLATIONS = array(
"last month" => "le mois dernier",
"_%n month ago_::_%n months ago_" => array("","Il y a %n mois"),
"last year" => "l'année dernière",
-"years ago" => "il y a plusieurs années"
+"years ago" => "il y a plusieurs années",
+"Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-\"" => "Seuls les caractères suivants sont autorisés dans un nom d'utilisateur : \"a-z\", \"A-Z\", \"0-9\", et \"_.@-\"",
+"A valid username must be provided" => "Un nom d'utilisateur valide doit être saisi",
+"A valid password must be provided" => "Un mot de passe valide doit être saisi",
+"The username is already being used" => "Le nom d'utilisateur est déjà utilisé"
);
$PLURAL_FORMS = "nplurals=2; plural=(n > 1);";
diff --git a/lib/l10n/gl.php b/lib/l10n/gl.php
index cc1351c2f15..0da1695e37f 100644
--- a/lib/l10n/gl.php
+++ b/lib/l10n/gl.php
@@ -66,6 +66,10 @@ $TRANSLATIONS = array(
"last month" => "último mes",
"_%n month ago_::_%n months ago_" => array("hai %n mes","hai %n meses"),
"last year" => "último ano",
-"years ago" => "anos atrás"
+"years ago" => "anos atrás",
+"Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-\"" => "Só se permiten os seguintes caracteres no nome de usuario: «a-z», «A-Z», «0-9», e «_.@-»",
+"A valid username must be provided" => "Debe fornecer un nome de usuario",
+"A valid password must be provided" => "Debe fornecer un contrasinal",
+"The username is already being used" => "Este nome de usuario xa está a ser usado"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/he.php b/lib/l10n/he.php
index 6a9020009e9..27267c2e34d 100644
--- a/lib/l10n/he.php
+++ b/lib/l10n/he.php
@@ -29,6 +29,8 @@ $TRANSLATIONS = array(
"last month" => "חודש שעבר",
"_%n month ago_::_%n months ago_" => array("","לפני %n חודשים"),
"last year" => "שנה שעברה",
-"years ago" => "שנים"
+"years ago" => "שנים",
+"A valid username must be provided" => "יש לספק שם משתמש תקני",
+"A valid password must be provided" => "יש לספק ססמה תקנית"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/hu_HU.php b/lib/l10n/hu_HU.php
index 2a03f72a51e..0637773d17c 100644
--- a/lib/l10n/hu_HU.php
+++ b/lib/l10n/hu_HU.php
@@ -60,6 +60,9 @@ $TRANSLATIONS = array(
"last month" => "múlt hónapban",
"_%n month ago_::_%n months ago_" => array("%n hónappal ezelőtt","%n hónappal ezelőtt"),
"last year" => "tavaly",
-"years ago" => "több éve"
+"years ago" => "több éve",
+"A valid username must be provided" => "Érvényes felhasználónevet kell megadnia",
+"A valid password must be provided" => "Érvényes jelszót kell megadnia",
+"The username is already being used" => "Ez a bejelentkezési név már foglalt"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/id.php b/lib/l10n/id.php
index 76dda80cf70..d694967cd42 100644
--- a/lib/l10n/id.php
+++ b/lib/l10n/id.php
@@ -60,6 +60,8 @@ $TRANSLATIONS = array(
"last month" => "bulan kemarin",
"_%n month ago_::_%n months ago_" => array("%n bulan yang lalu"),
"last year" => "tahun kemarin",
-"years ago" => "beberapa tahun lalu"
+"years ago" => "beberapa tahun lalu",
+"A valid username must be provided" => "Tuliskan nama pengguna yang valid",
+"A valid password must be provided" => "Tuliskan sandi yang valid"
);
$PLURAL_FORMS = "nplurals=1; plural=0;";
diff --git a/lib/l10n/it.php b/lib/l10n/it.php
index ed1cbc2e31a..b76b5060a4d 100644
--- a/lib/l10n/it.php
+++ b/lib/l10n/it.php
@@ -66,6 +66,10 @@ $TRANSLATIONS = array(
"last month" => "mese scorso",
"_%n month ago_::_%n months ago_" => array("%n mese fa","%n mesi fa"),
"last year" => "anno scorso",
-"years ago" => "anni fa"
+"years ago" => "anni fa",
+"Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-\"" => "Solo i seguenti caratteri sono ammessi in un nome utente: \"a-z\", \"A-Z\", \"0-9\", e \"_.@-\"",
+"A valid username must be provided" => "Deve essere fornito un nome utente valido",
+"A valid password must be provided" => "Deve essere fornita una password valida",
+"The username is already being used" => "Il nome utente è già utilizzato"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/ja.php b/lib/l10n/ja.php
index 015c885904e..6d72836f775 100644
--- a/lib/l10n/ja.php
+++ b/lib/l10n/ja.php
@@ -66,6 +66,9 @@ $TRANSLATIONS = array(
"last month" => "1ヶ月前",
"_%n month ago_::_%n months ago_" => array("%nヶ月前"),
"last year" => "1年前",
-"years ago" => "年前"
+"years ago" => "年前",
+"A valid username must be provided" => "有効なユーザー名を指定する必要があります",
+"A valid password must be provided" => "有効なパスワードを指定する必要があります",
+"The username is already being used" => "ユーザ名はすでに使われています"
);
$PLURAL_FORMS = "nplurals=1; plural=0;";
diff --git a/lib/l10n/jv.php b/lib/l10n/jv.php
new file mode 100644
index 00000000000..15f78e0bce6
--- /dev/null
+++ b/lib/l10n/jv.php
@@ -0,0 +1,8 @@
+<?php
+$TRANSLATIONS = array(
+"_%n minute ago_::_%n minutes ago_" => array("",""),
+"_%n hour ago_::_%n hours ago_" => array("",""),
+"_%n day go_::_%n days ago_" => array("",""),
+"_%n month ago_::_%n months ago_" => array("","")
+);
+$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/ka_GE.php b/lib/l10n/ka_GE.php
index e2a719d0746..f15563c297d 100644
--- a/lib/l10n/ka_GE.php
+++ b/lib/l10n/ka_GE.php
@@ -40,6 +40,8 @@ $TRANSLATIONS = array(
"last month" => "გასულ თვეში",
"_%n month ago_::_%n months ago_" => array(""),
"last year" => "ბოლო წელს",
-"years ago" => "წლის წინ"
+"years ago" => "წლის წინ",
+"A valid username must be provided" => "უნდა მიუთითოთ არსებული მომხმარებლის სახელი",
+"A valid password must be provided" => "უნდა მიუთითოთ არსებული პაროლი"
);
$PLURAL_FORMS = "nplurals=1; plural=0;";
diff --git a/lib/l10n/km.php b/lib/l10n/km.php
index 51dd4f33a7e..d5fdc025760 100644
--- a/lib/l10n/km.php
+++ b/lib/l10n/km.php
@@ -39,6 +39,8 @@ $TRANSLATIONS = array(
"last month" => "ខែមុន",
"_%n month ago_::_%n months ago_" => array("%n ខែ​មុន"),
"last year" => "ឆ្នាំ​មុន",
-"years ago" => "ឆ្នាំ​មុន"
+"years ago" => "ឆ្នាំ​មុន",
+"A valid username must be provided" => "ត្រូវ​ផ្ដល់​ឈ្មោះ​អ្នក​ប្រើ​ឲ្យ​បាន​ត្រឹម​ត្រូវ",
+"A valid password must be provided" => "ត្រូវ​ផ្ដល់​ពាក្យ​សម្ងាត់​ឲ្យ​បាន​ត្រឹម​ត្រូវ"
);
$PLURAL_FORMS = "nplurals=1; plural=0;";
diff --git a/lib/l10n/ko.php b/lib/l10n/ko.php
index 833476f6464..2c94ebdcc22 100644
--- a/lib/l10n/ko.php
+++ b/lib/l10n/ko.php
@@ -60,6 +60,8 @@ $TRANSLATIONS = array(
"last month" => "지난 달",
"_%n month ago_::_%n months ago_" => array("%n달 전 "),
"last year" => "작년",
-"years ago" => "년 전"
+"years ago" => "년 전",
+"A valid username must be provided" => "올바른 사용자 이름을 입력해야 함",
+"A valid password must be provided" => "올바른 암호를 입력해야 함"
);
$PLURAL_FORMS = "nplurals=1; plural=0;";
diff --git a/lib/l10n/lt_LT.php b/lib/l10n/lt_LT.php
index dac8eed7633..88aca7aba46 100644
--- a/lib/l10n/lt_LT.php
+++ b/lib/l10n/lt_LT.php
@@ -60,6 +60,8 @@ $TRANSLATIONS = array(
"last month" => "praeitą mėnesį",
"_%n month ago_::_%n months ago_" => array("Prieš %n mėnesį","Prieš %n mėnesius","Prieš %n mėnesių"),
"last year" => "praeitais metais",
-"years ago" => "prieš metus"
+"years ago" => "prieš metus",
+"A valid username must be provided" => "Vartotojo vardas turi būti tinkamas",
+"A valid password must be provided" => "Slaptažodis turi būti tinkamas"
);
$PLURAL_FORMS = "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);";
diff --git a/lib/l10n/lv.php b/lib/l10n/lv.php
index 5461e077ec9..1c8a31aff2f 100644
--- a/lib/l10n/lv.php
+++ b/lib/l10n/lv.php
@@ -43,6 +43,9 @@ $TRANSLATIONS = array(
"last month" => "pagājušajā mēnesī",
"_%n month ago_::_%n months ago_" => array("","","Pirms %n mēnešiem"),
"last year" => "gājušajā gadā",
-"years ago" => "gadus atpakaļ"
+"years ago" => "gadus atpakaļ",
+"A valid username must be provided" => "Jānorāda derīgs lietotājvārds",
+"A valid password must be provided" => "Jānorāda derīga parole",
+"The username is already being used" => "Šāds lietotājvārds jau tiek izmantots"
);
$PLURAL_FORMS = "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);";
diff --git a/lib/l10n/mk.php b/lib/l10n/mk.php
index deaf1bc8d05..a0b3c39865a 100644
--- a/lib/l10n/mk.php
+++ b/lib/l10n/mk.php
@@ -28,6 +28,8 @@ $TRANSLATIONS = array(
"last month" => "минатиот месец",
"_%n month ago_::_%n months ago_" => array("",""),
"last year" => "минатата година",
-"years ago" => "пред години"
+"years ago" => "пред години",
+"A valid username must be provided" => "Мора да се обезбеди валидно корисничко име ",
+"A valid password must be provided" => "Мора да се обезбеди валидна лозинка"
);
$PLURAL_FORMS = "nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;";
diff --git a/lib/l10n/nb_NO.php b/lib/l10n/nb_NO.php
index 4b41e54ef44..fd9b631f23c 100644
--- a/lib/l10n/nb_NO.php
+++ b/lib/l10n/nb_NO.php
@@ -60,6 +60,8 @@ $TRANSLATIONS = array(
"last month" => "forrige måned",
"_%n month ago_::_%n months ago_" => array("","%n dager siden"),
"last year" => "forrige år",
-"years ago" => "år siden"
+"years ago" => "år siden",
+"A valid username must be provided" => "Oppgi et gyldig brukernavn",
+"A valid password must be provided" => "Oppgi et gyldig passord"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/nl.php b/lib/l10n/nl.php
index dcf893af630..c43703c504e 100644
--- a/lib/l10n/nl.php
+++ b/lib/l10n/nl.php
@@ -66,6 +66,10 @@ $TRANSLATIONS = array(
"last month" => "vorige maand",
"_%n month ago_::_%n months ago_" => array("%n maand geleden","%n maanden geleden"),
"last year" => "vorig jaar",
-"years ago" => "jaar geleden"
+"years ago" => "jaar geleden",
+"Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-\"" => "Alleen de volgende tekens zijn toegestaan in een gebruikersnaam: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-\"",
+"A valid username must be provided" => "Er moet een geldige gebruikersnaam worden opgegeven",
+"A valid password must be provided" => "Er moet een geldig wachtwoord worden opgegeven",
+"The username is already being used" => "De gebruikersnaam bestaat al"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/nn_NO.php b/lib/l10n/nn_NO.php
index db257f35dce..77aebb26ffa 100644
--- a/lib/l10n/nn_NO.php
+++ b/lib/l10n/nn_NO.php
@@ -23,6 +23,8 @@ $TRANSLATIONS = array(
"last month" => "førre månad",
"_%n month ago_::_%n months ago_" => array("","%n månadar sidan"),
"last year" => "i fjor",
-"years ago" => "år sidan"
+"years ago" => "år sidan",
+"A valid username must be provided" => "Du må oppgje eit gyldig brukarnamn",
+"A valid password must be provided" => "Du må oppgje eit gyldig passord"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/pl.php b/lib/l10n/pl.php
index bc5e4a947c7..f786e1832a2 100644
--- a/lib/l10n/pl.php
+++ b/lib/l10n/pl.php
@@ -66,6 +66,10 @@ $TRANSLATIONS = array(
"last month" => "w zeszłym miesiącu",
"_%n month ago_::_%n months ago_" => array("%n miesiąc temu","%n miesięcy temu","%n miesięcy temu"),
"last year" => "w zeszłym roku",
-"years ago" => "lat temu"
+"years ago" => "lat temu",
+"Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-\"" => "W nazwach użytkowników dozwolone są wyłącznie następujące znaki: \"a-z\", \"A-Z\", \"0-9\", oraz \"_.@-\"",
+"A valid username must be provided" => "Należy podać prawidłową nazwę użytkownika",
+"A valid password must be provided" => "Należy podać prawidłowe hasło",
+"The username is already being used" => "Ta nazwa użytkownika jest już używana"
);
$PLURAL_FORMS = "nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);";
diff --git a/lib/l10n/pl_PL.php b/lib/l10n/pl_PL.php
deleted file mode 100644
index 5494e3dab25..00000000000
--- a/lib/l10n/pl_PL.php
+++ /dev/null
@@ -1,5 +0,0 @@
-<?php
-$TRANSLATIONS = array(
-"Settings" => "Ustawienia"
-);
-$PLURAL_FORMS = "nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);";
diff --git a/lib/l10n/pt_BR.php b/lib/l10n/pt_BR.php
index 6c8ea586de8..3cc02f76524 100644
--- a/lib/l10n/pt_BR.php
+++ b/lib/l10n/pt_BR.php
@@ -66,6 +66,10 @@ $TRANSLATIONS = array(
"last month" => "último mês",
"_%n month ago_::_%n months ago_" => array("","ha %n meses"),
"last year" => "último ano",
-"years ago" => "anos atrás"
+"years ago" => "anos atrás",
+"Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-\"" => "Somente os seguintes caracteres são permitidos no nome do usuário: \"a-z\", \"A-Z\", \"0-9\", e \"_.@-\"",
+"A valid username must be provided" => "Forneça um nome de usuário válido",
+"A valid password must be provided" => "Forneça uma senha válida",
+"The username is already being used" => "Este nome de usuário já está sendo usado"
);
$PLURAL_FORMS = "nplurals=2; plural=(n > 1);";
diff --git a/lib/l10n/pt_PT.php b/lib/l10n/pt_PT.php
index e6dd459a7e1..8b3c003678d 100644
--- a/lib/l10n/pt_PT.php
+++ b/lib/l10n/pt_PT.php
@@ -61,6 +61,8 @@ $TRANSLATIONS = array(
"last month" => "ultímo mês",
"_%n month ago_::_%n months ago_" => array("","%n meses atrás"),
"last year" => "ano passado",
-"years ago" => "anos atrás"
+"years ago" => "anos atrás",
+"A valid username must be provided" => "Um nome de utilizador válido deve ser fornecido",
+"A valid password must be provided" => "Uma password válida deve ser fornecida"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/ro.php b/lib/l10n/ro.php
index 6bff105a61f..87e9a92c464 100644
--- a/lib/l10n/ro.php
+++ b/lib/l10n/ro.php
@@ -31,6 +31,8 @@ $TRANSLATIONS = array(
"last month" => "ultima lună",
"_%n month ago_::_%n months ago_" => array("","",""),
"last year" => "ultimul an",
-"years ago" => "ani în urmă"
+"years ago" => "ani în urmă",
+"A valid username must be provided" => "Trebuie să furnizaţi un nume de utilizator valid",
+"A valid password must be provided" => "Trebuie să furnizaţi o parolă validă"
);
$PLURAL_FORMS = "nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));";
diff --git a/lib/l10n/ru.php b/lib/l10n/ru.php
index 214849721da..2611fcf7a6b 100644
--- a/lib/l10n/ru.php
+++ b/lib/l10n/ru.php
@@ -60,6 +60,8 @@ $TRANSLATIONS = array(
"last month" => "в прошлом месяце",
"_%n month ago_::_%n months ago_" => array("%n месяц назад","%n месяца назад","%n месяцев назад"),
"last year" => "в прошлом году",
-"years ago" => "несколько лет назад"
+"years ago" => "несколько лет назад",
+"A valid username must be provided" => "Укажите правильное имя пользователя",
+"A valid password must be provided" => "Укажите валидный пароль"
);
$PLURAL_FORMS = "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);";
diff --git a/lib/l10n/sk_SK.php b/lib/l10n/sk_SK.php
index 546e3017978..17108d4bdf6 100644
--- a/lib/l10n/sk_SK.php
+++ b/lib/l10n/sk_SK.php
@@ -31,6 +31,7 @@ $TRANSLATIONS = array(
"Application is not enabled" => "Aplikácia nie je zapnutá",
"Authentication error" => "Chyba autentifikácie",
"Token expired. Please reload page." => "Token vypršal. Obnovte, prosím, stránku.",
+"Unknown user" => "Neznámy používateľ",
"Files" => "Súbory",
"Text" => "Text",
"Images" => "Obrázky",
@@ -60,6 +61,8 @@ $TRANSLATIONS = array(
"last month" => "minulý mesiac",
"_%n month ago_::_%n months ago_" => array("pred %n mesiacom","pred %n mesiacmi","pred %n mesiacmi"),
"last year" => "minulý rok",
-"years ago" => "pred rokmi"
+"years ago" => "pred rokmi",
+"A valid username must be provided" => "Musíte zadať platné používateľské meno",
+"A valid password must be provided" => "Musíte zadať platné heslo"
);
$PLURAL_FORMS = "nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;";
diff --git a/lib/l10n/sl.php b/lib/l10n/sl.php
index 411a14370ee..6f9470401ed 100644
--- a/lib/l10n/sl.php
+++ b/lib/l10n/sl.php
@@ -66,6 +66,8 @@ $TRANSLATIONS = array(
"last month" => "zadnji mesec",
"_%n month ago_::_%n months ago_" => array("pred %n mesecem","pred %n mesecema","pred %n meseci","pred %n meseci"),
"last year" => "lansko leto",
-"years ago" => "let nazaj"
+"years ago" => "let nazaj",
+"A valid username must be provided" => "Navedeno mora biti veljavno uporabniško ime",
+"A valid password must be provided" => "Navedeno mora biti veljavno geslo"
);
$PLURAL_FORMS = "nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);";
diff --git a/lib/l10n/sq.php b/lib/l10n/sq.php
index b22663f76df..e29fa2cee53 100644
--- a/lib/l10n/sq.php
+++ b/lib/l10n/sq.php
@@ -41,6 +41,8 @@ $TRANSLATIONS = array(
"last month" => "muajin e shkuar",
"_%n month ago_::_%n months ago_" => array("","%n muaj më parë"),
"last year" => "vitin e shkuar",
-"years ago" => "vite më parë"
+"years ago" => "vite më parë",
+"A valid username must be provided" => "Duhet të jepni një emër të vlefshëm përdoruesi",
+"A valid password must be provided" => "Duhet të jepni një fjalëkalim te vlefshëm"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/sr.php b/lib/l10n/sr.php
index 47a84803683..f9155bfd575 100644
--- a/lib/l10n/sr.php
+++ b/lib/l10n/sr.php
@@ -28,6 +28,8 @@ $TRANSLATIONS = array(
"last month" => "прошлог месеца",
"_%n month ago_::_%n months ago_" => array("","",""),
"last year" => "прошле године",
-"years ago" => "година раније"
+"years ago" => "година раније",
+"A valid username must be provided" => "Морате унети исправно корисничко име",
+"A valid password must be provided" => "Морате унети исправну лозинку"
);
$PLURAL_FORMS = "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);";
diff --git a/lib/l10n/sv.php b/lib/l10n/sv.php
index a1f371210ac..70ca0bed383 100644
--- a/lib/l10n/sv.php
+++ b/lib/l10n/sv.php
@@ -31,6 +31,7 @@ $TRANSLATIONS = array(
"Application is not enabled" => "Applikationen är inte aktiverad",
"Authentication error" => "Fel vid autentisering",
"Token expired. Please reload page." => "Ogiltig token. Ladda om sidan.",
+"Unknown user" => "Okänd användare",
"Files" => "Filer",
"Text" => "Text",
"Images" => "Bilder",
@@ -39,8 +40,13 @@ $TRANSLATIONS = array(
"%s you may not use dots in the database name" => "%s du får inte använda punkter i databasnamnet",
"MS SQL username and/or password not valid: %s" => "MS SQL-användaren och/eller lösenordet var inte giltigt: %s",
"You need to enter either an existing account or the administrator." => "Du måste antingen ange ett befintligt konto eller administratör.",
+"MySQL/MariaDB username and/or password not valid" => "MySQL/MariaDB användarnamn och/eller lösenord är felaktigt",
"DB Error: \"%s\"" => "DB error: \"%s\"",
"Offending command was: \"%s\"" => "Det felaktiga kommandot var: \"%s\"",
+"MySQL/MariaDB user '%s'@'localhost' exists already." => "MySQL/MariaDB användare '%s'@'localhost' existerar redan.",
+"Drop this user from MySQL/MariaDB" => "Radera denna användare från MySQL/MariaDB",
+"MySQL/MariaDB user '%s'@'%%' already exists" => "MySQL/MariaDB användare '%s'@'%%' existerar redan",
+"Drop this user from MySQL/MariaDB." => "Radera denna användare från MySQL/MariaDB.",
"Oracle connection could not be established" => "Oracle-anslutning kunde inte etableras",
"Oracle username and/or password not valid" => "Oracle-användarnamnet och/eller lösenordet är felaktigt",
"Offending command was: \"%s\", name: %s, password: %s" => "Det felande kommandot var: \"%s\", name: %s, password: %s",
@@ -60,6 +66,10 @@ $TRANSLATIONS = array(
"last month" => "förra månaden",
"_%n month ago_::_%n months ago_" => array("%n månad sedan","%n månader sedan"),
"last year" => "förra året",
-"years ago" => "år sedan"
+"years ago" => "år sedan",
+"Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-\"" => "Endast följande tecken är tillåtna i ett användarnamn: \"az\", \"AZ\", \"0-9\", och \"_ @ -.\"",
+"A valid username must be provided" => "Ett giltigt användarnamn måste anges",
+"A valid password must be provided" => "Ett giltigt lösenord måste anges",
+"The username is already being used" => "Användarnamnet används redan"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/tr.php b/lib/l10n/tr.php
index 2fce8b87bf4..0be1c4b186a 100644
--- a/lib/l10n/tr.php
+++ b/lib/l10n/tr.php
@@ -39,25 +39,25 @@ $TRANSLATIONS = array(
"%s enter the database name." => "%s veritabanı adını girin.",
"%s you may not use dots in the database name" => "%s veritabanı adında nokta kullanamayabilirsiniz",
"MS SQL username and/or password not valid: %s" => "MS SQL kullanıcı adı ve/veya parolası geçersiz: %s",
-"You need to enter either an existing account or the administrator." => "Bir konto veya kullanici birlemek ihtiyacin. ",
+"You need to enter either an existing account or the administrator." => "Siz veya yönetici mevcut bir hesap girmeli.",
"MySQL/MariaDB username and/or password not valid" => "MySQL/MariaDB kullanıcı adı ve/veya parolası geçersiz",
-"DB Error: \"%s\"" => "DB Hata: ''%s''",
-"Offending command was: \"%s\"" => "Komut rahasiz ''%s''. ",
+"DB Error: \"%s\"" => "VT Hatası: \"%s\"",
+"Offending command was: \"%s\"" => "Saldırgan komut: \"%s\"",
"MySQL/MariaDB user '%s'@'localhost' exists already." => "MySQL/MariaDB kullanıcı '%s'@'localhost' zaten mevcut.",
"Drop this user from MySQL/MariaDB" => "Bu kullanıcıyı MySQL/MariaDB'dan at (drop)",
"MySQL/MariaDB user '%s'@'%%' already exists" => "MySQL/MariaDB kullanıcısı '%s'@'%%' zaten mevcut",
"Drop this user from MySQL/MariaDB." => "Bu kullanıcıyı MySQL/MariaDB'dan at (drop)",
"Oracle connection could not be established" => "Oracle bağlantısı kurulamadı",
-"Oracle username and/or password not valid" => "Adi klullanici ve/veya parola Oracle mantikli değildir. ",
+"Oracle username and/or password not valid" => "Oracle kullanıcı adı ve/veya parolası geçerli değil",
"Offending command was: \"%s\", name: %s, password: %s" => "Hatalı komut: \"%s\", ad: %s, parola: %s",
-"PostgreSQL username and/or password not valid" => "PostgreSQL adi kullanici ve/veya parola yasal degildir. ",
-"Set an admin username." => "Bir adi kullanici vermek. ",
-"Set an admin password." => "Parola yonetici birlemek. ",
-"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Web sunucunuz dosya transferi için düzgün bir şekilde yapılandırılmamış. WevDAV arabirimini sorunlu gözüküyor.",
+"PostgreSQL username and/or password not valid" => "PostgreSQL kullanıcı adı ve/veya parolası geçerli değil",
+"Set an admin username." => "Bir yönetici kullanıcı adı ayarlayın.",
+"Set an admin password." => "Bir yönetici kullanıcı parolası ayarlayın.",
+"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Web sunucunuz dosya aktarımı için düzgün bir şekilde yapılandırılmamış. WevDAV arayüzü sorunlu görünüyor.",
"Please double check the <a href='%s'>installation guides</a>." => "Lütfen <a href='%s'>kurulum kılavuzlarını</a> iki kez kontrol edin.",
"%s shared »%s« with you" => "%s sizinle »%s« paylaşımında bulundu",
"Could not find category \"%s\"" => "\"%s\" kategorisi bulunamadı",
-"seconds ago" => "saniye önce",
+"seconds ago" => "saniyeler önce",
"_%n minute ago_::_%n minutes ago_" => array("","%n dakika önce"),
"_%n hour ago_::_%n hours ago_" => array("","%n saat önce"),
"today" => "bugün",
@@ -66,6 +66,10 @@ $TRANSLATIONS = array(
"last month" => "geçen ay",
"_%n month ago_::_%n months ago_" => array("","%n ay önce"),
"last year" => "geçen yıl",
-"years ago" => "yıl önce"
+"years ago" => "yıl önce",
+"Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-\"" => "Kullanıcı adında sadece bu karakterlere izin verilmektedir: \"a-z\", \"A-Z\", \"0-9\", ve \"_.@-\"",
+"A valid username must be provided" => "Geçerli bir kullanıcı adı mutlaka sağlanmalı",
+"A valid password must be provided" => "Geçerli bir parola mutlaka sağlanmalı",
+"The username is already being used" => "Bu kullanıcı adı zaten kullanımda"
);
$PLURAL_FORMS = "nplurals=2; plural=(n > 1);";
diff --git a/lib/l10n/ug.php b/lib/l10n/ug.php
index e2cf38ecc8c..8cfa99732ab 100644
--- a/lib/l10n/ug.php
+++ b/lib/l10n/ug.php
@@ -14,6 +14,8 @@ $TRANSLATIONS = array(
"today" => "بۈگۈن",
"yesterday" => "تۈنۈگۈن",
"_%n day go_::_%n days ago_" => array(""),
-"_%n month ago_::_%n months ago_" => array("")
+"_%n month ago_::_%n months ago_" => array(""),
+"A valid username must be provided" => "چوقۇم ئىناۋەتلىك ئىشلەتكۈچى ئىسمىدىن بىرنى تەمىنلەش كېرەك",
+"A valid password must be provided" => "چوقۇم ئىناۋەتلىك ئىم تەمىنلەش كېرەك"
);
$PLURAL_FORMS = "nplurals=1; plural=0;";
diff --git a/lib/l10n/uk.php b/lib/l10n/uk.php
index 94163f0b6f5..fed6277fdd8 100644
--- a/lib/l10n/uk.php
+++ b/lib/l10n/uk.php
@@ -43,6 +43,8 @@ $TRANSLATIONS = array(
"last month" => "минулого місяця",
"_%n month ago_::_%n months ago_" => array("","","%n місяців тому"),
"last year" => "минулого року",
-"years ago" => "роки тому"
+"years ago" => "роки тому",
+"A valid username must be provided" => "Потрібно задати вірне ім'я користувача",
+"A valid password must be provided" => "Потрібно задати вірний пароль"
);
$PLURAL_FORMS = "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);";
diff --git a/lib/l10n/zh_CN.php b/lib/l10n/zh_CN.php
index 684ee17f98e..8fca52f3dbd 100644
--- a/lib/l10n/zh_CN.php
+++ b/lib/l10n/zh_CN.php
@@ -48,6 +48,8 @@ $TRANSLATIONS = array(
"last month" => "上月",
"_%n month ago_::_%n months ago_" => array("%n 月前"),
"last year" => "去年",
-"years ago" => "年前"
+"years ago" => "年前",
+"A valid username must be provided" => "必须提供合法的用户名",
+"A valid password must be provided" => "必须提供合法的密码"
);
$PLURAL_FORMS = "nplurals=1; plural=0;";
diff --git a/lib/l10n/zh_TW.php b/lib/l10n/zh_TW.php
index 1fbae6e2355..83616cf6a42 100644
--- a/lib/l10n/zh_TW.php
+++ b/lib/l10n/zh_TW.php
@@ -60,6 +60,8 @@ $TRANSLATIONS = array(
"last month" => "上個月",
"_%n month ago_::_%n months ago_" => array("%n 個月前"),
"last year" => "去年",
-"years ago" => "幾年前"
+"years ago" => "幾年前",
+"A valid username must be provided" => "必須提供一個有效的用戶名",
+"A valid password must be provided" => "一定要提供一個有效的密碼"
);
$PLURAL_FORMS = "nplurals=1; plural=0;";
diff --git a/lib/private/appconfig.php b/lib/private/appconfig.php
index cdaaebb87e5..fed6989a438 100644
--- a/lib/private/appconfig.php
+++ b/lib/private/appconfig.php
@@ -147,7 +147,7 @@ class AppConfig implements \OCP\IAppConfig {
*/
public function hasKey($app, $key) {
$values = $this->getAppValues($app);
- return isset($values[$key]);
+ return array_key_exists($key, $values);
}
/**
@@ -218,8 +218,8 @@ class AppConfig implements \OCP\IAppConfig {
/**
* get multiply values, either the app or key can be used as wildcard by setting it to false
*
- * @param boolean $app
- * @param string $key
+ * @param string|false $app
+ * @param string|false $key
* @return array
*/
public function getValues($app, $key) {
diff --git a/lib/private/appframework/dependencyinjection/dicontainer.php b/lib/private/appframework/dependencyinjection/dicontainer.php
index 4821ecaf67b..e478225a53d 100644
--- a/lib/private/appframework/dependencyinjection/dicontainer.php
+++ b/lib/private/appframework/dependencyinjection/dicontainer.php
@@ -92,13 +92,13 @@ class DIContainer extends SimpleContainer implements IAppContainer{
return new SecurityMiddleware($app, $c['Request']);
});
- $middleWares = $this->middleWares;
- $this['MiddlewareDispatcher'] = $this->share(function($c) use ($middleWares) {
+ $middleWares = &$this->middleWares;
+ $this['MiddlewareDispatcher'] = $this->share(function($c) use (&$middleWares) {
$dispatcher = new MiddlewareDispatcher();
$dispatcher->registerMiddleware($c['SecurityMiddleware']);
foreach($middleWares as $middleWare) {
- $dispatcher->registerMiddleware($middleWare);
+ $dispatcher->registerMiddleware($c[$middleWare]);
}
return $dispatcher;
@@ -133,10 +133,10 @@ class DIContainer extends SimpleContainer implements IAppContainer{
}
/**
- * @param Middleware $middleWare
+ * @param string $middleWare
* @return boolean|null
*/
- function registerMiddleWare(Middleware $middleWare) {
+ function registerMiddleWare($middleWare) {
array_push($this->middleWares, $middleWare);
}
diff --git a/lib/private/appframework/http/request.php b/lib/private/appframework/http/request.php
index 40f47a7bd2f..643fa685adc 100644
--- a/lib/private/appframework/http/request.php
+++ b/lib/private/appframework/http/request.php
@@ -60,7 +60,14 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* @param string|false 'requesttoken' the requesttoken or false when not available
* @see http://www.php.net/manual/en/reserved.variables.php
*/
- public function __construct(array $vars=array()) {
+ public function __construct(array $vars=array(), $stream='php://input') {
+
+ $this->inputStream = $stream;
+ $this->items['params'] = array();
+
+ if(!array_key_exists('method', $vars)) {
+ $vars['method'] = 'GET';
+ }
foreach($this->allowedKeys as $name) {
$this->items[$name] = isset($vars[$name])
@@ -68,25 +75,32 @@ class Request implements \ArrayAccess, \Countable, IRequest {
: array();
}
- if (defined('PHPUNIT_RUN') && PHPUNIT_RUN
- && in_array('fakeinput', stream_get_wrappers())) {
- $this->inputStream = 'fakeinput://data';
- } else {
- $this->inputStream = 'php://input';
- }
-
- // Only 'application/x-www-form-urlencoded' requests are automatically
- // transformed by PHP, 'application/json' must be decoded manually.
- if ($this->method === 'POST'
- && strpos($this->getHeader('Content-Type'), 'application/json') !== false
- ) {
- $this->items['params'] = $this->items['post'] = json_decode(file_get_contents($this->inputStream), true);
- }
+ // 'application/json' must be decoded manually.
+ if (strpos($this->getHeader('Content-Type'), 'application/json') !== false) {
+ $params = json_decode(file_get_contents($this->inputStream), true);
+ if(count($params) > 0) {
+ $this->items['params'] = $params;
+ if($vars['method'] === 'POST') {
+ $this->items['post'] = $params;
+ }
+ }
+ // Handle application/x-www-form-urlencoded for methods other than GET
+ // or post correctly
+ } elseif($vars['method'] !== 'GET'
+ && $vars['method'] !== 'POST'
+ && strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') !== false) {
+
+ parse_str(file_get_contents($this->inputStream), $params);
+ if(is_array($params)) {
+ $this->items['params'] = $params;
+ }
+ }
$this->items['parameters'] = array_merge(
$this->items['get'],
$this->items['post'],
- $this->items['urlParams']
+ $this->items['urlParams'],
+ $this->items['params']
);
}
@@ -313,47 +327,22 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* @throws \LogicException
*/
protected function getContent() {
- if ($this->content === false && $this->method === 'PUT') {
- throw new \LogicException(
- '"put" can only be accessed once if not '
- . 'application/x-www-form-urlencoded or application/json.'
- );
- }
-
// If the content can't be parsed into an array then return a stream resource.
if ($this->method === 'PUT'
&& strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') === false
&& strpos($this->getHeader('Content-Type'), 'application/json') === false
) {
+ if ($this->content === false) {
+ throw new \LogicException(
+ '"put" can only be accessed once if not '
+ . 'application/x-www-form-urlencoded or application/json.'
+ );
+ }
$this->content = false;
return fopen($this->inputStream, 'rb');
+ } else {
+ return $this->parameters;
}
-
- if (is_null($this->content)) {
- $this->content = file_get_contents($this->inputStream);
-
- /*
- * Normal jquery ajax requests are sent as application/x-www-form-urlencoded
- * and in $_GET and $_POST PHP transformes the data into an array.
- * The first condition mimics this.
- * The second condition allows for sending raw application/json data while
- * still getting the result as an array.
- *
- */
- if (strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') !== false) {
- parse_str($this->content, $content);
- if(is_array($content)) {
- $this->content = $content;
- }
- } elseif (strpos($this->getHeader('Content-Type'), 'application/json') !== false) {
- $content = json_decode($this->content, true);
- if(is_array($content)) {
- $this->content = $content;
- }
- }
- }
-
- return $this->content;
}
/**
diff --git a/lib/private/appframework/routing/routeconfig.php b/lib/private/appframework/routing/routeconfig.php
index 35bee75cc4d..a3bbde6af53 100644
--- a/lib/private/appframework/routing/routeconfig.php
+++ b/lib/private/appframework/routing/routeconfig.php
@@ -84,7 +84,15 @@ class RouteConfig {
// register the route
$handler = new RouteActionHandler($this->container, $controllerName, $actionName);
- $this->router->create($this->appName.'.'.$controller.'.'.$action, $url)->method($verb)->action($handler);
+ $router = $this->router->create($this->appName.'.'.$controller.'.'.$action, $url)
+ ->method($verb)
+ ->action($handler);
+
+ // optionally register requirements for route. This is used to
+ // tell the route parser how url parameters should be matched
+ if(array_key_exists('requirements', $simpleRoute)) {
+ $router->requirements($simpleRoute['requirements']);
+ }
}
}
diff --git a/lib/private/cache.php b/lib/private/cache.php
index a311f10a00f..961270c334c 100644
--- a/lib/private/cache.php
+++ b/lib/private/cache.php
@@ -97,7 +97,7 @@ class Cache {
/**
* creates cache key based on the files given
- * @param $files
+ * @param string[] $files
* @return string
*/
static public function generateCacheKeyFromFiles($files) {
diff --git a/lib/private/cache/file.php b/lib/private/cache/file.php
index 8a6ef39f61b..2fd77c437fe 100644
--- a/lib/private/cache/file.php
+++ b/lib/private/cache/file.php
@@ -1,6 +1,7 @@
<?php
/**
* Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl>
+ * Copyright (c) 2014 Vincent Petry <pvince81@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
@@ -10,22 +11,22 @@ namespace OC\Cache;
class File {
protected $storage;
+
+ /**
+ * Returns the cache storage for the logged in user
+ * @return cache storage
+ */
protected function getStorage() {
if (isset($this->storage)) {
return $this->storage;
}
if(\OC_User::isLoggedIn()) {
\OC\Files\Filesystem::initMountPoints(\OC_User::getUser());
- $subdir = 'cache';
- $view = new \OC\Files\View('/' . \OC_User::getUser());
- if(!$view->file_exists($subdir)) {
- $view->mkdir($subdir);
- }
- $this->storage = new \OC\Files\View('/' . \OC_User::getUser().'/'.$subdir);
+ $this->storage = new \OC\Files\View('/' . \OC_User::getUser() . '/cache');
return $this->storage;
}else{
\OC_Log::write('core', 'Can\'t get cache storage, user not logged in', \OC_Log::ERROR);
- return false;
+ throw new \OC\ForbiddenException('Can\t get cache storage, user not logged in');
}
}
@@ -83,11 +84,6 @@ class File {
public function hasKey($key) {
$storage = $this->getStorage();
if ($storage && $storage->is_file($key)) {
- $mtime = $storage->filemtime($key);
- if ($mtime < time()) {
- $storage->unlink($key);
- return false;
- }
return true;
}
return false;
diff --git a/lib/private/config.php b/lib/private/config.php
index 56f47256134..6701ca0532b 100644
--- a/lib/private/config.php
+++ b/lib/private/config.php
@@ -172,7 +172,7 @@ class Config {
$result = @file_put_contents($this->configFilename, $content);
if (!$result) {
$defaults = new \OC_Defaults;
- $url = \OC_Helper::linkToDocs('admin-dir-permissions');
+ $url = \OC_Helper::linkToDocs('admin-dir_permissions');
throw new HintException(
"Can't write into config directory!",
'This can usually be fixed by '
diff --git a/lib/private/connector/sabre/node.php b/lib/private/connector/sabre/node.php
index 3a5c721dda5..55e626c4c85 100644
--- a/lib/private/connector/sabre/node.php
+++ b/lib/private/connector/sabre/node.php
@@ -115,11 +115,14 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
/**
* @brief Returns the last modification time, as a unix timestamp
- * @return int
+ * @return int timestamp as integer
*/
public function getLastModified() {
- return $this->info->getMtime();
-
+ $timestamp = $this->info->getMtime();
+ if (!empty($timestamp)) {
+ return (int)$timestamp;
+ }
+ return $timestamp;
}
/**
diff --git a/lib/private/connector/sabre/quotaplugin.php b/lib/private/connector/sabre/quotaplugin.php
index 13fb187eed3..78d3172725a 100644
--- a/lib/private/connector/sabre/quotaplugin.php
+++ b/lib/private/connector/sabre/quotaplugin.php
@@ -61,8 +61,19 @@ class OC_Connector_Sabre_QuotaPlugin extends Sabre_DAV_ServerPlugin {
$uri = '/' . $uri;
}
list($parentUri, $newName) = Sabre_DAV_URLUtil::splitPath($uri);
+ $req = $this->server->httpRequest;
+ if ($req->getHeader('OC-Chunked')) {
+ $info = OC_FileChunking::decodeName($newName);
+ $chunkHandler = new OC_FileChunking($info);
+ // substract the already uploaded size to see whether
+ // there is still enough space for the remaining chunks
+ $length -= $chunkHandler->getCurrentSize();
+ }
$freeSpace = $this->getFreeSpace($parentUri);
if ($freeSpace !== \OC\Files\SPACE_UNKNOWN && $length > $freeSpace) {
+ if (isset($chunkHandler)) {
+ $chunkHandler->cleanup();
+ }
throw new Sabre_DAV_Exception_InsufficientStorage();
}
}
diff --git a/lib/private/contactsmanager.php b/lib/private/contactsmanager.php
index fc6745b4505..1cb3da7098f 100644
--- a/lib/private/contactsmanager.php
+++ b/lib/private/contactsmanager.php
@@ -47,7 +47,7 @@ namespace OC {
* This function can be used to delete the contact identified by the given id
*
* @param object $id the unique identifier to a contact
- * @param $address_book_key
+ * @param string $address_book_key identifier of the address book in which the contact shall be deleted
* @return bool successful or not
*/
public function delete($id, $address_book_key) {
@@ -66,7 +66,7 @@ namespace OC {
* Otherwise the contact will be updated by replacing the entire data set.
*
* @param array $properties this array if key-value-pairs defines a contact
- * @param $address_book_key string to identify the address book in which the contact shall be created or updated
+ * @param string $address_book_key identifier of the address book in which the contact shall be created or updated
* @return array representing the contact just created or updated
*/
public function createOrUpdate($properties, $address_book_key) {
diff --git a/lib/private/davclient.php b/lib/private/davclient.php
index afa4e1103b4..916dc11d17a 100644
--- a/lib/private/davclient.php
+++ b/lib/private/davclient.php
@@ -29,6 +29,8 @@ class OC_DAVClient extends \Sabre_DAV_Client {
protected $requestTimeout;
+ protected $verifyHost;
+
/**
* @brief Sets the request timeout or 0 to disable timeout.
* @param integer $timeout in seconds or 0 to disable
@@ -37,10 +39,21 @@ class OC_DAVClient extends \Sabre_DAV_Client {
$this->requestTimeout = (int)$timeout;
}
+ /**
+ * @brief Sets the CURLOPT_SSL_VERIFYHOST setting
+ * @param integer $value value to set CURLOPT_SSL_VERIFYHOST to
+ */
+ public function setVerifyHost($value) {
+ $this->verifyHost = $value;
+ }
+
protected function curlRequest($url, $settings) {
if ($this->requestTimeout > 0) {
$settings[CURLOPT_TIMEOUT] = $this->requestTimeout;
}
+ if (!is_null($this->verifyHost)) {
+ $settings[CURLOPT_SSL_VERIFYHOST] = $this->verifyHost;
+ }
return parent::curlRequest($url, $settings);
}
}
diff --git a/lib/private/db.php b/lib/private/db.php
index cfdac766bff..322a13642ae 100644
--- a/lib/private/db.php
+++ b/lib/private/db.php
@@ -313,9 +313,8 @@ 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
- * @param string $table
+ * @param string $table The table to insert into in the form '*PREFIX*tableName'
+ * @param array $input An array of fieldname/value pairs
* @return boolean number of updated rows
*/
public static function insertIfNotExist($table, $input) {
diff --git a/lib/private/db/statementwrapper.php b/lib/private/db/statementwrapper.php
index eaf215c7231..492209b883b 100644
--- a/lib/private/db/statementwrapper.php
+++ b/lib/private/db/statementwrapper.php
@@ -8,6 +8,11 @@
/**
* small wrapper around \Doctrine\DBAL\Driver\Statement to make it behave, more like an MDB2 Statement
+ *
+ * @method boolean bindValue(mixed $param, mixed $value, integer $type = null);
+ * @method string errorCode();
+ * @method array errorInfo();
+ * @method integer rowCount();
*/
class OC_DB_StatementWrapper {
/**
@@ -161,6 +166,8 @@ class OC_DB_StatementWrapper {
/**
* provide an alias for fetch
+ *
+ * @return mixed
*/
public function fetchRow() {
return $this->statement->fetch();
@@ -168,12 +175,13 @@ class OC_DB_StatementWrapper {
/**
* Provide a simple fetchOne.
+ *
* fetch single column from the next row
- * @param int $colnum the column number to fetch
+ * @param int $column the column number to fetch
* @return string
*/
- public function fetchOne($colnum = 0) {
- return $this->statement->fetchColumn($colnum);
+ public function fetchOne($column = 0) {
+ return $this->statement->fetchColumn($column);
}
/**
diff --git a/lib/private/defaults.php b/lib/private/defaults.php
index 79be211b82f..fca798568c5 100644
--- a/lib/private/defaults.php
+++ b/lib/private/defaults.php
@@ -29,8 +29,8 @@ class OC_Defaults {
$this->defaultEntity = "ownCloud"; /* e.g. company name, used for footers and copyright notices */
$this->defaultName = "ownCloud"; /* short name, used when referring to the software */
$this->defaultTitle = "ownCloud"; /* can be a longer name, for titles */
- $this->defaultBaseUrl = "http://owncloud.org";
- $this->defaultSyncClientUrl = " http://owncloud.org/sync-clients/";
+ $this->defaultBaseUrl = "https://owncloud.org";
+ $this->defaultSyncClientUrl = "https://owncloud.org/sync-clients/";
$this->defaultDocBaseUrl = "http://doc.owncloud.org";
$this->defaultSlogan = $this->l->t("web services under your control");
$this->defaultLogoClaim = "";
diff --git a/lib/private/filechunking.php b/lib/private/filechunking.php
index be7f4e14a11..1da02fc81e3 100644
--- a/lib/private/filechunking.php
+++ b/lib/private/filechunking.php
@@ -64,20 +64,46 @@ class OC_FileChunking {
return $parts == $this->info['chunkcount'];
}
+ /**
+ * Assembles the chunks into the file specified by the path.
+ * Chunks are deleted afterwards.
+ *
+ * @param string $f target path
+ *
+ * @return assembled file size
+ *
+ * @throws \OC\InsufficientStorageException when file could not be fully
+ * assembled due to lack of free space
+ */
public function assemble($f) {
$cache = $this->getCache();
$prefix = $this->getPrefix();
$count = 0;
- for($i=0; $i < $this->info['chunkcount']; $i++) {
+ for ($i = 0; $i < $this->info['chunkcount']; $i++) {
$chunk = $cache->get($prefix.$i);
+ // remove after reading to directly save space
+ $cache->remove($prefix.$i);
$count += fwrite($f, $chunk);
}
- $this->cleanup();
return $count;
}
/**
+ * Returns the size of the chunks already present
+ * @return size in bytes
+ */
+ public function getCurrentSize() {
+ $cache = $this->getCache();
+ $prefix = $this->getPrefix();
+ $total = 0;
+ for ($i = 0; $i < $this->info['chunkcount']; $i++) {
+ $total += $cache->size($prefix.$i);
+ }
+ return $total;
+ }
+
+ /**
* Removes all chunks which belong to this transmission
*/
public function cleanup() {
@@ -128,7 +154,15 @@ class OC_FileChunking {
}
/**
- * @param string $path
+ * Assembles the chunks into the file specified by the path.
+ * Also triggers the relevant hooks and proxies.
+ *
+ * @param string $path target path
+ *
+ * @return assembled file size or false if file could not be created
+ *
+ * @throws \OC\InsufficientStorageException when file could not be fully
+ * assembled due to lack of free space
*/
public function file_assemble($path) {
$absolutePath = \OC\Files\Filesystem::normalizePath(\OC\Files\Filesystem::getView()->getAbsolutePath($path));
diff --git a/lib/private/files.php b/lib/private/files.php
index 7e7a27f48dc..bfe6d3c02da 100644
--- a/lib/private/files.php
+++ b/lib/private/files.php
@@ -148,8 +148,9 @@ class OC_Files {
set_time_limit($executionTime);
} else {
if ($xsendfile) {
+ $view = \OC\Files\Filesystem::getView();
/** @var $storage \OC\Files\Storage\Storage */
- list($storage) = \OC\Files\Filesystem::resolvePath($filename);
+ list($storage) = $view->resolvePath($filename);
if ($storage->isLocal()) {
self::addSendfileHeader(\OC\Files\Filesystem::getLocalFile($filename));
} else {
diff --git a/lib/private/files/cache/cache.php b/lib/private/files/cache/cache.php
index abc11e76470..1c9de56f8c5 100644
--- a/lib/private/files/cache/cache.php
+++ b/lib/private/files/cache/cache.php
@@ -594,7 +594,25 @@ class Cache {
}
/**
+ * get the path of a file on this storage by it's id
+ *
+ * @param int $id
+ * @return string | null
+ */
+ public function getPathById($id) {
+ $sql = 'SELECT `path` FROM `*PREFIX*filecache` WHERE `fileid` = ? AND `storage` = ?';
+ $result = \OC_DB::executeAudited($sql, array($id, $this->getNumericStorageId()));
+ if ($row = $result->fetchRow()) {
+ return $row['path'];
+ } else {
+ return null;
+ }
+ }
+
+ /**
* get the storage id of the storage for a file and the internal path of the file
+ * unlike getPathById this does not limit the search to files on this storage and
+ * instead does a global search in the cache table
*
* @param int $id
* @return array, first element holding the storage id, second the path
diff --git a/lib/private/files/filesystem.php b/lib/private/files/filesystem.php
index c31e0c38180..7e27650c557 100644
--- a/lib/private/files/filesystem.php
+++ b/lib/private/files/filesystem.php
@@ -321,11 +321,36 @@ class Filesystem {
self::mount('\OC\Files\Storage\Local', array('datadir' => $root), $user);
}
+ self::mountCacheDir($user);
+
// Chance to mount for other storages
\OC_Hook::emit('OC_Filesystem', 'post_initMountPoints', array('user' => $user, 'user_dir' => $root));
}
/**
+ * Mounts the cache directory
+ * @param string $user user name
+ */
+ private static function mountCacheDir($user) {
+ $cacheBaseDir = \OC_Config::getValue('cache_path', '');
+ if ($cacheBaseDir === '') {
+ // use local cache dir relative to the user's home
+ $subdir = 'cache';
+ $view = new \OC\Files\View('/' . $user);
+ if(!$view->file_exists($subdir)) {
+ $view->mkdir($subdir);
+ }
+ } else {
+ $cacheDir = rtrim($cacheBaseDir, '/') . '/' . $user;
+ if (!file_exists($cacheDir)) {
+ mkdir($cacheDir, 0770, true);
+ }
+ // mount external cache dir to "/$user/cache" mount point
+ self::mount('\OC\Files\Storage\Local', array('datadir' => $cacheDir), '/' . $user . '/cache');
+ }
+ }
+
+ /**
* get the default filesystem view
*
* @return View
diff --git a/lib/private/files/storage/common.php b/lib/private/files/storage/common.php
index 3c078d7b1b4..33b8549ff78 100644
--- a/lib/private/files/storage/common.php
+++ b/lib/private/files/storage/common.php
@@ -118,17 +118,17 @@ abstract class Common implements \OC\Files\Storage\Storage {
if (!$handle) {
return false;
}
- $size = $this->filesize($path);
- if ($size == 0) {
- return '';
- }
- return fread($handle, $size);
+ $data = stream_get_contents($handle);
+ fclose($handle);
+ return $data;
}
public function file_put_contents($path, $data) {
$handle = $this->fopen($path, "w");
$this->removeCachedFile($path);
- return fwrite($handle, $data);
+ $count = fwrite($handle, $data);
+ fclose($handle);
+ return $count;
}
public function rename($path1, $path2) {
@@ -159,10 +159,11 @@ abstract class Common implements \OC\Files\Storage\Storage {
}
public function hash($type, $path, $raw = false) {
- $tmpFile = $this->getLocalFile($path);
- $hash = hash($type, $tmpFile, $raw);
- unlink($tmpFile);
- return $hash;
+ $fh = $this->fopen($path, 'rb');
+ $ctx = hash_init($type);
+ hash_update_stream($ctx, $fh);
+ fclose($fh);
+ return hash_final($ctx, $raw);
}
public function search($query) {
diff --git a/lib/private/files/storage/local.php b/lib/private/files/storage/local.php
index 0f906ec55b4..571bf7f97c1 100644
--- a/lib/private/files/storage/local.php
+++ b/lib/private/files/storage/local.php
@@ -256,7 +256,7 @@ if (\OC_Util::runningOnWindows()) {
return 0;
}
- public function hash($path, $type, $raw = false) {
+ public function hash($type, $path, $raw = false) {
return hash_file($type, $this->datadir . $path, $raw);
}
diff --git a/lib/private/files/storage/mappedlocal.php b/lib/private/files/storage/mappedlocal.php
index 026f6ec895e..94ee28ca763 100644
--- a/lib/private/files/storage/mappedlocal.php
+++ b/lib/private/files/storage/mappedlocal.php
@@ -276,7 +276,7 @@ class MappedLocal extends \OC\Files\Storage\Common{
return 0;
}
- public function hash($path, $type, $raw=false) {
+ public function hash($type, $path, $raw=false) {
return hash_file($type, $this->buildPath($path), $raw);
}
diff --git a/lib/private/files/view.php b/lib/private/files/view.php
index f06c2fcd66c..94be7114865 100644
--- a/lib/private/files/view.php
+++ b/lib/private/files/view.php
@@ -832,6 +832,9 @@ class View {
$user = \OC_User::getUser();
if (!$cache->inCache($internalPath)) {
+ if (!$storage->file_exists($internalPath)) {
+ return false;
+ }
$scanner = $storage->getScanner($internalPath);
$scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW);
} else {
@@ -1129,15 +1132,22 @@ class View {
* @return string
*/
public function getPath($id) {
- list($storage, $internalPath) = Cache\Cache::getById($id);
- $mounts = Filesystem::getMountByStorageId($storage);
+ $manager = Filesystem::getMountManager();
+ $mounts = $manager->findIn($this->fakeRoot);
+ $mounts[] = $manager->find($this->fakeRoot);
+ // reverse the array so we start with the storage this view is in
+ // which is the most likely to contain the file we're looking for
+ $mounts = array_reverse($mounts);
foreach ($mounts as $mount) {
/**
- * @var \OC\Files\Mount $mount
+ * @var \OC\Files\Mount\Mount $mount
*/
- $fullPath = $mount->getMountPoint() . $internalPath;
- if (!is_null($path = $this->getRelativePath($fullPath))) {
- return $path;
+ $cache = $mount->getStorage()->getCache();
+ if ($internalPath = $cache->getPathById($id)) {
+ $fullPath = $mount->getMountPoint() . $internalPath;
+ if (!is_null($path = $this->getRelativePath($fullPath))) {
+ return $path;
+ }
}
}
return null;
diff --git a/lib/private/forbiddenexception.php b/lib/private/forbiddenexception.php
new file mode 100644
index 00000000000..14a4cd14984
--- /dev/null
+++ b/lib/private/forbiddenexception.php
@@ -0,0 +1,16 @@
+<?php
+/**
+ * Copyright (c) 2014 Vincent Petry <pvince81@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC;
+
+/**
+ * Exception thrown whenever access to a resource has
+ * been forbidden or whenever a user isn't authenticated.
+ */
+class ForbiddenException extends \Exception {
+}
diff --git a/lib/private/group/backend.php b/lib/private/group/backend.php
index 2e17b5d0b7f..b0ed0d90d76 100644
--- a/lib/private/group/backend.php
+++ b/lib/private/group/backend.php
@@ -34,6 +34,7 @@ define('OC_GROUP_BACKEND_DELETE_GROUP', 0x00000010);
define('OC_GROUP_BACKEND_ADD_TO_GROUP', 0x00000100);
define('OC_GROUP_BACKEND_REMOVE_FROM_GOUP', 0x00001000);
define('OC_GROUP_BACKEND_GET_DISPLAYNAME', 0x00010000);
+define('OC_GROUP_BACKEND_COUNT_USERS', 0x00100000);
/**
* Abstract base class for user management
@@ -45,6 +46,7 @@ abstract class OC_Group_Backend implements OC_Group_Interface {
OC_GROUP_BACKEND_ADD_TO_GROUP => 'addToGroup',
OC_GROUP_BACKEND_REMOVE_FROM_GOUP => 'removeFromGroup',
OC_GROUP_BACKEND_GET_DISPLAYNAME => 'displayNamesInGroup',
+ OC_GROUP_BACKEND_COUNT_USERS => 'countUsersInGroup',
);
/**
diff --git a/lib/private/group/database.php b/lib/private/group/database.php
index d0974685ff6..3815dcff2e5 100644
--- a/lib/private/group/database.php
+++ b/lib/private/group/database.php
@@ -212,6 +212,20 @@ class OC_Group_Database extends OC_Group_Backend {
}
/**
+ * @brief get the number of all users matching the search string in a group
+ * @param string $gid
+ * @param string $search
+ * @param int $limit
+ * @param int $offset
+ * @return int | false
+ */
+ public function countUsersInGroup($gid, $search = '') {
+ $stmt = OC_DB::prepare('SELECT COUNT(`uid`) AS `count` FROM `*PREFIX*group_user` WHERE `gid` = ? AND `uid` LIKE ?');
+ $result = $stmt->execute(array($gid, $search.'%'));
+ return $result->fetchOne();
+ }
+
+ /**
* @brief get a list of all display names in a group
* @param string $gid
* @param string $search
diff --git a/lib/private/group/dummy.php b/lib/private/group/dummy.php
index da26e1b910e..94cbb607ad1 100644
--- a/lib/private/group/dummy.php
+++ b/lib/private/group/dummy.php
@@ -157,4 +157,14 @@ class OC_Group_Dummy extends OC_Group_Backend {
}
}
+ /**
+ * @brief get the number of all users in a group
+ * @returns int | bool
+ */
+ public function countUsersInGroup($gid, $search = '', $limit = -1, $offset = 0) {
+ if(isset($this->groups[$gid])) {
+ return count($this->groups[$gid]);
+ }
+ }
+
}
diff --git a/lib/private/group/group.php b/lib/private/group/group.php
index 8d2aa87a788..a2b8a0dcbea 100644
--- a/lib/private/group/group.php
+++ b/lib/private/group/group.php
@@ -187,6 +187,27 @@ class Group {
}
/**
+ * returns the number of users matching the search string
+ *
+ * @param string $search
+ * @return int | bool
+ */
+ public function count($search) {
+ $users = false;
+ foreach ($this->backends as $backend) {
+ if($backend->implementsActions(OC_GROUP_BACKEND_COUNT_USERS)) {
+ if($users === false) {
+ //we could directly add to a bool variable, but this would
+ //be ugly
+ $users = 0;
+ }
+ $users += $backend->countUsersInGroup($this->gid, $search);
+ }
+ }
+ return $users;
+ }
+
+ /**
* search for users in the group by displayname
*
* @param string $search
diff --git a/lib/private/helper.php b/lib/private/helper.php
index 98a86388d20..da3d3cd1c6e 100644
--- a/lib/private/helper.php
+++ b/lib/private/helper.php
@@ -78,8 +78,7 @@ class OC_Helper {
* Returns a absolute url to the given app and file.
*/
public static function linkToAbsolute($app, $file, $args = array()) {
- $urlLinkTo = self::linkTo($app, $file, $args);
- return self::makeURLAbsolute($urlLinkTo);
+ return self::linkTo($app, $file, $args);
}
/**
@@ -876,12 +875,15 @@ class OC_Helper {
* Calculate the disc space for the given path
*
* @param string $path
+ * @param \OCP\Files\FileInfo $rootInfo (optional)
* @return array
*/
- public static function getStorageInfo($path) {
+ public static function getStorageInfo($path, $rootInfo = null) {
// return storage info without adding mount points
- $rootInfo = \OC\Files\Filesystem::getFileInfo($path, false);
- $used = $rootInfo['size'];
+ if (is_null($rootInfo)) {
+ $rootInfo = \OC\Files\Filesystem::getFileInfo($path, false);
+ }
+ $used = $rootInfo->getSize();
if ($used < 0) {
$used = 0;
}
diff --git a/lib/private/image.php b/lib/private/image.php
index c987ce92c3c..f1b8acc41b7 100644
--- a/lib/private/image.php
+++ b/lib/private/image.php
@@ -34,7 +34,7 @@ class OC_Image {
/**
* @brief Get mime type for an image file.
- * @param string|null $filepath The path to a local image file.
+ * @param string|null $filePath The path to a local image file.
* @return string The mime type if the it could be determined, otherwise an empty string.
*/
static public function getMimeTypeForFile($filePath) {
diff --git a/lib/private/l10n.php b/lib/private/l10n.php
index 197b2d6791b..175360e27a3 100644
--- a/lib/private/l10n.php
+++ b/lib/private/l10n.php
@@ -75,7 +75,7 @@ class OC_L10N implements \OCP\IL10N {
* get an L10N instance
* @param string $app
* @param string|null $lang
- * @return OC_L10N
+ * @return \OC_L10N
*/
public static function get($app, $lang=null) {
if (is_null($lang)) {
@@ -89,7 +89,6 @@ class OC_L10N implements \OCP\IL10N {
* @brief The constructor
* @param string $app app requesting l10n
* @param string $lang default: null Language
- * @returns OC_L10N-Object
*
* If language is not set, the constructor tries to find the right
* language.
@@ -352,7 +351,7 @@ class OC_L10N implements \OCP\IL10N {
/**
* @brief Localization
* @param string $type Type of localization
- * @param $params parameters for this localization
+ * @param array $data parameters for this localization
* @returns String or false
*
* Returns the localized data.
diff --git a/lib/private/legacy/appconfig.php b/lib/private/legacy/appconfig.php
index b6c3542a673..cb5cef7e350 100644
--- a/lib/private/legacy/appconfig.php
+++ b/lib/private/legacy/appconfig.php
@@ -116,8 +116,6 @@ class OC_Appconfig {
/**
* get multiply values, either the app or key can be used as wildcard by setting it to false
*
- * @param app
- * @param key
* @param string|false $app
* @param string|false $key
* @return array
diff --git a/lib/private/legacy/config.php b/lib/private/legacy/config.php
index ab67c8d3020..6c2103179ab 100644
--- a/lib/private/legacy/config.php
+++ b/lib/private/legacy/config.php
@@ -63,8 +63,8 @@ class OC_Config {
/**
* @brief Gets a value from config.php
* @param string $key key
- * @param string $default = null default value
- * @return string the value or $default
+ * @param mixed $default = null default value
+ * @return mixed the value or $default
*
* This function gets the value from config.php. If it does not exist,
* $default will be returned.
@@ -76,7 +76,7 @@ class OC_Config {
/**
* @brief Sets a value
* @param string $key key
- * @param string $value value
+ * @param mixed $value value
*
* This function sets the value and writes the config.php.
*
diff --git a/lib/private/mail.php b/lib/private/mail.php
index 79f51609631..f9083cc4e64 100644
--- a/lib/private/mail.php
+++ b/lib/private/mail.php
@@ -137,6 +137,9 @@ class OC_Mail {
* @return string
*/
public static function buildAsciiEmail($emailAddress) {
+ if (!function_exists('idn_to_ascii')) {
+ return $emailAddress;
+ }
list($name, $domain) = explode('@', $emailAddress, 2);
$domain = idn_to_ascii($domain);
diff --git a/lib/private/ocs/cloud.php b/lib/private/ocs/cloud.php
index 06d6a8eb4b0..c8bb9425f1a 100644
--- a/lib/private/ocs/cloud.php
+++ b/lib/private/ocs/cloud.php
@@ -99,31 +99,4 @@ class OC_OCS_Cloud {
);
return new OC_OCS_Result($data);
}
-
- public static function getUserPublickey($parameters) {
-
- if(OC_User::userExists($parameters['user'])) {
- // calculate the disc space
- // TODO
- return new OC_OCS_Result(array());
- } else {
- return new OC_OCS_Result(null, 300);
- }
- }
-
- public static function getUserPrivatekey($parameters) {
- $user = OC_User::getUser();
- if(OC_User::isAdminUser($user) or ($user==$parameters['user'])) {
-
- if(OC_User::userExists($user)) {
- // calculate the disc space
- $txt = 'this is the private key of '.$parameters['user'];
- echo($txt);
- } else {
- return new OC_OCS_Result(null, 300, 'User does not exist');
- }
- } else {
- return new OC_OCS_Result('null', 300, 'You don´t have permission to access this ressource.');
- }
- }
}
diff --git a/lib/private/ocs/result.php b/lib/private/ocs/result.php
index 9f14e8da7e8..0e3b85d5905 100644
--- a/lib/private/ocs/result.php
+++ b/lib/private/ocs/result.php
@@ -96,7 +96,7 @@ class OC_OCS_Result{
* @return bool
*/
public function succeeded() {
- return (substr($this->statusCode, 0, 1) === '1');
+ return ($this->statusCode == 100);
}
diff --git a/lib/private/preview.php b/lib/private/preview.php
index 0c1af3c9588..0187b4aacbb 100755
--- a/lib/private/preview.php
+++ b/lib/private/preview.php
@@ -13,6 +13,8 @@
*/
namespace OC;
+use OC\Preview\Provider;
+
require_once 'preview/image.php';
require_once 'preview/movies.php';
require_once 'preview/mp3.php';
@@ -39,15 +41,16 @@ class Preview {
private $file;
private $maxX;
private $maxY;
- private $scalingup;
- private $mimetype;
+ private $scalingUp;
+ private $mimeType;
//filemapper used for deleting previews
// index is path, value is fileinfo
static public $deleteFileMapper = array();
- //preview images object
/**
+ * preview images object
+ *
* @var \OC_Image
*/
private $preview;
@@ -109,7 +112,7 @@ class Preview {
* @brief returns the path of the file you want a thumbnail from
* @return string
*/
- public function getFile() {
+ public function getFile() {
return $this->file;
}
@@ -134,7 +137,7 @@ class Preview {
* @return bool
*/
public function getScalingUp() {
- return $this->scalingup;
+ return $this->scalingUp;
}
/**
@@ -191,18 +194,18 @@ class Preview {
if ($file !== '') {
$this->getFileInfo();
if($this->info !== null && $this->info !== false) {
- $this->mimetype = $this->info->getMimetype();
+ $this->mimeType = $this->info->getMimetype();
}
}
return $this;
}
/**
- * @brief set mimetype explicitely
- * @param string $mimetype
+ * @brief set mime type explicitly
+ * @param string $mimeType
*/
- public function setMimetype($mimetype) {
- $this->mimetype = $mimetype;
+ public function setMimetype($mimeType) {
+ $this->mimeType = $mimeType;
}
/**
@@ -254,7 +257,7 @@ class Preview {
if ($this->getMaxScaleFactor() === 1) {
$scalingUp = false;
}
- $this->scalingup = $scalingUp;
+ $this->scalingUp = $scalingUp;
return $this;
}
@@ -314,35 +317,68 @@ class Preview {
/**
* @brief check if thumbnail or bigger version of thumbnail of file is cached
- * @return mixed (bool / string)
- * false if thumbnail does not exist
- * path to thumbnail if thumbnail exists
+ * @param int $fileId fileId of the original image
+ * @return string|false path to thumbnail if it exists or false
*/
- private function isCached() {
- $file = $this->getFile();
+ public function isCached($fileId) {
+ if (is_null($fileId)) {
+ return false;
+ }
+
$maxX = $this->getMaxX();
$maxY = $this->getMaxY();
- $scalingUp = $this->getScalingUp();
- $maxScaleFactor = $this->getMaxScaleFactor();
- $fileInfo = $this->getFileInfo($file);
- $fileId = $fileInfo->getId();
+ $previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/';
+
+ //does a preview with the wanted height and width already exist?
+ if ($this->userView->file_exists($previewPath . $maxX . '-' . $maxY . '.png')) {
+ return $previewPath . $maxX . '-' . $maxY . '.png';
+ }
+
+ return $this->isCachedBigger($fileId);
+ }
+
+ /**
+ * @brief check if a bigger version of thumbnail of file is cached
+ * @param int $fileId fileId of the original image
+ * @return string|false path to bigger thumbnail if it exists or false
+ */
+ private function isCachedBigger($fileId) {
if (is_null($fileId)) {
return false;
}
- $previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/';
- if (!$this->userView->is_dir($previewPath)) {
- return false;
+ $maxX = $this->getMaxX();
+
+ //array for usable cached thumbnails
+ $possibleThumbnails = $this->getPossibleThumbnails($fileId);
+
+ foreach ($possibleThumbnails as $width => $path) {
+ if ($width < $maxX) {
+ continue;
+ } else {
+ return $path;
+ }
}
- //does a preview with the wanted height and width already exist?
- if ($this->userView->file_exists($previewPath . $maxX . '-' . $maxY . '.png')) {
- return $previewPath . $maxX . '-' . $maxY . '.png';
+ return false;
+ }
+
+ /**
+ * @brief get possible bigger thumbnails of the given image
+ * @param int $fileId fileId of the original image
+ * @return array of paths to bigger thumbnails
+ */
+ private function getPossibleThumbnails($fileId) {
+
+ if (is_null($fileId)) {
+ return array();
}
- $wantedAspectRatio = (float)($maxX / $maxY);
+ $previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/';
+
+ $wantedAspectRatio = (float) ($this->getMaxX() / $this->getMaxY());
//array for usable cached thumbnails
$possibleThumbnails = array();
@@ -350,53 +386,47 @@ class Preview {
$allThumbnails = $this->userView->getDirectoryContent($previewPath);
foreach ($allThumbnails as $thumbnail) {
$name = rtrim($thumbnail['name'], '.png');
- $size = explode('-', $name);
- $x = (int)$size[0];
- $y = (int)$size[1];
+ list($x, $y, $aspectRatio) = $this->getDimensionsFromFilename($name);
- $aspectRatio = (float)($x / $y);
- if ($aspectRatio !== $wantedAspectRatio) {
+ if (abs($aspectRatio - $wantedAspectRatio) >= 0.000001
+ || $this->unscalable($x, $y)
+ ) {
continue;
}
-
- if ($x < $maxX || $y < $maxY) {
- if ($scalingUp) {
- $scalefactor = $maxX / $x;
- if ($scalefactor > $maxScaleFactor) {
- continue;
- }
- } else {
- continue;
- }
- }
$possibleThumbnails[$x] = $thumbnail['path'];
}
- if (count($possibleThumbnails) === 0) {
- return false;
- }
-
- if (count($possibleThumbnails) === 1) {
- return current($possibleThumbnails);
- }
-
ksort($possibleThumbnails);
- if (key(reset($possibleThumbnails)) > $maxX) {
- return current(reset($possibleThumbnails));
- }
+ return $possibleThumbnails;
+ }
- if (key(end($possibleThumbnails)) < $maxX) {
- return current(end($possibleThumbnails));
- }
+ private function getDimensionsFromFilename($name) {
+ $size = explode('-', $name);
+ $x = (int) $size[0];
+ $y = (int) $size[1];
+ $aspectRatio = (float) ($x / $y);
+ return array($x, $y, $aspectRatio);
+ }
- foreach ($possibleThumbnails as $width => $path) {
- if ($width < $maxX) {
- continue;
+ private function unscalable($x, $y) {
+
+ $maxX = $this->getMaxX();
+ $maxY = $this->getMaxY();
+ $scalingUp = $this->getScalingUp();
+ $maxScaleFactor = $this->getMaxScaleFactor();
+
+ if ($x < $maxX || $y < $maxY) {
+ if ($scalingUp) {
+ $scalefactor = $maxX / $x;
+ if ($scalefactor > $maxScaleFactor) {
+ return true;
+ }
} else {
- return $path;
+ return true;
}
}
+ return false;
}
/**
@@ -420,7 +450,7 @@ class Preview {
}
$fileId = $fileInfo->getId();
- $cached = $this->isCached();
+ $cached = $this->isCached($fileId);
if ($cached) {
$stream = $this->userView->fopen($cached, 'r');
@@ -434,13 +464,14 @@ class Preview {
if (is_null($this->preview)) {
$preview = null;
- foreach (self::$providers as $supportedMimetype => $provider) {
- if (!preg_match($supportedMimetype, $this->mimetype)) {
+ foreach (self::$providers as $supportedMimeType => $provider) {
+ if (!preg_match($supportedMimeType, $this->mimeType)) {
continue;
}
\OC_Log::write('core', 'Generating preview for "' . $file . '" with "' . get_class($provider) . '"', \OC_Log::DEBUG);
+ /** @var $provider Provider */
$preview = $provider->getThumbnail($file, $maxX, $maxY, $scalingUp, $this->fileView);
if (!($preview instanceof \OC_Image)) {
@@ -484,7 +515,6 @@ class Preview {
$this->getPreview();
}
$this->preview->show('image/png');
- return;
}
/**
@@ -493,7 +523,6 @@ class Preview {
*/
public function show() {
$this->showPreview();
- return;
}
/**
@@ -505,7 +534,7 @@ class Preview {
$x = $this->getMaxX();
$y = $this->getMaxY();
$scalingUp = $this->getScalingUp();
- $maxscalefactor = $this->getMaxScaleFactor();
+ $maxScaleFactor = $this->getMaxScaleFactor();
if (!($image instanceof \OC_Image)) {
\OC_Log::write('core', '$this->preview is not an instance of OC_Image', \OC_Log::DEBUG);
@@ -514,16 +543,16 @@ class Preview {
$image->fixOrientation();
- $realx = (int)$image->width();
- $realy = (int)$image->height();
+ $realX = (int)$image->width();
+ $realY = (int)$image->height();
- if ($x === $realx && $y === $realy) {
+ if ($x === $realX && $y === $realY) {
$this->preview = $image;
return;
}
- $factorX = $x / $realx;
- $factorY = $y / $realy;
+ $factorX = $x / $realX;
+ $factorY = $y / $realY;
if ($factorX >= $factorY) {
$factor = $factorX;
@@ -537,25 +566,25 @@ class Preview {
}
}
- if (!is_null($maxscalefactor)) {
- if ($factor > $maxscalefactor) {
- \OC_Log::write('core', 'scalefactor reduced from ' . $factor . ' to ' . $maxscalefactor, \OC_Log::DEBUG);
- $factor = $maxscalefactor;
+ if (!is_null($maxScaleFactor)) {
+ if ($factor > $maxScaleFactor) {
+ \OC_Log::write('core', 'scale factor reduced from ' . $factor . ' to ' . $maxScaleFactor, \OC_Log::DEBUG);
+ $factor = $maxScaleFactor;
}
}
- $newXsize = (int)($realx * $factor);
- $newYsize = (int)($realy * $factor);
+ $newXSize = (int)($realX * $factor);
+ $newYSize = (int)($realY * $factor);
- $image->preciseResize($newXsize, $newYsize);
+ $image->preciseResize($newXSize, $newYSize);
- if ($newXsize === $x && $newYsize === $y) {
+ if ($newXSize === $x && $newYSize === $y) {
$this->preview = $image;
return;
}
- if ($newXsize >= $x && $newYsize >= $y) {
- $cropX = floor(abs($x - $newXsize) * 0.5);
+ if ($newXSize >= $x && $newYSize >= $y) {
+ $cropX = floor(abs($x - $newXSize) * 0.5);
//don't crop previews on the Y axis, this sucks if it's a document.
//$cropY = floor(abs($y - $newYsize) * 0.5);
$cropY = 0;
@@ -566,36 +595,36 @@ class Preview {
return;
}
- if ($newXsize < $x || $newYsize < $y) {
- if ($newXsize > $x) {
- $cropX = floor(($newXsize - $x) * 0.5);
- $image->crop($cropX, 0, $x, $newYsize);
+ if ($newXSize < $x || $newYSize < $y) {
+ if ($newXSize > $x) {
+ $cropX = floor(($newXSize - $x) * 0.5);
+ $image->crop($cropX, 0, $x, $newYSize);
}
- if ($newYsize > $y) {
- $cropY = floor(($newYsize - $y) * 0.5);
- $image->crop(0, $cropY, $newXsize, $y);
+ if ($newYSize > $y) {
+ $cropY = floor(($newYSize - $y) * 0.5);
+ $image->crop(0, $cropY, $newXSize, $y);
}
- $newXsize = (int)$image->width();
- $newYsize = (int)$image->height();
+ $newXSize = (int)$image->width();
+ $newYSize = (int)$image->height();
//create transparent background layer
- $backgroundlayer = imagecreatetruecolor($x, $y);
- $white = imagecolorallocate($backgroundlayer, 255, 255, 255);
- imagefill($backgroundlayer, 0, 0, $white);
+ $backgroundLayer = imagecreatetruecolor($x, $y);
+ $white = imagecolorallocate($backgroundLayer, 255, 255, 255);
+ imagefill($backgroundLayer, 0, 0, $white);
$image = $image->resource();
- $mergeX = floor(abs($x - $newXsize) * 0.5);
- $mergeY = floor(abs($y - $newYsize) * 0.5);
+ $mergeX = floor(abs($x - $newXSize) * 0.5);
+ $mergeY = floor(abs($y - $newYSize) * 0.5);
- imagecopy($backgroundlayer, $image, $mergeX, $mergeY, 0, 0, $newXsize, $newYsize);
+ imagecopy($backgroundLayer, $image, $mergeX, $mergeY, 0, 0, $newXSize, $newYSize);
//$black = imagecolorallocate(0,0,0);
//imagecolortransparent($transparentlayer, $black);
- $image = new \OC_Image($backgroundlayer);
+ $image = new \OC_Image($backgroundLayer);
$this->preview = $image;
return;
@@ -630,6 +659,7 @@ class Preview {
$class = $provider['class'];
$options = $provider['options'];
+ /** @var $object Provider */
$object = new $class($options);
self::$providers[$object->getMimeType()] = $object;
@@ -640,7 +670,7 @@ class Preview {
}
public static function post_write($args) {
- self::post_delete($args);
+ self::post_delete($args, 'files/');
}
public static function prepare_delete_files($args) {
@@ -676,9 +706,9 @@ class Preview {
}
/**
- * @param string $mimetype
+ * @param string $mimeType
*/
- public static function isMimeSupported($mimetype) {
+ public static function isMimeSupported($mimeType) {
if (!\OC_Config::getValue('enable_previews', true)) {
return false;
}
@@ -690,8 +720,8 @@ class Preview {
//remove last element because it has the mimetype *
$providers = array_slice(self::$providers, 0, -1);
- foreach ($providers as $supportedMimetype => $provider) {
- if (preg_match($supportedMimetype, $mimetype)) {
+ foreach ($providers as $supportedMimeType => $provider) {
+ if (preg_match($supportedMimeType, $mimeType)) {
return true;
}
}
diff --git a/lib/private/request.php b/lib/private/request.php
index 8041c4f0048..7cbbb0676b1 100755
--- a/lib/private/request.php
+++ b/lib/private/request.php
@@ -166,10 +166,11 @@ class OC_Request {
*/
public static function scriptName() {
$name = $_SERVER['SCRIPT_NAME'];
- if (OC_Config::getValue('overwritewebroot', '') !== '' and self::isOverwriteCondition()) {
+ $overwriteWebRoot = OC_Config::getValue('overwritewebroot', '');
+ if ($overwriteWebRoot !== '' and self::isOverwriteCondition()) {
$serverroot = str_replace("\\", '/', substr(__DIR__, 0, -strlen('lib/private/')));
$suburi = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen($serverroot)));
- $name = OC_Config::getValue('overwritewebroot', '') . $suburi;
+ $name = '/' . ltrim($overwriteWebRoot . $suburi, '/');
}
return $name;
}
diff --git a/lib/private/route/router.php b/lib/private/route/router.php
index bad74c925fa..fa0ad6ab95b 100644
--- a/lib/private/route/router.php
+++ b/lib/private/route/router.php
@@ -114,10 +114,10 @@ class Router implements IRouter {
}
}
foreach ($routingFiles as $app => $file) {
- if (!$this->loadedApps[$app]) {
+ if (!isset($this->loadedApps[$app])) {
$this->loadedApps[$app] = true;
$this->useCollection($app);
- require_once $file;
+ $this->requireRouteFile($file);
$collection = $this->getCollection($app);
$collection->addPrefix('/apps/' . $app);
$this->root->addCollection($collection);
@@ -183,7 +183,7 @@ class Router implements IRouter {
// empty string / 'apps' / $app / rest of the route
list(, , $app,) = explode('/', $url, 4);
$this->loadRoutes($app);
- } else if (substr($url, 0, 6) === '/core/' or substr($url, 0, 5) === '/ocs/' or substr($url, 0, 10) === '/settings/') {
+ } else if (substr($url, 0, 6) === '/core/' or substr($url, 0, 10) === '/settings/') {
$this->loadRoutes('core');
} else {
$this->loadRoutes();
@@ -230,4 +230,12 @@ class Router implements IRouter {
return $this->getGenerator()->generate($name, $parameters, $absolute);
}
+ /**
+ * To isolate the variable scope used inside the $file it is required in it's own method
+ * @param $file
+ */
+ private function requireRouteFile($file) {
+ require_once $file;
+ }
+
}
diff --git a/lib/private/server.php b/lib/private/server.php
index 5c83f3ef495..5d90a0b19fc 100644
--- a/lib/private/server.php
+++ b/lib/private/server.php
@@ -35,6 +35,13 @@ class Server extends SimpleContainer implements IServerContainer {
$requesttoken = false;
}
+ if (defined('PHPUNIT_RUN') && PHPUNIT_RUN
+ && in_array('fakeinput', stream_get_wrappers())) {
+ $stream = 'fakeinput://data';
+ } else {
+ $stream = 'php://input';
+ }
+
return new Request(
array(
'get' => $_GET,
@@ -48,7 +55,7 @@ class Server extends SimpleContainer implements IServerContainer {
: null,
'urlParams' => $urlParams,
'requesttoken' => $requesttoken,
- )
+ ), $stream
);
});
$this->registerService('PreviewManager', function($c) {
@@ -302,7 +309,7 @@ class Server extends SimpleContainer implements IServerContainer {
/**
* get an L10N instance
- * @param $app string appid
+ * @param string $app appid
* @return \OC_L10N
*/
function getL10N($app) {
diff --git a/lib/private/share/constants.php b/lib/private/share/constants.php
new file mode 100644
index 00000000000..7e4223d10fa
--- /dev/null
+++ b/lib/private/share/constants.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Bjoern Schiessle
+ * @copyright 2014 Bjoern Schiessle <schiessle@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/>.
+ */
+
+namespace OC\Share;
+
+class Constants {
+
+ const SHARE_TYPE_USER = 0;
+ const SHARE_TYPE_GROUP = 1;
+ const SHARE_TYPE_LINK = 3;
+ const SHARE_TYPE_EMAIL = 4;
+ const SHARE_TYPE_CONTACT = 5;
+ const SHARE_TYPE_REMOTE = 6;
+
+ const FORMAT_NONE = -1;
+ const FORMAT_STATUSES = -2;
+ const FORMAT_SOURCES = -3;
+
+ const TOKEN_LENGTH = 32; // see db_structure.xml
+
+ protected static $shareTypeUserAndGroups = -1;
+ protected static $shareTypeGroupUserUnique = 2;
+ protected static $backends = array();
+ protected static $backendTypes = array();
+ protected static $isResharingAllowed;
+}
diff --git a/lib/private/share/helper.php b/lib/private/share/helper.php
new file mode 100644
index 00000000000..fde55667281
--- /dev/null
+++ b/lib/private/share/helper.php
@@ -0,0 +1,202 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Bjoern Schiessle
+ * @copyright 2014 Bjoern Schiessle <schiessle@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/>.
+ */
+
+namespace OC\Share;
+
+class Helper extends \OC\Share\Constants {
+
+ /**
+ * Generate a unique target for the item
+ * @param string Item type
+ * @param string Item source
+ * @param int SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
+ * @param string User or group the item is being shared with
+ * @param string User that is the owner of shared item
+ * @param string The suggested target originating from a reshare (optional)
+ * @param int The id of the parent group share (optional)
+ * @return string Item target
+ */
+ public static function generateTarget($itemType, $itemSource, $shareType, $shareWith, $uidOwner,
+ $suggestedTarget = null, $groupParent = null) {
+ $backend = \OC\Share\Share::getBackend($itemType);
+ if ($shareType == self::SHARE_TYPE_LINK) {
+ if (isset($suggestedTarget)) {
+ return $suggestedTarget;
+ }
+ return $backend->generateTarget($itemSource, false);
+ } else {
+ if ($itemType == 'file' || $itemType == 'folder') {
+ $column = 'file_target';
+ $columnSource = 'file_source';
+ } else {
+ $column = 'item_target';
+ $columnSource = 'item_source';
+ }
+ if ($shareType == self::SHARE_TYPE_USER) {
+ // Share with is a user, so set share type to user and groups
+ $shareType = self::$shareTypeUserAndGroups;
+ $userAndGroups = array_merge(array($shareWith), \OC_Group::getUserGroups($shareWith));
+ } else {
+ $userAndGroups = false;
+ }
+ $exclude = null;
+ // Backend has 3 opportunities to generate a unique target
+ for ($i = 0; $i < 2; $i++) {
+ // Check if suggested target exists first
+ if ($i == 0 && isset($suggestedTarget)) {
+ $target = $suggestedTarget;
+ } else {
+ if ($shareType == self::SHARE_TYPE_GROUP) {
+ $target = $backend->generateTarget($itemSource, false, $exclude);
+ } else {
+ $target = $backend->generateTarget($itemSource, $shareWith, $exclude);
+ }
+ if (is_array($exclude) && in_array($target, $exclude)) {
+ break;
+ }
+ }
+ // Check if target already exists
+ $checkTarget = \OC\Share\Share::getItems($itemType, $target, $shareType, $shareWith);
+ if (!empty($checkTarget)) {
+ foreach ($checkTarget as $item) {
+ // Skip item if it is the group parent row
+ if (isset($groupParent) && $item['id'] == $groupParent) {
+ if (count($checkTarget) == 1) {
+ return $target;
+ } else {
+ continue;
+ }
+ }
+ if ($item['uid_owner'] == $uidOwner) {
+ if ($itemType == 'file' || $itemType == 'folder') {
+ $meta = \OC\Files\Filesystem::getFileInfo($itemSource);
+ if ($item['file_source'] == $meta['fileid']) {
+ return $target;
+ }
+ } else if ($item['item_source'] == $itemSource) {
+ return $target;
+ }
+ }
+ }
+ if (!isset($exclude)) {
+ $exclude = array();
+ }
+ // Find similar targets to improve backend's chances to generate a unqiue target
+ if ($userAndGroups) {
+ if ($column == 'file_target') {
+ $checkTargets = \OC_DB::prepare('SELECT `'.$column.'` FROM `*PREFIX*share`'
+ .' WHERE `item_type` IN (\'file\', \'folder\')'
+ .' AND `share_type` IN (?,?,?)'
+ .' AND `share_with` IN (\''.implode('\',\'', $userAndGroups).'\')');
+ $result = $checkTargets->execute(array(self::SHARE_TYPE_USER, self::SHARE_TYPE_GROUP,
+ self::$shareTypeGroupUserUnique));
+ } else {
+ $checkTargets = \OC_DB::prepare('SELECT `'.$column.'` FROM `*PREFIX*share`'
+ .' WHERE `item_type` = ? AND `share_type` IN (?,?,?)'
+ .' AND `share_with` IN (\''.implode('\',\'', $userAndGroups).'\')');
+ $result = $checkTargets->execute(array($itemType, self::SHARE_TYPE_USER,
+ self::SHARE_TYPE_GROUP, self::$shareTypeGroupUserUnique));
+ }
+ } else {
+ if ($column == 'file_target') {
+ $checkTargets = \OC_DB::prepare('SELECT `'.$column.'` FROM `*PREFIX*share`'
+ .' WHERE `item_type` IN (\'file\', \'folder\')'
+ .' AND `share_type` = ? AND `share_with` = ?');
+ $result = $checkTargets->execute(array(self::SHARE_TYPE_GROUP, $shareWith));
+ } else {
+ $checkTargets = \OC_DB::prepare('SELECT `'.$column.'` FROM `*PREFIX*share`'
+ .' WHERE `item_type` = ? AND `share_type` = ? AND `share_with` = ?');
+ $result = $checkTargets->execute(array($itemType, self::SHARE_TYPE_GROUP, $shareWith));
+ }
+ }
+ while ($row = $result->fetchRow()) {
+ $exclude[] = $row[$column];
+ }
+ } else {
+ return $target;
+ }
+ }
+ }
+ $message = 'Sharing backend registered for '.$itemType.' did not generate a unique target for '.$itemSource;
+ \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
+ throw new \Exception($message);
+ }
+
+ /**
+ * Delete all reshares of an item
+ * @param int Id of item to delete
+ * @param bool If true, exclude the parent from the delete (optional)
+ * @param string The user that the parent was shared with (optinal)
+ */
+ public static function delete($parent, $excludeParent = false, $uidOwner = null) {
+ $ids = array($parent);
+ $parents = array($parent);
+ while (!empty($parents)) {
+ $parents = "'".implode("','", $parents)."'";
+ // Check the owner on the first search of reshares, useful for
+ // finding and deleting the reshares by a single user of a group share
+ if (count($ids) == 1 && isset($uidOwner)) {
+ $query = \OC_DB::prepare('SELECT `id`, `uid_owner`, `item_type`, `item_target`, `parent`'
+ .' FROM `*PREFIX*share` WHERE `parent` IN ('.$parents.') AND `uid_owner` = ?');
+ $result = $query->execute(array($uidOwner));
+ } else {
+ $query = \OC_DB::prepare('SELECT `id`, `item_type`, `item_target`, `parent`, `uid_owner`'
+ .' FROM `*PREFIX*share` WHERE `parent` IN ('.$parents.')');
+ $result = $query->execute();
+ }
+ // Reset parents array, only go through loop again if items are found
+ $parents = array();
+ while ($item = $result->fetchRow()) {
+ // Search for a duplicate parent share, this occurs when an
+ // item is shared to the same user through a group and user or the
+ // same item is shared by different users
+ $userAndGroups = array_merge(array($item['uid_owner']), \OC_Group::getUserGroups($item['uid_owner']));
+ $query = \OC_DB::prepare('SELECT `id`, `permissions` FROM `*PREFIX*share`'
+ .' WHERE `item_type` = ?'
+ .' AND `item_target` = ?'
+ .' AND `share_type` IN (?,?,?)'
+ .' AND `share_with` IN (\''.implode('\',\'', $userAndGroups).'\')'
+ .' AND `uid_owner` != ? AND `id` != ?');
+ $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'] & \OCP\PERMISSION_SHARE) {
+ $query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `parent` = ? WHERE `id` = ?');
+ $query->execute(array($duplicateParent['id'], $item['id']));
+ continue;
+ }
+ }
+ $ids[] = $item['id'];
+ $parents[] = $item['id'];
+ }
+ }
+ if ($excludeParent) {
+ unset($ids[0]);
+ }
+ if (!empty($ids)) {
+ $ids = "'".implode("','", $ids)."'";
+ $query = \OC_DB::prepare('DELETE FROM `*PREFIX*share` WHERE `id` IN ('.$ids.')');
+ $query->execute();
+ }
+ }
+}
diff --git a/lib/private/share/hooks.php b/lib/private/share/hooks.php
new file mode 100644
index 00000000000..a33c71eedd2
--- /dev/null
+++ b/lib/private/share/hooks.php
@@ -0,0 +1,108 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Bjoern Schiessle
+ * @copyright 2014 Bjoern Schiessle <schiessle@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/>.
+ */
+
+namespace OC\Share;
+
+class Hooks extends \OC\Share\Constants {
+ /**
+ * Function that is called after a user is deleted. Cleans up the shares of that user.
+ * @param array arguments
+ */
+ public static function post_deleteUser($arguments) {
+ // Delete any items shared with the deleted user
+ $query = \OC_DB::prepare('DELETE FROM `*PREFIX*share`'
+ .' WHERE `share_with` = ? AND `share_type` = ? OR `share_type` = ?');
+ $result = $query->execute(array($arguments['uid'], self::SHARE_TYPE_USER, self::$shareTypeGroupUserUnique));
+ // Delete any items the deleted user shared
+ $query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*share` WHERE `uid_owner` = ?');
+ $result = $query->execute(array($arguments['uid']));
+ while ($item = $result->fetchRow()) {
+ Helper::delete($item['id']);
+ }
+ }
+
+ /**
+ * Function that is called after a user is added to a group.
+ * TODO what does it do?
+ * @param array arguments
+ */
+ public static function post_addToGroup($arguments) {
+ // Find the group shares and check if the user needs a unique target
+ $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share` WHERE `share_type` = ? AND `share_with` = ?');
+ $result = $query->execute(array(self::SHARE_TYPE_GROUP, $arguments['gid']));
+ $query = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`item_type`, `item_source`,'
+ .' `item_target`, `parent`, `share_type`, `share_with`, `uid_owner`, `permissions`,'
+ .' `stime`, `file_source`, `file_target`) VALUES (?,?,?,?,?,?,?,?,?,?,?)');
+ while ($item = $result->fetchRow()) {
+ if ($item['item_type'] == 'file' || $item['item_type'] == 'file') {
+ $itemTarget = null;
+ } else {
+ $itemTarget = Helper::generateTarget($item['item_type'], $item['item_source'], self::SHARE_TYPE_USER,
+ $arguments['uid'], $item['uid_owner'], $item['item_target'], $item['id']);
+ }
+ if (isset($item['file_source'])) {
+ $fileTarget = Helper::generateTarget($item['item_type'], $item['item_source'], self::SHARE_TYPE_USER,
+ $arguments['uid'], $item['uid_owner'], $item['file_target'], $item['id']);
+ } else {
+ $fileTarget = null;
+ }
+ // Insert an extra row for the group share if the item or file target is unique for this user
+ if ($itemTarget != $item['item_target'] || $fileTarget != $item['file_target']) {
+ $query->execute(array($item['item_type'], $item['item_source'], $itemTarget, $item['id'],
+ self::$shareTypeGroupUserUnique, $arguments['uid'], $item['uid_owner'], $item['permissions'],
+ $item['stime'], $item['file_source'], $fileTarget));
+ \OC_DB::insertid('*PREFIX*share');
+ }
+ }
+ }
+
+ /**
+ * Function that is called after a user is removed from a group. Shares are cleaned up.
+ * @param array arguments
+ */
+ public static function post_removeFromGroup($arguments) {
+ $sql = 'SELECT `id`, `share_type` FROM `*PREFIX*share`'
+ .' WHERE (`share_type` = ? AND `share_with` = ?) OR (`share_type` = ? AND `share_with` = ?)';
+ $result = \OC_DB::executeAudited($sql, array(self::SHARE_TYPE_GROUP, $arguments['gid'],
+ self::$shareTypeGroupUserUnique, $arguments['uid']));
+ while ($item = $result->fetchRow()) {
+ if ($item['share_type'] == self::SHARE_TYPE_GROUP) {
+ // Delete all reshares by this user of the group share
+ Helper::delete($item['id'], true, $arguments['uid']);
+ } else {
+ Helper::delete($item['id']);
+ }
+ }
+ }
+
+ /**
+ * Function that is called after a group is removed. Cleans up the shares to that group.
+ * @param array arguments
+ */
+ public static function post_deleteGroup($arguments) {
+ $sql = 'SELECT `id` FROM `*PREFIX*share` WHERE `share_type` = ? AND `share_with` = ?';
+ $result = \OC_DB::executeAudited($sql, array(self::SHARE_TYPE_GROUP, $arguments['gid']));
+ while ($item = $result->fetchRow()) {
+ Helper::delete($item['id']);
+ }
+ }
+
+}
diff --git a/lib/private/share/mailnotifications.php b/lib/private/share/mailnotifications.php
index 45734818731..4799db52330 100644
--- a/lib/private/share/mailnotifications.php
+++ b/lib/private/share/mailnotifications.php
@@ -30,7 +30,6 @@ class MailNotifications {
/**
*
- * @param string $recipient user id
* @param string $sender user id (if nothing is set we use the currently logged-in user)
*/
public function __construct($sender = null) {
diff --git a/lib/private/share/share.php b/lib/private/share/share.php
new file mode 100644
index 00000000000..d4f08e8e016
--- /dev/null
+++ b/lib/private/share/share.php
@@ -0,0 +1,1629 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Bjoern Schiessle, Michael Gapczynski
+ * @copyright 2012 Michael Gapczynski <mtgap@owncloud.com>
+ * 2014 Bjoern Schiessle <schiessle@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/>.
+ */
+
+namespace OC\Share;
+
+/**
+ * This class provides the ability for apps to share their content between users.
+ * Apps must create a backend class that implements OCP\Share_Backend and register it with this class.
+ *
+ * It provides the following hooks:
+ * - post_shared
+ */
+class Share extends \OC\Share\Constants {
+
+ /** CRUDS permissions (Create, Read, Update, Delete, Share) using a bitmask
+ * Construct permissions for share() and setPermissions with Or (|) e.g.
+ * Give user read and update permissions: PERMISSION_READ | PERMISSION_UPDATE
+ *
+ * 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
+ */
+
+ /**
+ * Register a sharing backend class that implements OCP\Share_Backend for an item type
+ * @param string Item type
+ * @param string Backend class
+ * @param string (optional) Depends on item type
+ * @param array (optional) List of supported file extensions if this item type depends on files
+ * @return Returns true if backend is registered or false if error
+ */
+ public static function registerBackend($itemType, $class, $collectionOf = null, $supportedFileExtensions = null) {
+ if (self::isEnabled()) {
+ if (!isset(self::$backendTypes[$itemType])) {
+ self::$backendTypes[$itemType] = array(
+ 'class' => $class,
+ 'collectionOf' => $collectionOf,
+ 'supportedFileExtensions' => $supportedFileExtensions
+ );
+ if(count(self::$backendTypes) === 1) {
+ \OC_Util::addScript('core', 'share');
+ \OC_Util::addStyle('core', 'share');
+ }
+ return true;
+ }
+ \OC_Log::write('OCP\Share',
+ 'Sharing backend '.$class.' not registered, '.self::$backendTypes[$itemType]['class']
+ .' is already registered for '.$itemType,
+ \OC_Log::WARN);
+ }
+ return false;
+ }
+
+ /**
+ * Check if the Share API is enabled
+ * @return Returns true if enabled or false
+ *
+ * The Share API is enabled by default if not configured
+ */
+ public static function isEnabled() {
+ if (\OC_Appconfig::getValue('core', 'shareapi_enabled', 'yes') == 'yes') {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Find which users can access a shared item
+ * @param $path to the file
+ * @param $user owner of the file
+ * @param include owner to the list of users with access to the file
+ * @return array
+ * @note $path needs to be relative to user data dir, e.g. 'file.txt'
+ * not '/admin/data/file.txt'
+ */
+ public static function getUsersSharingFile($path, $user, $includeOwner = false) {
+
+ $shares = array();
+ $publicShare = false;
+ $source = -1;
+ $cache = false;
+
+ $view = new \OC\Files\View('/' . $user . '/files');
+ if ($view->file_exists($path)) {
+ $meta = $view->getFileInfo($path);
+ } else {
+ // if the file doesn't exists yet we start with the parent folder
+ $meta = $view->getFileInfo(dirname($path));
+ }
+
+ if($meta !== false) {
+ $source = $meta['fileid'];
+ $cache = new \OC\Files\Cache\Cache($meta['storage']);
+ }
+
+ while ($source !== -1) {
+
+ // Fetch all shares with another user
+ $query = \OC_DB::prepare(
+ 'SELECT `share_with`
+ FROM
+ `*PREFIX*share`
+ WHERE
+ `item_source` = ? AND `share_type` = ? AND `item_type` IN (\'file\', \'folder\')'
+ );
+
+ $result = $query->execute(array($source, self::SHARE_TYPE_USER));
+
+ if (\OCP\DB::isError($result)) {
+ \OCP\Util::writeLog('OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR);
+ } else {
+ while ($row = $result->fetchRow()) {
+ $shares[] = $row['share_with'];
+ }
+ }
+ // We also need to take group shares into account
+
+ $query = \OC_DB::prepare(
+ 'SELECT `share_with`
+ FROM
+ `*PREFIX*share`
+ WHERE
+ `item_source` = ? AND `share_type` = ? AND `item_type` IN (\'file\', \'folder\')'
+ );
+
+ $result = $query->execute(array($source, self::SHARE_TYPE_GROUP));
+
+ if (\OCP\DB::isError($result)) {
+ \OCP\Util::writeLog('OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR);
+ } else {
+ while ($row = $result->fetchRow()) {
+ $usersInGroup = \OC_Group::usersInGroup($row['share_with']);
+ $shares = array_merge($shares, $usersInGroup);
+ }
+ }
+
+ //check for public link shares
+ if (!$publicShare) {
+ $query = \OC_DB::prepare(
+ 'SELECT `share_with`
+ FROM
+ `*PREFIX*share`
+ WHERE
+ `item_source` = ? AND `share_type` = ? AND `item_type` IN (\'file\', \'folder\')'
+ );
+
+ $result = $query->execute(array($source, self::SHARE_TYPE_LINK));
+
+ if (\OCP\DB::isError($result)) {
+ \OCP\Util::writeLog('OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR);
+ } else {
+ if ($result->fetchRow()) {
+ $publicShare = true;
+ }
+ }
+ }
+
+ // let's get the parent for the next round
+ $meta = $cache->get((int)$source);
+ if($meta !== false) {
+ $source = (int)$meta['parent'];
+ } else {
+ $source = -1;
+ }
+ }
+ // Include owner in list of users, if requested
+ if ($includeOwner) {
+ $shares[] = $user;
+ }
+
+ return array("users" => array_unique($shares), "public" => $publicShare);
+ }
+
+ /**
+ * Get the items of item type shared with the current user
+ * @param string Item type
+ * @param int Format (optional) Format type must be defined by the backend
+ * @param mixed Parameters (optional)
+ * @param int Number of items to return (optional) Returns all by default
+ * @param bool include collections (optional)
+ * @return Return depends on format
+ */
+ public static function getItemsSharedWith($itemType, $format = self::FORMAT_NONE,
+ $parameters = null, $limit = -1, $includeCollections = false) {
+ return self::getItems($itemType, null, self::$shareTypeUserAndGroups, \OC_User::getUser(), null, $format,
+ $parameters, $limit, $includeCollections);
+ }
+
+ /**
+ * Get the item of item type shared with the current user
+ * @param string $itemType
+ * @param string $itemTarget
+ * @param int $format (optional) Format type must be defined by the backend
+ * @param mixed Parameters (optional)
+ * @param bool include collections (optional)
+ * @return Return depends on format
+ */
+ public static function getItemSharedWith($itemType, $itemTarget, $format = self::FORMAT_NONE,
+ $parameters = null, $includeCollections = false) {
+ return self::getItems($itemType, $itemTarget, self::$shareTypeUserAndGroups, \OC_User::getUser(), null, $format,
+ $parameters, 1, $includeCollections);
+ }
+
+ /**
+ * Get the item of item type shared with a given user by source
+ * @param string $itemType
+ * @param string $itemSource
+ * @param string $user User user to whom the item was shared
+ * @return array Return list of items with file_target, permissions and expiration
+ */
+ public static function getItemSharedWithUser($itemType, $itemSource, $user) {
+
+ $shares = array();
+
+ // first check if there is a db entry for the specific user
+ $query = \OC_DB::prepare(
+ 'SELECT `file_target`, `permissions`, `expiration`
+ FROM
+ `*PREFIX*share`
+ WHERE
+ `item_source` = ? AND `item_type` = ? AND `share_with` = ?'
+ );
+
+ $result = \OC_DB::executeAudited($query, array($itemSource, $itemType, $user));
+
+ while ($row = $result->fetchRow()) {
+ $shares[] = $row;
+ }
+
+ //if didn't found a result than let's look for a group share.
+ if(empty($shares)) {
+ $groups = \OC_Group::getUserGroups($user);
+
+ $query = \OC_DB::prepare(
+ 'SELECT `file_target`, `permissions`, `expiration`
+ FROM
+ `*PREFIX*share`
+ WHERE
+ `item_source` = ? AND `item_type` = ? AND `share_with` in (?)'
+ );
+
+ $result = \OC_DB::executeAudited($query, array($itemSource, $itemType, implode(',', $groups)));
+
+ while ($row = $result->fetchRow()) {
+ $shares[] = $row;
+ }
+ }
+
+ return $shares;
+
+ }
+
+ /**
+ * Get the item of item type shared with the current user by source
+ * @param string Item type
+ * @param string Item source
+ * @param int Format (optional) Format type must be defined by the backend
+ * @param mixed Parameters
+ * @param bool include collections
+ * @return Return depends on format
+ */
+ public static function getItemSharedWithBySource($itemType, $itemSource, $format = self::FORMAT_NONE,
+ $parameters = null, $includeCollections = false) {
+ return self::getItems($itemType, $itemSource, self::$shareTypeUserAndGroups, \OC_User::getUser(), null, $format,
+ $parameters, 1, $includeCollections, true);
+ }
+
+ /**
+ * Get the item of item type shared by a link
+ * @param string Item type
+ * @param string Item source
+ * @param string Owner of link
+ * @return Item
+ */
+ public static function getItemSharedWithByLink($itemType, $itemSource, $uidOwner) {
+ return self::getItems($itemType, $itemSource, self::SHARE_TYPE_LINK, null, $uidOwner, self::FORMAT_NONE,
+ null, 1);
+ }
+
+ /**
+ * Based on the given token the share information will be returned - password protected shares will be verified
+ * @param string $token
+ * @return array | bool false will be returned in case the token is unknown or unauthorized
+ */
+ public static function getShareByToken($token, $checkPasswordProtection = true) {
+ $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share` WHERE `token` = ?', 1);
+ $result = $query->execute(array($token));
+ if (\OC_DB::isError($result)) {
+ \OC_Log::write('OCP\Share', \OC_DB::getErrorMessage($result) . ', token=' . $token, \OC_Log::ERROR);
+ }
+ $row = $result->fetchRow();
+ if ($row === false) {
+ return false;
+ }
+ if (is_array($row) and self::expireItem($row)) {
+ return false;
+ }
+
+ // password protected shares need to be authenticated
+ if ($checkPasswordProtection && !\OCP\Share::checkPasswordProtectedShare($row)) {
+ return false;
+ }
+
+ return $row;
+ }
+
+ /**
+ * resolves reshares down to the last real share
+ * @param $linkItem
+ * @return $fileOwner
+ */
+ public static function resolveReShare($linkItem)
+ {
+ if (isset($linkItem['parent'])) {
+ $parent = $linkItem['parent'];
+ while (isset($parent)) {
+ $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share` WHERE `id` = ?', 1);
+ $item = $query->execute(array($parent))->fetchRow();
+ if (isset($item['parent'])) {
+ $parent = $item['parent'];
+ } else {
+ return $item;
+ }
+ }
+ }
+ return $linkItem;
+ }
+
+
+ /**
+ * Get the shared items of item type owned by the current user
+ * @param string Item type
+ * @param int Format (optional) Format type must be defined by the backend
+ * @param mixed Parameters
+ * @param int Number of items to return (optional) Returns all by default
+ * @param bool include collections
+ * @return Return depends on format
+ */
+ public static function getItemsShared($itemType, $format = self::FORMAT_NONE, $parameters = null,
+ $limit = -1, $includeCollections = false) {
+ return self::getItems($itemType, null, null, null, \OC_User::getUser(), $format,
+ $parameters, $limit, $includeCollections);
+ }
+
+ /**
+ * Get the shared item of item type owned by the current user
+ * @param string Item type
+ * @param string Item source
+ * @param int Format (optional) Format type must be defined by the backend
+ * @param mixed Parameters
+ * @param bool include collections
+ * @return Return depends on format
+ */
+ public static function getItemShared($itemType, $itemSource, $format = self::FORMAT_NONE,
+ $parameters = null, $includeCollections = false) {
+ return self::getItems($itemType, $itemSource, null, null, \OC_User::getUser(), $format,
+ $parameters, -1, $includeCollections);
+ }
+
+ /**
+ * Get all users an item is shared with
+ * @param string Item type
+ * @param string Item source
+ * @param string Owner
+ * @param bool Include collections
+ * @praram bool check expire date
+ * @return Return array of users
+ */
+ public static function getUsersItemShared($itemType, $itemSource, $uidOwner, $includeCollections = false, $checkExpireDate = true) {
+
+ $users = array();
+ $items = self::getItems($itemType, $itemSource, null, null, $uidOwner, self::FORMAT_NONE, null, -1, $includeCollections, false, $checkExpireDate);
+ if ($items) {
+ foreach ($items as $item) {
+ if ((int)$item['share_type'] === self::SHARE_TYPE_USER) {
+ $users[] = $item['share_with'];
+ } else if ((int)$item['share_type'] === self::SHARE_TYPE_GROUP) {
+ $users = array_merge($users, \OC_Group::usersInGroup($item['share_with']));
+ }
+ }
+ }
+ return $users;
+ }
+
+ /**
+ * Share an item with a user, group, or via private link
+ * @param string $itemType
+ * @param string $itemSource
+ * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
+ * @param string $shareWith User or group the item is being shared with
+ * @param int $permissions CRUDS
+ * @param null $itemSourceName
+ * @throws \Exception
+ * @internal param \OCP\Item $string type
+ * @internal param \OCP\Item $string source
+ * @internal param \OCP\SHARE_TYPE_USER $int , SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
+ * @internal param \OCP\User $string or group the item is being shared with
+ * @internal param \OCP\CRUDS $int permissions
+ * @return bool|string Returns true on success or false on failure, Returns token on success for links
+ */
+ public static function shareItem($itemType, $itemSource, $shareType, $shareWith, $permissions, $itemSourceName = null) {
+ $uidOwner = \OC_User::getUser();
+ $sharingPolicy = \OC_Appconfig::getValue('core', 'shareapi_share_policy', 'global');
+
+ if (is_null($itemSourceName)) {
+ $itemSourceName = $itemSource;
+ }
+
+ // verify that the file exists before we try to share it
+ if ($itemType === 'file' or $itemType === 'folder') {
+ $path = \OC\Files\Filesystem::getPath($itemSource);
+ if (!$path) {
+ $message = 'Sharing ' . $itemSourceName . ' failed, because the file does not exist';
+ \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
+ throw new \Exception($message);
+ }
+ }
+
+ // Verify share type and sharing conditions are met
+ if ($shareType === self::SHARE_TYPE_USER) {
+ if ($shareWith == $uidOwner) {
+ $message = 'Sharing '.$itemSourceName.' failed, because the user '.$shareWith.' is the item owner';
+ \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
+ throw new \Exception($message);
+ }
+ if (!\OC_User::userExists($shareWith)) {
+ $message = 'Sharing '.$itemSourceName.' failed, because the user '.$shareWith.' does not exist';
+ \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
+ throw new \Exception($message);
+ }
+ if ($sharingPolicy == 'groups_only') {
+ $inGroup = array_intersect(\OC_Group::getUserGroups($uidOwner), \OC_Group::getUserGroups($shareWith));
+ if (empty($inGroup)) {
+ $message = 'Sharing '.$itemSourceName.' failed, because the user '
+ .$shareWith.' is not a member of any groups that '.$uidOwner.' is a member of';
+ \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
+ throw new \Exception($message);
+ }
+ }
+ // Check if the item source is already shared with the user, either from the same owner or a different user
+ if ($checkExists = self::getItems($itemType, $itemSource, self::$shareTypeUserAndGroups,
+ $shareWith, null, self::FORMAT_NONE, null, 1, true, true)) {
+ // Only allow the same share to occur again if it is the same
+ // owner and is not a user share, this use case is for increasing
+ // permissions for a specific user
+ if ($checkExists['uid_owner'] != $uidOwner || $checkExists['share_type'] == $shareType) {
+ $message = 'Sharing '.$itemSourceName.' failed, because this item is already shared with '.$shareWith;
+ \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
+ throw new \Exception($message);
+ }
+ }
+ } else if ($shareType === self::SHARE_TYPE_GROUP) {
+ if (!\OC_Group::groupExists($shareWith)) {
+ $message = 'Sharing '.$itemSourceName.' failed, because the group '.$shareWith.' does not exist';
+ \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
+ throw new \Exception($message);
+ }
+ if ($sharingPolicy == 'groups_only' && !\OC_Group::inGroup($uidOwner, $shareWith)) {
+ $message = 'Sharing '.$itemSourceName.' failed, because '
+ .$uidOwner.' is not a member of the group '.$shareWith;
+ \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
+ throw new \Exception($message);
+ }
+ // Check if the item source is already shared with the group, either from the same owner or a different user
+ // The check for each user in the group is done inside the put() function
+ if ($checkExists = self::getItems($itemType, $itemSource, self::SHARE_TYPE_GROUP, $shareWith,
+ null, self::FORMAT_NONE, null, 1, true, true)) {
+ // Only allow the same share to occur again if it is the same
+ // owner and is not a group share, this use case is for increasing
+ // permissions for a specific user
+ if ($checkExists['uid_owner'] != $uidOwner || $checkExists['share_type'] == $shareType) {
+ $message = 'Sharing '.$itemSourceName.' failed, because this item is already shared with '.$shareWith;
+ \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
+ throw new \Exception($message);
+ }
+ }
+ // Convert share with into an array with the keys group and users
+ $group = $shareWith;
+ $shareWith = array();
+ $shareWith['group'] = $group;
+ $shareWith['users'] = array_diff(\OC_Group::usersInGroup($group), array($uidOwner));
+ } else if ($shareType === self::SHARE_TYPE_LINK) {
+ if (\OC_Appconfig::getValue('core', 'shareapi_allow_links', 'yes') == 'yes') {
+ // when updating a link share
+ if ($checkExists = self::getItems($itemType, $itemSource, self::SHARE_TYPE_LINK, null,
+ $uidOwner, self::FORMAT_NONE, null, 1)) {
+ // remember old token
+ $oldToken = $checkExists['token'];
+ $oldPermissions = $checkExists['permissions'];
+ //delete the old share
+ Helper::delete($checkExists['id']);
+ }
+
+ // Generate hash of password - same method as user passwords
+ if (isset($shareWith)) {
+ $forcePortable = (CRYPT_BLOWFISH != 1);
+ $hasher = new \PasswordHash(8, $forcePortable);
+ $shareWith = $hasher->HashPassword($shareWith.\OC_Config::getValue('passwordsalt', ''));
+ } else {
+ // reuse the already set password, but only if we change permissions
+ // otherwise the user disabled the password protection
+ if ($checkExists && (int)$permissions !== (int)$oldPermissions) {
+ $shareWith = $checkExists['share_with'];
+ }
+ }
+
+ // Generate token
+ if (isset($oldToken)) {
+ $token = $oldToken;
+ } else {
+ $token = \OC_Util::generateRandomBytes(self::TOKEN_LENGTH);
+ }
+ $result = self::put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions,
+ null, $token, $itemSourceName);
+ if ($result) {
+ return $token;
+ } else {
+ return false;
+ }
+ }
+ $message = 'Sharing '.$itemSourceName.' failed, because sharing with links is not allowed';
+ \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
+ throw new \Exception($message);
+ return false;
+ } else {
+ // Future share types need to include their own conditions
+ $message = 'Share type '.$shareType.' is not valid for '.$itemSource;
+ \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
+ throw new \Exception($message);
+ }
+ // Put the item into the database
+ return self::put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions, null, null, $itemSourceName);
+ }
+
+ /**
+ * Unshare an item from a user, group, or delete a private link
+ * @param string Item type
+ * @param string Item source
+ * @param int SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
+ * @param string User or group the item is being shared with
+ * @return Returns true on success or false on failure
+ */
+ public static function unshare($itemType, $itemSource, $shareType, $shareWith) {
+ $item = self::getItems($itemType, $itemSource, $shareType, $shareWith, \OC_User::getUser(),self::FORMAT_NONE, null, 1);
+ if (!empty($item)) {
+ self::unshareItem($item);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Unshare an item from all users, groups, and remove all links
+ * @param string Item type
+ * @param string Item source
+ * @return Returns true on success or false on failure
+ */
+ public static function unshareAll($itemType, $itemSource) {
+ // Get all of the owners of shares of this item.
+ $query = \OC_DB::prepare( 'SELECT `uid_owner` from `*PREFIX*share` WHERE `item_type`=? AND `item_source`=?' );
+ $result = $query->execute(array($itemType, $itemSource));
+ $shares = array();
+ // Add each owner's shares to the array of all shares for this item.
+ while ($row = $result->fetchRow()) {
+ $shares = array_merge($shares, self::getItems($itemType, $itemSource, null, null, $row['uid_owner']));
+ }
+ if (!empty($shares)) {
+ // Pass all the vars we have for now, they may be useful
+ $hookParams = array(
+ 'itemType' => $itemType,
+ 'itemSource' => $itemSource,
+ 'shares' => $shares,
+ );
+ \OC_Hook::emit('OCP\Share', 'pre_unshareAll', $hookParams);
+ foreach ($shares as $share) {
+ self::unshareItem($share);
+ }
+ \OC_Hook::emit('OCP\Share', 'post_unshareAll', $hookParams);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Unshare an item shared with the current user
+ * @param string Item type
+ * @param string Item target
+ * @return Returns true on success or false on failure
+ *
+ * Unsharing from self is not allowed for items inside collections
+ */
+ public static function unshareFromSelf($itemType, $itemTarget) {
+ $item = self::getItemSharedWith($itemType, $itemTarget);
+ if (!empty($item)) {
+ if ((int)$item['share_type'] === self::SHARE_TYPE_GROUP) {
+ // Insert an extra row for the group share and set permission
+ // to 0 to prevent it from showing up for the user
+ $query = \OC_DB::prepare('INSERT INTO `*PREFIX*share`'
+ .' (`item_type`, `item_source`, `item_target`, `parent`, `share_type`,'
+ .' `share_with`, `uid_owner`, `permissions`, `stime`, `file_source`, `file_target`)'
+ .' VALUES (?,?,?,?,?,?,?,?,?,?,?)');
+ $query->execute(array($item['item_type'], $item['item_source'], $item['item_target'],
+ $item['id'], self::$shareTypeGroupUserUnique,
+ \OC_User::getUser(), $item['uid_owner'], 0, $item['stime'], $item['file_source'],
+ $item['file_target']));
+ \OC_DB::insertid('*PREFIX*share');
+ // Delete all reshares by this user of the group share
+ Helper::delete($item['id'], true, \OC_User::getUser());
+ } else if ((int)$item['share_type'] === self::$shareTypeGroupUserUnique) {
+ // Set permission to 0 to prevent it from showing up for the user
+ $query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `permissions` = ? WHERE `id` = ?');
+ $query->execute(array(0, $item['id']));
+ Helper::delete($item['id'], true);
+ } else {
+ Helper::delete($item['id']);
+ }
+ return true;
+ }
+ return false;
+ }
+ /**
+ * sent status if users got informed by mail about share
+ * @param string $itemType
+ * @param string $itemSource
+ * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
+ * @param bool $status
+ */
+ public static function setSendMailStatus($itemType, $itemSource, $shareType, $status) {
+ $status = $status ? 1 : 0;
+
+ $query = \OC_DB::prepare(
+ 'UPDATE `*PREFIX*share`
+ SET `mail_send` = ?
+ WHERE `item_type` = ? AND `item_source` = ? AND `share_type` = ?');
+
+ $result = $query->execute(array($status, $itemType, $itemSource, $shareType));
+
+ if($result === false) {
+ \OC_Log::write('OCP\Share', 'Couldn\'t set send mail status', \OC_Log::ERROR);
+ }
+ }
+
+ /**
+ * Set the permissions of an item for a specific user or group
+ * @param string Item type
+ * @param string Item source
+ * @param int SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
+ * @param string User or group the item is being shared with
+ * @param int CRUDS permissions
+ * @return Returns true on success or false on failure
+ */
+ public static function setPermissions($itemType, $itemSource, $shareType, $shareWith, $permissions) {
+ if ($item = self::getItems($itemType, $itemSource, $shareType, $shareWith,
+ \OC_User::getUser(), self::FORMAT_NONE, null, 1, false)) {
+ // Check if this item is a reshare and verify that the permissions
+ // granted don't exceed the parent shared item
+ if (isset($item['parent'])) {
+ $query = \OC_DB::prepare('SELECT `permissions` FROM `*PREFIX*share` WHERE `id` = ?', 1);
+ $result = $query->execute(array($item['parent']))->fetchRow();
+ if (~(int)$result['permissions'] & $permissions) {
+ $message = 'Setting permissions for '.$itemSource.' failed,'
+ .' because the permissions exceed permissions granted to '.\OC_User::getUser();
+ \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
+ throw new \Exception($message);
+ }
+ }
+ $query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `permissions` = ? WHERE `id` = ?');
+ $query->execute(array($permissions, $item['id']));
+ if ($itemType === 'file' || $itemType === 'folder') {
+ \OC_Hook::emit('OCP\Share', 'post_update_permissions', array(
+ 'itemType' => $itemType,
+ 'itemSource' => $itemSource,
+ 'shareType' => $shareType,
+ 'shareWith' => $shareWith,
+ 'uidOwner' => \OC_User::getUser(),
+ 'permissions' => $permissions,
+ 'path' => $item['path'],
+ ));
+ }
+ // Check if permissions were removed
+ if ($item['permissions'] & ~$permissions) {
+ // If share permission is removed all reshares must be deleted
+ if (($item['permissions'] & \OCP\PERMISSION_SHARE) && (~$permissions & \OCP\PERMISSION_SHARE)) {
+ Helper::delete($item['id'], true);
+ } else {
+ $ids = array();
+ $parents = array($item['id']);
+ while (!empty($parents)) {
+ $parents = "'".implode("','", $parents)."'";
+ $query = \OC_DB::prepare('SELECT `id`, `permissions` FROM `*PREFIX*share`'
+ .' WHERE `parent` IN ('.$parents.')');
+ $result = $query->execute();
+ // Reset parents array, only go through loop again if
+ // items are found that need permissions removed
+ $parents = array();
+ while ($item = $result->fetchRow()) {
+ // Check if permissions need to be removed
+ if ($item['permissions'] & ~$permissions) {
+ // Add to list of items that need permissions removed
+ $ids[] = $item['id'];
+ $parents[] = $item['id'];
+ }
+ }
+ }
+ // Remove the permissions for all reshares of this item
+ if (!empty($ids)) {
+ $ids = "'".implode("','", $ids)."'";
+ // TODO this should be done with Doctrine platform objects
+ if (\OC_Config::getValue( "dbtype") === 'oci') {
+ $andOp = 'BITAND(`permissions`, ?)';
+ } else {
+ $andOp = '`permissions` & ?';
+ }
+ $query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `permissions` = '.$andOp
+ .' WHERE `id` IN ('.$ids.')');
+ $query->execute(array($permissions));
+ }
+ }
+ }
+ return true;
+ }
+ $message = 'Setting permissions for '.$itemSource.' failed, because the item was not found';
+ \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
+ throw new \Exception($message);
+ }
+
+ /**
+ * Set expiration date for a share
+ * @param string $itemType
+ * @param string $itemSource
+ * @param string $date expiration date
+ * @return \OCP\Share_Backend
+ */
+ public static function setExpirationDate($itemType, $itemSource, $date) {
+ $user = \OC_User::getUser();
+ $items = self::getItems($itemType, $itemSource, null, null, $user, self::FORMAT_NONE, null, -1, false);
+ if (!empty($items)) {
+ if ($date == '') {
+ $date = null;
+ } else {
+ $date = new \DateTime($date);
+ }
+ $query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `expiration` = ? WHERE `id` = ?');
+ $query->bindValue(1, $date, 'datetime');
+ foreach ($items as $item) {
+ $query->bindValue(2, (int) $item['id']);
+ $query->execute();
+ \OC_Hook::emit('OCP\Share', 'post_set_expiration_date', array(
+ 'itemType' => $itemType,
+ 'itemSource' => $itemSource,
+ 'date' => $date,
+ 'uidOwner' => $user
+ ));
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Checks whether a share has expired, calls unshareItem() if yes.
+ * @param array $item Share data (usually database row)
+ * @return bool True if item was expired, false otherwise.
+ */
+ protected static function expireItem(array $item) {
+ if (!empty($item['expiration'])) {
+ $now = new \DateTime();
+ $expires = new \DateTime($item['expiration']);
+ if ($now > $expires) {
+ self::unshareItem($item);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Unshares a share given a share data array
+ * @param array $item Share data (usually database row)
+ * @return null
+ */
+ protected static function unshareItem(array $item) {
+ // Pass all the vars we have for now, they may be useful
+ $hookParams = array(
+ 'itemType' => $item['item_type'],
+ 'itemSource' => $item['item_source'],
+ 'shareType' => $item['share_type'],
+ 'shareWith' => $item['share_with'],
+ 'itemParent' => $item['parent'],
+ 'uidOwner' => $item['uid_owner'],
+ );
+
+ \OC_Hook::emit('OCP\Share', 'pre_unshare', $hookParams + array(
+ 'fileSource' => $item['file_source'],
+ ));
+ Helper::delete($item['id']);
+ \OC_Hook::emit('OCP\Share', 'post_unshare', $hookParams);
+ }
+
+ /**
+ * Get the backend class for the specified item type
+ * @param string $itemType
+ * @return \OCP\Share_Backend
+ */
+ public static function getBackend($itemType) {
+ if (isset(self::$backends[$itemType])) {
+ return self::$backends[$itemType];
+ } else if (isset(self::$backendTypes[$itemType]['class'])) {
+ $class = self::$backendTypes[$itemType]['class'];
+ if (class_exists($class)) {
+ self::$backends[$itemType] = new $class;
+ if (!(self::$backends[$itemType] instanceof \OCP\Share_Backend)) {
+ $message = 'Sharing backend '.$class.' must implement the interface OCP\Share_Backend';
+ \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
+ throw new \Exception($message);
+ }
+ return self::$backends[$itemType];
+ } else {
+ $message = 'Sharing backend '.$class.' not found';
+ \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
+ throw new \Exception($message);
+ }
+ }
+ $message = 'Sharing backend for '.$itemType.' not found';
+ \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
+ throw new \Exception($message);
+ }
+
+ /**
+ * Check if resharing is allowed
+ * @return Returns true if allowed or false
+ *
+ * Resharing is allowed by default if not configured
+ */
+ private static function isResharingAllowed() {
+ if (!isset(self::$isResharingAllowed)) {
+ if (\OC_Appconfig::getValue('core', 'shareapi_allow_resharing', 'yes') == 'yes') {
+ self::$isResharingAllowed = true;
+ } else {
+ self::$isResharingAllowed = false;
+ }
+ }
+ return self::$isResharingAllowed;
+ }
+
+ /**
+ * Get a list of collection item types for the specified item type
+ * @param string Item type
+ * @return array
+ */
+ private static function getCollectionItemTypes($itemType) {
+ $collectionTypes = array($itemType);
+ foreach (self::$backendTypes as $type => $backend) {
+ if (in_array($backend['collectionOf'], $collectionTypes)) {
+ $collectionTypes[] = $type;
+ }
+ }
+ // TODO Add option for collections to be collection of themselves, only 'folder' does it now...
+ if (!self::getBackend($itemType) instanceof \OCP\Share_Backend_Collection || $itemType != 'folder') {
+ unset($collectionTypes[0]);
+ }
+ // Return array if collections were found or the item type is a
+ // collection itself - collections can be inside collections
+ if (count($collectionTypes) > 0) {
+ return $collectionTypes;
+ }
+ return false;
+ }
+
+ /**
+ * Get shared items from the database
+ * @param string Item type
+ * @param string Item source or target (optional)
+ * @param int SHARE_TYPE_USER, SHARE_TYPE_GROUP, SHARE_TYPE_LINK, $shareTypeUserAndGroups, or $shareTypeGroupUserUnique
+ * @param string User or group the item is being shared with
+ * @param string User that is the owner of shared items (optional)
+ * @param int Format to convert items to with formatItems()
+ * @param mixed Parameters to pass to formatItems()
+ * @param int Number of items to return, -1 to return all matches (optional)
+ * @param bool Include collection item types (optional)
+ * @param bool TODO (optional)
+ * @prams bool check expire date
+ * @return array
+ *
+ * See public functions getItem(s)... for parameter usage
+ *
+ */
+ public static function getItems($itemType, $item = null, $shareType = null, $shareWith = null,
+ $uidOwner = null, $format = self::FORMAT_NONE, $parameters = null, $limit = -1,
+ $includeCollections = false, $itemShareWithBySource = false, $checkExpireDate = true) {
+ if (!self::isEnabled()) {
+ return array();
+ }
+ $backend = self::getBackend($itemType);
+ $collectionTypes = false;
+ // Get filesystem root to add it to the file target and remove from the
+ // file source, match file_source with the file cache
+ if ($itemType == 'file' || $itemType == 'folder') {
+ if(!is_null($uidOwner)) {
+ $root = \OC\Files\Filesystem::getRoot();
+ } else {
+ $root = '';
+ }
+ $where = 'INNER JOIN `*PREFIX*filecache` ON `file_source` = `*PREFIX*filecache`.`fileid`';
+ if (!isset($item)) {
+ $where .= ' WHERE `file_target` IS NOT NULL';
+ }
+ $fileDependent = true;
+ $queryArgs = array();
+ } else {
+ $fileDependent = false;
+ $root = '';
+ $collectionTypes = self::getCollectionItemTypes($itemType);
+ if ($includeCollections && !isset($item) && $collectionTypes) {
+ // If includeCollections is true, find collections of this item type, e.g. a music album contains songs
+ if (!in_array($itemType, $collectionTypes)) {
+ $itemTypes = array_merge(array($itemType), $collectionTypes);
+ } else {
+ $itemTypes = $collectionTypes;
+ }
+ $placeholders = join(',', array_fill(0, count($itemTypes), '?'));
+ $where = ' WHERE `item_type` IN ('.$placeholders.'))';
+ $queryArgs = $itemTypes;
+ } else {
+ $where = ' WHERE `item_type` = ?';
+ $queryArgs = array($itemType);
+ }
+ }
+ if (\OC_Appconfig::getValue('core', 'shareapi_allow_links', 'yes') !== 'yes') {
+ $where .= ' AND `share_type` != ?';
+ $queryArgs[] = self::SHARE_TYPE_LINK;
+ }
+ if (isset($shareType)) {
+ // Include all user and group items
+ if ($shareType == self::$shareTypeUserAndGroups && isset($shareWith)) {
+ $where .= ' AND `share_type` IN (?,?,?)';
+ $queryArgs[] = self::SHARE_TYPE_USER;
+ $queryArgs[] = self::SHARE_TYPE_GROUP;
+ $queryArgs[] = self::$shareTypeGroupUserUnique;
+ $userAndGroups = array_merge(array($shareWith), \OC_Group::getUserGroups($shareWith));
+ $placeholders = join(',', array_fill(0, count($userAndGroups), '?'));
+ $where .= ' AND `share_with` IN ('.$placeholders.')';
+ $queryArgs = array_merge($queryArgs, $userAndGroups);
+ // Don't include own group shares
+ $where .= ' AND `uid_owner` != ?';
+ $queryArgs[] = $shareWith;
+ } else {
+ $where .= ' AND `share_type` = ?';
+ $queryArgs[] = $shareType;
+ if (isset($shareWith)) {
+ $where .= ' AND `share_with` = ?';
+ $queryArgs[] = $shareWith;
+ }
+ }
+ }
+ if (isset($uidOwner)) {
+ $where .= ' AND `uid_owner` = ?';
+ $queryArgs[] = $uidOwner;
+ if (!isset($shareType)) {
+ // Prevent unique user targets for group shares from being selected
+ $where .= ' AND `share_type` != ?';
+ $queryArgs[] = self::$shareTypeGroupUserUnique;
+ }
+ if ($fileDependent) {
+ $column = 'file_source';
+ } else {
+ $column = 'item_source';
+ }
+ } else {
+ if ($fileDependent) {
+ $column = 'file_target';
+ } else {
+ $column = 'item_target';
+ }
+ }
+ if (isset($item)) {
+ $collectionTypes = self::getCollectionItemTypes($itemType);
+ if ($includeCollections && $collectionTypes) {
+ $where .= ' AND (';
+ } else {
+ $where .= ' AND';
+ }
+ // If looking for own shared items, check item_source else check item_target
+ if (isset($uidOwner) || $itemShareWithBySource) {
+ // If item type is a file, file source needs to be checked in case the item was converted
+ if ($fileDependent) {
+ $where .= ' `file_source` = ?';
+ $column = 'file_source';
+ } else {
+ $where .= ' `item_source` = ?';
+ $column = 'item_source';
+ }
+ } else {
+ if ($fileDependent) {
+ $where .= ' `file_target` = ?';
+ $item = \OC\Files\Filesystem::normalizePath($item);
+ } else {
+ $where .= ' `item_target` = ?';
+ }
+ }
+ $queryArgs[] = $item;
+ if ($includeCollections && $collectionTypes) {
+ $placeholders = join(',', array_fill(0, count($collectionTypes), '?'));
+ $where .= ' OR `item_type` IN ('.$placeholders.'))';
+ $queryArgs = array_merge($queryArgs, $collectionTypes);
+ }
+ }
+ if ($limit != -1 && !$includeCollections) {
+ if ($shareType == self::$shareTypeUserAndGroups) {
+ // Make sure the unique user target is returned if it exists,
+ // unique targets should follow the group share in the database
+ // If the limit is not 1, the filtering can be done later
+ $where .= ' ORDER BY `*PREFIX*share`.`id` DESC';
+ }
+ // The limit must be at least 3, because filtering needs to be done
+ if ($limit < 3) {
+ $queryLimit = 3;
+ } else {
+ $queryLimit = $limit;
+ }
+ } else {
+ $queryLimit = null;
+ }
+ $select = self::createSelectStatement($format, $fileDependent, $uidOwner);
+ $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();
+ $switchedItems = array();
+ $mounts = array();
+ while ($row = $result->fetchRow()) {
+ self::transformDBResults($row);
+ // Filter out duplicate group shares for users with unique targets
+ if ($row['share_type'] == self::$shareTypeGroupUserUnique && isset($items[$row['parent']])) {
+ $row['share_type'] = self::SHARE_TYPE_GROUP;
+ $row['share_with'] = $items[$row['parent']]['share_with'];
+ // Remove the parent group share
+ unset($items[$row['parent']]);
+ if ($row['permissions'] == 0) {
+ continue;
+ }
+ } else if (!isset($uidOwner)) {
+ // Check if the same target already exists
+ if (isset($targets[$row[$column]])) {
+ // Check if the same owner shared with the user twice
+ // through a group and user share - this is allowed
+ $id = $targets[$row[$column]];
+ if (isset($items[$id]) && $items[$id]['uid_owner'] == $row['uid_owner']) {
+ // Switch to group share type to ensure resharing conditions aren't bypassed
+ if ($items[$id]['share_type'] != self::SHARE_TYPE_GROUP) {
+ $items[$id]['share_type'] = self::SHARE_TYPE_GROUP;
+ $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'] & \OCP\PERMISSION_SHARE
+ && (int)$row['permissions'] & \OCP\PERMISSION_SHARE) {
+ $items[$row['id']] = $items[$id];
+ $switchedItems[$id] = $row['id'];
+ unset($items[$id]);
+ $id = $row['id'];
+ }
+ // Combine the permissions for the item
+ $items[$id]['permissions'] |= (int)$row['permissions'];
+ continue;
+ }
+ } else {
+ $targets[$row[$column]] = $row['id'];
+ }
+ }
+ // Remove root from file source paths if retrieving own shared items
+ if (isset($uidOwner) && isset($row['path'])) {
+ if (isset($row['parent'])) {
+ // FIXME: Doesn't always construct the correct path, example:
+ // Folder '/a/b', share '/a' and '/a/b' to user2
+ // user2 reshares /Shared/b and ask for share status of /Shared/a/b
+ // expected result: path=/Shared/a/b; actual result /Shared/b because of the parent
+ $query = \OC_DB::prepare('SELECT `file_target` FROM `*PREFIX*share` WHERE `id` = ?');
+ $parentResult = $query->execute(array($row['parent']));
+ if (\OC_DB::isError($result)) {
+ \OC_Log::write('OCP\Share', 'Can\'t select parent: ' .
+ \OC_DB::getErrorMessage($result) . ', select=' . $select . ' where=' . $where,
+ \OC_Log::ERROR);
+ } else {
+ $parentRow = $parentResult->fetchRow();
+ $tmpPath = '/Shared' . $parentRow['file_target'];
+ // find the right position where the row path continues from the target path
+ $pos = strrpos($row['path'], $parentRow['file_target']);
+ $subPath = substr($row['path'], $pos);
+ $splitPath = explode('/', $subPath);
+ foreach (array_slice($splitPath, 2) as $pathPart) {
+ $tmpPath = $tmpPath . '/' . $pathPart;
+ }
+ $row['path'] = $tmpPath;
+ }
+ } else {
+ if (!isset($mounts[$row['storage']])) {
+ $mountPoints = \OC\Files\Filesystem::getMountByNumericId($row['storage']);
+ if (is_array($mountPoints)) {
+ $mounts[$row['storage']] = current($mountPoints);
+ }
+ }
+ if ($mounts[$row['storage']]) {
+ $path = $mounts[$row['storage']]->getMountPoint().$row['path'];
+ $row['path'] = substr($path, $root);
+ }
+ }
+ }
+ if($checkExpireDate) {
+ if (self::expireItem($row)) {
+ continue;
+ }
+ }
+ // Check if resharing is allowed, if not remove share permission
+ if (isset($row['permissions']) && !self::isResharingAllowed()) {
+ $row['permissions'] &= ~\OCP\PERMISSION_SHARE;
+ }
+ // Add display names to result
+ if ( isset($row['share_with']) && $row['share_with'] != '') {
+ $row['share_with_displayname'] = \OCP\User::getDisplayName($row['share_with']);
+ }
+ if ( isset($row['uid_owner']) && $row['uid_owner'] != '') {
+ $row['displayname_owner'] = \OCP\User::getDisplayName($row['uid_owner']);
+ }
+
+ $items[$row['id']] = $row;
+ }
+ if (!empty($items)) {
+ $collectionItems = array();
+ foreach ($items as &$row) {
+ // Return only the item instead of a 2-dimensional array
+ if ($limit == 1 && $row[$column] == $item && ($row['item_type'] == $itemType || $itemType == 'file')) {
+ if ($format == self::FORMAT_NONE) {
+ return $row;
+ } else {
+ break;
+ }
+ }
+ // Check if this is a collection of the requested item type
+ if ($includeCollections && $collectionTypes && in_array($row['item_type'], $collectionTypes)) {
+ if (($collectionBackend = self::getBackend($row['item_type']))
+ && $collectionBackend instanceof \OCP\Share_Backend_Collection) {
+ // Collections can be inside collections, check if the item is a collection
+ if (isset($item) && $row['item_type'] == $itemType && $row[$column] == $item) {
+ $collectionItems[] = $row;
+ } else {
+ $collection = array();
+ $collection['item_type'] = $row['item_type'];
+ if ($row['item_type'] == 'file' || $row['item_type'] == 'folder') {
+ $collection['path'] = basename($row['path']);
+ }
+ $row['collection'] = $collection;
+ // Fetch all of the children sources
+ $children = $collectionBackend->getChildren($row[$column]);
+ foreach ($children as $child) {
+ $childItem = $row;
+ $childItem['item_type'] = $itemType;
+ if ($row['item_type'] != 'file' && $row['item_type'] != 'folder') {
+ $childItem['item_source'] = $child['source'];
+ $childItem['item_target'] = $child['target'];
+ }
+ if ($backend instanceof \OCP\Share_Backend_File_Dependent) {
+ if ($row['item_type'] == 'file' || $row['item_type'] == 'folder') {
+ $childItem['file_source'] = $child['source'];
+ } else { // TODO is this really needed if we already know that we use the file backend?
+ $meta = \OC\Files\Filesystem::getFileInfo($child['file_path']);
+ $childItem['file_source'] = $meta['fileid'];
+ }
+ $childItem['file_target'] =
+ \OC\Files\Filesystem::normalizePath($child['file_path']);
+ }
+ if (isset($item)) {
+ if ($childItem[$column] == $item) {
+ // Return only the item instead of a 2-dimensional array
+ if ($limit == 1) {
+ if ($format == self::FORMAT_NONE) {
+ return $childItem;
+ } else {
+ // Unset the items array and break out of both loops
+ $items = array();
+ $items[] = $childItem;
+ break 2;
+ }
+ } else {
+ $collectionItems[] = $childItem;
+ }
+ }
+ } else {
+ $collectionItems[] = $childItem;
+ }
+ }
+ }
+ }
+ // Remove collection item
+ $toRemove = $row['id'];
+ if (array_key_exists($toRemove, $switchedItems)) {
+ $toRemove = $switchedItems[$toRemove];
+ }
+ unset($items[$toRemove]);
+ }
+ }
+ if (!empty($collectionItems)) {
+ $items = array_merge($items, $collectionItems);
+ }
+
+ return self::formatResult($items, $column, $backend, $format, $parameters);
+ }
+
+ return array();
+ }
+
+ /**
+ * Put shared item into the database
+ * @param string Item type
+ * @param string Item source
+ * @param int SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
+ * @param string User or group the item is being shared with
+ * @param string User that is the owner of shared item
+ * @param int CRUDS permissions
+ * @param bool|array Parent folder target (optional)
+ * @param string token (optional)
+ * @param string name of the source item (optional)
+ * @return bool Returns true on success or false on failure
+ */
+ private static function put($itemType, $itemSource, $shareType, $shareWith, $uidOwner,
+ $permissions, $parentFolder = null, $token = null, $itemSourceName = null) {
+ $backend = self::getBackend($itemType);
+
+ // Check if this is a reshare
+ if ($checkReshare = self::getItemSharedWithBySource($itemType, $itemSource, self::FORMAT_NONE, null, true)) {
+
+ // Check if attempting to share back to owner
+ if ($checkReshare['uid_owner'] == $shareWith && $shareType == self::SHARE_TYPE_USER) {
+ $message = 'Sharing '.$itemSourceName.' failed, because the user '.$shareWith.' is the original sharer';
+ \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
+ throw new \Exception($message);
+ }
+ // Check if share permissions is granted
+ if (self::isResharingAllowed() && (int)$checkReshare['permissions'] & \OCP\PERMISSION_SHARE) {
+ if (~(int)$checkReshare['permissions'] & $permissions) {
+ $message = 'Sharing '.$itemSourceName
+ .' failed, because the permissions exceed permissions granted to '.$uidOwner;
+ \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
+ throw new \Exception($message);
+ } else {
+ // TODO Don't check if inside folder
+ $parent = $checkReshare['id'];
+ $itemSource = $checkReshare['item_source'];
+ $fileSource = $checkReshare['file_source'];
+ $suggestedItemTarget = $checkReshare['item_target'];
+ $suggestedFileTarget = $checkReshare['file_target'];
+ $filePath = $checkReshare['file_target'];
+ }
+ } else {
+ $message = 'Sharing '.$itemSourceName.' failed, because resharing is not allowed';
+ \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
+ throw new \Exception($message);
+ }
+ } else {
+ $parent = null;
+ $suggestedItemTarget = null;
+ $suggestedFileTarget = null;
+ if (!$backend->isValidSource($itemSource, $uidOwner)) {
+ $message = 'Sharing '.$itemSource.' failed, because the sharing backend for '
+ .$itemType.' could not find its source';
+ \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
+ throw new \Exception($message);
+ }
+ if ($backend instanceof \OCP\Share_Backend_File_Dependent) {
+ $filePath = $backend->getFilePath($itemSource, $uidOwner);
+ if ($itemType == 'file' || $itemType == 'folder') {
+ $fileSource = $itemSource;
+ } else {
+ $meta = \OC\Files\Filesystem::getFileInfo($filePath);
+ $fileSource = $meta['fileid'];
+ }
+ if ($fileSource == -1) {
+ $message = 'Sharing '.$itemSource.' failed, because the file could not be found in the file cache';
+ \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
+ throw new \Exception($message);
+ }
+ } else {
+ $filePath = null;
+ $fileSource = null;
+ }
+ }
+ $query = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`item_type`, `item_source`, `item_target`,'
+ .' `parent`, `share_type`, `share_with`, `uid_owner`, `permissions`, `stime`, `file_source`,'
+ .' `file_target`, `token`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)');
+ // Share with a group
+ if ($shareType == self::SHARE_TYPE_GROUP) {
+ $groupItemTarget = Helper::generateTarget($itemType, $itemSource, $shareType, $shareWith['group'],
+ $uidOwner, $suggestedItemTarget);
+ $run = true;
+ $error = '';
+ \OC_Hook::emit('OCP\Share', 'pre_shared', array(
+ 'itemType' => $itemType,
+ 'itemSource' => $itemSource,
+ 'itemTarget' => $groupItemTarget,
+ 'shareType' => $shareType,
+ 'shareWith' => $shareWith['group'],
+ 'uidOwner' => $uidOwner,
+ 'permissions' => $permissions,
+ 'fileSource' => $fileSource,
+ 'token' => $token,
+ 'run' => &$run,
+ 'error' => &$error
+ ));
+
+ if ($run === false) {
+ throw new \Exception($error);
+ }
+
+ if (isset($fileSource)) {
+ if ($parentFolder) {
+ if ($parentFolder === true) {
+ $groupFileTarget = Helper::generateTarget('file', $filePath, $shareType,
+ $shareWith['group'], $uidOwner, $suggestedFileTarget);
+ // Set group default file target for future use
+ $parentFolders[0]['folder'] = $groupFileTarget;
+ } else {
+ // Get group default file target
+ $groupFileTarget = $parentFolder[0]['folder'].$itemSource;
+ $parent = $parentFolder[0]['id'];
+ }
+ } else {
+ $groupFileTarget = Helper::generateTarget('file', $filePath, $shareType, $shareWith['group'],
+ $uidOwner, $suggestedFileTarget);
+ }
+ } else {
+ $groupFileTarget = null;
+ }
+ $query->execute(array($itemType, $itemSource, $groupItemTarget, $parent, $shareType,
+ $shareWith['group'], $uidOwner, $permissions, time(), $fileSource, $groupFileTarget, $token));
+ // Save this id, any extra rows for this group share will need to reference it
+ $parent = \OC_DB::insertid('*PREFIX*share');
+ // Loop through all users of this group in case we need to add an extra row
+ foreach ($shareWith['users'] as $uid) {
+ $itemTarget = Helper::generateTarget($itemType, $itemSource, self::SHARE_TYPE_USER, $uid,
+ $uidOwner, $suggestedItemTarget, $parent);
+ if (isset($fileSource)) {
+ if ($parentFolder) {
+ if ($parentFolder === true) {
+ $fileTarget = Helper::generateTarget('file', $filePath, self::SHARE_TYPE_USER, $uid,
+ $uidOwner, $suggestedFileTarget, $parent);
+ if ($fileTarget != $groupFileTarget) {
+ $parentFolders[$uid]['folder'] = $fileTarget;
+ }
+ } else if (isset($parentFolder[$uid])) {
+ $fileTarget = $parentFolder[$uid]['folder'].$itemSource;
+ $parent = $parentFolder[$uid]['id'];
+ }
+ } else {
+ $fileTarget = Helper::generateTarget('file', $filePath, self::SHARE_TYPE_USER,
+ $uid, $uidOwner, $suggestedFileTarget, $parent);
+ }
+ } else {
+ $fileTarget = null;
+ }
+ // Insert an extra row for the group share if the item or file target is unique for this user
+ if ($itemTarget != $groupItemTarget || (isset($fileSource) && $fileTarget != $groupFileTarget)) {
+ $query->execute(array($itemType, $itemSource, $itemTarget, $parent,
+ self::$shareTypeGroupUserUnique, $uid, $uidOwner, $permissions, time(),
+ $fileSource, $fileTarget, $token));
+ $id = \OC_DB::insertid('*PREFIX*share');
+ }
+ }
+ \OC_Hook::emit('OCP\Share', 'post_shared', array(
+ 'itemType' => $itemType,
+ 'itemSource' => $itemSource,
+ 'itemTarget' => $groupItemTarget,
+ 'parent' => $parent,
+ 'shareType' => $shareType,
+ 'shareWith' => $shareWith['group'],
+ 'uidOwner' => $uidOwner,
+ 'permissions' => $permissions,
+ 'fileSource' => $fileSource,
+ 'fileTarget' => $groupFileTarget,
+ 'id' => $parent,
+ 'token' => $token
+ ));
+
+ if ($parentFolder === true) {
+ // Return parent folders to preserve file target paths for potential children
+ return $parentFolders;
+ }
+ } else {
+ $itemTarget = Helper::generateTarget($itemType, $itemSource, $shareType, $shareWith, $uidOwner,
+ $suggestedItemTarget);
+ $run = true;
+ $error = '';
+ \OC_Hook::emit('OCP\Share', 'pre_shared', array(
+ 'itemType' => $itemType,
+ 'itemSource' => $itemSource,
+ 'itemTarget' => $itemTarget,
+ 'shareType' => $shareType,
+ 'shareWith' => $shareWith,
+ 'uidOwner' => $uidOwner,
+ 'permissions' => $permissions,
+ 'fileSource' => $fileSource,
+ 'token' => $token,
+ 'run' => &$run,
+ 'error' => &$error
+ ));
+
+ if ($run === false) {
+ throw new \Exception($error);
+ }
+
+ if (isset($fileSource)) {
+ if ($parentFolder) {
+ if ($parentFolder === true) {
+ $fileTarget = Helper::generateTarget('file', $filePath, $shareType, $shareWith,
+ $uidOwner, $suggestedFileTarget);
+ $parentFolders['folder'] = $fileTarget;
+ } else {
+ $fileTarget = $parentFolder['folder'].$itemSource;
+ $parent = $parentFolder['id'];
+ }
+ } else {
+ $fileTarget = Helper::generateTarget('file', $filePath, $shareType, $shareWith, $uidOwner,
+ $suggestedFileTarget);
+ }
+ } else {
+ $fileTarget = null;
+ }
+ $query->execute(array($itemType, $itemSource, $itemTarget, $parent, $shareType, $shareWith, $uidOwner,
+ $permissions, time(), $fileSource, $fileTarget, $token));
+ $id = \OC_DB::insertid('*PREFIX*share');
+ \OC_Hook::emit('OCP\Share', 'post_shared', array(
+ 'itemType' => $itemType,
+ 'itemSource' => $itemSource,
+ 'itemTarget' => $itemTarget,
+ 'parent' => $parent,
+ 'shareType' => $shareType,
+ 'shareWith' => $shareWith,
+ 'uidOwner' => $uidOwner,
+ 'permissions' => $permissions,
+ 'fileSource' => $fileSource,
+ 'fileTarget' => $fileTarget,
+ 'id' => $id,
+ 'token' => $token
+ ));
+ if ($parentFolder === true) {
+ $parentFolders['id'] = $id;
+ // Return parent folder to preserve file target paths for potential children
+ return $parentFolders;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Delete all shares with type SHARE_TYPE_LINK
+ */
+ public static function removeAllLinkShares() {
+ // Delete any link shares
+ $query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*share` WHERE `share_type` = ?');
+ $result = $query->execute(array(self::SHARE_TYPE_LINK));
+ while ($item = $result->fetchRow()) {
+ Helper::delete($item['id']);
+ }
+ }
+
+ /**
+ * In case a password protected link is not yet authenticated this function will return false
+ *
+ * @param array $linkItem
+ * @return bool
+ */
+ public static function checkPasswordProtectedShare(array $linkItem) {
+ if (!isset($linkItem['share_with'])) {
+ return true;
+ }
+ if (!isset($linkItem['share_type'])) {
+ return true;
+ }
+ if (!isset($linkItem['id'])) {
+ return true;
+ }
+
+ if ($linkItem['share_type'] != \OCP\Share::SHARE_TYPE_LINK) {
+ return true;
+ }
+
+ if ( \OC::$session->exists('public_link_authenticated')
+ && \OC::$session->get('public_link_authenticated') === $linkItem['id'] ) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * @breif construct select statement
+ * @param int $format
+ * @param bool $fileDependent ist it a file/folder share or a generla share
+ * @param string $uidOwner
+ * @return string select statement
+ */
+ private static function createSelectStatement($format, $fileDependent, $uidOwner = null) {
+ $select = '*';
+ if ($format == self::FORMAT_STATUSES) {
+ if ($fileDependent) {
+ $select = '`*PREFIX*share`.`id`, `*PREFIX*share`.`parent`, `share_type`, `path`, `storage`, `share_with`, `uid_owner` , `file_source`';
+ } else {
+ $select = '`id`, `parent`, `share_type`, `share_with`, `uid_owner`, `item_source`';
+ }
+ } else {
+ if (isset($uidOwner)) {
+ if ($fileDependent) {
+ $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `*PREFIX*share`.`parent`,'
+ . ' `share_type`, `share_with`, `file_source`, `path`, `permissions`, `stime`,'
+ . ' `expiration`, `token`, `storage`, `mail_send`, `uid_owner`';
+ } else {
+ $select = '`id`, `item_type`, `item_source`, `parent`, `share_type`, `share_with`, `permissions`,'
+ . ' `stime`, `file_source`, `expiration`, `token`, `mail_send`, `uid_owner`';
+ }
+ } else {
+ if ($fileDependent) {
+ if ($format == \OC_Share_Backend_File::FORMAT_GET_FOLDER_CONTENTS || $format == \OC_Share_Backend_File::FORMAT_FILE_APP_ROOT) {
+ $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `*PREFIX*share`.`parent`, `uid_owner`, '
+ . '`share_type`, `share_with`, `file_source`, `path`, `file_target`, '
+ . '`permissions`, `expiration`, `storage`, `*PREFIX*filecache`.`parent` as `file_parent`, '
+ . '`name`, `mtime`, `mimetype`, `mimepart`, `size`, `unencrypted_size`, `encrypted`, `etag`, `mail_send`';
+ } else {
+ $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `item_target`,
+ `*PREFIX*share`.`parent`, `share_type`, `share_with`, `uid_owner`,
+ `file_source`, `path`, `file_target`, `permissions`, `stime`, `expiration`, `token`, `storage`, `mail_send`';
+ }
+ }
+ }
+ }
+ return $select;
+ }
+
+
+ /**
+ * @brief transform db results
+ * @param array $row result
+ */
+ private static function transformDBResults(&$row) {
+ if (isset($row['id'])) {
+ $row['id'] = (int) $row['id'];
+ }
+ if (isset($row['share_type'])) {
+ $row['share_type'] = (int) $row['share_type'];
+ }
+ if (isset($row['parent'])) {
+ $row['parent'] = (int) $row['parent'];
+ }
+ if (isset($row['file_parent'])) {
+ $row['file_parent'] = (int) $row['file_parent'];
+ }
+ if (isset($row['file_source'])) {
+ $row['file_source'] = (int) $row['file_source'];
+ }
+ if (isset($row['permissions'])) {
+ $row['permissions'] = (int) $row['permissions'];
+ }
+ if (isset($row['storage'])) {
+ $row['storage'] = (int) $row['storage'];
+ }
+ if (isset($row['stime'])) {
+ $row['stime'] = (int) $row['stime'];
+ }
+ }
+
+ /**
+ * @brief format result
+ * @param array $items result
+ * @prams string $column is it a file share or a general share ('file_target' or 'item_target')
+ * @params \OCP\Share_Backend $backend sharing backend
+ * @param int $format
+ * @param array additional format parameters
+ * @return array formate result
+ */
+ private static function formatResult($items, $column, $backend, $format = self::FORMAT_NONE , $parameters = null) {
+ if ($format === self::FORMAT_NONE) {
+ return $items;
+ } else if ($format === self::FORMAT_STATUSES) {
+ $statuses = array();
+ foreach ($items as $item) {
+ if ($item['share_type'] === self::SHARE_TYPE_LINK) {
+ $statuses[$item[$column]]['link'] = true;
+ } else if (!isset($statuses[$item[$column]])) {
+ $statuses[$item[$column]]['link'] = false;
+ }
+ if ('file_target') {
+ $statuses[$item[$column]]['path'] = $item['path'];
+ }
+ }
+ return $statuses;
+ } else {
+ return $backend->formatItems($items, $format, $parameters);
+ }
+ }
+}
diff --git a/lib/private/template/base.php b/lib/private/template/base.php
index 7aa0cb4a956..3d7c685c1cf 100644
--- a/lib/private/template/base.php
+++ b/lib/private/template/base.php
@@ -77,7 +77,7 @@ class Base {
/**
* @brief Appends a variable
* @param string $key key
- * @param string $value value
+ * @param mixed $value value
* @return boolean|null
*
* This function assigns a variable in an array context. If the key already
diff --git a/lib/private/template/functions.php b/lib/private/template/functions.php
index a72d41f72da..3c42d441efa 100644
--- a/lib/private/template/functions.php
+++ b/lib/private/template/functions.php
@@ -7,16 +7,17 @@
*/
/**
- * Prints an XSS escaped string
- * @param string $string the string which will be escaped and printed
+ * Prints a sanitized string
+ * @param string|array $string the string which will be escaped and printed
*/
function p($string) {
print(OC_Util::sanitizeHTML($string));
}
/**
- * Prints an unescaped string
- * @param string $string the string which will be printed as it is
+ * Prints an unsanitized string - usage of this function may result into XSS.
+ * Consider using p() instead.
+ * @param string|array $string the string which will be printed as it is
*/
function print_unescaped($string) {
print($string);
diff --git a/lib/private/urlgenerator.php b/lib/private/urlgenerator.php
index 44b46ef6700..260eeb15108 100644
--- a/lib/private/urlgenerator.php
+++ b/lib/private/urlgenerator.php
@@ -60,7 +60,7 @@ class URLGenerator implements IURLGenerator {
$app_path = \OC_App::getAppPath($app);
// Check if the app is in the app folder
if ($app_path && file_exists($app_path . '/' . $file)) {
- if (substr($file, -3) == 'php' || substr($file, -3) == 'css') {
+ if (substr($file, -3) == 'php') {
$urlLinkTo = \OC::$WEBROOT . '/index.php/apps/' . $app;
if ($frontControllerActive) {
@@ -148,6 +148,12 @@ class URLGenerator implements IURLGenerator {
*/
public function getAbsoluteURL($url) {
$separator = $url[0] === '/' ? '' : '/';
- return \OC_Request::serverProtocol() . '://' . \OC_Request::serverHost() . $separator . $url;
+
+ // The ownCloud web root can already be prepended.
+ $webRoot = substr($url, 0, strlen(\OC::$WEBROOT)) === \OC::$WEBROOT
+ ? ''
+ : \OC::$WEBROOT;
+
+ return \OC_Request::serverProtocol() . '://' . \OC_Request::serverHost(). $webRoot . $separator . $url;
}
}
diff --git a/lib/private/user.php b/lib/private/user.php
index a89b7286c10..dc4c7ec3b61 100644
--- a/lib/private/user.php
+++ b/lib/private/user.php
@@ -321,8 +321,6 @@ class OC_User {
*/
public static function isLoggedIn() {
if (\OC::$session->get('user_id') && self::$incognitoMode === false) {
- OC_App::loadApps(array('authentication'));
- self::setupBackends();
return self::userExists(\OC::$session->get('user_id'));
}
return false;
diff --git a/lib/private/user/manager.php b/lib/private/user/manager.php
index 8583a451f2d..a2ad9d17702 100644
--- a/lib/private/user/manager.php
+++ b/lib/private/user/manager.php
@@ -239,24 +239,25 @@ class Manager extends PublicEmitter {
* @return bool | \OC\User\User the created user of false
*/
public function createUser($uid, $password) {
+ $l = \OC_L10N::get('lib');
// Check the name for bad characters
// Allowed are: "a-z", "A-Z", "0-9" and "_.@-"
if (preg_match('/[^a-zA-Z0-9 _\.@\-]/', $uid)) {
- throw new \Exception('Only the following characters are allowed in a username:'
- . ' "a-z", "A-Z", "0-9", and "_.@-"');
+ throw new \Exception($l->t('Only the following characters are allowed in a username:'
+ . ' "a-z", "A-Z", "0-9", and "_.@-"'));
}
// No empty username
if (trim($uid) == '') {
- throw new \Exception('A valid username must be provided');
+ throw new \Exception($l->t('A valid username must be provided'));
}
// No empty password
if (trim($password) == '') {
- throw new \Exception('A valid password must be provided');
+ throw new \Exception($l->t('A valid password must be provided'));
}
// Check if user already exists
if ($this->userExists($uid)) {
- throw new \Exception('The username is already being used');
+ throw new \Exception($l->t('The username is already being used'));
}
$this->emit('\OC\User', 'preCreateUser', array($uid, $password));
diff --git a/lib/private/util.php b/lib/private/util.php
index 87e173fa765..e20de308e87 100755
--- a/lib/private/util.php
+++ b/lib/private/util.php
@@ -30,9 +30,7 @@ class OC_Util {
}
// load all filesystem apps before, so no setup-hook gets lost
- if(!isset($RUNTIME_NOAPPS) || !$RUNTIME_NOAPPS) {
- OC_App::loadApps(array('filesystem'));
- }
+ OC_App::loadApps(array('filesystem'));
// the filesystem will finish when $user is not empty,
// mark fs setup here to avoid doing the setup from loading
@@ -703,17 +701,18 @@ class OC_Util {
* @return void
*/
public static function redirectToDefaultPage() {
+ $urlGenerator = \OC::$server->getURLGenerator();
if(isset($_REQUEST['redirect_url'])) {
- $location = OC_Helper::makeURLAbsolute(urldecode($_REQUEST['redirect_url']));
+ $location = urldecode($_REQUEST['redirect_url']);
}
else if (isset(OC::$REQUESTEDAPP) && !empty(OC::$REQUESTEDAPP)) {
- $location = OC_Helper::linkToAbsolute( OC::$REQUESTEDAPP, 'index.php' );
+ $location = $urlGenerator->getAbsoluteURL('/index.php/apps/'.OC::$REQUESTEDAPP.'/index.php');
} else {
$defaultPage = OC_Appconfig::getValue('core', 'defaultpage');
if ($defaultPage) {
- $location = OC_Helper::makeURLAbsolute(OC::$WEBROOT.'/'.$defaultPage);
+ $location = $urlGenerator->getAbsoluteURL($defaultPage);
} else {
- $location = OC_Helper::linkToAbsolute( 'files', 'index.php' );
+ $location = $urlGenerator->getAbsoluteURL('/index.php/files/index.php');
}
}
OC_Log::write('core', 'redirectToDefaultPage: '.$location, OC_Log::DEBUG);
@@ -806,7 +805,7 @@ class OC_Util {
array_walk_recursive($value, 'OC_Util::sanitizeHTML');
} else {
//Specify encoding for PHP<5.4
- $value = htmlentities((string)$value, ENT_QUOTES, 'UTF-8');
+ $value = htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8');
}
return $value;
}
@@ -903,6 +902,8 @@ class OC_Util {
// for this self test we don't care if the ssl certificate is self signed and the peer cannot be verified.
$client->setVerifyPeer(false);
+ // also don't care if the host can't be verified
+ $client->setVerifyHost(0);
$return = true;
try {
@@ -1074,13 +1075,13 @@ class OC_Util {
public static function getUrlContent($url) {
if (function_exists('curl_init')) {
$curl = curl_init();
+ $max_redirects = 10;
curl_setopt($curl, CURLOPT_HEADER, 0);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($curl, CURLOPT_URL, $url);
- curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
- curl_setopt($curl, CURLOPT_MAXREDIRS, 10);
+
curl_setopt($curl, CURLOPT_USERAGENT, "ownCloud Server Crawler");
if(OC_Config::getValue('proxy', '') != '') {
@@ -1089,9 +1090,50 @@ class OC_Util {
if(OC_Config::getValue('proxyuserpwd', '') != '') {
curl_setopt($curl, CURLOPT_PROXYUSERPWD, OC_Config::getValue('proxyuserpwd'));
}
- $data = curl_exec($curl);
+
+ if (ini_get('open_basedir') === '' && ini_get('safe_mode' === 'Off')) {
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
+ curl_setopt($curl, CURLOPT_MAXREDIRS, $max_redirects);
+ $data = curl_exec($curl);
+ } else {
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false);
+ $mr = $max_redirects;
+ if ($mr > 0) {
+ $newurl = curl_getinfo($curl, CURLINFO_EFFECTIVE_URL);
+
+ $rcurl = curl_copy_handle($curl);
+ curl_setopt($rcurl, CURLOPT_HEADER, true);
+ curl_setopt($rcurl, CURLOPT_NOBODY, true);
+ curl_setopt($rcurl, CURLOPT_FORBID_REUSE, false);
+ curl_setopt($rcurl, CURLOPT_RETURNTRANSFER, true);
+ do {
+ curl_setopt($rcurl, CURLOPT_URL, $newurl);
+ $header = curl_exec($rcurl);
+ if (curl_errno($rcurl)) {
+ $code = 0;
+ } else {
+ $code = curl_getinfo($rcurl, CURLINFO_HTTP_CODE);
+ if ($code == 301 || $code == 302) {
+ preg_match('/Location:(.*?)\n/', $header, $matches);
+ $newurl = trim(array_pop($matches));
+ } else {
+ $code = 0;
+ }
+ }
+ } while ($code && --$mr);
+ curl_close($rcurl);
+ if ($mr > 0) {
+ curl_setopt($curl, CURLOPT_URL, $newurl);
+ }
+ }
+
+ if($mr == 0 && $max_redirects > 0) {
+ $data = false;
+ } else {
+ $data = curl_exec($curl);
+ }
+ }
curl_close($curl);
-
} else {
$contextArray = null;
diff --git a/lib/public/appframework/controller.php b/lib/public/appframework/controller.php
index 7c2219bd046..758f0a80083 100644
--- a/lib/public/appframework/controller.php
+++ b/lib/public/appframework/controller.php
@@ -38,10 +38,10 @@ use OCP\IRequest;
abstract class Controller {
/**
- * app container for dependency injection
- * @var \OCP\AppFramework\IAppContainer
+ * app name
+ * @var string
*/
- protected $app;
+ protected $appName;
/**
* current request
@@ -51,11 +51,11 @@ abstract class Controller {
/**
* constructor of the controller
- * @param IAppContainer $app interface to the app
+ * @param string $appName the name of the app
* @param IRequest $request an instance of the request
*/
- public function __construct(IAppContainer $app, IRequest $request){
- $this->app = $app;
+ public function __construct($appName, IRequest $request){
+ $this->appName = $appName;
$this->request = $request;
}
@@ -136,7 +136,7 @@ abstract class Controller {
*/
public function render($templateName, array $params=array(),
$renderAs='user', array $headers=array()){
- $response = new TemplateResponse($this->app->getAppName(), $templateName);
+ $response = new TemplateResponse($this->appName, $templateName);
$response->setParams($params);
$response->renderAs($renderAs);
diff --git a/lib/public/appframework/http/jsonresponse.php b/lib/public/appframework/http/jsonresponse.php
index b54b23a34e6..6628c4514d9 100644
--- a/lib/public/appframework/http/jsonresponse.php
+++ b/lib/public/appframework/http/jsonresponse.php
@@ -66,9 +66,12 @@ class JSONResponse extends Response {
* Sets values in the data json array
* @param array|object $data an array or object which will be transformed
* to JSON
+ * @return JSONResponse Reference to this object
*/
public function setData($data){
$this->data = $data;
+
+ return $this;
}
diff --git a/lib/public/appframework/http/response.php b/lib/public/appframework/http/response.php
index d223621d4fd..45402d9b3b3 100644
--- a/lib/public/appframework/http/response.php
+++ b/lib/public/appframework/http/response.php
@@ -80,6 +80,7 @@ class Response {
$this->addHeader('Cache-Control', 'no-cache, must-revalidate');
}
+ return $this;
}
@@ -88,6 +89,7 @@ class Response {
* function
* @param string $name The name of the HTTP header
* @param string $value The value, null will delete it
+ * @return Response Reference to this object
*/
public function addHeader($name, $value) {
if(is_null($value)) {
@@ -95,6 +97,8 @@ class Response {
} else {
$this->headers[$name] = $value;
}
+
+ return $this;
}
@@ -130,9 +134,12 @@ class Response {
/**
* Set response status
* @param int $status a HTTP status code, see also the STATUS constants
+ * @return Response Reference to this object
*/
public function setStatus($status) {
$this->status = $status;
+
+ return $this;
}
@@ -165,18 +172,24 @@ class Response {
/**
* Set the ETag
* @param string $ETag
+ * @return Response Reference to this object
*/
public function setETag($ETag) {
$this->ETag = $ETag;
+
+ return $this;
}
/**
* Set "last modified" date
* @param \DateTime $lastModified
+ * @return Response Reference to this object
*/
public function setLastModified($lastModified) {
$this->lastModified = $lastModified;
+
+ return $this;
}
diff --git a/lib/public/appframework/http/templateresponse.php b/lib/public/appframework/http/templateresponse.php
index 2200a38beca..f5baf788ada 100644
--- a/lib/public/appframework/http/templateresponse.php
+++ b/lib/public/appframework/http/templateresponse.php
@@ -74,9 +74,12 @@ class TemplateResponse extends Response {
* Sets template parameters
* @param array $params an array with key => value structure which sets template
* variables
+ * @return TemplateResponse Reference to this object
*/
public function setParams(array $params){
$this->params = $params;
+
+ return $this;
}
@@ -104,9 +107,12 @@ class TemplateResponse extends Response {
* settings header and footer, user renders the normal
* normal page including footer and header and blank
* just renders the plain template
+ * @return TemplateResponse Reference to this object
*/
public function renderAs($renderAs){
$this->renderAs = $renderAs;
+
+ return $this;
}
diff --git a/lib/public/appframework/iappcontainer.php b/lib/public/appframework/iappcontainer.php
index e4f5f37cad2..a0b0c06881a 100644
--- a/lib/public/appframework/iappcontainer.php
+++ b/lib/public/appframework/iappcontainer.php
@@ -50,10 +50,10 @@ interface IAppContainer extends IContainer{
function getServer();
/**
- * @param Middleware $middleWare
+ * @param string $middleWare
* @return boolean
*/
- function registerMiddleWare(Middleware $middleWare);
+ function registerMiddleWare($middleWare);
/**
* @return boolean
diff --git a/lib/public/config.php b/lib/public/config.php
index bb973939f44..8e3791b449b 100644
--- a/lib/public/config.php
+++ b/lib/public/config.php
@@ -64,7 +64,7 @@ class Config {
public static function setSystemValue( $key, $value ) {
try {
\OC_Config::setValue( $key, $value );
- } catch (Exception $e) {
+ } catch (\Exception $e) {
return false;
}
return true;
@@ -96,7 +96,7 @@ class Config {
public static function setAppValue( $app, $key, $value ) {
try {
\OC_Appconfig::setValue( $app, $key, $value );
- } catch (Exception $e) {
+ } catch (\Exception $e) {
return false;
}
return true;
@@ -131,7 +131,7 @@ class Config {
public static function setUserValue( $user, $app, $key, $value ) {
try {
\OC_Preferences::setValue( $user, $app, $key, $value );
- } catch (Exception $e) {
+ } catch (\Exception $e) {
return false;
}
return true;
diff --git a/lib/public/contacts/imanager.php b/lib/public/contacts/imanager.php
index 5b9d64ecc41..005b71f298b 100644
--- a/lib/public/contacts/imanager.php
+++ b/lib/public/contacts/imanager.php
@@ -96,7 +96,7 @@ namespace OCP\Contacts {
* This function can be used to delete the contact identified by the given id
*
* @param object $id the unique identifier to a contact
- * @param $address_book_key
+ * @param string $address_book_key identifier of the address book in which the contact shall be deleted
* @return bool successful or not
*/
function delete($id, $address_book_key);
@@ -106,7 +106,7 @@ namespace OCP\Contacts {
* Otherwise the contact will be updated by replacing the entire data set.
*
* @param array $properties this array if key-value-pairs defines a contact
- * @param $address_book_key string to identify the address book in which the contact shall be created or updated
+ * @param string $address_book_key identifier of the address book in which the contact shall be created or updated
* @return array representing the contact just created or updated
*/
function createOrUpdate($properties, $address_book_key);
diff --git a/lib/public/iappconfig.php b/lib/public/iappconfig.php
index 1f31898bf2c..2b014df2e42 100644
--- a/lib/public/iappconfig.php
+++ b/lib/public/iappconfig.php
@@ -55,9 +55,8 @@ interface IAppConfig {
/**
* get multiply values, either the app or key can be used as wildcard by setting it to false
*
- * @param app
- * @param key
- * @param string $key
+ * @param string|false $key
+ * @param string|false $app
* @return array
*/
public function getValues($app, $key);
diff --git a/lib/public/il10n.php b/lib/public/il10n.php
index 1c025e7824f..1388274c21a 100644
--- a/lib/public/il10n.php
+++ b/lib/public/il10n.php
@@ -23,7 +23,7 @@ namespace OCP;
interface IL10N {
/**
* Translating
- * @param $text String The text we need a translation for
+ * @param string $text The text we need a translation for
* @param array $parameters default:array() Parameters for sprintf
* @return \OC_L10N_String Translation or the same text
*
@@ -34,9 +34,9 @@ interface IL10N {
/**
* Translating
- * @param $text_singular String the string to translate for exactly one object
- * @param $text_plural String the string to translate for n objects
- * @param $count Integer Number of objects
+ * @param string $text_singular the string to translate for exactly one object
+ * @param string $text_plural the string to translate for n objects
+ * @param integer $count Number of objects
* @param array $parameters default:array() Parameters for sprintf
* @return \OC_L10N_String Translation or the same text
*
@@ -51,8 +51,8 @@ interface IL10N {
/**
* Localization
- * @param $type Type of localization
- * @param $params parameters for this localization
+ * @param string $type Type of localization
+ * @param array $data parameters for this localization
* @return String or false
*
* Returns the localized data.
diff --git a/lib/public/iservercontainer.php b/lib/public/iservercontainer.php
index dc3aff663d4..600d81d83af 100644
--- a/lib/public/iservercontainer.php
+++ b/lib/public/iservercontainer.php
@@ -122,7 +122,7 @@ interface IServerContainer {
/**
* get an L10N instance
- * @param $app string appid
+ * @param string $app appid
* @return \OCP\IL10N
*/
function getL10N($app);
diff --git a/lib/public/share.php b/lib/public/share.php
index 5066d40354d..564839e86b6 100644
--- a/lib/public/share.php
+++ b/lib/public/share.php
@@ -2,8 +2,9 @@
/**
* ownCloud
*
- * @author Michael Gapczynski
- * @copyright 2012 Michael Gapczynski mtgap@owncloud.com
+ * @author Bjoern Schiessle, Michael Gapczynski
+ * @copyright 2012 Michael Gapczynski <mtgap@owncloud.com>
+ * 2014 Bjoern Schiessle <schiessle@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
@@ -36,41 +37,7 @@ namespace OCP;
* It provides the following hooks:
* - post_shared
*/
-class Share {
-
- const SHARE_TYPE_USER = 0;
- const SHARE_TYPE_GROUP = 1;
- const SHARE_TYPE_LINK = 3;
- const SHARE_TYPE_EMAIL = 4;
- const SHARE_TYPE_CONTACT = 5;
- const SHARE_TYPE_REMOTE = 6;
-
- /** CRUDS permissions (Create, Read, Update, Delete, Share) using a bitmask
- * Construct permissions for share() and setPermissions with Or (|) e.g.
- * Give user read and update permissions: PERMISSION_READ | PERMISSION_UPDATE
- *
- * 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 FORMAT_NONE = -1;
- const FORMAT_STATUSES = -2;
- const FORMAT_SOURCES = -3;
-
- const TOKEN_LENGTH = 32; // see db_structure.xml
-
- private static $shareTypeUserAndGroups = -1;
- private static $shareTypeGroupUserUnique = 2;
- private static $backends = array();
- private static $backendTypes = array();
- private static $isResharingAllowed;
+class Share extends \OC\Share\Constants {
/**
* Register a sharing backend class that implements OCP\Share_Backend for an item type
@@ -78,169 +45,33 @@ class Share {
* @param string Backend class
* @param string (optional) Depends on item type
* @param array (optional) List of supported file extensions if this item type depends on files
- * @param string $itemType
- * @param string $class
- * @param string $collectionOf
- * @return boolean true if backend is registered or false if error
+ * @return Returns true if backend is registered or false if error
*/
public static function registerBackend($itemType, $class, $collectionOf = null, $supportedFileExtensions = null) {
- if (self::isEnabled()) {
- if (!isset(self::$backendTypes[$itemType])) {
- self::$backendTypes[$itemType] = array(
- 'class' => $class,
- 'collectionOf' => $collectionOf,
- 'supportedFileExtensions' => $supportedFileExtensions
- );
- if(count(self::$backendTypes) === 1) {
- \OC_Util::addScript('core', 'share');
- \OC_Util::addStyle('core', 'share');
- }
- return true;
- }
- \OC_Log::write('OCP\Share',
- 'Sharing backend '.$class.' not registered, '.self::$backendTypes[$itemType]['class']
- .' is already registered for '.$itemType,
- \OC_Log::WARN);
- }
- return false;
+ return \OC\Share\Share::registerBackend($itemType, $class, $collectionOf, $supportedFileExtensions);
}
/**
* Check if the Share API is enabled
- * @return boolean true if enabled or false
+ * @return Returns true if enabled or false
*
* The Share API is enabled by default if not configured
*/
public static function isEnabled() {
- if (\OC_Appconfig::getValue('core', 'shareapi_enabled', 'yes') == 'yes') {
- return true;
- }
- return false;
- }
-
- /**
- * Prepare a path to be passed to DB as file_target
- * @param string $path path
- * @return string Prepared path
- */
- public static function prepFileTarget( $path ) {
-
- // Paths in DB are stored with leading slashes, so add one if necessary
- if ( substr( $path, 0, 1 ) !== '/' ) {
-
- $path = '/' . $path;
-
- }
-
- return $path;
-
+ return \OC\Share\Share::isEnabled();
}
/**
* Find which users can access a shared item
* @param string $path to the file
- * @param $user owner of the file
- * @param include owner to the list of users with access to the file
+ * @param string $user owner of the file
+ * @param bool $includeOwner include owner to the list of users with access to the file
* @return array
* @note $path needs to be relative to user data dir, e.g. 'file.txt'
* not '/admin/data/file.txt'
*/
public static function getUsersSharingFile($path, $user, $includeOwner = false) {
-
- $shares = array();
- $publicShare = false;
- $source = -1;
- $cache = false;
-
- $view = new \OC\Files\View('/' . $user . '/files');
- if ($view->file_exists($path)) {
- $meta = $view->getFileInfo($path);
- } else {
- // if the file doesn't exists yet we start with the parent folder
- $meta = $view->getFileInfo(dirname($path));
- }
-
- if($meta !== false) {
- $source = $meta['fileid'];
- $cache = new \OC\Files\Cache\Cache($meta['storage']);
- }
-
- while ($source !== -1) {
-
- // Fetch all shares with another user
- $query = \OC_DB::prepare(
- 'SELECT `share_with`
- FROM
- `*PREFIX*share`
- WHERE
- `item_source` = ? AND `share_type` = ? AND `item_type` IN (\'file\', \'folder\')'
- );
-
- $result = $query->execute(array($source, self::SHARE_TYPE_USER));
-
- if (\OCP\DB::isError($result)) {
- \OCP\Util::writeLog('OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR);
- } else {
- while ($row = $result->fetchRow()) {
- $shares[] = $row['share_with'];
- }
- }
- // We also need to take group shares into account
-
- $query = \OC_DB::prepare(
- 'SELECT `share_with`
- FROM
- `*PREFIX*share`
- WHERE
- `item_source` = ? AND `share_type` = ? AND `item_type` IN (\'file\', \'folder\')'
- );
-
- $result = $query->execute(array($source, self::SHARE_TYPE_GROUP));
-
- if (\OCP\DB::isError($result)) {
- \OCP\Util::writeLog('OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR);
- } else {
- while ($row = $result->fetchRow()) {
- $usersInGroup = \OC_Group::usersInGroup($row['share_with']);
- $shares = array_merge($shares, $usersInGroup);
- }
- }
-
- //check for public link shares
- if (!$publicShare) {
- $query = \OC_DB::prepare(
- 'SELECT `share_with`
- FROM
- `*PREFIX*share`
- WHERE
- `item_source` = ? AND `share_type` = ? AND `item_type` IN (\'file\', \'folder\')'
- );
-
- $result = $query->execute(array($source, self::SHARE_TYPE_LINK));
-
- if (\OCP\DB::isError($result)) {
- \OCP\Util::writeLog('OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR);
- } else {
- if ($result->fetchRow()) {
- $publicShare = true;
- }
- }
- }
-
- // let's get the parent for the next round
- $meta = $cache->get((int)$source);
- if($meta !== false) {
- $source = (int)$meta['parent'];
- } else {
- $source = -1;
- }
- }
- // Include owner in list of users, if requested
- if ($includeOwner) {
- $shares[] = $user;
- }
-
- return array("users" => array_unique($shares), "public" => $publicShare);
+ return \OC\Share\Share::getUsersSharingFile($path, $user, $includeOwner);
}
/**
@@ -250,13 +81,12 @@ class Share {
* @param mixed Parameters (optional)
* @param int Number of items to return (optional) Returns all by default
* @param bool include collections (optional)
- * @param string $itemType
* @return Return depends on format
*/
public static function getItemsSharedWith($itemType, $format = self::FORMAT_NONE,
$parameters = null, $limit = -1, $includeCollections = false) {
- return self::getItems($itemType, null, self::$shareTypeUserAndGroups, \OC_User::getUser(), null, $format,
- $parameters, $limit, $includeCollections);
+
+ return \OC\Share\Share::getItemsSharedWith($itemType, $format, $parameters, $limit, $includeCollections);
}
/**
@@ -266,12 +96,12 @@ class Share {
* @param int $format (optional) Format type must be defined by the backend
* @param mixed Parameters (optional)
* @param bool include collections (optional)
- * @return string depends on format
+ * @return Return depends on format
*/
public static function getItemSharedWith($itemType, $itemTarget, $format = self::FORMAT_NONE,
$parameters = null, $includeCollections = false) {
- return self::getItems($itemType, $itemTarget, self::$shareTypeUserAndGroups, \OC_User::getUser(), null, $format,
- $parameters, 1, $includeCollections);
+
+ return \OC\Share\Share::getItemSharedWith($itemType, $itemTarget, $format, $parameters, $includeCollections);
}
/**
@@ -282,45 +112,7 @@ class Share {
* @return array Return list of items with file_target, permissions and expiration
*/
public static function getItemSharedWithUser($itemType, $itemSource, $user) {
-
- $shares = array();
-
- // first check if there is a db entry for the specific user
- $query = \OC_DB::prepare(
- 'SELECT `file_target`, `permissions`, `expiration`
- FROM
- `*PREFIX*share`
- WHERE
- `item_source` = ? AND `item_type` = ? AND `share_with` = ?'
- );
-
- $result = \OC_DB::executeAudited($query, array($itemSource, $itemType, $user));
-
- while ($row = $result->fetchRow()) {
- $shares[] = $row;
- }
-
- //if didn't found a result than let's look for a group share.
- if(empty($shares)) {
- $groups = \OC_Group::getUserGroups($user);
-
- $query = \OC_DB::prepare(
- 'SELECT `file_target`, `permissions`, `expiration`
- FROM
- `*PREFIX*share`
- WHERE
- `item_source` = ? AND `item_type` = ? AND `share_with` in (?)'
- );
-
- $result = \OC_DB::executeAudited($query, array($itemSource, $itemType, implode(',', $groups)));
-
- while ($row = $result->fetchRow()) {
- $shares[] = $row;
- }
- }
-
- return $shares;
-
+ return \OC\Share\Share::getItemSharedWithUser($itemType, $itemSource, $user);
}
/**
@@ -334,8 +126,7 @@ class Share {
*/
public static function getItemSharedWithBySource($itemType, $itemSource, $format = self::FORMAT_NONE,
$parameters = null, $includeCollections = false) {
- return self::getItems($itemType, $itemSource, self::$shareTypeUserAndGroups, \OC_User::getUser(), null, $format,
- $parameters, 1, $includeCollections, true);
+ return \OC\Share\Share::getItemSharedWithBySource($itemType, $itemSource, $format, $parameters, $includeCollections);
}
/**
@@ -346,8 +137,7 @@ class Share {
* @return Item
*/
public static function getItemSharedWithByLink($itemType, $itemSource, $uidOwner) {
- return self::getItems($itemType, $itemSource, self::SHARE_TYPE_LINK, null, $uidOwner, self::FORMAT_NONE,
- null, 1);
+ return \OC\Share\Share::getItemSharedWithByLink($itemType, $itemSource, $uidOwner);
}
/**
@@ -356,25 +146,7 @@ class Share {
* @return array | bool false will be returned in case the token is unknown or unauthorized
*/
public static function getShareByToken($token, $checkPasswordProtection = true) {
- $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share` WHERE `token` = ?', 1);
- $result = $query->execute(array($token));
- if (\OC_DB::isError($result)) {
- \OC_Log::write('OCP\Share', \OC_DB::getErrorMessage($result) . ', token=' . $token, \OC_Log::ERROR);
- }
- $row = $result->fetchRow();
- if ($row === false) {
- return false;
- }
- if (is_array($row) and self::expireItem($row)) {
- return false;
- }
-
- // password protected shares need to be authenticated
- if ($checkPasswordProtection && !\OCP\Share::checkPasswordProtectedShare($row)) {
- return false;
- }
-
- return $row;
+ return \OC\Share\Share::getShareByToken($token, $checkPasswordProtection);
}
/**
@@ -382,21 +154,8 @@ class Share {
* @param $linkItem
* @return $fileOwner
*/
- public static function resolveReShare($linkItem)
- {
- if (isset($linkItem['parent'])) {
- $parent = $linkItem['parent'];
- while (isset($parent)) {
- $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share` WHERE `id` = ?', 1);
- $item = $query->execute(array($parent))->fetchRow();
- if (isset($item['parent'])) {
- $parent = $item['parent'];
- } else {
- return $item;
- }
- }
- }
- return $linkItem;
+ public static function resolveReShare($linkItem) {
+ return \OC\Share\Share::resolveReShare($linkItem);
}
@@ -407,13 +166,12 @@ class Share {
* @param mixed Parameters
* @param int Number of items to return (optional) Returns all by default
* @param bool include collections
- * @param string $itemType
* @return Return depends on format
*/
public static function getItemsShared($itemType, $format = self::FORMAT_NONE, $parameters = null,
$limit = -1, $includeCollections = false) {
- return self::getItems($itemType, null, null, null, \OC_User::getUser(), $format,
- $parameters, $limit, $includeCollections);
+
+ return \OC\Share\Share::getItemsShared($itemType, $format, $parameters, $limit, $includeCollections);
}
/**
@@ -427,8 +185,8 @@ class Share {
*/
public static function getItemShared($itemType, $itemSource, $format = self::FORMAT_NONE,
$parameters = null, $includeCollections = false) {
- return self::getItems($itemType, $itemSource, null, null, \OC_User::getUser(), $format,
- $parameters, -1, $includeCollections);
+
+ return \OC\Share\Share::getItemShared($itemType, $itemSource, $format, $parameters, $includeCollections);
}
/**
@@ -441,19 +199,7 @@ class Share {
* @return Return array of users
*/
public static function getUsersItemShared($itemType, $itemSource, $uidOwner, $includeCollections = false, $checkExpireDate = true) {
-
- $users = array();
- $items = self::getItems($itemType, $itemSource, null, null, $uidOwner, self::FORMAT_NONE, null, -1, $includeCollections, false, $checkExpireDate);
- if ($items) {
- foreach ($items as $item) {
- if ((int)$item['share_type'] === self::SHARE_TYPE_USER) {
- $users[] = $item['share_with'];
- } else if ((int)$item['share_type'] === self::SHARE_TYPE_GROUP) {
- $users = array_merge($users, \OC_Group::usersInGroup($item['share_with']));
- }
- }
- }
- return $users;
+ return \OC\Share\Share::getUsersItemShared($itemType, $itemSource, $uidOwner, $includeCollections, $checkExpireDate);
}
/**
@@ -473,176 +219,7 @@ class Share {
* @return bool|string Returns true on success or false on failure, Returns token on success for links
*/
public static function shareItem($itemType, $itemSource, $shareType, $shareWith, $permissions, $itemSourceName = null) {
- $uidOwner = \OC_User::getUser();
- $sharingPolicy = \OC_Appconfig::getValue('core', 'shareapi_share_policy', 'global');
-
- if (is_null($itemSourceName)) {
- $itemSourceName = $itemSource;
- }
-
- // Verify share type and sharing conditions are met
- if ($shareType === self::SHARE_TYPE_USER) {
- if ($shareWith == $uidOwner) {
- $message = 'Sharing '.$itemSourceName.' failed, because the user '.$shareWith.' is the item owner';
- \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
- throw new \Exception($message);
- }
- if (!\OC_User::userExists($shareWith)) {
- $message = 'Sharing '.$itemSourceName.' failed, because the user '.$shareWith.' does not exist';
- \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
- throw new \Exception($message);
- }
- if ($sharingPolicy == 'groups_only') {
- $inGroup = array_intersect(\OC_Group::getUserGroups($uidOwner), \OC_Group::getUserGroups($shareWith));
- if (empty($inGroup)) {
- $message = 'Sharing '.$itemSourceName.' failed, because the user '
- .$shareWith.' is not a member of any groups that '.$uidOwner.' is a member of';
- \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
- throw new \Exception($message);
- }
- }
- // Check if the item source is already shared with the user, either from the same owner or a different user
- if ($checkExists = self::getItems($itemType, $itemSource, self::$shareTypeUserAndGroups,
- $shareWith, null, self::FORMAT_NONE, null, 1, true, true)) {
- // Only allow the same share to occur again if it is the same
- // owner and is not a user share, this use case is for increasing
- // permissions for a specific user
- if ($checkExists['uid_owner'] != $uidOwner || $checkExists['share_type'] == $shareType) {
- $message = 'Sharing '.$itemSourceName.' failed, because this item is already shared with '.$shareWith;
- \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
- throw new \Exception($message);
- }
- }
- } else if ($shareType === self::SHARE_TYPE_GROUP) {
- if (!\OC_Group::groupExists($shareWith)) {
- $message = 'Sharing '.$itemSourceName.' failed, because the group '.$shareWith.' does not exist';
- \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
- throw new \Exception($message);
- }
- if ($sharingPolicy == 'groups_only' && !\OC_Group::inGroup($uidOwner, $shareWith)) {
- $message = 'Sharing '.$itemSourceName.' failed, because '
- .$uidOwner.' is not a member of the group '.$shareWith;
- \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
- throw new \Exception($message);
- }
- // Check if the item source is already shared with the group, either from the same owner or a different user
- // The check for each user in the group is done inside the put() function
- if ($checkExists = self::getItems($itemType, $itemSource, self::SHARE_TYPE_GROUP, $shareWith,
- null, self::FORMAT_NONE, null, 1, true, true)) {
- // Only allow the same share to occur again if it is the same
- // owner and is not a group share, this use case is for increasing
- // permissions for a specific user
- if ($checkExists['uid_owner'] != $uidOwner || $checkExists['share_type'] == $shareType) {
- $message = 'Sharing '.$itemSourceName.' failed, because this item is already shared with '.$shareWith;
- \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
- throw new \Exception($message);
- }
- }
- // Convert share with into an array with the keys group and users
- $group = $shareWith;
- $shareWith = array();
- $shareWith['group'] = $group;
- $shareWith['users'] = array_diff(\OC_Group::usersInGroup($group), array($uidOwner));
- } else if ($shareType === self::SHARE_TYPE_LINK) {
- if (\OC_Appconfig::getValue('core', 'shareapi_allow_links', 'yes') == 'yes') {
- // when updating a link share
- if ($checkExists = self::getItems($itemType, $itemSource, self::SHARE_TYPE_LINK, null,
- $uidOwner, self::FORMAT_NONE, null, 1)) {
- // remember old token
- $oldToken = $checkExists['token'];
- $oldPermissions = $checkExists['permissions'];
- //delete the old share
- self::delete($checkExists['id']);
- }
-
- // Generate hash of password - same method as user passwords
- if (isset($shareWith)) {
- $forcePortable = (CRYPT_BLOWFISH != 1);
- $hasher = new \PasswordHash(8, $forcePortable);
- $shareWith = $hasher->HashPassword($shareWith.\OC_Config::getValue('passwordsalt', ''));
- } else {
- // reuse the already set password, but only if we change permissions
- // otherwise the user disabled the password protection
- if ($checkExists && (int)$permissions !== (int)$oldPermissions) {
- $shareWith = $checkExists['share_with'];
- }
- }
-
- // Generate token
- if (isset($oldToken)) {
- $token = $oldToken;
- } else {
- $token = \OC_Util::generateRandomBytes(self::TOKEN_LENGTH);
- }
- $result = self::put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions,
- null, $token, $itemSourceName);
- if ($result) {
- return $token;
- } else {
- return false;
- }
- }
- $message = 'Sharing '.$itemSourceName.' failed, because sharing with links is not allowed';
- \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
- throw new \Exception($message);
- return false;
-// } else if ($shareType === self::SHARE_TYPE_CONTACT) {
-// if (!\OC_App::isEnabled('contacts')) {
-// $message = 'Sharing '.$itemSource.' failed, because the contacts app is not enabled';
-// \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
-// return false;
-// }
-// $vcard = \OC_Contacts_App::getContactVCard($shareWith);
-// if (!isset($vcard)) {
-// $message = 'Sharing '.$itemSource.' failed, because the contact does not exist';
-// \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
-// throw new \Exception($message);
-// }
-// $details = \OC_Contacts_VCard::structureContact($vcard);
-// // TODO Add ownCloud user to contacts vcard
-// if (!isset($details['EMAIL'])) {
-// $message = 'Sharing '.$itemSource.' failed, because no email address is associated with the contact';
-// \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
-// throw new \Exception($message);
-// }
-// return self::shareItem($itemType, $itemSource, self::SHARE_TYPE_EMAIL, $details['EMAIL'], $permissions);
- } else {
- // Future share types need to include their own conditions
- $message = 'Share type '.$shareType.' is not valid for '.$itemSource;
- \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
- throw new \Exception($message);
- }
- // If the item is a folder, scan through the folder looking for equivalent item types
-// if ($itemType == 'folder') {
-// $parentFolder = self::put('folder', $itemSource, $shareType, $shareWith, $uidOwner, $permissions, true);
-// if ($parentFolder && $files = \OC\Files\Filesystem::getDirectoryContent($itemSource)) {
-// for ($i = 0; $i < count($files); $i++) {
-// $name = substr($files[$i]['name'], strpos($files[$i]['name'], $itemSource) - strlen($itemSource));
-// if ($files[$i]['mimetype'] == 'httpd/unix-directory'
-// && $children = \OC\Files\Filesystem::getDirectoryContent($name, '/')
-// ) {
-// // Continue scanning into child folders
-// array_push($files, $children);
-// } else {
-// // Check file extension for an equivalent item type to convert to
-// $extension = strtolower(substr($itemSource, strrpos($itemSource, '.') + 1));
-// foreach (self::$backends as $type => $backend) {
-// if (isset($backend->dependsOn) && $backend->dependsOn == 'file' && isset($backend->supportedFileExtensions) && in_array($extension, $backend->supportedFileExtensions)) {
-// $itemType = $type;
-// break;
-// }
-// }
-// // Pass on to put() to check if this item should be converted, the item won't be inserted into the database unless it can be converted
-// self::put($itemType, $name, $shareType, $shareWith, $uidOwner, $permissions, $parentFolder);
-// }
-// }
-// return true;
-// }
-// return false;
-// } else {
- // Put the item into the database
- return self::put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions, null, null, $itemSourceName);
-// }
+ return \OC\Share\Share::shareItem($itemType, $itemSource, $shareType, $shareWith, $permissions, $itemSourceName);
}
/**
@@ -651,88 +228,32 @@ class Share {
* @param string Item source
* @param int SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
* @param string User or group the item is being shared with
- * @return boolean true on success or false on failure
+ * @return Returns true on success or false on failure
*/
public static function unshare($itemType, $itemSource, $shareType, $shareWith) {
- if ($item = self::getItems($itemType, $itemSource, $shareType, $shareWith, \OC_User::getUser(),
- self::FORMAT_NONE, null, 1)) {
- self::unshareItem($item);
- return true;
- }
- return false;
+ return \OC\Share\Share::unshare($itemType, $itemSource, $shareType, $shareWith);
}
/**
* Unshare an item from all users, groups, and remove all links
* @param string Item type
* @param string Item source
- * @param string $itemType
- * @param string $itemSource
- * @return boolean true on success or false on failure
+ * @return Returns true on success or false on failure
*/
public static function unshareAll($itemType, $itemSource) {
- // Get all of the owners of shares of this item.
- $query = \OC_DB::prepare( 'SELECT `uid_owner` from `*PREFIX*share` WHERE `item_type`=? AND `item_source`=?' );
- $result = $query->execute(array($itemType, $itemSource));
- $shares = array();
- // Add each owner's shares to the array of all shares for this item.
- while ($row = $result->fetchRow()) {
- $shares = array_merge($shares, self::getItems($itemType, $itemSource, null, null, $row['uid_owner']));
- }
- if (!empty($shares)) {
- // Pass all the vars we have for now, they may be useful
- $hookParams = array(
- 'itemType' => $itemType,
- 'itemSource' => $itemSource,
- 'shares' => $shares,
- );
- \OC_Hook::emit('OCP\Share', 'pre_unshareAll', $hookParams);
- foreach ($shares as $share) {
- self::unshareItem($share);
- }
- \OC_Hook::emit('OCP\Share', 'post_unshareAll', $hookParams);
- return true;
- }
- return false;
+ return \OC\Share\Share::unshareAll($itemType, $itemSource);
}
/**
* Unshare an item shared with the current user
* @param string Item type
* @param string Item target
- * @param string $itemType
- * @param string $itemTarget
- * @return boolean true on success or false on failure
+ * @return Returns true on success or false on failure
*
* Unsharing from self is not allowed for items inside collections
*/
public static function unshareFromSelf($itemType, $itemTarget) {
- if ($item = self::getItemSharedWith($itemType, $itemTarget)) {
- if ((int)$item['share_type'] === self::SHARE_TYPE_GROUP) {
- // Insert an extra row for the group share and set permission
- // to 0 to prevent it from showing up for the user
- $query = \OC_DB::prepare('INSERT INTO `*PREFIX*share`'
- .' (`item_type`, `item_source`, `item_target`, `parent`, `share_type`,'
- .' `share_with`, `uid_owner`, `permissions`, `stime`, `file_source`, `file_target`)'
- .' VALUES (?,?,?,?,?,?,?,?,?,?,?)');
- $query->execute(array($item['item_type'], $item['item_source'], $item['item_target'],
- $item['id'], self::$shareTypeGroupUserUnique,
- \OC_User::getUser(), $item['uid_owner'], 0, $item['stime'], $item['file_source'],
- $item['file_target']));
- \OC_DB::insertid('*PREFIX*share');
- // Delete all reshares by this user of the group share
- self::delete($item['id'], true, \OC_User::getUser());
- } else if ((int)$item['share_type'] === self::$shareTypeGroupUserUnique) {
- // Set permission to 0 to prevent it from showing up for the user
- $query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `permissions` = ? WHERE `id` = ?');
- $query->execute(array(0, $item['id']));
- self::delete($item['id'], true);
- } else {
- self::delete($item['id']);
- }
- return true;
- }
- return false;
+ return \OC\Share\Share::unshareFromSelf($itemType, $itemTarget);
}
/**
* sent status if users got informed by mail about share
@@ -742,102 +263,20 @@ class Share {
* @param bool $status
*/
public static function setSendMailStatus($itemType, $itemSource, $shareType, $status) {
- $status = $status ? 1 : 0;
-
- $query = \OC_DB::prepare(
- 'UPDATE `*PREFIX*share`
- SET `mail_send` = ?
- WHERE `item_type` = ? AND `item_source` = ? AND `share_type` = ?');
-
- $result = $query->execute(array($status, $itemType, $itemSource, $shareType));
-
- if($result === false) {
- \OC_Log::write('OCP\Share', 'Couldn\'t set send mail status', \OC_Log::ERROR);
- }
+ return \OC\Share\Share::setSendMailStatus($itemType, $itemSource, $shareType, $status);
}
/**
* Set the permissions of an item for a specific user or group
- * @param string $itemType Item type
- * @param string $itemSource Item source
- * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
- * @param string $shareWith User or group the item is being shared with
- * @param integer|null $permissions CRUDS
- * @return boolean true on success or false on failure
+ * @param string Item type
+ * @param string Item source
+ * @param int SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
+ * @param string User or group the item is being shared with
+ * @param int CRUDS permissions
+ * @return Returns true on success or false on failure
*/
public static function setPermissions($itemType, $itemSource, $shareType, $shareWith, $permissions) {
- if ($item = self::getItems($itemType, $itemSource, $shareType, $shareWith,
- \OC_User::getUser(), self::FORMAT_NONE, null, 1, false)) {
- // Check if this item is a reshare and verify that the permissions
- // granted don't exceed the parent shared item
- if (isset($item['parent'])) {
- $query = \OC_DB::prepare('SELECT `permissions` FROM `*PREFIX*share` WHERE `id` = ?', 1);
- $result = $query->execute(array($item['parent']))->fetchRow();
- if (~(int)$result['permissions'] & $permissions) {
- $message = 'Setting permissions for '.$itemSource.' failed,'
- .' because the permissions exceed permissions granted to '.\OC_User::getUser();
- \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
- throw new \Exception($message);
- }
- }
- $query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `permissions` = ? WHERE `id` = ?');
- $query->execute(array($permissions, $item['id']));
- if ($itemType === 'file' || $itemType === 'folder') {
- \OC_Hook::emit('OCP\Share', 'post_update_permissions', array(
- 'itemType' => $itemType,
- 'itemSource' => $itemSource,
- 'shareType' => $shareType,
- 'shareWith' => $shareWith,
- 'uidOwner' => \OC_User::getUser(),
- 'permissions' => $permissions,
- 'path' => $item['path'],
- ));
- }
- // Check if permissions were removed
- if ($item['permissions'] & ~$permissions) {
- // If share permission is removed all reshares must be deleted
- if (($item['permissions'] & PERMISSION_SHARE) && (~$permissions & PERMISSION_SHARE)) {
- self::delete($item['id'], true);
- } else {
- $ids = array();
- $parents = array($item['id']);
- while (!empty($parents)) {
- $parents = "'".implode("','", $parents)."'";
- $query = \OC_DB::prepare('SELECT `id`, `permissions` FROM `*PREFIX*share`'
- .' WHERE `parent` IN ('.$parents.')');
- $result = $query->execute();
- // Reset parents array, only go through loop again if
- // items are found that need permissions removed
- $parents = array();
- while ($item = $result->fetchRow()) {
- // Check if permissions need to be removed
- if ($item['permissions'] & ~$permissions) {
- // Add to list of items that need permissions removed
- $ids[] = $item['id'];
- $parents[] = $item['id'];
- }
- }
- }
- // Remove the permissions for all reshares of this item
- if (!empty($ids)) {
- $ids = "'".implode("','", $ids)."'";
- // TODO this should be done with Doctrine platform objects
- if (\OC_Config::getValue( "dbtype") === 'oci') {
- $andOp = 'BITAND(`permissions`, ?)';
- } else {
- $andOp = '`permissions` & ?';
- }
- $query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `permissions` = '.$andOp
- .' WHERE `id` IN ('.$ids.')');
- $query->execute(array($permissions));
- }
- }
- }
- return true;
- }
- $message = 'Setting permissions for '.$itemSource.' failed, because the item was not found';
- \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
- throw new \Exception($message);
+ return \OC\Share\Share::setPermissions($itemType, $itemSource, $shareType, $shareWith, $permissions);
}
/**
@@ -845,67 +284,10 @@ class Share {
* @param string $itemType
* @param string $itemSource
* @param string $date expiration date
- * @return boolean
+ * @return Share_Backend
*/
public static function setExpirationDate($itemType, $itemSource, $date) {
- if ($items = self::getItems($itemType, $itemSource, null, null, \OC_User::getUser(),
- self::FORMAT_NONE, null, -1, false)) {
- if (!empty($items)) {
- if ($date == '') {
- $date = null;
- } else {
- $date = new \DateTime($date);
- }
- $query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `expiration` = ? WHERE `id` = ?');
- $query->bindValue(1, $date, 'datetime');
- foreach ($items as $item) {
- $query->bindValue(2, (int) $item['id']);
- $query->execute();
- }
- return true;
- }
- }
- return false;
- }
-
- /**
- * Checks whether a share has expired, calls unshareItem() if yes.
- * @param array $item Share data (usually database row)
- * @return bool True if item was expired, false otherwise.
- */
- protected static function expireItem(array $item) {
- if (!empty($item['expiration'])) {
- $now = new \DateTime();
- $expires = new \DateTime($item['expiration']);
- if ($now > $expires) {
- self::unshareItem($item);
- return true;
- }
- }
- return false;
- }
-
- /**
- * Unshares a share given a share data array
- * @param array $item Share data (usually database row)
- * @return null
- */
- protected static function unshareItem(array $item) {
- // Pass all the vars we have for now, they may be useful
- $hookParams = array(
- 'itemType' => $item['item_type'],
- 'itemSource' => $item['item_source'],
- 'shareType' => $item['share_type'],
- 'shareWith' => $item['share_with'],
- 'itemParent' => $item['parent'],
- 'uidOwner' => $item['uid_owner'],
- );
-
- \OC_Hook::emit('OCP\Share', 'pre_unshare', $hookParams + array(
- 'fileSource' => $item['file_source'],
- ));
- self::delete($item['id']);
- \OC_Hook::emit('OCP\Share', 'post_unshare', $hookParams);
+ return \OC\Share\Share::setExpirationDate($itemType, $itemSource, $date);
}
/**
@@ -914,1018 +296,14 @@ class Share {
* @return Share_Backend
*/
public static function getBackend($itemType) {
- if (isset(self::$backends[$itemType])) {
- return self::$backends[$itemType];
- } else if (isset(self::$backendTypes[$itemType]['class'])) {
- $class = self::$backendTypes[$itemType]['class'];
- if (class_exists($class)) {
- self::$backends[$itemType] = new $class;
- if (!(self::$backends[$itemType] instanceof Share_Backend)) {
- $message = 'Sharing backend '.$class.' must implement the interface OCP\Share_Backend';
- \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
- throw new \Exception($message);
- }
- return self::$backends[$itemType];
- } else {
- $message = 'Sharing backend '.$class.' not found';
- \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
- throw new \Exception($message);
- }
- }
- $message = 'Sharing backend for '.$itemType.' not found';
- \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
- throw new \Exception($message);
- }
-
- /**
- * Check if resharing is allowed
- * @return boolean true if allowed or false
- *
- * Resharing is allowed by default if not configured
- */
- private static function isResharingAllowed() {
- if (!isset(self::$isResharingAllowed)) {
- if (\OC_Appconfig::getValue('core', 'shareapi_allow_resharing', 'yes') == 'yes') {
- self::$isResharingAllowed = true;
- } else {
- self::$isResharingAllowed = false;
- }
- }
- return self::$isResharingAllowed;
- }
-
- /**
- * Get a list of collection item types for the specified item type
- * @param string Item type
- * @return array
- */
- private static function getCollectionItemTypes($itemType) {
- $collectionTypes = array($itemType);
- foreach (self::$backendTypes as $type => $backend) {
- if (in_array($backend['collectionOf'], $collectionTypes)) {
- $collectionTypes[] = $type;
- }
- }
- // TODO Add option for collections to be collection of themselves, only 'folder' does it now...
- if (!self::getBackend($itemType) instanceof Share_Backend_Collection || $itemType != 'folder') {
- unset($collectionTypes[0]);
- }
- // Return array if collections were found or the item type is a
- // collection itself - collections can be inside collections
- if (count($collectionTypes) > 0) {
- return $collectionTypes;
- }
- return false;
- }
-
- /**
- * Get shared items from the database
- * @param string Item type
- * @param string Item source or target (optional)
- * @param int SHARE_TYPE_USER, SHARE_TYPE_GROUP, SHARE_TYPE_LINK, $shareTypeUserAndGroups, or $shareTypeGroupUserUnique
- * @param string User or group the item is being shared with
- * @param string User that is the owner of shared items (optional)
- * @param int Format to convert items to with formatItems()
- * @param mixed Parameters to pass to formatItems()
- * @param int Number of items to return, -1 to return all matches (optional)
- * @param bool Include collection item types (optional)
- * @param bool TODO (optional)
- * @prams bool check expire date
- * @return mixed
- *
- * See public functions getItem(s)... for parameter usage
- *
- */
- private static function getItems($itemType, $item = null, $shareType = null, $shareWith = null,
- $uidOwner = null, $format = self::FORMAT_NONE, $parameters = null, $limit = -1,
- $includeCollections = false, $itemShareWithBySource = false, $checkExpireDate = true) {
- if (!self::isEnabled()) {
- if ($limit == 1 || (isset($uidOwner) && isset($item))) {
- return false;
- } else {
- return array();
- }
- }
- $backend = self::getBackend($itemType);
- $collectionTypes = false;
- // Get filesystem root to add it to the file target and remove from the
- // file source, match file_source with the file cache
- if ($itemType == 'file' || $itemType == 'folder') {
- if(!is_null($uidOwner)) {
- $root = \OC\Files\Filesystem::getRoot();
- } else {
- $root = '';
- }
- $where = 'INNER JOIN `*PREFIX*filecache` ON `file_source` = `*PREFIX*filecache`.`fileid`';
- if (!isset($item)) {
- $where .= ' WHERE `file_target` IS NOT NULL';
- }
- $fileDependent = true;
- $queryArgs = array();
- } else {
- $fileDependent = false;
- $root = '';
- if ($includeCollections && !isset($item) && ($collectionTypes = self::getCollectionItemTypes($itemType))) {
- // If includeCollections is true, find collections of this item type, e.g. a music album contains songs
- if (!in_array($itemType, $collectionTypes)) {
- $itemTypes = array_merge(array($itemType), $collectionTypes);
- } else {
- $itemTypes = $collectionTypes;
- }
- $placeholders = join(',', array_fill(0, count($itemTypes), '?'));
- $where = ' WHERE `item_type` IN ('.$placeholders.'))';
- $queryArgs = $itemTypes;
- } else {
- $where = ' WHERE `item_type` = ?';
- $queryArgs = array($itemType);
- }
- }
- if (\OC_Appconfig::getValue('core', 'shareapi_allow_links', 'yes') !== 'yes') {
- $where .= ' AND `share_type` != ?';
- $queryArgs[] = self::SHARE_TYPE_LINK;
- }
- if (isset($shareType)) {
- // Include all user and group items
- if ($shareType == self::$shareTypeUserAndGroups && isset($shareWith)) {
- $where .= ' AND `share_type` IN (?,?,?)';
- $queryArgs[] = self::SHARE_TYPE_USER;
- $queryArgs[] = self::SHARE_TYPE_GROUP;
- $queryArgs[] = self::$shareTypeGroupUserUnique;
- $userAndGroups = array_merge(array($shareWith), \OC_Group::getUserGroups($shareWith));
- $placeholders = join(',', array_fill(0, count($userAndGroups), '?'));
- $where .= ' AND `share_with` IN ('.$placeholders.')';
- $queryArgs = array_merge($queryArgs, $userAndGroups);
- // Don't include own group shares
- $where .= ' AND `uid_owner` != ?';
- $queryArgs[] = $shareWith;
- } else {
- $where .= ' AND `share_type` = ?';
- $queryArgs[] = $shareType;
- if (isset($shareWith)) {
- $where .= ' AND `share_with` = ?';
- $queryArgs[] = $shareWith;
- }
- }
- }
- if (isset($uidOwner)) {
- $where .= ' AND `uid_owner` = ?';
- $queryArgs[] = $uidOwner;
- if (!isset($shareType)) {
- // Prevent unique user targets for group shares from being selected
- $where .= ' AND `share_type` != ?';
- $queryArgs[] = self::$shareTypeGroupUserUnique;
- }
- if ($itemType == 'file' || $itemType == 'folder') {
- $column = 'file_source';
- } else {
- $column = 'item_source';
- }
- } else {
- if ($itemType == 'file' || $itemType == 'folder') {
- $column = 'file_target';
- } else {
- $column = 'item_target';
- }
- }
- if (isset($item)) {
- if ($includeCollections && $collectionTypes = self::getCollectionItemTypes($itemType)) {
- $where .= ' AND (';
- } else {
- $where .= ' AND';
- }
- // If looking for own shared items, check item_source else check item_target
- if (isset($uidOwner) || $itemShareWithBySource) {
- // If item type is a file, file source needs to be checked in case the item was converted
- if ($itemType == 'file' || $itemType == 'folder') {
- $where .= ' `file_source` = ?';
- $column = 'file_source';
- } else {
- $where .= ' `item_source` = ?';
- $column = 'item_source';
- }
- } else {
- if ($itemType == 'file' || $itemType == 'folder') {
- $where .= ' `file_target` = ?';
- $item = \OC\Files\Filesystem::normalizePath($item);
- } else {
- $where .= ' `item_target` = ?';
- }
- }
- $queryArgs[] = $item;
- if ($includeCollections && $collectionTypes) {
- $placeholders = join(',', array_fill(0, count($collectionTypes), '?'));
- $where .= ' OR `item_type` IN ('.$placeholders.'))';
- $queryArgs = array_merge($queryArgs, $collectionTypes);
- }
- }
- if ($limit != -1 && !$includeCollections) {
- if ($shareType == self::$shareTypeUserAndGroups) {
- // Make sure the unique user target is returned if it exists,
- // unique targets should follow the group share in the database
- // If the limit is not 1, the filtering can be done later
- $where .= ' ORDER BY `*PREFIX*share`.`id` DESC';
- }
- // The limit must be at least 3, because filtering needs to be done
- if ($limit < 3) {
- $queryLimit = 3;
- } else {
- $queryLimit = $limit;
- }
- } else {
- $queryLimit = null;
- }
- // TODO Optimize selects
- if ($format == self::FORMAT_STATUSES) {
- if ($itemType == 'file' || $itemType == 'folder') {
- $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `*PREFIX*share`.`parent`,'
- .' `share_type`, `file_source`, `path`, `expiration`, `storage`, `share_with`, `mail_send`, `uid_owner`';
- } else {
- $select = '`id`, `item_type`, `item_source`, `parent`, `share_type`, `share_with`, `expiration`, `mail_send`, `uid_owner`';
- }
- } else {
- if (isset($uidOwner)) {
- if ($itemType == 'file' || $itemType == 'folder') {
- $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `*PREFIX*share`.`parent`,'
- .' `share_type`, `share_with`, `file_source`, `path`, `permissions`, `stime`,'
- .' `expiration`, `token`, `storage`, `mail_send`, `uid_owner`';
- } else {
- $select = '`id`, `item_type`, `item_source`, `parent`, `share_type`, `share_with`, `permissions`,'
- .' `stime`, `file_source`, `expiration`, `token`, `mail_send`, `uid_owner`';
- }
- } else {
- if ($fileDependent) {
- if (($itemType == 'file' || $itemType == 'folder')
- && $format == \OC_Share_Backend_File::FORMAT_GET_FOLDER_CONTENTS
- || $format == \OC_Share_Backend_File::FORMAT_FILE_APP_ROOT
- ) {
- $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `*PREFIX*share`.`parent`, `uid_owner`, '
- .'`share_type`, `share_with`, `file_source`, `path`, `file_target`, '
- .'`permissions`, `expiration`, `storage`, `*PREFIX*filecache`.`parent` as `file_parent`, '
- .'`name`, `mtime`, `mimetype`, `mimepart`, `size`, `unencrypted_size`, `encrypted`, `etag`, `mail_send`';
- } else {
- $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `item_target`,
- `*PREFIX*share`.`parent`, `share_type`, `share_with`, `uid_owner`,
- `file_source`, `path`, `file_target`, `permissions`, `stime`, `expiration`, `token`, `storage`, `mail_send`';
- }
- } else {
- $select = '*';
- }
- }
- }
- $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();
- $switchedItems = array();
- $mounts = array();
- while ($row = $result->fetchRow()) {
- if (isset($row['id'])) {
- $row['id']=(int)$row['id'];
- }
- if (isset($row['share_type'])) {
- $row['share_type']=(int)$row['share_type'];
- }
- if (isset($row['parent'])) {
- $row['parent']=(int)$row['parent'];
- }
- if (isset($row['file_parent'])) {
- $row['file_parent']=(int)$row['file_parent'];
- }
- if (isset($row['file_source'])) {
- $row['file_source']=(int)$row['file_source'];
- }
- if (isset($row['permissions'])) {
- $row['permissions']=(int)$row['permissions'];
- }
- if (isset($row['storage'])) {
- $row['storage']=(int)$row['storage'];
- }
- if (isset($row['stime'])) {
- $row['stime']=(int)$row['stime'];
- }
- // Filter out duplicate group shares for users with unique targets
- if ($row['share_type'] == self::$shareTypeGroupUserUnique && isset($items[$row['parent']])) {
- $row['share_type'] = self::SHARE_TYPE_GROUP;
- $row['share_with'] = $items[$row['parent']]['share_with'];
- // Remove the parent group share
- unset($items[$row['parent']]);
- if ($row['permissions'] == 0) {
- continue;
- }
- } else if (!isset($uidOwner)) {
- // Check if the same target already exists
- if (isset($targets[$row[$column]])) {
- // Check if the same owner shared with the user twice
- // through a group and user share - this is allowed
- $id = $targets[$row[$column]];
- if (isset($items[$id]) && $items[$id]['uid_owner'] == $row['uid_owner']) {
- // Switch to group share type to ensure resharing conditions aren't bypassed
- if ($items[$id]['share_type'] != self::SHARE_TYPE_GROUP) {
- $items[$id]['share_type'] = self::SHARE_TYPE_GROUP;
- $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'] & PERMISSION_SHARE
- && (int)$row['permissions'] & PERMISSION_SHARE) {
- $items[$row['id']] = $items[$id];
- $switchedItems[$id] = $row['id'];
- unset($items[$id]);
- $id = $row['id'];
- }
- // Combine the permissions for the item
- $items[$id]['permissions'] |= (int)$row['permissions'];
- continue;
- }
- } else {
- $targets[$row[$column]] = $row['id'];
- }
- }
- // Remove root from file source paths if retrieving own shared items
- if (isset($uidOwner) && isset($row['path'])) {
- if (isset($row['parent'])) {
- // FIXME: Doesn't always construct the correct path, example:
- // Folder '/a/b', share '/a' and '/a/b' to user2
- // user2 reshares /Shared/b and ask for share status of /Shared/a/b
- // expected result: path=/Shared/a/b; actual result /Shared/b because of the parent
- $query = \OC_DB::prepare('SELECT `file_target` FROM `*PREFIX*share` WHERE `id` = ?');
- $parentResult = $query->execute(array($row['parent']));
- if (\OC_DB::isError($result)) {
- \OC_Log::write('OCP\Share', 'Can\'t select parent: ' .
- \OC_DB::getErrorMessage($result) . ', select=' . $select . ' where=' . $where,
- \OC_Log::ERROR);
- } else {
- $parentRow = $parentResult->fetchRow();
- $tmpPath = '/Shared' . $parentRow['file_target'];
- // find the right position where the row path continues from the target path
- $pos = strrpos($row['path'], $parentRow['file_target']);
- $subPath = substr($row['path'], $pos);
- $splitPath = explode('/', $subPath);
- foreach (array_slice($splitPath, 2) as $pathPart) {
- $tmpPath = $tmpPath . '/' . $pathPart;
- }
- $row['path'] = $tmpPath;
- }
- } else {
- if (!isset($mounts[$row['storage']])) {
- $mountPoints = \OC\Files\Filesystem::getMountByNumericId($row['storage']);
- if (is_array($mountPoints)) {
- $mounts[$row['storage']] = current($mountPoints);
- }
- }
- if ($mounts[$row['storage']]) {
- $path = $mounts[$row['storage']]->getMountPoint().$row['path'];
- $row['path'] = substr($path, $root);
- }
- }
- }
- if($checkExpireDate) {
- if (self::expireItem($row)) {
- continue;
- }
- }
- // Check if resharing is allowed, if not remove share permission
- if (isset($row['permissions']) && !self::isResharingAllowed()) {
- $row['permissions'] &= ~PERMISSION_SHARE;
- }
- // Add display names to result
- if ( isset($row['share_with']) && $row['share_with'] != '') {
- $row['share_with_displayname'] = \OCP\User::getDisplayName($row['share_with']);
- }
- if ( isset($row['uid_owner']) && $row['uid_owner'] != '') {
- $row['displayname_owner'] = \OCP\User::getDisplayName($row['uid_owner']);
- }
-
- $items[$row['id']] = $row;
- }
- if (!empty($items)) {
- $collectionItems = array();
- foreach ($items as &$row) {
- // Return only the item instead of a 2-dimensional array
- if ($limit == 1 && $row[$column] == $item && ($row['item_type'] == $itemType || $itemType == 'file')) {
- if ($format == self::FORMAT_NONE) {
- return $row;
- } else {
- break;
- }
- }
- // Check if this is a collection of the requested item type
- if ($includeCollections && $collectionTypes && in_array($row['item_type'], $collectionTypes)) {
- if (($collectionBackend = self::getBackend($row['item_type']))
- && $collectionBackend instanceof Share_Backend_Collection) {
- // Collections can be inside collections, check if the item is a collection
- if (isset($item) && $row['item_type'] == $itemType && $row[$column] == $item) {
- $collectionItems[] = $row;
- } else {
- $collection = array();
- $collection['item_type'] = $row['item_type'];
- if ($row['item_type'] == 'file' || $row['item_type'] == 'folder') {
- $collection['path'] = basename($row['path']);
- }
- $row['collection'] = $collection;
- // Fetch all of the children sources
- $children = $collectionBackend->getChildren($row[$column]);
- foreach ($children as $child) {
- $childItem = $row;
- $childItem['item_type'] = $itemType;
- if ($row['item_type'] != 'file' && $row['item_type'] != 'folder') {
- $childItem['item_source'] = $child['source'];
- $childItem['item_target'] = $child['target'];
- }
- if ($backend instanceof Share_Backend_File_Dependent) {
- if ($row['item_type'] == 'file' || $row['item_type'] == 'folder') {
- $childItem['file_source'] = $child['source'];
- } else {
- $meta = \OC\Files\Filesystem::getFileInfo($child['file_path']);
- $childItem['file_source'] = $meta['fileid'];
- }
- $childItem['file_target'] =
- \OC\Files\Filesystem::normalizePath($child['file_path']);
- }
- if (isset($item)) {
- if ($childItem[$column] == $item) {
- // Return only the item instead of a 2-dimensional array
- if ($limit == 1) {
- if ($format == self::FORMAT_NONE) {
- return $childItem;
- } else {
- // Unset the items array and break out of both loops
- $items = array();
- $items[] = $childItem;
- break 2;
- }
- } else {
- $collectionItems[] = $childItem;
- }
- }
- } else {
- $collectionItems[] = $childItem;
- }
- }
- }
- }
- // Remove collection item
- $toRemove = $row['id'];
- if (array_key_exists($toRemove, $switchedItems)) {
- $toRemove = $switchedItems[$toRemove];
- }
- unset($items[$toRemove]);
- }
- }
- if (!empty($collectionItems)) {
- $items = array_merge($items, $collectionItems);
- }
- if (empty($items) && $limit == 1) {
- return false;
- }
- if ($format == self::FORMAT_NONE) {
- return $items;
- } else if ($format == self::FORMAT_STATUSES) {
- $statuses = array();
- foreach ($items as $item) {
- if ($item['share_type'] == self::SHARE_TYPE_LINK) {
- $statuses[$item[$column]]['link'] = true;
- } else if (!isset($statuses[$item[$column]])) {
- $statuses[$item[$column]]['link'] = false;
- }
- if ($itemType == 'file' || $itemType == 'folder') {
- $statuses[$item[$column]]['path'] = $item['path'];
- }
- }
- return $statuses;
- } else {
- return $backend->formatItems($items, $format, $parameters);
- }
- } else if ($limit == 1 || (isset($uidOwner) && isset($item))) {
- return false;
- }
- return array();
- }
-
- /**
- * Put shared item into the database
- * @param string $itemType Item type
- * @param string $itemSource Item source
- * @param integer $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
- * @param string $shareWith User or group the item is being shared with
- * @param string $uidOwner User that is the owner of shared item
- * @param int $permissions CRUDS permissions
- * @param bool|array, $parentFolder Parent folder target (optional)
- * @param string $token (optional)
- * @param string $itemSourceName name of the source item (optional)
- * @return bool Returns true on success or false on failure
- */
- private static function put($itemType, $itemSource, $shareType, $shareWith, $uidOwner,
- $permissions, $parentFolder = null, $token = null, $itemSourceName = null) {
- $backend = self::getBackend($itemType);
-
- // Check if this is a reshare
- if ($checkReshare = self::getItemSharedWithBySource($itemType, $itemSource, self::FORMAT_NONE, null, true)) {
-
- // Check if attempting to share back to owner
- if ($checkReshare['uid_owner'] == $shareWith && $shareType == self::SHARE_TYPE_USER) {
- $message = 'Sharing '.$itemSourceName.' failed, because the user '.$shareWith.' is the original sharer';
- \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
- throw new \Exception($message);
- }
- // Check if share permissions is granted
- if (self::isResharingAllowed() && (int)$checkReshare['permissions'] & PERMISSION_SHARE) {
- if (~(int)$checkReshare['permissions'] & $permissions) {
- $message = 'Sharing '.$itemSourceName
- .' failed, because the permissions exceed permissions granted to '.$uidOwner;
- \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
- throw new \Exception($message);
- } else {
- // TODO Don't check if inside folder
- $parent = $checkReshare['id'];
- $itemSource = $checkReshare['item_source'];
- $fileSource = $checkReshare['file_source'];
- $suggestedItemTarget = $checkReshare['item_target'];
- $suggestedFileTarget = $checkReshare['file_target'];
- $filePath = $checkReshare['file_target'];
- }
- } else {
- $message = 'Sharing '.$itemSourceName.' failed, because resharing is not allowed';
- \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
- throw new \Exception($message);
- }
- } else {
- $parent = null;
- $suggestedItemTarget = null;
- $suggestedFileTarget = null;
- if (!$backend->isValidSource($itemSource, $uidOwner)) {
- $message = 'Sharing '.$itemSource.' failed, because the sharing backend for '
- .$itemType.' could not find its source';
- \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
- throw new \Exception($message);
- }
- $parent = null;
- if ($backend instanceof Share_Backend_File_Dependent) {
- $filePath = $backend->getFilePath($itemSource, $uidOwner);
- if ($itemType == 'file' || $itemType == 'folder') {
- $fileSource = $itemSource;
- } else {
- $meta = \OC\Files\Filesystem::getFileInfo($filePath);
- $fileSource = $meta['fileid'];
- }
- if ($fileSource == -1) {
- $message = 'Sharing '.$itemSource.' failed, because the file could not be found in the file cache';
- \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
- throw new \Exception($message);
- }
- } else {
- $filePath = null;
- $fileSource = null;
- }
- }
- $query = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`item_type`, `item_source`, `item_target`,'
- .' `parent`, `share_type`, `share_with`, `uid_owner`, `permissions`, `stime`, `file_source`,'
- .' `file_target`, `token`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)');
- // Share with a group
- if ($shareType == self::SHARE_TYPE_GROUP) {
- $groupItemTarget = self::generateTarget($itemType, $itemSource, $shareType, $shareWith['group'],
- $uidOwner, $suggestedItemTarget);
- $run = true;
- $error = '';
- \OC_Hook::emit('OCP\Share', 'pre_shared', array(
- 'itemType' => $itemType,
- 'itemSource' => $itemSource,
- 'itemTarget' => $groupItemTarget,
- 'shareType' => $shareType,
- 'shareWith' => $shareWith['group'],
- 'uidOwner' => $uidOwner,
- 'permissions' => $permissions,
- 'fileSource' => $fileSource,
- 'token' => $token,
- 'run' => &$run,
- 'error' => &$error
- ));
-
- if ($run === false) {
- throw new \Exception($error);
- }
-
- if (isset($fileSource)) {
- if ($parentFolder) {
- if ($parentFolder === true) {
- $groupFileTarget = self::generateTarget('file', $filePath, $shareType,
- $shareWith['group'], $uidOwner, $suggestedFileTarget);
- // Set group default file target for future use
- $parentFolders[0]['folder'] = $groupFileTarget;
- } else {
- // Get group default file target
- $groupFileTarget = $parentFolder[0]['folder'].$itemSource;
- $parent = $parentFolder[0]['id'];
- }
- } else {
- $groupFileTarget = self::generateTarget('file', $filePath, $shareType, $shareWith['group'],
- $uidOwner, $suggestedFileTarget);
- }
- } else {
- $groupFileTarget = null;
- }
- $query->execute(array($itemType, $itemSource, $groupItemTarget, $parent, $shareType,
- $shareWith['group'], $uidOwner, $permissions, time(), $fileSource, $groupFileTarget, $token));
- // Save this id, any extra rows for this group share will need to reference it
- $parent = \OC_DB::insertid('*PREFIX*share');
- // Loop through all users of this group in case we need to add an extra row
- foreach ($shareWith['users'] as $uid) {
- $itemTarget = self::generateTarget($itemType, $itemSource, self::SHARE_TYPE_USER, $uid,
- $uidOwner, $suggestedItemTarget, $parent);
- if (isset($fileSource)) {
- if ($parentFolder) {
- if ($parentFolder === true) {
- $fileTarget = self::generateTarget('file', $filePath, self::SHARE_TYPE_USER, $uid,
- $uidOwner, $suggestedFileTarget, $parent);
- if ($fileTarget != $groupFileTarget) {
- $parentFolders[$uid]['folder'] = $fileTarget;
- }
- } else if (isset($parentFolder[$uid])) {
- $fileTarget = $parentFolder[$uid]['folder'].$itemSource;
- $parent = $parentFolder[$uid]['id'];
- }
- } else {
- $fileTarget = self::generateTarget('file', $filePath, self::SHARE_TYPE_USER,
- $uid, $uidOwner, $suggestedFileTarget, $parent);
- }
- } else {
- $fileTarget = null;
- }
- // Insert an extra row for the group share if the item or file target is unique for this user
- if ($itemTarget != $groupItemTarget || (isset($fileSource) && $fileTarget != $groupFileTarget)) {
- $query->execute(array($itemType, $itemSource, $itemTarget, $parent,
- self::$shareTypeGroupUserUnique, $uid, $uidOwner, $permissions, time(),
- $fileSource, $fileTarget, $token));
- $id = \OC_DB::insertid('*PREFIX*share');
- }
- }
- \OC_Hook::emit('OCP\Share', 'post_shared', array(
- 'itemType' => $itemType,
- 'itemSource' => $itemSource,
- 'itemTarget' => $groupItemTarget,
- 'parent' => $parent,
- 'shareType' => $shareType,
- 'shareWith' => $shareWith['group'],
- 'uidOwner' => $uidOwner,
- 'permissions' => $permissions,
- 'fileSource' => $fileSource,
- 'fileTarget' => $groupFileTarget,
- 'id' => $parent,
- 'token' => $token
- ));
-
- if ($parentFolder === true) {
- // Return parent folders to preserve file target paths for potential children
- return $parentFolders;
- }
- } else {
- $itemTarget = self::generateTarget($itemType, $itemSource, $shareType, $shareWith, $uidOwner,
- $suggestedItemTarget);
- $run = true;
- $error = '';
- \OC_Hook::emit('OCP\Share', 'pre_shared', array(
- 'itemType' => $itemType,
- 'itemSource' => $itemSource,
- 'itemTarget' => $itemTarget,
- 'shareType' => $shareType,
- 'shareWith' => $shareWith,
- 'uidOwner' => $uidOwner,
- 'permissions' => $permissions,
- 'fileSource' => $fileSource,
- 'token' => $token,
- 'run' => &$run,
- 'error' => &$error
- ));
-
- if ($run === false) {
- throw new \Exception($error);
- }
-
- if (isset($fileSource)) {
- if ($parentFolder) {
- if ($parentFolder === true) {
- $fileTarget = self::generateTarget('file', $filePath, $shareType, $shareWith,
- $uidOwner, $suggestedFileTarget);
- $parentFolders['folder'] = $fileTarget;
- } else {
- $fileTarget = $parentFolder['folder'].$itemSource;
- $parent = $parentFolder['id'];
- }
- } else {
- $fileTarget = self::generateTarget('file', $filePath, $shareType, $shareWith, $uidOwner,
- $suggestedFileTarget);
- }
- } else {
- $fileTarget = null;
- }
- $query->execute(array($itemType, $itemSource, $itemTarget, $parent, $shareType, $shareWith, $uidOwner,
- $permissions, time(), $fileSource, $fileTarget, $token));
- $id = \OC_DB::insertid('*PREFIX*share');
- \OC_Hook::emit('OCP\Share', 'post_shared', array(
- 'itemType' => $itemType,
- 'itemSource' => $itemSource,
- 'itemTarget' => $itemTarget,
- 'parent' => $parent,
- 'shareType' => $shareType,
- 'shareWith' => $shareWith,
- 'uidOwner' => $uidOwner,
- 'permissions' => $permissions,
- 'fileSource' => $fileSource,
- 'fileTarget' => $fileTarget,
- 'id' => $id,
- 'token' => $token
- ));
- if ($parentFolder === true) {
- $parentFolders['id'] = $id;
- // Return parent folder to preserve file target paths for potential children
- return $parentFolders;
- }
- }
- return true;
- }
-
- /**
- * Generate a unique target for the item
- * @param string Item type
- * @param string Item source
- * @param int SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
- * @param string User or group the item is being shared with
- * @param string User that is the owner of shared item
- * @param string The suggested target originating from a reshare (optional)
- * @param int The id of the parent group share (optional)
- * @param integer $shareType
- * @return string Item target
- */
- private static function generateTarget($itemType, $itemSource, $shareType, $shareWith, $uidOwner,
- $suggestedTarget = null, $groupParent = null) {
- $backend = self::getBackend($itemType);
- if ($shareType == self::SHARE_TYPE_LINK) {
- if (isset($suggestedTarget)) {
- return $suggestedTarget;
- }
- return $backend->generateTarget($itemSource, false);
- } else {
- if ($itemType == 'file' || $itemType == 'folder') {
- $column = 'file_target';
- $columnSource = 'file_source';
- } else {
- $column = 'item_target';
- $columnSource = 'item_source';
- }
- if ($shareType == self::SHARE_TYPE_USER) {
- // Share with is a user, so set share type to user and groups
- $shareType = self::$shareTypeUserAndGroups;
- $userAndGroups = array_merge(array($shareWith), \OC_Group::getUserGroups($shareWith));
- } else {
- $userAndGroups = false;
- }
- $exclude = null;
- // Backend has 3 opportunities to generate a unique target
- for ($i = 0; $i < 2; $i++) {
- // Check if suggested target exists first
- if ($i == 0 && isset($suggestedTarget)) {
- $target = $suggestedTarget;
- } else {
- if ($shareType == self::SHARE_TYPE_GROUP) {
- $target = $backend->generateTarget($itemSource, false, $exclude);
- } else {
- $target = $backend->generateTarget($itemSource, $shareWith, $exclude);
- }
- if (is_array($exclude) && in_array($target, $exclude)) {
- break;
- }
- }
- // Check if target already exists
- $checkTarget = self::getItems($itemType, $target, $shareType, $shareWith);
- if (!empty($checkTarget)) {
- foreach ($checkTarget as $item) {
- // Skip item if it is the group parent row
- if (isset($groupParent) && $item['id'] == $groupParent) {
- if (count($checkTarget) == 1) {
- return $target;
- } else {
- continue;
- }
- }
- if ($item['uid_owner'] == $uidOwner) {
- if ($itemType == 'file' || $itemType == 'folder') {
- $meta = \OC\Files\Filesystem::getFileInfo($itemSource);
- if ($item['file_source'] == $meta['fileid']) {
- return $target;
- }
- } else if ($item['item_source'] == $itemSource) {
- return $target;
- }
- }
- }
- if (!isset($exclude)) {
- $exclude = array();
- }
- // Find similar targets to improve backend's chances to generate a unqiue target
- if ($userAndGroups) {
- if ($column == 'file_target') {
- $checkTargets = \OC_DB::prepare('SELECT `'.$column.'` FROM `*PREFIX*share`'
- .' WHERE `item_type` IN (\'file\', \'folder\')'
- .' AND `share_type` IN (?,?,?)'
- .' AND `share_with` IN (\''.implode('\',\'', $userAndGroups).'\')');
- $result = $checkTargets->execute(array(self::SHARE_TYPE_USER, self::SHARE_TYPE_GROUP,
- self::$shareTypeGroupUserUnique));
- } else {
- $checkTargets = \OC_DB::prepare('SELECT `'.$column.'` FROM `*PREFIX*share`'
- .' WHERE `item_type` = ? AND `share_type` IN (?,?,?)'
- .' AND `share_with` IN (\''.implode('\',\'', $userAndGroups).'\')');
- $result = $checkTargets->execute(array($itemType, self::SHARE_TYPE_USER,
- self::SHARE_TYPE_GROUP, self::$shareTypeGroupUserUnique));
- }
- } else {
- if ($column == 'file_target') {
- $checkTargets = \OC_DB::prepare('SELECT `'.$column.'` FROM `*PREFIX*share`'
- .' WHERE `item_type` IN (\'file\', \'folder\')'
- .' AND `share_type` = ? AND `share_with` = ?');
- $result = $checkTargets->execute(array(self::SHARE_TYPE_GROUP, $shareWith));
- } else {
- $checkTargets = \OC_DB::prepare('SELECT `'.$column.'` FROM `*PREFIX*share`'
- .' WHERE `item_type` = ? AND `share_type` = ? AND `share_with` = ?');
- $result = $checkTargets->execute(array($itemType, self::SHARE_TYPE_GROUP, $shareWith));
- }
- }
- while ($row = $result->fetchRow()) {
- $exclude[] = $row[$column];
- }
- } else {
- return $target;
- }
- }
- }
- $message = 'Sharing backend registered for '.$itemType.' did not generate a unique target for '.$itemSource;
- \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
- throw new \Exception($message);
- }
-
- /**
- * Delete all reshares of an item
- * @param int Id of item to delete
- * @param bool If true, exclude the parent from the delete (optional)
- * @param string The user that the parent was shared with (optinal)
- */
- private static function delete($parent, $excludeParent = false, $uidOwner = null) {
- $ids = array($parent);
- $parents = array($parent);
- while (!empty($parents)) {
- $parents = "'".implode("','", $parents)."'";
- // Check the owner on the first search of reshares, useful for
- // finding and deleting the reshares by a single user of a group share
- if (count($ids) == 1 && isset($uidOwner)) {
- $query = \OC_DB::prepare('SELECT `id`, `uid_owner`, `item_type`, `item_target`, `parent`'
- .' FROM `*PREFIX*share` WHERE `parent` IN ('.$parents.') AND `uid_owner` = ?');
- $result = $query->execute(array($uidOwner));
- } else {
- $query = \OC_DB::prepare('SELECT `id`, `item_type`, `item_target`, `parent`, `uid_owner`'
- .' FROM `*PREFIX*share` WHERE `parent` IN ('.$parents.')');
- $result = $query->execute();
- }
- // Reset parents array, only go through loop again if items are found
- $parents = array();
- while ($item = $result->fetchRow()) {
- // Search for a duplicate parent share, this occurs when an
- // item is shared to the same user through a group and user or the
- // same item is shared by different users
- $userAndGroups = array_merge(array($item['uid_owner']), \OC_Group::getUserGroups($item['uid_owner']));
- $query = \OC_DB::prepare('SELECT `id`, `permissions` FROM `*PREFIX*share`'
- .' WHERE `item_type` = ?'
- .' AND `item_target` = ?'
- .' AND `share_type` IN (?,?,?)'
- .' AND `share_with` IN (\''.implode('\',\'', $userAndGroups).'\')'
- .' AND `uid_owner` != ? AND `id` != ?');
- $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'] & PERMISSION_SHARE) {
- $query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `parent` = ? WHERE `id` = ?');
- $query->execute(array($duplicateParent['id'], $item['id']));
- continue;
- }
- }
- $ids[] = $item['id'];
- $parents[] = $item['id'];
- }
- }
- if ($excludeParent) {
- unset($ids[0]);
- }
- if (!empty($ids)) {
- $ids = "'".implode("','", $ids)."'";
- $query = \OC_DB::prepare('DELETE FROM `*PREFIX*share` WHERE `id` IN ('.$ids.')');
- $query->execute();
- }
+ return \OC\Share\Share::getBackend($itemType);
}
/**
* Delete all shares with type SHARE_TYPE_LINK
*/
public static function removeAllLinkShares() {
- // Delete any link shares
- $query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*share` WHERE `share_type` = ?');
- $result = $query->execute(array(self::SHARE_TYPE_LINK));
- while ($item = $result->fetchRow()) {
- self::delete($item['id']);
- }
- }
-
- /**
- * Hook Listeners
- */
-
- /**
- * Function that is called after a user is deleted. Cleans up the shares of that user.
- * @param array arguments
- */
- public static function post_deleteUser($arguments) {
- // Delete any items shared with the deleted user
- $query = \OC_DB::prepare('DELETE FROM `*PREFIX*share`'
- .' WHERE `share_with` = ? AND `share_type` = ? OR `share_type` = ?');
- $result = $query->execute(array($arguments['uid'], self::SHARE_TYPE_USER, self::$shareTypeGroupUserUnique));
- // Delete any items the deleted user shared
- $query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*share` WHERE `uid_owner` = ?');
- $result = $query->execute(array($arguments['uid']));
- while ($item = $result->fetchRow()) {
- self::delete($item['id']);
- }
- }
-
- /**
- * Function that is called after a user is added to a group.
- * TODO what does it do?
- * @param array arguments
- */
- public static function post_addToGroup($arguments) {
- // Find the group shares and check if the user needs a unique target
- $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share` WHERE `share_type` = ? AND `share_with` = ?');
- $result = $query->execute(array(self::SHARE_TYPE_GROUP, $arguments['gid']));
- $query = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`item_type`, `item_source`,'
- .' `item_target`, `parent`, `share_type`, `share_with`, `uid_owner`, `permissions`,'
- .' `stime`, `file_source`, `file_target`) VALUES (?,?,?,?,?,?,?,?,?,?,?)');
- while ($item = $result->fetchRow()) {
- if ($item['item_type'] == 'file' || $item['item_type'] == 'file') {
- $itemTarget = null;
- } else {
- $itemTarget = self::generateTarget($item['item_type'], $item['item_source'], self::SHARE_TYPE_USER,
- $arguments['uid'], $item['uid_owner'], $item['item_target'], $item['id']);
- }
- if (isset($item['file_source'])) {
- $fileTarget = self::generateTarget($item['item_type'], $item['item_source'], self::SHARE_TYPE_USER,
- $arguments['uid'], $item['uid_owner'], $item['file_target'], $item['id']);
- } else {
- $fileTarget = null;
- }
- // Insert an extra row for the group share if the item or file target is unique for this user
- if ($itemTarget != $item['item_target'] || $fileTarget != $item['file_target']) {
- $query->execute(array($item['item_type'], $item['item_source'], $itemTarget, $item['id'],
- self::$shareTypeGroupUserUnique, $arguments['uid'], $item['uid_owner'], $item['permissions'],
- $item['stime'], $item['file_source'], $fileTarget));
- \OC_DB::insertid('*PREFIX*share');
- }
- }
- }
-
- /**
- * Function that is called after a user is removed from a group. Shares are cleaned up.
- * @param array arguments
- */
- public static function post_removeFromGroup($arguments) {
- // TODO Don't call if user deleted?
- $sql = 'SELECT `id`, `share_type` FROM `*PREFIX*share`'
- .' WHERE (`share_type` = ? AND `share_with` = ?) OR (`share_type` = ? AND `share_with` = ?)';
- $result = \OC_DB::executeAudited($sql, array(self::SHARE_TYPE_GROUP, $arguments['gid'],
- self::$shareTypeGroupUserUnique, $arguments['uid']));
- while ($item = $result->fetchRow()) {
- if ($item['share_type'] == self::SHARE_TYPE_GROUP) {
- // Delete all reshares by this user of the group share
- self::delete($item['id'], true, $arguments['uid']);
- } else {
- self::delete($item['id']);
- }
- }
- }
-
- /**
- * Function that is called after a group is removed. Cleans up the shares to that group.
- * @param array arguments
- */
- public static function post_deleteGroup($arguments) {
- $sql = 'SELECT `id` FROM `*PREFIX*share` WHERE `share_type` = ? AND `share_with` = ?';
- $result = \OC_DB::executeAudited($sql, array(self::SHARE_TYPE_GROUP, $arguments['gid']));
- while ($item = $result->fetchRow()) {
- self::delete($item['id']);
- }
+ return \OC\Share\Share::removeAllLinkShares();
}
/**
@@ -1935,26 +313,7 @@ class Share {
* @return bool
*/
public static function checkPasswordProtectedShare(array $linkItem) {
- if (!isset($linkItem['share_with'])) {
- return true;
- }
- if (!isset($linkItem['share_type'])) {
- return true;
- }
- if (!isset($linkItem['id'])) {
- return true;
- }
-
- if ($linkItem['share_type'] != \OCP\Share::SHARE_TYPE_LINK) {
- return true;
- }
-
- if ( \OC::$session->exists('public_link_authenticated')
- && \OC::$session->get('public_link_authenticated') === $linkItem['id'] ) {
- return true;
- }
-
- return false;
+ return \OC\Share\Share::checkPasswordProtectedShare($linkItem);
}
}
@@ -1967,9 +326,7 @@ interface Share_Backend {
* Get the source of the item to be stored in the database
* @param string Item source
* @param string Owner of the item
- * @param string $itemSource
- * @param string $uidOwner
- * @return boolean Source
+ * @return mixed|array|false Source
*
* Return an array if the item is file dependent, the array needs two keys: 'item' and 'file'
* Return false if the item does not exist for the user
@@ -1992,8 +349,8 @@ interface Share_Backend {
/**
* Converts the shared item sources back into the item in the specified format
- * @param array $items Shared items
- * @param integer $format
+ * @param array Shared items
+ * @param int Format
* @return TODO
*
* The items array is a 3-dimensional array with the item_source as the
@@ -2025,9 +382,6 @@ interface Share_Backend_File_Dependent extends Share_Backend {
* Get the file path of the item
* @param string Item source
* @param string User that is the owner of shared item
- * @param string $itemSource
- * @param string $uidOwner
- * @return boolean
*/
public function getFilePath($itemSource, $uidOwner);