summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorAndreas Fischer <bantu@owncloud.com>2013-12-14 18:32:48 +0100
committerAndreas Fischer <bantu@owncloud.com>2013-12-14 18:32:48 +0100
commitc205d8d1c957ab5421a5864d183257f596336d2d (patch)
treea097ff1232f1283074c2cbd589fa1fddac037391 /lib
parentd73285c1869591da74c148b577d780a73313fe90 (diff)
parent77b68505c2164330803ce5d5dcbb9fd07438e18d (diff)
downloadnextcloud-server-c205d8d1c957ab5421a5864d183257f596336d2d.tar.gz
nextcloud-server-c205d8d1c957ab5421a5864d183257f596336d2d.zip
Merge remote-tracking branch 'owncloud/master' into fixing-3417-master
* owncloud/master: (1989 commits) [tx-robot] updated from transifex dont try to register background jobs if we haven't upgraded yet adjust test coding style coding style On webdav sesssions, loginname was compared to username which does not need to match necessarily rely only on php DateTime to parse the db datetime string LDAP: fix method behind save button on advancend and expert tabs, fixes at least Home Folder setinng Fix webroot for update page Update 3rdparty ref update 3rdparty toggle select all checkbox remove unneeded ; in comment LDAP: the browser shall not autofill userdn and password, usually login credentials are inserted. fixes #6283 Add test for having utf8 filenames in the cache fix fallback overwriting result of getHome [tx-robot] updated from transifex fix smbclient directory listing parser cache the home folder of a User Send "SET NAMES utf8" to MySQL for PHP below 5.3.6 ... Conflicts: lib/util.php
Diffstat (limited to 'lib')
-rw-r--r--lib/autoloader.php44
-rw-r--r--lib/base.php313
-rw-r--r--lib/cache/fileglobalgc.php8
-rw-r--r--lib/connector/sabre/file.php159
-rw-r--r--lib/connector/sabre/quotaplugin.php60
-rw-r--r--lib/fileproxy/quota.php114
-rw-r--r--lib/l10n/ach.php8
-rw-r--r--lib/l10n/ady.php8
-rw-r--r--lib/l10n/af.php8
-rw-r--r--lib/l10n/af_ZA.php7
-rw-r--r--lib/l10n/ar.php16
-rw-r--r--lib/l10n/az.php8
-rw-r--r--lib/l10n/be.php8
-rw-r--r--lib/l10n/bg_BG.php16
-rw-r--r--lib/l10n/bn_BD.php9
-rw-r--r--lib/l10n/bs.php8
-rw-r--r--lib/l10n/ca.php34
-rw-r--r--lib/l10n/cs_CZ.php34
-rw-r--r--lib/l10n/cy_GB.php16
-rw-r--r--lib/l10n/da.php33
-rw-r--r--lib/l10n/de.php34
-rw-r--r--lib/l10n/de_AT.php8
-rw-r--r--lib/l10n/de_CH.php21
-rw-r--r--lib/l10n/de_DE.php34
-rw-r--r--lib/l10n/el.php19
-rw-r--r--lib/l10n/en@pirate.php6
-rw-r--r--lib/l10n/en_GB.php71
-rw-r--r--lib/l10n/eo.php15
-rw-r--r--lib/l10n/es.php36
-rw-r--r--lib/l10n/es_AR.php33
-rw-r--r--lib/l10n/es_MX.php8
-rw-r--r--lib/l10n/et_EE.php34
-rw-r--r--lib/l10n/eu.php34
-rw-r--r--lib/l10n/fa.php16
-rw-r--r--lib/l10n/fi_FI.php28
-rw-r--r--lib/l10n/fr.php34
-rw-r--r--lib/l10n/fr_CA.php8
-rw-r--r--lib/l10n/gl.php34
-rw-r--r--lib/l10n/he.php15
-rw-r--r--lib/l10n/hi.php5
-rw-r--r--lib/l10n/hr.php5
-rw-r--r--lib/l10n/hu_HU.php33
-rw-r--r--lib/l10n/hy.php8
-rw-r--r--lib/l10n/ia.php7
-rw-r--r--lib/l10n/id.php16
-rw-r--r--lib/l10n/is.php15
-rw-r--r--lib/l10n/it.php34
-rw-r--r--lib/l10n/ja_JP.php34
-rw-r--r--lib/l10n/ka.php8
-rw-r--r--lib/l10n/ka_GE.php16
-rw-r--r--lib/l10n/km.php8
-rw-r--r--lib/l10n/kn.php8
-rw-r--r--lib/l10n/ko.php44
-rw-r--r--lib/l10n/ku_IQ.php7
-rw-r--r--lib/l10n/lb.php9
-rw-r--r--lib/l10n/lt_LT.php54
-rw-r--r--lib/l10n/lv.php18
-rw-r--r--lib/l10n/mk.php17
-rw-r--r--lib/l10n/ml_IN.php8
-rw-r--r--lib/l10n/ms_MY.php7
-rw-r--r--lib/l10n/my_MM.php16
-rw-r--r--lib/l10n/nb_NO.php15
-rw-r--r--lib/l10n/nds.php8
-rw-r--r--lib/l10n/ne.php8
-rw-r--r--lib/l10n/nl.php34
-rw-r--r--lib/l10n/nn_NO.php11
-rw-r--r--lib/l10n/nqo.php8
-rw-r--r--lib/l10n/oc.php8
-rw-r--r--lib/l10n/pa.php16
-rw-r--r--lib/l10n/pl.php34
-rw-r--r--lib/l10n/pt_BR.php34
-rw-r--r--lib/l10n/pt_PT.php34
-rw-r--r--lib/l10n/ro.php20
-rw-r--r--lib/l10n/ru.php34
-rw-r--r--lib/l10n/ru_RU.php8
-rw-r--r--lib/l10n/si_LK.php8
-rw-r--r--lib/l10n/sk.php8
-rw-r--r--lib/l10n/sk_SK.php36
-rw-r--r--lib/l10n/sl.php42
-rw-r--r--lib/l10n/sq.php16
-rw-r--r--lib/l10n/sr.php16
-rw-r--r--lib/l10n/sr@latin.php13
-rw-r--r--lib/l10n/sv.php34
-rw-r--r--lib/l10n/sw_KE.php8
-rw-r--r--lib/l10n/ta_LK.php15
-rw-r--r--lib/l10n/te.php6
-rw-r--r--lib/l10n/th_TH.php16
-rw-r--r--lib/l10n/tr.php40
-rw-r--r--lib/l10n/tzm.php8
-rw-r--r--lib/l10n/ug.php12
-rw-r--r--lib/l10n/uk.php18
-rw-r--r--lib/l10n/ur_PK.php7
-rw-r--r--lib/l10n/uz.php8
-rw-r--r--lib/l10n/vi.php16
-rw-r--r--lib/l10n/zh_CN.GB2312.php33
-rw-r--r--lib/l10n/zh_CN.php19
-rw-r--r--lib/l10n/zh_HK.php7
-rw-r--r--lib/l10n/zh_TW.php33
-rw-r--r--lib/ocs/activity.php28
-rw-r--r--lib/ocs/privatedata.php66
-rwxr-xr-xlib/private/activitymanager.php69
-rw-r--r--lib/private/allconfig.php77
-rw-r--r--lib/private/api.php (renamed from lib/api.php)94
-rw-r--r--lib/private/app.php (renamed from lib/app.php)117
-rw-r--r--lib/private/appconfig.php (renamed from lib/appconfig.php)6
-rw-r--r--lib/private/appframework/app.php99
-rw-r--r--lib/private/appframework/core/api.php184
-rw-r--r--lib/private/appframework/dependencyinjection/dicontainer.php196
-rw-r--r--lib/private/appframework/http.php149
-rw-r--r--lib/private/appframework/http/dispatcher.php101
-rw-r--r--lib/private/appframework/http/downloadresponse.php50
-rw-r--r--lib/private/appframework/http/redirectresponse.php57
-rw-r--r--lib/private/appframework/http/request.php389
-rw-r--r--lib/private/appframework/middleware/middlewaredispatcher.php159
-rw-r--r--lib/private/appframework/middleware/security/securityexception.php41
-rw-r--r--lib/private/appframework/middleware/security/securitymiddleware.php140
-rw-r--r--lib/private/appframework/routing/routeactionhandler.php42
-rw-r--r--lib/private/appframework/routing/routeconfig.php186
-rw-r--r--lib/private/appframework/utility/methodannotationreader.php61
-rw-r--r--lib/private/appframework/utility/simplecontainer.php44
-rw-r--r--lib/private/appframework/utility/timefactory.php42
-rw-r--r--lib/private/apphelper.php25
-rw-r--r--lib/private/archive.php (renamed from lib/archive.php)5
-rw-r--r--lib/private/archive/tar.php (renamed from lib/archive/tar.php)0
-rw-r--r--lib/private/archive/zip.php (renamed from lib/archive/zip.php)0
-rw-r--r--lib/private/arrayparser.php (renamed from lib/arrayparser.php)0
-rw-r--r--lib/private/avatar.php91
-rw-r--r--lib/private/avatarmanager.php26
-rw-r--r--lib/private/backgroundjob.php (renamed from lib/backgroundjob.php)0
-rw-r--r--lib/private/backgroundjob/job.php (renamed from lib/backgroundjob/job.php)23
-rw-r--r--lib/private/backgroundjob/joblist.php (renamed from lib/backgroundjob/joblist.php)2
-rw-r--r--lib/private/backgroundjob/legacy/queuedjob.php (renamed from lib/backgroundjob/legacy/queuedjob.php)0
-rw-r--r--lib/private/backgroundjob/legacy/regularjob.php (renamed from lib/backgroundjob/legacy/regularjob.php)0
-rw-r--r--lib/private/backgroundjob/queuedjob.php (renamed from lib/backgroundjob/queuedjob.php)5
-rw-r--r--lib/private/backgroundjob/timedjob.php (renamed from lib/backgroundjob/timedjob.php)6
-rw-r--r--lib/private/cache.php (renamed from lib/cache.php)23
-rw-r--r--lib/private/cache/broker.php (renamed from lib/cache/broker.php)12
-rw-r--r--lib/private/cache/file.php (renamed from lib/cache/file.php)44
-rw-r--r--lib/private/cache/fileglobal.php (renamed from lib/cache/fileglobal.php)29
-rw-r--r--lib/private/cache/fileglobalgc.php9
-rw-r--r--lib/private/cache/usercache.php77
-rw-r--r--lib/private/config.php (renamed from lib/config.php)4
-rw-r--r--lib/private/connector/sabre/ServiceUnavailable.php (renamed from lib/connector/sabre/ServiceUnavailable.php)0
-rw-r--r--lib/private/connector/sabre/aborteduploaddetectionplugin.php107
-rw-r--r--lib/private/connector/sabre/auth.php (renamed from lib/connector/sabre/auth.php)3
-rw-r--r--lib/private/connector/sabre/directory.php (renamed from lib/connector/sabre/directory.php)82
-rw-r--r--lib/private/connector/sabre/exception/entitytoolarge.php22
-rw-r--r--lib/private/connector/sabre/exception/unsupportedmediatype.php22
-rw-r--r--lib/private/connector/sabre/file.php263
-rw-r--r--lib/private/connector/sabre/filesplugin.php103
-rw-r--r--lib/private/connector/sabre/locks.php (renamed from lib/connector/sabre/locks.php)0
-rw-r--r--lib/private/connector/sabre/maintenanceplugin.php (renamed from lib/connector/sabre/maintenanceplugin.php)0
-rw-r--r--lib/private/connector/sabre/node.php (renamed from lib/connector/sabre/node.php)65
-rw-r--r--lib/private/connector/sabre/objecttree.php (renamed from lib/connector/sabre/objecttree.php)60
-rw-r--r--lib/private/connector/sabre/principal.php (renamed from lib/connector/sabre/principal.php)14
-rw-r--r--lib/private/connector/sabre/quotaplugin.php97
-rw-r--r--lib/private/connector/sabre/request.php (renamed from lib/connector/sabre/request.php)0
-rw-r--r--lib/private/connector/sabre/server.php235
-rw-r--r--lib/private/contactsmanager.php145
-rw-r--r--lib/private/davclient.php46
-rw-r--r--lib/private/db.php (renamed from lib/db.php)25
-rw-r--r--lib/private/db/adapter.php (renamed from lib/db/adapter.php)0
-rw-r--r--lib/private/db/adapteroci8.php (renamed from lib/db/adapteroci8.php)0
-rw-r--r--lib/private/db/adapterpgsql.php (renamed from lib/db/adapterpgsql.php)0
-rw-r--r--lib/private/db/adaptersqlite.php (renamed from lib/db/adaptersqlite.php)0
-rw-r--r--lib/private/db/adaptersqlsrv.php (renamed from lib/db/adaptersqlsrv.php)7
-rw-r--r--lib/private/db/connection.php (renamed from lib/db/connection.php)0
-rw-r--r--lib/private/db/connectionwrapper.php99
-rw-r--r--lib/private/db/mdb2schemamanager.php (renamed from lib/db/mdb2schemamanager.php)29
-rw-r--r--lib/private/db/mdb2schemareader.php (renamed from lib/db/mdb2schemareader.php)7
-rw-r--r--lib/private/db/mdb2schemawriter.php (renamed from lib/db/mdb2schemawriter.php)0
-rw-r--r--lib/private/db/oracleconnection.php50
-rw-r--r--lib/private/db/statementwrapper.php (renamed from lib/db/statementwrapper.php)0
-rw-r--r--lib/private/defaults.php (renamed from lib/defaults.php)55
-rw-r--r--lib/private/eventsource.php (renamed from lib/eventsource.php)0
-rw-r--r--lib/private/filechunking.php (renamed from lib/filechunking.php)35
-rw-r--r--lib/private/fileproxy.php (renamed from lib/fileproxy.php)0
-rw-r--r--lib/private/fileproxy/fileoperations.php (renamed from lib/fileproxy/fileoperations.php)0
-rw-r--r--lib/private/files.php (renamed from lib/files.php)17
-rw-r--r--lib/private/files/cache/backgroundwatcher.php (renamed from lib/files/cache/backgroundwatcher.php)0
-rw-r--r--lib/private/files/cache/cache.php (renamed from lib/files/cache/cache.php)66
-rw-r--r--lib/private/files/cache/homecache.php53
-rw-r--r--lib/private/files/cache/legacy.php (renamed from lib/files/cache/legacy.php)0
-rw-r--r--lib/private/files/cache/permissions.php (renamed from lib/files/cache/permissions.php)0
-rw-r--r--lib/private/files/cache/scanner.php (renamed from lib/files/cache/scanner.php)120
-rw-r--r--lib/private/files/cache/storage.php (renamed from lib/files/cache/storage.php)15
-rw-r--r--lib/private/files/cache/updater.php (renamed from lib/files/cache/updater.php)83
-rw-r--r--lib/private/files/cache/upgrade.php (renamed from lib/files/cache/upgrade.php)10
-rw-r--r--lib/private/files/cache/watcher.php (renamed from lib/files/cache/watcher.php)9
-rw-r--r--lib/private/files/filesystem.php (renamed from lib/files/filesystem.php)59
-rw-r--r--lib/private/files/mapper.php (renamed from lib/files/mapper.php)0
-rw-r--r--lib/private/files/mount/manager.php (renamed from lib/files/mount/manager.php)7
-rw-r--r--lib/private/files/mount/mount.php (renamed from lib/files/mount/mount.php)7
-rw-r--r--lib/private/files/node/file.php155
-rw-r--r--lib/private/files/node/folder.php382
-rw-r--r--lib/private/files/node/node.php245
-rw-r--r--lib/private/files/node/nonexistingfile.php89
-rw-r--r--lib/private/files/node/nonexistingfolder.php113
-rw-r--r--lib/private/files/node/root.php337
-rw-r--r--lib/private/files/storage/common.php (renamed from lib/files/storage/common.php)72
-rw-r--r--lib/private/files/storage/commontest.php (renamed from lib/files/storage/commontest.php)4
-rw-r--r--lib/private/files/storage/home.php66
-rw-r--r--lib/private/files/storage/loader.php (renamed from lib/files/storage/loader.php)0
-rw-r--r--lib/private/files/storage/local.php (renamed from lib/files/storage/local.php)10
-rw-r--r--lib/private/files/storage/mappedlocal.php (renamed from lib/files/storage/mappedlocal.php)26
-rw-r--r--lib/private/files/storage/storage.php64
-rw-r--r--lib/private/files/storage/temporary.php (renamed from lib/files/storage/temporary.php)0
-rw-r--r--lib/private/files/storage/wrapper/quota.php104
-rw-r--r--lib/private/files/storage/wrapper/wrapper.php (renamed from lib/files/storage/wrapper/wrapper.php)10
-rw-r--r--lib/private/files/stream/close.php (renamed from lib/files/stream/close.php)0
-rw-r--r--lib/private/files/stream/dir.php (renamed from lib/files/stream/dir.php)0
-rw-r--r--lib/private/files/stream/oc.php (renamed from lib/files/stream/oc.php)0
-rw-r--r--lib/private/files/stream/quota.php140
-rw-r--r--lib/private/files/stream/staticstream.php (renamed from lib/files/stream/staticstream.php)0
-rw-r--r--lib/private/files/type/detection.php125
-rw-r--r--lib/private/files/type/templatemanager.php46
-rw-r--r--lib/private/files/utils/scanner.php (renamed from lib/files/utils/scanner.php)6
-rw-r--r--lib/private/files/view.php (renamed from lib/files/view.php)139
-rw-r--r--lib/private/geo.php (renamed from lib/geo.php)2
-rw-r--r--lib/private/group.php (renamed from lib/group.php)4
-rw-r--r--lib/private/group/backend.php (renamed from lib/group/backend.php)0
-rw-r--r--lib/private/group/database.php (renamed from lib/group/database.php)0
-rw-r--r--lib/private/group/dummy.php (renamed from lib/group/dummy.php)0
-rw-r--r--lib/private/group/example.php (renamed from lib/group/example.php)0
-rw-r--r--lib/private/group/group.php (renamed from lib/group/group.php)38
-rw-r--r--lib/private/group/interface.php (renamed from lib/group/interface.php)0
-rw-r--r--lib/private/group/manager.php (renamed from lib/group/manager.php)0
-rw-r--r--lib/private/helper.php (renamed from lib/helper.php)566
-rw-r--r--lib/private/hintexception.php (renamed from lib/hintexception.php)0
-rw-r--r--lib/private/hook.php (renamed from lib/hook.php)0
-rw-r--r--lib/private/hooks/basicemitter.php (renamed from lib/hooks/basicemitter.php)0
-rw-r--r--lib/private/hooks/emitter.php (renamed from lib/hooks/emitter.php)0
-rw-r--r--lib/private/hooks/forwardingemitter.php (renamed from lib/hooks/forwardingemitter.php)0
-rw-r--r--lib/private/hooks/legacyemitter.php (renamed from lib/hooks/legacyemitter.php)0
-rw-r--r--lib/private/hooks/publicemitter.php (renamed from lib/hooks/publicemitter.php)0
-rw-r--r--lib/private/image.php (renamed from lib/image.php)306
-rw-r--r--lib/private/installer.php (renamed from lib/installer.php)88
-rw-r--r--lib/private/json.php (renamed from lib/json.php)0
-rw-r--r--lib/private/l10n.php (renamed from lib/l10n.php)69
-rw-r--r--lib/private/l10n/factory.php34
-rw-r--r--lib/private/l10n/string.php (renamed from lib/l10n/string.php)0
-rw-r--r--lib/private/legacy/cache.php10
-rw-r--r--lib/private/legacy/cache/fileglobalgc.php4
-rw-r--r--lib/private/legacy/config.php (renamed from lib/legacy/config.php)12
-rw-r--r--lib/private/legacy/filesystem.php (renamed from lib/legacy/filesystem.php)0
-rw-r--r--lib/private/legacy/filesystemview.php (renamed from lib/legacy/filesystemview.php)0
-rw-r--r--lib/private/legacy/log.php (renamed from lib/legacy/log.php)0
-rw-r--r--lib/private/legacy/preferences.php146
-rw-r--r--lib/private/legacy/updater.php (renamed from lib/legacy/updater.php)0
-rw-r--r--lib/private/log.php (renamed from lib/log.php)0
-rw-r--r--lib/private/log/errorhandler.php (renamed from lib/log/errorhandler.php)0
-rw-r--r--lib/private/log/owncloud.php (renamed from lib/log/owncloud.php)31
-rw-r--r--lib/private/log/rotate.php35
-rw-r--r--lib/private/log/syslog.php (renamed from lib/log/syslog.php)0
-rw-r--r--lib/private/mail.php (renamed from lib/mail.php)0
-rw-r--r--lib/private/memcache/apc.php (renamed from lib/memcache/apc.php)0
-rw-r--r--lib/private/memcache/apcu.php (renamed from lib/memcache/apcu.php)0
-rw-r--r--lib/private/memcache/cache.php (renamed from lib/memcache/cache.php)0
-rw-r--r--lib/private/memcache/factory.php (renamed from lib/memcache/factory.php)29
-rw-r--r--lib/private/memcache/memcached.php (renamed from lib/memcache/memcached.php)0
-rw-r--r--lib/private/memcache/xcache.php (renamed from lib/memcache/xcache.php)0
-rw-r--r--lib/private/migrate.php (renamed from lib/migrate.php)0
-rw-r--r--lib/private/migration/content.php (renamed from lib/migration/content.php)3
-rw-r--r--lib/private/migration/provider.php (renamed from lib/migration/provider.php)0
-rw-r--r--lib/private/mimetypes.list.php (renamed from lib/mimetypes.list.php)0
-rw-r--r--lib/private/minimizer.php (renamed from lib/minimizer.php)0
-rw-r--r--lib/private/minimizer/css.php (renamed from lib/minimizer/css.php)0
-rw-r--r--lib/private/minimizer/js.php (renamed from lib/minimizer/js.php)0
-rw-r--r--lib/private/navigationmanager.php64
-rw-r--r--lib/private/notsquareexception.php12
-rw-r--r--lib/private/ocs.php (renamed from lib/ocs.php)32
-rw-r--r--lib/private/ocs/cloud.php (renamed from lib/ocs/cloud.php)55
-rw-r--r--lib/private/ocs/config.php (renamed from lib/ocs/config.php)0
-rw-r--r--lib/private/ocs/person.php (renamed from lib/ocs/person.php)0
-rw-r--r--lib/private/ocs/privatedata.php108
-rw-r--r--lib/private/ocs/result.php (renamed from lib/ocs/result.php)2
-rw-r--r--lib/private/ocsclient.php (renamed from lib/ocsclient.php)56
-rw-r--r--lib/private/preferences.php (renamed from lib/preferences.php)153
-rwxr-xr-xlib/private/preview.php641
-rw-r--r--lib/private/preview/image.php36
-rw-r--r--lib/private/preview/movies.php90
-rw-r--r--lib/private/preview/mp3.php50
-rw-r--r--lib/private/preview/office-cl.php139
-rw-r--r--lib/private/preview/office-fallback.php143
-rw-r--r--lib/private/preview/office.php29
-rw-r--r--lib/private/preview/pdf.php40
-rw-r--r--lib/private/preview/provider.php25
-rw-r--r--lib/private/preview/svg.php46
-rw-r--r--lib/private/preview/txt.php72
-rw-r--r--lib/private/preview/unknown.php49
-rwxr-xr-xlib/private/previewmanager.php38
-rw-r--r--lib/private/repair.php21
-rwxr-xr-xlib/private/request.php (renamed from lib/request.php)39
-rw-r--r--lib/private/response.php (renamed from lib/response.php)0
-rw-r--r--lib/private/route.php (renamed from lib/route.php)8
-rw-r--r--lib/private/router.php (renamed from lib/router.php)0
-rw-r--r--lib/private/search.php (renamed from lib/search.php)0
-rw-r--r--lib/private/search/provider.php (renamed from lib/search/provider.php)0
-rw-r--r--lib/private/search/provider/file.php (renamed from lib/search/provider/file.php)3
-rw-r--r--lib/private/search/result.php (renamed from lib/search/result.php)4
-rw-r--r--lib/private/server.php316
-rw-r--r--lib/private/session/internal.php (renamed from lib/session/internal.php)0
-rw-r--r--lib/private/session/memory.php (renamed from lib/session/memory.php)0
-rw-r--r--lib/private/session/session.php (renamed from lib/session/session.php)35
-rw-r--r--lib/private/setup.php (renamed from lib/setup.php)19
-rw-r--r--lib/private/setup/abstractdatabase.php (renamed from lib/setup/abstractdatabase.php)4
-rw-r--r--lib/private/setup/mssql.php (renamed from lib/setup/mssql.php)0
-rw-r--r--lib/private/setup/mysql.php (renamed from lib/setup/mysql.php)2
-rw-r--r--lib/private/setup/oci.php (renamed from lib/setup/oci.php)65
-rw-r--r--lib/private/setup/postgresql.php (renamed from lib/setup/postgresql.php)2
-rw-r--r--lib/private/setup/sqlite.php (renamed from lib/setup/sqlite.php)0
-rw-r--r--lib/private/subadmin.php (renamed from lib/subadmin.php)0
-rw-r--r--lib/private/tagmanager.php68
-rw-r--r--lib/private/tags.php642
-rw-r--r--lib/private/template.php (renamed from lib/template.php)0
-rw-r--r--lib/private/template/base.php (renamed from lib/template/base.php)0
-rw-r--r--lib/private/template/cssresourcelocator.php (renamed from lib/template/cssresourcelocator.php)0
-rw-r--r--lib/private/template/functions.php (renamed from lib/template/functions.php)73
-rw-r--r--lib/private/template/jsresourcelocator.php (renamed from lib/template/jsresourcelocator.php)0
-rw-r--r--lib/private/template/resourcelocator.php (renamed from lib/template/resourcelocator.php)0
-rw-r--r--lib/private/template/templatefilelocator.php (renamed from lib/template/templatefilelocator.php)0
-rw-r--r--lib/private/templatelayout.php (renamed from lib/templatelayout.php)5
-rw-r--r--lib/private/updater.php (renamed from lib/updater.php)9
-rw-r--r--lib/private/urlgenerator.php129
-rw-r--r--lib/private/user.php (renamed from lib/user.php)204
-rw-r--r--lib/private/user/backend.php (renamed from lib/user/backend.php)15
-rw-r--r--lib/private/user/database.php (renamed from lib/user/database.php)135
-rw-r--r--lib/private/user/dummy.php (renamed from lib/user/dummy.php)4
-rw-r--r--lib/private/user/example.php (renamed from lib/user/example.php)0
-rw-r--r--lib/private/user/http.php (renamed from lib/user/http.php)8
-rw-r--r--lib/private/user/interface.php (renamed from lib/user/interface.php)2
-rw-r--r--lib/private/user/manager.php (renamed from lib/user/manager.php)33
-rw-r--r--lib/private/user/session.php (renamed from lib/user/session.php)60
-rw-r--r--lib/private/user/user.php (renamed from lib/user/user.php)45
-rwxr-xr-xlib/private/util.php1139
-rw-r--r--lib/private/vobject.php (renamed from lib/vobject.php)0
-rw-r--r--lib/private/vobject/compoundproperty.php (renamed from lib/vobject/compoundproperty.php)2
-rw-r--r--lib/private/vobject/stringproperty.php (renamed from lib/vobject/stringproperty.php)2
-rw-r--r--lib/public/activity/iconsumer.php48
-rw-r--r--lib/public/activity/imanager.php59
-rw-r--r--lib/public/api.php46
-rw-r--r--lib/public/app.php90
-rw-r--r--lib/public/appframework/app.php111
-rw-r--r--lib/public/appframework/controller.php151
-rw-r--r--lib/public/appframework/http.php94
-rw-r--r--lib/public/appframework/http/jsonresponse.php83
-rw-r--r--lib/public/appframework/http/response.php183
-rw-r--r--lib/public/appframework/http/templateresponse.php137
-rw-r--r--lib/public/appframework/iapi.php81
-rw-r--r--lib/public/appframework/iappcontainer.php75
-rw-r--r--lib/public/appframework/middleware.php104
-rw-r--r--lib/public/authentication/iapachebackend.php55
-rw-r--r--lib/public/backgroundjob.php26
-rw-r--r--lib/public/config.php54
-rw-r--r--lib/public/contacts.php55
-rw-r--r--lib/public/contacts/imanager.php154
-rw-r--r--lib/public/db.php63
-rw-r--r--lib/public/defaults.php75
-rw-r--r--lib/public/files.php66
-rw-r--r--lib/public/files/alreadyexistsexception.php35
-rw-r--r--lib/public/files/entitytoolargeexception.php35
-rw-r--r--lib/public/files/file.php74
-rw-r--r--lib/public/files/folder.php140
-rw-r--r--lib/public/files/invalidcontentexception.php35
-rw-r--r--lib/public/files/invalidpathexception.php35
-rw-r--r--lib/public/files/node.php180
-rw-r--r--lib/public/files/notenoughspaceexception.php35
-rw-r--r--lib/public/files/notfoundexception.php35
-rw-r--r--lib/public/files/notpermittedexception.php35
-rw-r--r--lib/public/files/storage.php (renamed from lib/files/storage/storage.php)79
-rw-r--r--lib/public/groupinterface.php42
-rw-r--r--lib/public/iaddressbook.php5
-rw-r--r--lib/public/iavatar.php38
-rw-r--r--lib/public/iavatarmanager.php23
-rw-r--r--lib/public/icache.php74
-rw-r--r--lib/public/iconfig.php86
-rw-r--r--lib/public/icontainer.php72
-rw-r--r--lib/public/idbconnection.php95
-rw-r--r--lib/public/ihelper.php44
-rw-r--r--lib/public/il10n.php75
-rw-r--r--lib/public/image.php46
-rw-r--r--lib/public/inavigationmanager.php48
-rw-r--r--lib/public/ipreview.php60
-rw-r--r--lib/public/irequest.php123
-rw-r--r--lib/public/iservercontainer.php172
-rw-r--r--lib/public/isession.php78
-rw-r--r--lib/public/itagmanager.php55
-rw-r--r--lib/public/itags.php172
-rw-r--r--lib/public/iurlgenerator.php68
-rw-r--r--lib/public/iusersession.php51
-rw-r--r--lib/public/json.php42
-rw-r--r--lib/public/response.php94
-rw-r--r--lib/public/share.php856
-rw-r--r--lib/public/template.php105
-rw-r--r--lib/public/user.php91
-rw-r--r--lib/public/userinterface.php44
-rw-r--r--lib/public/util.php275
-rwxr-xr-xlib/util.php908
-rw-r--r--lib/vcategories.php821
399 files changed, 17761 insertions, 5175 deletions
diff --git a/lib/autoloader.php b/lib/autoloader.php
index 21170639092..3451f799e18 100644
--- a/lib/autoloader.php
+++ b/lib/autoloader.php
@@ -16,6 +16,12 @@ class Autoloader {
private $classPaths = array();
/**
+ * Optional low-latency memory cache for class to path mapping.
+ * @var \OC\Memcache\Cache
+ */
+ protected $memoryCache;
+
+ /**
* Add a custom prefix to the autoloader
*
* @param string $prefix
@@ -73,9 +79,10 @@ class Autoloader {
}
} elseif (strpos($class, 'OC_') === 0) {
// first check for legacy classes if underscores are used
- $paths[] = 'legacy/' . strtolower(str_replace('_', '/', substr($class, 3)) . '.php');
- $paths[] = strtolower(str_replace('_', '/', substr($class, 3)) . '.php');
+ $paths[] = 'private/legacy/' . strtolower(str_replace('_', '/', substr($class, 3)) . '.php');
+ $paths[] = 'private/' . strtolower(str_replace('_', '/', substr($class, 3)) . '.php');
} elseif (strpos($class, 'OC\\') === 0) {
+ $paths[] = 'private/' . strtolower(str_replace('\\', '/', substr($class, 3)) . '.php');
$paths[] = strtolower(str_replace('\\', '/', substr($class, 3)) . '.php');
} elseif (strpos($class, 'OCP\\') === 0) {
$paths[] = 'public/' . strtolower(str_replace('\\', '/', substr($class, 4)) . '.php');
@@ -112,15 +119,38 @@ class Autoloader {
* @return bool
*/
public function load($class) {
- $paths = $this->findClass($class);
+ $pathsToRequire = null;
+ if ($this->memoryCache) {
+ $pathsToRequire = $this->memoryCache->get($class);
+ }
- if (is_array($paths)) {
- foreach ($paths as $path) {
- if ($fullPath = stream_resolve_include_path($path)) {
- require_once $fullPath;
+ if (!is_array($pathsToRequire)) {
+ // No cache or cache miss
+ $pathsToRequire = array();
+ foreach ($this->findClass($class) as $path) {
+ $fullPath = stream_resolve_include_path($path);
+ if ($fullPath) {
+ $pathsToRequire[] = $fullPath;
}
}
+
+ if ($this->memoryCache) {
+ $this->memoryCache->set($class, $pathsToRequire, 60); // cache 60 sec
+ }
}
+
+ foreach ($pathsToRequire as $fullPath) {
+ require_once $fullPath;
+ }
+
return false;
}
+
+ /**
+ * @brief Sets the optional low-latency cache for class to path mapping.
+ * @param \OC\Memcache\Cache $memoryCache Instance of memory cache.
+ */
+ public function setMemoryCache(\OC\Memcache\Cache $memoryCache = null) {
+ $this->memoryCache = $memoryCache;
+ }
}
diff --git a/lib/base.php b/lib/base.php
index eaee8424651..d3e483f4948 100644
--- a/lib/base.php
+++ b/lib/base.php
@@ -69,8 +69,9 @@ class OC {
* check if owncloud runs in cli mode
*/
public static $CLI = false;
- /*
- * OC router
+
+ /**
+ * @var OC_Router
*/
protected static $router = null;
@@ -84,6 +85,11 @@ class OC {
*/
public static $loader = null;
+ /**
+ * @var \OC\Server
+ */
+ public static $server = null;
+
public static function initPaths() {
// calculate the root directories
OC::$SERVERROOT = str_replace("\\", '/', substr(__DIR__, 0, -4));
@@ -91,7 +97,7 @@ class OC {
// ensure we can find OC_Config
set_include_path(
OC::$SERVERROOT . '/lib' . PATH_SEPARATOR .
- get_include_path()
+ get_include_path()
);
OC::$SUBURI = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen(OC::$SERVERROOT)));
@@ -125,8 +131,8 @@ class OC {
OC::$THIRDPARTYROOT = rtrim(dirname(OC::$SERVERROOT), '/');
} else {
throw new Exception('3rdparty directory not found! Please put the ownCloud 3rdparty'
- .' folder in the ownCloud folder or the folder above.'
- .' You can also configure the location in the config.php file.');
+ . ' folder in the ownCloud folder or the folder above.'
+ . ' You can also configure the location in the config.php file.');
}
// search the apps folder
$config_paths = OC_Config::getValue('apps_paths', array());
@@ -150,7 +156,7 @@ class OC {
if (empty(OC::$APPSROOTS)) {
throw new Exception('apps directory not found! Please put the ownCloud apps folder in the ownCloud folder'
- .' or the folder above. You can also configure the location in the config.php file.');
+ . ' or the folder above. You can also configure the location in the config.php file.');
}
$paths = array();
foreach (OC::$APPSROOTS as $path) {
@@ -159,24 +165,33 @@ class OC {
// set the right include path
set_include_path(
- OC::$SERVERROOT . '/lib' . PATH_SEPARATOR .
- OC::$SERVERROOT . '/config' . PATH_SEPARATOR .
- OC::$THIRDPARTYROOT . '/3rdparty' . PATH_SEPARATOR .
- implode($paths, PATH_SEPARATOR) . PATH_SEPARATOR .
- get_include_path() . PATH_SEPARATOR .
- OC::$SERVERROOT
+ OC::$SERVERROOT . '/lib/private' . PATH_SEPARATOR .
+ OC::$SERVERROOT . '/config' . PATH_SEPARATOR .
+ OC::$THIRDPARTYROOT . '/3rdparty' . PATH_SEPARATOR .
+ implode($paths, PATH_SEPARATOR) . PATH_SEPARATOR .
+ get_include_path() . PATH_SEPARATOR .
+ OC::$SERVERROOT
);
}
public static function checkConfig() {
if (file_exists(OC::$SERVERROOT . "/config/config.php")
- and !is_writable(OC::$SERVERROOT . "/config/config.php")) {
+ and !is_writable(OC::$SERVERROOT . "/config/config.php")
+ ) {
$defaults = new OC_Defaults();
- OC_Template::printErrorPage(
- "Can't write into config directory!",
- 'This can usually be fixed by '
- .'<a href="' . $defaults->getDocBaseUrl() . '/server/5.0/admin_manual/installation/installation_source.html#set-the-directory-permissions" target="_blank">giving the webserver write access to the config directory</a>.'
- );
+ if (self::$CLI) {
+ echo "Can't write into config directory!\n";
+ echo "This can usually be fixed by giving the webserver write access to the config directory\n";
+ echo "\n";
+ echo "See " . \OC_Helper::linkToDocs('admin-dir_permissions') . "\n";
+ exit;
+ } else {
+ OC_Template::printErrorPage(
+ "Can't write into config directory!",
+ 'This can usually be fixed by '
+ . '<a href="' . \OC_Helper::linkToDocs('admin-dir_permissions') . '" target="_blank">giving the webserver write access to the config directory</a>.'
+ );
+ }
}
}
@@ -218,34 +233,64 @@ class OC {
header('Retry-After: 120');
// render error page
- OC_Template::printErrorPage('ownCloud is in maintenance mode');
+ $tmpl = new OC_Template('', 'update.user', 'guest');
+ $tmpl->printPage();
+ die();
}
}
- public static function checkUpgrade($showTemplate = true) {
+ public static function checkSingleUserMode() {
+ $user = OC_User::getUserSession()->getUser();
+ $group = OC_Group::getManager()->get('admin');
+ if ($user && OC_Config::getValue('singleuser', false) && !$group->inGroup($user)) {
+ // send http status 503
+ header('HTTP/1.1 503 Service Temporarily Unavailable');
+ header('Status: 503 Service Temporarily Unavailable');
+ header('Retry-After: 120');
+
+ // render error page
+ $tmpl = new OC_Template('', 'singleuser.user', 'guest');
+ $tmpl->printPage();
+ die();
+ }
+ }
+
+ /**
+ * check if the instance needs to preform an upgrade
+ *
+ * @return bool
+ */
+ public static function needUpgrade() {
if (OC_Config::getValue('installed', false)) {
$installedVersion = OC_Config::getValue('version', '0.0.0');
$currentVersion = implode('.', OC_Util::getVersion());
- if (version_compare($currentVersion, $installedVersion, '>')) {
- if ($showTemplate && !OC_Config::getValue('maintenance', false)) {
- OC_Config::setValue('theme', '');
- $minimizerCSS = new OC_Minimizer_CSS();
- $minimizerCSS->clearCache();
- $minimizerJS = new OC_Minimizer_JS();
- $minimizerJS->clearCache();
- OC_Util::addscript('update');
- $tmpl = new OC_Template('', 'update', 'guest');
- $tmpl->assign('version', OC_Util::getVersionString());
- $tmpl->printPage();
- exit();
- } else {
- return true;
- }
- }
+ return version_compare($currentVersion, $installedVersion, '>');
+ } else {
return false;
}
}
+ public static function checkUpgrade($showTemplate = true) {
+ if (self::needUpgrade()) {
+ if ($showTemplate && !OC_Config::getValue('maintenance', false)) {
+ OC_Config::setValue('theme', '');
+ $minimizerCSS = new OC_Minimizer_CSS();
+ $minimizerCSS->clearCache();
+ $minimizerJS = new OC_Minimizer_JS();
+ $minimizerJS->clearCache();
+ OC_Util::addScript('config'); // needed for web root
+ OC_Util::addScript('update');
+ $tmpl = new OC_Template('', 'update.admin', 'guest');
+ $tmpl->assign('version', OC_Util::getVersionString());
+ $tmpl->printPage();
+ exit();
+ } else {
+ return true;
+ }
+ }
+ return false;
+ }
+
public static function initTemplateEngine() {
// Add the stuff we need always
OC_Util::addScript("jquery-1.10.0.min");
@@ -253,24 +298,35 @@ class OC {
OC_Util::addScript("jquery-ui-1.10.0.custom");
OC_Util::addScript("jquery-showpassword");
OC_Util::addScript("jquery.infieldlabel");
+ OC_Util::addScript("jquery.placeholder");
OC_Util::addScript("jquery-tipsy");
OC_Util::addScript("compatibility");
OC_Util::addScript("jquery.ocdialog");
OC_Util::addScript("oc-dialogs");
- OC_Util::addScript("octemplate");
OC_Util::addScript("js");
+ OC_Util::addScript("octemplate");
OC_Util::addScript("eventsource");
OC_Util::addScript("config");
//OC_Util::addScript( "multiselect" );
OC_Util::addScript('search', 'result');
OC_Util::addScript('router');
+ OC_Util::addScript("oc-requesttoken");
+
+ // avatars
+ if (\OC_Config::getValue('enable_avatars', true) === true) {
+ \OC_Util::addScript('placeholder');
+ \OC_Util::addScript('3rdparty', 'md5/md5.min');
+ \OC_Util::addScript('jquery.avatar');
+ \OC_Util::addScript('avatar');
+ }
OC_Util::addStyle("styles");
+ OC_Util::addStyle("apps");
+ OC_Util::addStyle("fixes");
OC_Util::addStyle("multiselect");
OC_Util::addStyle("jquery-ui-1.10.0.custom");
OC_Util::addStyle("jquery-tipsy");
OC_Util::addStyle("jquery.ocdialog");
- OC_Util::addScript("oc-requesttoken");
}
public static function initSession() {
@@ -278,26 +334,20 @@ class OC {
ini_set('session.cookie_httponly', '1;');
// set the cookie path to the ownCloud directory
- $cookie_path = OC::$WEBROOT ?: '/';
+ $cookie_path = OC::$WEBROOT ? : '/';
ini_set('session.cookie_path', $cookie_path);
//set the session object to a dummy session so code relying on the session existing still works
self::$session = new \OC\Session\Memory('');
-
- try{
+
+ try {
// set the session name to the instance id - which is unique
self::$session = new \OC\Session\Internal(OC_Util::getInstanceId());
// if session cant be started break with http 500 error
- }catch (Exception $e){
- OC_Log::write('core', 'Session could not be initialized',
- OC_Log::ERROR);
-
- header('HTTP/1.1 500 Internal Server Error');
- OC_Util::addStyle("styles");
- $error = 'Session could not be initialized. Please contact your ';
- $error .= 'system administrator';
-
- OC_Template::printErrorPage($error);
+ } catch (Exception $e) {
+ //show the user a detailed error page
+ OC_Response::setStatus(OC_Response::STATUS_INTERNAL_SERVER_ERROR);
+ OC_Template::printExceptionErrorPage($e);
}
$sessionLifeTime = self::getSessionLifeTime();
@@ -329,6 +379,9 @@ class OC {
return OC_Config::getValue('session_lifetime', 60 * 60 * 24);
}
+ /**
+ * @return OC_Router
+ */
public static function getRouter() {
if (!isset(OC::$router)) {
OC::$router = new OC_Router();
@@ -352,10 +405,11 @@ class OC {
public static function init() {
// register autoloader
require_once __DIR__ . '/autoloader.php';
- self::$loader=new \OC\Autoloader();
+ self::$loader = new \OC\Autoloader();
self::$loader->registerPrefix('Doctrine\\Common', 'doctrine/common/lib');
self::$loader->registerPrefix('Doctrine\\DBAL', 'doctrine/dbal/lib');
self::$loader->registerPrefix('Symfony\\Component\\Routing', 'symfony/routing');
+ self::$loader->registerPrefix('Symfony\\Component\\Console', 'symfony/console');
self::$loader->registerPrefix('Sabre\\VObject', '3rdparty');
self::$loader->registerPrefix('Sabre_', '3rdparty');
self::$loader->registerPrefix('Patchwork', '3rdparty');
@@ -373,7 +427,7 @@ class OC {
ini_set('arg_separator.output', '&amp;');
// try to switch magic quotes off.
- if (get_magic_quotes_gpc()==1) {
+ if (get_magic_quotes_gpc() == 1) {
ini_set('magic_quotes_runtime', 0);
}
@@ -398,7 +452,8 @@ class OC {
//set http auth headers for apache+php-cgi work around
if (isset($_SERVER['HTTP_AUTHORIZATION'])
- && preg_match('/Basic\s+(.*)$/i', $_SERVER['HTTP_AUTHORIZATION'], $matches)) {
+ && preg_match('/Basic\s+(.*)$/i', $_SERVER['HTTP_AUTHORIZATION'], $matches)
+ ) {
list($name, $password) = explode(':', base64_decode($matches[1]), 2);
$_SERVER['PHP_AUTH_USER'] = strip_tags($name);
$_SERVER['PHP_AUTH_PW'] = strip_tags($password);
@@ -406,14 +461,23 @@ class OC {
//set http auth headers for apache+php-cgi work around if variable gets renamed by apache
if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])
- && preg_match('/Basic\s+(.*)$/i', $_SERVER['REDIRECT_HTTP_AUTHORIZATION'], $matches)) {
+ && preg_match('/Basic\s+(.*)$/i', $_SERVER['REDIRECT_HTTP_AUTHORIZATION'], $matches)
+ ) {
list($name, $password) = explode(':', base64_decode($matches[1]), 2);
$_SERVER['PHP_AUTH_USER'] = strip_tags($name);
$_SERVER['PHP_AUTH_PW'] = strip_tags($password);
}
self::initPaths();
- OC_Util::issetlocaleworking();
+ if (OC_Config::getValue('instanceid', false)) {
+ // \OC\Memcache\Cache has a hidden dependency on
+ // OC_Util::getInstanceId() for namespacing. See #5409.
+ try {
+ self::$loader->setMemoryCache(\OC\Memcache\Factory::createLowLatency('Autoloader'));
+ } catch (\Exception $ex) {
+ }
+ }
+ OC_Util::isSetLocaleWorking();
// set debug mode if an xdebug session is active
if (!defined('DEBUG') || !DEBUG) {
@@ -435,10 +499,14 @@ class OC {
stream_wrapper_register('fakedir', 'OC\Files\Stream\Dir');
stream_wrapper_register('static', 'OC\Files\Stream\StaticStream');
stream_wrapper_register('close', 'OC\Files\Stream\Close');
+ stream_wrapper_register('quota', 'OC\Files\Stream\Quota');
stream_wrapper_register('oc', 'OC\Files\Stream\OC');
+ // setup the basic server
+ self::$server = new \OC\Server();
+
self::initTemplateEngine();
- if ( !self::$CLI ) {
+ if (!self::$CLI) {
self::initSession();
} else {
self::$session = new \OC\Session\Memory('');
@@ -449,7 +517,14 @@ class OC {
$errors = OC_Util::checkServer();
if (count($errors) > 0) {
- OC_Template::printGuestPage('', 'error', array('errors' => $errors));
+ if (self::$CLI) {
+ foreach ($errors as $error) {
+ echo $error['error'] . "\n";
+ echo $error['hint'] . "\n\n";
+ }
+ } else {
+ OC_Template::printGuestPage('', 'error', array('errors' => $errors));
+ }
exit;
}
@@ -459,14 +534,19 @@ class OC {
// User and Groups
if (!OC_Config::getValue("installed", false)) {
- self::$session->set('user_id','');
+ self::$session->set('user_id', '');
}
OC_User::useBackend(new OC_User_Database());
OC_Group::useBackend(new OC_Group_Database());
if (isset($_SERVER['PHP_AUTH_USER']) && self::$session->exists('user_id')
- && $_SERVER['PHP_AUTH_USER'] != self::$session->get('user_id')) {
+ && $_SERVER['PHP_AUTH_USER'] !== self::$session->get('loginname')) {
+ $sessionUser = self::$session->get('loginname');
+ $serverUser = $_SERVER['PHP_AUTH_USER'];
+ OC_Log::write('core',
+ "Session user-id ($sessionUser) doesn't match SERVER[PHP_AUTH_USER] ($serverUser).",
+ OC_Log::WARN);
OC_User::logout();
}
@@ -474,7 +554,7 @@ class OC {
// This includes plugins for users and filesystems as well
global $RUNTIME_NOAPPS;
global $RUNTIME_APPTYPES;
- if (!$RUNTIME_NOAPPS) {
+ if (!$RUNTIME_NOAPPS && !self::checkUpgrade(false)) {
if ($RUNTIME_APPTYPES) {
OC_App::loadApps($RUNTIME_APPTYPES);
} else {
@@ -487,7 +567,9 @@ class OC {
self::registerCacheHooks();
self::registerFilesystemHooks();
+ self::registerPreviewHooks();
self::registerShareHooks();
+ self::registerLogRotate();
//make sure temporary files are cleaned up
register_shutdown_function(array('OC_Helper', 'cleanTmp'));
@@ -521,12 +603,6 @@ class OC {
}
}
- // write error into log if locale can't be set
- if (OC_Util::issetlocaleworking() == false) {
- OC_Log::write('core',
- 'setting locale to en_US.UTF-8/en_US.UTF8 failed. Support is probably not installed on your system',
- OC_Log::ERROR);
- }
if (OC_Config::getValue('installed', false) && !self::checkUpgrade(false)) {
if (OC_Appconfig::getValue('core', 'backgroundjobs_mode', 'ajax') == 'ajax') {
OC_Util::addScript('backgroundjobs');
@@ -538,14 +614,22 @@ class OC {
* register hooks for the cache
*/
public static function registerCacheHooks() {
- if (OC_Config::getValue('installed', false)) { //don't try to do this before we are properly setup
- // register cache cleanup jobs
- try { //if this is executed before the upgrade to the new backgroundjob system is completed it will throw an exception
- \OCP\BackgroundJob::registerJob('OC_Cache_FileGlobalGC');
- } catch (Exception $e) {
+ if (OC_Config::getValue('installed', false) && !self::needUpgrade()) { //don't try to do this before we are properly setup
+ \OCP\BackgroundJob::registerJob('OC\Cache\FileGlobalGC');
- }
- OC_Hook::connect('OC_User', 'post_login', 'OC_Cache_File', 'loginListener');
+ // NOTE: This will be replaced to use OCP
+ $userSession = \OC_User::getUserSession();
+ $userSession->listen('postLogin', '\OC\Cache\File', 'loginListener');
+ }
+ }
+
+ /**
+ * register hooks for the cache
+ */
+ public static function registerLogRotate() {
+ if (OC_Config::getValue('installed', false) && OC_Config::getValue('log_rotate_size', false) && !self::needUpgrade()) {
+ //don't try to do this before we are properly setup
+ \OCP\BackgroundJob::registerJob('OC\Log\Rotate', OC_Config::getValue("datadirectory", OC::$SERVERROOT . '/data') . '/owncloud.log');
}
}
@@ -559,10 +643,20 @@ class OC {
}
/**
+ * register hooks for previews
+ */
+ public static function registerPreviewHooks() {
+ OC_Hook::connect('OC_Filesystem', 'post_write', 'OC\Preview', 'post_write');
+ OC_Hook::connect('OC_Filesystem', 'delete', 'OC\Preview', 'post_delete');
+ OC_Hook::connect('\OCP\Versions', 'delete', 'OC\Preview', 'post_delete');
+ OC_Hook::connect('\OCP\Trashbin', 'delete', 'OC\Preview', 'post_delete');
+ }
+
+ /**
* register hooks for sharing
*/
public static function registerShareHooks() {
- if(\OC_Config::getValue('installed')) {
+ 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');
@@ -585,7 +679,7 @@ class OC {
}
$request = OC_Request::getPathInfo();
- if(substr($request, -3) !== '.js') {// we need these files during the upgrade
+ if (substr($request, -3) !== '.js') { // we need these files during the upgrade
self::checkMaintenanceMode();
self::checkUpgrade();
}
@@ -593,11 +687,12 @@ class OC {
// Test it the user is already authenticated using Apaches AuthType Basic... very usable in combination with LDAP
OC::tryBasicAuthLogin();
- if (!self::$CLI) {
+ if (!self::$CLI and (!isset($_GET["logout"]) or ($_GET["logout"] !== 'true'))) {
try {
if (!OC_Config::getValue('maintenance', false)) {
OC_App::loadApps();
}
+ self::checkSingleUserMode();
OC::getRouter()->match(OC_Request::getRawPathInfo());
return;
} catch (Symfony\Component\Routing\Exception\ResourceNotFoundException $e) {
@@ -630,7 +725,11 @@ class OC {
}
// Handle WebDAV
if ($_SERVER['REQUEST_METHOD'] == 'PROPFIND') {
- header('location: ' . OC_Helper::linkToRemote('webdav'));
+ // not allowed any more to prevent people
+ // mounting this root directly.
+ // Users need to mount remote.php/webdav instead.
+ header('HTTP/1.1 405 Method Not Allowed');
+ header('Status: 405 Method Not Allowed');
return;
}
@@ -666,12 +765,15 @@ class OC {
$app = $param['app'];
$file = $param['file'];
$app_path = OC_App::getAppPath($app);
- $file = $app_path . '/' . $file;
- unset($app, $app_path);
- if (file_exists($file)) {
- require_once $file;
- return true;
+ if (OC_App::isEnabled($app) && $app_path !== false) {
+ $file = $app_path . '/' . $file;
+ unset($app, $app_path);
+ if (file_exists($file)) {
+ require_once $file;
+ return true;
+ }
}
+ header('HTTP/1.0 404 Not Found');
return false;
}
@@ -691,12 +793,23 @@ class OC {
protected static function handleLogin() {
OC_App::loadApps(array('prelogin'));
$error = array();
- // remember was checked after last login
- if (OC::tryRememberLogin()) {
+
+ // auth possible via apache module?
+ if (OC::tryApacheAuth()) {
+ $error[] = 'apacheauthfailed';
+ } // remember was checked after last login
+ elseif (OC::tryRememberLogin()) {
$error[] = 'invalidcookie';
- // Someone wants to log in :
- } elseif (OC::tryFormLogin()) {
+ } // logon via web form
+ elseif (OC::tryFormLogin()) {
$error[] = 'invalidpassword';
+ if ( OC_Config::getValue('log_authfailip', false) ) {
+ OC_Log::write('core', 'Login failed: user \''.$_POST["user"].'\' , wrong password, IP:'.$_SERVER['REMOTE_ADDR'],
+ OC_Log::WARN);
+ } else {
+ OC_Log::write('core', 'Login failed: user \''.$_POST["user"].'\' , wrong password, IP:set log_authfailip=true in conf',
+ OC_Log::WARN);
+ }
}
OC_Util::displayLoginPage(array_unique($error));
@@ -713,11 +826,26 @@ class OC {
}
}
+ protected static function tryApacheAuth() {
+ $return = OC_User::handleApacheAuth();
+
+ // if return is true we are logged in -> redirect to the default page
+ if ($return === true) {
+ $_REQUEST['redirect_url'] = \OC_Request::requestUri();
+ OC_Util::redirectToDefaultPage();
+ exit;
+ }
+
+ // in case $return is null apache based auth is not enabled
+ return is_null($return) ? false : true;
+ }
+
protected static function tryRememberLogin() {
if (!isset($_COOKIE["oc_remember_login"])
|| !isset($_COOKIE["oc_token"])
|| !isset($_COOKIE["oc_username"])
|| !$_COOKIE["oc_remember_login"]
+ || !OC_Util::rememberLoginAllowed()
) {
return false;
}
@@ -735,7 +863,7 @@ class OC {
if (in_array($_COOKIE['oc_token'], $tokens, true)) {
// replace successfully used token with a new one
OC_Preferences::deleteKey($_COOKIE['oc_username'], 'login_token', $_COOKIE['oc_token']);
- $token = OC_Util::generate_random_bytes(32);
+ $token = OC_Util::generateRandomBytes(32);
OC_Preferences::setValue($_COOKIE['oc_username'], 'login_token', $token, time());
OC_User::setMagicInCookie($_COOKIE['oc_username'], $token);
// login
@@ -769,14 +897,15 @@ class OC {
self::$session->set('timezone', $_POST['timezone-offset']);
}
- self::cleanupLoginTokens($_POST['user']);
+ $userid = OC_User::getUser();
+ self::cleanupLoginTokens($userid);
if (!empty($_POST["remember_login"])) {
if (defined("DEBUG") && DEBUG) {
OC_Log::write('core', 'Setting remember login to cookie', OC_Log::DEBUG);
}
- $token = OC_Util::generate_random_bytes(32);
- OC_Preferences::setValue($_POST['user'], 'login_token', $token, time());
- OC_User::setMagicInCookie($_POST["user"], $token);
+ $token = OC_Util::generateRandomBytes(32);
+ OC_Preferences::setValue($userid, 'login_token', $token, time());
+ OC_User::setMagicInCookie($userid, $token);
} else {
OC_User::unsetMagicInCookie();
}
diff --git a/lib/cache/fileglobalgc.php b/lib/cache/fileglobalgc.php
deleted file mode 100644
index a29c31f9063..00000000000
--- a/lib/cache/fileglobalgc.php
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php
-
-
-class OC_Cache_FileGlobalGC extends \OC\BackgroundJob\Job{
- public function run($argument){
- OC_Cache_FileGlobal::gc();
- }
-}
diff --git a/lib/connector/sabre/file.php b/lib/connector/sabre/file.php
deleted file mode 100644
index 06ab73e3e4d..00000000000
--- a/lib/connector/sabre/file.php
+++ /dev/null
@@ -1,159 +0,0 @@
-<?php
-
-/**
- * ownCloud
- *
- * @author Jakob Sack
- * @copyright 2011 Jakob Sack kde@jakobsack.de
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
- *
- * You should have received a copy of the GNU Affero General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_DAV_IFile {
-
- /**
- * Updates the data
- *
- * The data argument is a readable stream resource.
- *
- * After a succesful put operation, you may choose to return an ETag. The
- * etag must always be surrounded by double-quotes. These quotes must
- * appear in the actual string you're returning.
- *
- * Clients may use the ETag from a PUT request to later on make sure that
- * when they update the file, the contents haven't changed in the mean
- * time.
- *
- * If you don't plan to store the file byte-by-byte, and you return a
- * different object on a subsequent GET you are strongly recommended to not
- * return an ETag, and just return null.
- *
- * @param resource $data
- * @throws Sabre_DAV_Exception_Forbidden
- * @return string|null
- */
- public function put($data) {
-
- if (!\OC\Files\Filesystem::isUpdatable($this->path)) {
- throw new \Sabre_DAV_Exception_Forbidden();
- }
-
- // mark file as partial while uploading (ignored by the scanner)
- $partpath = $this->path . '.part';
-
- \OC\Files\Filesystem::file_put_contents($partpath, $data);
-
- //detect aborted upload
- if (isset ($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
- if (isset($_SERVER['CONTENT_LENGTH'])) {
- $expected = $_SERVER['CONTENT_LENGTH'];
- $actual = \OC\Files\Filesystem::filesize($partpath);
- if ($actual != $expected) {
- \OC\Files\Filesystem::unlink($partpath);
- throw new Sabre_DAV_Exception_BadRequest(
- 'expected filesize ' . $expected . ' got ' . $actual);
- }
- }
- }
-
- // rename to correct path
- \OC\Files\Filesystem::rename($partpath, $this->path);
-
- //allow sync clients to send the mtime along in a header
- $mtime = OC_Request::hasModificationTime();
- if ($mtime !== false) {
- if (\OC\Files\Filesystem::touch($this->path, $mtime)) {
- header('X-OC-MTime: accepted');
- }
- }
-
- return OC_Connector_Sabre_Node::getETagPropertyForPath($this->path);
- }
-
- /**
- * Returns the data
- *
- * @return string
- */
- public function get() {
-
- return \OC\Files\Filesystem::fopen($this->path, 'rb');
-
- }
-
- /**
- * Delete the current file
- *
- * @return void
- * @throws Sabre_DAV_Exception_Forbidden
- */
- public function delete() {
-
- if (!\OC\Files\Filesystem::isDeletable($this->path)) {
- throw new \Sabre_DAV_Exception_Forbidden();
- }
- \OC\Files\Filesystem::unlink($this->path);
-
- }
-
- /**
- * Returns the size of the node, in bytes
- *
- * @return int
- */
- public function getSize() {
- $this->getFileinfoCache();
- if ($this->fileinfo_cache['size'] > -1) {
- return $this->fileinfo_cache['size'];
- } else {
- return null;
- }
- }
-
- /**
- * Returns the ETag for a file
- *
- * An ETag is a unique identifier representing the current version of the
- * file. If the file changes, the ETag MUST change. The ETag is an
- * arbritrary string, but MUST be surrounded by double-quotes.
- *
- * Return null if the ETag can not effectively be determined
- *
- * @return mixed
- */
- public function getETag() {
- $properties = $this->getProperties(array(self::GETETAG_PROPERTYNAME));
- if (isset($properties[self::GETETAG_PROPERTYNAME])) {
- return $properties[self::GETETAG_PROPERTYNAME];
- }
- return null;
- }
-
- /**
- * Returns the mime-type for a file
- *
- * If null is returned, we'll assume application/octet-stream
- *
- * @return mixed
- */
- public function getContentType() {
- if (isset($this->fileinfo_cache['mimetype'])) {
- return $this->fileinfo_cache['mimetype'];
- }
-
- return \OC\Files\Filesystem::getMimeType($this->path);
-
- }
-}
diff --git a/lib/connector/sabre/quotaplugin.php b/lib/connector/sabre/quotaplugin.php
deleted file mode 100644
index c80a33d04b1..00000000000
--- a/lib/connector/sabre/quotaplugin.php
+++ /dev/null
@@ -1,60 +0,0 @@
-<?php
-
-/**
- * This plugin check user quota and deny creating files when they exceeds the quota.
- *
- * @copyright Copyright (C) 2012 entreCables S.L. All rights reserved.
- * @author Sergio Cambra
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
- */
-class OC_Connector_Sabre_QuotaPlugin extends Sabre_DAV_ServerPlugin {
-
- /**
- * Reference to main server object
- *
- * @var Sabre_DAV_Server
- */
- private $server;
-
- /**
- * This initializes the plugin.
- *
- * This function is called by Sabre_DAV_Server, after
- * addPlugin is called.
- *
- * This method should set up the requires event subscriptions.
- *
- * @param Sabre_DAV_Server $server
- * @return void
- */
- public function initialize(Sabre_DAV_Server $server) {
-
- $this->server = $server;
- $this->server->subscribeEvent('beforeWriteContent', array($this, 'checkQuota'), 10);
- $this->server->subscribeEvent('beforeCreateFile', array($this, 'checkQuota'), 10);
-
- }
-
- /**
- * This method is called before any HTTP method and forces users to be authenticated
- *
- * @param string $method
- * @throws Sabre_DAV_Exception
- * @return bool
- */
- public function checkQuota($uri, $data = null) {
- $expected = $this->server->httpRequest->getHeader('X-Expected-Entity-Length');
- $length = $expected ? $expected : $this->server->httpRequest->getHeader('Content-Length');
- if ($length) {
- if (substr($uri, 0, 1)!=='/') {
- $uri='/'.$uri;
- }
- list($parentUri, $newName) = Sabre_DAV_URLUtil::splitPath($uri);
- $freeSpace = \OC\Files\Filesystem::free_space($parentUri);
- if ($freeSpace !== \OC\Files\FREE_SPACE_UNKNOWN && $length > $freeSpace) {
- throw new Sabre_DAV_Exception_InsufficientStorage();
- }
- }
- return true;
- }
-}
diff --git a/lib/fileproxy/quota.php b/lib/fileproxy/quota.php
deleted file mode 100644
index 3dac3264fbe..00000000000
--- a/lib/fileproxy/quota.php
+++ /dev/null
@@ -1,114 +0,0 @@
-<?php
-
-/**
-* ownCloud
-*
-* @author Robin Appelman
-* @copyright 2011 Robin Appelman icewind1991@gmail.com
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
-* License as published by the Free Software Foundation; either
-* version 3 of the License, or any later version.
-*
-* This library is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
-*
-* You should have received a copy of the GNU Affero General Public
-* License along with this library. If not, see <http://www.gnu.org/licenses/>.
-*
-*/
-
-/**
- * user quota management
- */
-
-class OC_FileProxy_Quota extends OC_FileProxy{
- static $rootView;
- private $userQuota=array();
-
- /**
- * get the quota for the user
- * @param user
- * @return int
- */
- private function getQuota($user) {
- if(in_array($user, $this->userQuota)) {
- return $this->userQuota[$user];
- }
- $userQuota=OC_Preferences::getValue($user, 'files', 'quota', 'default');
- if($userQuota=='default') {
- $userQuota=OC_AppConfig::getValue('files', 'default_quota', 'none');
- }
- if($userQuota=='none') {
- $this->userQuota[$user]=-1;
- }else{
- $this->userQuota[$user]=OC_Helper::computerFileSize($userQuota);
- }
- return $this->userQuota[$user];
-
- }
-
- /**
- * get the free space in the path's owner home folder
- * @param path
- * @return int
- */
- private function getFreeSpace($path) {
- /**
- * @var \OC\Files\Storage\Storage $storage
- * @var string $internalPath
- */
- list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path);
- $owner = $storage->getOwner($internalPath);
- if (!$owner) {
- return -1;
- }
-
- $totalSpace = $this->getQuota($owner);
- if($totalSpace == -1) {
- return -1;
- }
-
- $view = new \OC\Files\View("/".$owner."/files");
-
- $rootInfo = $view->getFileInfo('/');
- $usedSpace = isset($rootInfo['size'])?$rootInfo['size']:0;
- return $totalSpace - $usedSpace;
- }
-
- public function postFree_space($path, $space) {
- $free=$this->getFreeSpace($path);
- if($free==-1) {
- return $space;
- }
- if ($space < 0){
- return $free;
- }
- return min($free, $space);
- }
-
- public function preFile_put_contents($path, $data) {
- if (is_resource($data)) {
- $data = '';//TODO: find a way to get the length of the stream without emptying it
- }
- return (strlen($data)<$this->getFreeSpace($path) or $this->getFreeSpace($path)==-1);
- }
-
- public function preCopy($path1, $path2) {
- if(!self::$rootView) {
- self::$rootView = new \OC\Files\View('');
- }
- return (self::$rootView->filesize($path1)<$this->getFreeSpace($path2) or $this->getFreeSpace($path2)==-1);
- }
-
- public function preFromTmpFile($tmpfile, $path) {
- return (filesize($tmpfile)<$this->getFreeSpace($path) or $this->getFreeSpace($path)==-1);
- }
-
- public function preFromUploadedFile($tmpfile, $path) {
- return (filesize($tmpfile)<$this->getFreeSpace($path) or $this->getFreeSpace($path)==-1);
- }
-}
diff --git a/lib/l10n/ach.php b/lib/l10n/ach.php
new file mode 100644
index 00000000000..406ff5f5a26
--- /dev/null
+++ b/lib/l10n/ach.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/ady.php b/lib/l10n/ady.php
new file mode 100644
index 00000000000..15f78e0bce6
--- /dev/null
+++ b/lib/l10n/ady.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/af.php b/lib/l10n/af.php
new file mode 100644
index 00000000000..15f78e0bce6
--- /dev/null
+++ b/lib/l10n/af.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/af_ZA.php b/lib/l10n/af_ZA.php
index 67353b8fb42..d6bf5771e8d 100644
--- a/lib/l10n/af_ZA.php
+++ b/lib/l10n/af_ZA.php
@@ -4,8 +4,11 @@ $TRANSLATIONS = array(
"Personal" => "Persoonlik",
"Settings" => "Instellings",
"Users" => "Gebruikers",
-"Apps" => "Toepassings",
"Admin" => "Admin",
-"web services under your control" => "webdienste onder jou beheer"
+"web services under your control" => "webdienste onder jou beheer",
+"_%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/ar.php b/lib/l10n/ar.php
index 50881cb627b..6870c549940 100644
--- a/lib/l10n/ar.php
+++ b/lib/l10n/ar.php
@@ -4,14 +4,12 @@ $TRANSLATIONS = array(
"Personal" => "شخصي",
"Settings" => "إعدادات",
"Users" => "المستخدمين",
-"Apps" => "التطبيقات",
"Admin" => "المدير",
"web services under your control" => "خدمات الشبكة تحت سيطرتك",
"ZIP download is turned off." => "تحميل ملفات ZIP متوقف",
"Files need to be downloaded one by one." => "الملفات بحاجة الى ان يتم تحميلها واحد تلو الاخر",
"Back to Files" => "العودة الى الملفات",
"Selected files too large to generate zip file." => "الملفات المحددة كبيرة جدا ليتم ضغطها في ملف zip",
-"couldn't be determined" => "تعذّر تحديده",
"Application is not enabled" => "التطبيق غير مفعّل",
"Authentication error" => "لم يتم التأكد من الشخصية بنجاح",
"Token expired. Please reload page." => "انتهت صلاحية الكلمة , يرجى اعادة تحميل الصفحة",
@@ -37,18 +35,16 @@ $TRANSLATIONS = array(
"Set an admin password." => "اعداد كلمة مرور للمدير",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "اعدادات خادمك غير صحيحة بشكل تسمح لك بمزامنة ملفاتك وذلك بسبب أن واجهة WebDAV تبدو معطلة",
"Please double check the <a href='%s'>installation guides</a>." => "الرجاء التحقق من <a href='%s'>دليل التنصيب</a>.",
+"Could not find category \"%s\"" => "تعذر العثور على المجلد \"%s\"",
"seconds ago" => "منذ ثواني",
-"1 minute ago" => "منذ دقيقة",
-"%d minutes ago" => "%d دقيقة مضت",
-"1 hour ago" => "قبل ساعة مضت",
-"%d hours ago" => "%d ساعة مضت",
+"_%n minute ago_::_%n minutes ago_" => array("","","","","",""),
+"_%n hour ago_::_%n hours ago_" => array("","","","","",""),
"today" => "اليوم",
"yesterday" => "يوم أمس",
-"%d days ago" => "%d يوم مضى",
+"_%n day go_::_%n days ago_" => array("","","","","",""),
"last month" => "الشهر الماضي",
-"%d months ago" => "%d شهر مضت",
+"_%n month ago_::_%n months ago_" => array("","","","","",""),
"last year" => "السنةالماضية",
-"years ago" => "سنة مضت",
-"Could not find category \"%s\"" => "تعذر العثور على المجلد \"%s\""
+"years ago" => "سنة مضت"
);
$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/az.php b/lib/l10n/az.php
new file mode 100644
index 00000000000..e7b09649a24
--- /dev/null
+++ b/lib/l10n/az.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=1; plural=0;";
diff --git a/lib/l10n/be.php b/lib/l10n/be.php
new file mode 100644
index 00000000000..1570411eb86
--- /dev/null
+++ b/lib/l10n/be.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=4; 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/bg_BG.php b/lib/l10n/bg_BG.php
index 4a558426a89..c9de3d64d89 100644
--- a/lib/l10n/bg_BG.php
+++ b/lib/l10n/bg_BG.php
@@ -4,14 +4,12 @@ $TRANSLATIONS = array(
"Personal" => "Лични",
"Settings" => "Настройки",
"Users" => "Потребители",
-"Apps" => "Приложения",
"Admin" => "Админ",
"web services under your control" => "уеб услуги под Ваш контрол",
"ZIP download is turned off." => "Изтеглянето като ZIP е изключено.",
"Files need to be downloaded one by one." => "Файловете трябва да се изтеглят един по един.",
"Back to Files" => "Назад към файловете",
"Selected files too large to generate zip file." => "Избраните файлове са прекалено големи за генерирането на ZIP архив.",
-"couldn't be determined" => "не може да се определи",
"Application is not enabled" => "Приложението не е включено.",
"Authentication error" => "Възникна проблем с идентификацията",
"Token expired. Please reload page." => "Ключът е изтекъл, моля презаредете страницата",
@@ -38,18 +36,16 @@ $TRANSLATIONS = array(
"Set an admin password." => "Въведете парола за администратор.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Вашият web сървър все още не е удачно настроен да позволява синхронизация на файлове, защото WebDAV интерфейсът изглежда не работи.",
"Please double check the <a href='%s'>installation guides</a>." => "Моля направете повторна справка с <a href='%s'>ръководството за инсталиране</a>.",
+"Could not find category \"%s\"" => "Невъзможно откриване на категорията \"%s\"",
"seconds ago" => "преди секунди",
-"1 minute ago" => "преди 1 минута",
-"%d minutes ago" => "преди %d минути",
-"1 hour ago" => "преди 1 час",
-"%d hours ago" => "преди %d часа",
+"_%n minute ago_::_%n minutes ago_" => array("",""),
+"_%n hour ago_::_%n hours ago_" => array("",""),
"today" => "днес",
"yesterday" => "вчера",
-"%d days ago" => "преди %d дни",
+"_%n day go_::_%n days ago_" => array("",""),
"last month" => "последният месец",
-"%d months ago" => "преди %d месеца",
+"_%n month ago_::_%n months ago_" => array("",""),
"last year" => "последната година",
-"years ago" => "последните години",
-"Could not find category \"%s\"" => "Невъзможно откриване на категорията \"%s\""
+"years ago" => "последните години"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/bn_BD.php b/lib/l10n/bn_BD.php
index 3e1340b3689..a42435a2a47 100644
--- a/lib/l10n/bn_BD.php
+++ b/lib/l10n/bn_BD.php
@@ -4,7 +4,6 @@ $TRANSLATIONS = array(
"Personal" => "ব্যক্তিগত",
"Settings" => "নিয়ামকসমূহ",
"Users" => "ব্যবহারকারী",
-"Apps" => "অ্যাপ",
"Admin" => "প্রশাসন",
"web services under your control" => "ওয়েব সার্ভিস আপনার হাতের মুঠোয়",
"ZIP download is turned off." => "ZIP ডাউনলোড বন্ধ করা আছে।",
@@ -17,13 +16,13 @@ $TRANSLATIONS = array(
"Files" => "ফাইল",
"Text" => "টেক্সট",
"seconds ago" => "সেকেন্ড পূর্বে",
-"1 minute ago" => "১ মিনিট পূর্বে",
-"%d minutes ago" => "%d মিনিট পূর্বে",
-"1 hour ago" => "1 ঘন্টা পূর্বে",
+"_%n minute ago_::_%n minutes ago_" => array("",""),
+"_%n hour ago_::_%n hours ago_" => array("",""),
"today" => "আজ",
"yesterday" => "গতকাল",
-"%d days ago" => "%d দিন পূর্বে",
+"_%n day go_::_%n days ago_" => array("",""),
"last month" => "গত মাস",
+"_%n month ago_::_%n months ago_" => array("",""),
"last year" => "গত বছর",
"years ago" => "বছর পূর্বে"
);
diff --git a/lib/l10n/bs.php b/lib/l10n/bs.php
new file mode 100644
index 00000000000..3cb98906e62
--- /dev/null
+++ b/lib/l10n/bs.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=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/ca.php b/lib/l10n/ca.php
index a0c7b10e734..e7250befc2f 100644
--- a/lib/l10n/ca.php
+++ b/lib/l10n/ca.php
@@ -1,20 +1,34 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "L'aplicació \"%s\" no es pot instal·lar perquè no és compatible amb aquesta versió d'ownCloud.",
+"No app name specified" => "No heu especificat cap nom d'aplicació",
"Help" => "Ajuda",
"Personal" => "Personal",
"Settings" => "Configuració",
"Users" => "Usuaris",
-"Apps" => "Aplicacions",
"Admin" => "Administració",
"Failed to upgrade \"%s\"." => "Ha fallat l'actualització \"%s\".",
+"Unknown filetype" => "Tipus de fitxer desconegut",
+"Invalid image" => "Imatge no vàlida",
"web services under your control" => "controleu els vostres serveis web",
"cannot open \"%s\"" => "no es pot obrir \"%s\"",
"ZIP download is turned off." => "La baixada en ZIP està desactivada.",
"Files need to be downloaded one by one." => "Els fitxers s'han de baixar d'un en un.",
"Back to Files" => "Torna a Fitxers",
"Selected files too large to generate zip file." => "Els fitxers seleccionats son massa grans per generar un fitxer zip.",
-"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Baixeu els fitxers en trossos petits, de forma separada, o pregunteu a l'administrador.",
-"couldn't be determined" => "no s'ha pogut determinar",
+"Please download the files separately in smaller chunks or kindly ask your administrator." => "Baixeu els fitxers separadament en petits trossos o pregunteu a l'administrador.",
+"No source specified when installing app" => "No heu especificat la font en instal·lar l'aplicació",
+"No href specified when installing app from http" => "No heu especificat href en instal·lar l'aplicació des de http",
+"No path specified when installing app from local file" => "No heu seleccionat el camí en instal·lar una aplicació des d'un fitxer local",
+"Archives of type %s are not supported" => "Els fitxers del tipus %s no són compatibles",
+"Failed to open archive when installing app" => "Ha fallat l'obertura del fitxer en instal·lar l'aplicació",
+"App does not provide an info.xml file" => "L'aplicació no proporciona un fitxer info.xml",
+"App can't be installed because of not allowed code in the App" => "L'aplicació no es pot instal·lar perquè hi ha codi no autoritzat en l'aplicació",
+"App can't be installed because it is not compatible with this version of ownCloud" => "L'aplicació no es pot instal·lar perquè no és compatible amb aquesta versió d'ownCloud",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "L'aplicació no es pot instal·lar perquè conté l'etiqueta <shipped>vertader</shipped> que no es permet per aplicacions no enviades",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "L'aplicació no es pot instal·lar perquè la versió a info.xml/version no és la mateixa que la versió indicada des de la botiga d'aplicacions",
+"App directory already exists" => "La carpeta de l'aplicació ja existeix",
+"Can't create app folder. Please fix permissions. %s" => "No es pot crear la carpeta de l'aplicació. Arregleu els permisos. %s",
"Application is not enabled" => "L'aplicació no està habilitada",
"Authentication error" => "Error d'autenticació",
"Token expired. Please reload page." => "El testimoni ha expirat. Torneu a carregar la pàgina.",
@@ -41,19 +55,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "Establiu una contrasenya per l'administrador.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "El servidor web no està configurat correctament per permetre la sincronització de fitxers perquè la interfície WebDAV sembla no funcionar correctament.",
"Please double check the <a href='%s'>installation guides</a>." => "Comproveu les <a href='%s'>guies d'instal·lació</a>.",
+"Could not find category \"%s\"" => "No s'ha trobat la categoria \"%s\"",
"seconds ago" => "segons enrere",
-"1 minute ago" => "fa 1 minut",
-"%d minutes ago" => "fa %d minuts",
-"1 hour ago" => "fa 1 hora",
-"%d hours ago" => "fa %d hores",
+"_%n minute ago_::_%n minutes ago_" => array("fa %n minut","fa %n minuts"),
+"_%n hour ago_::_%n hours ago_" => array("fa %n hora","fa %n hores"),
"today" => "avui",
"yesterday" => "ahir",
-"%d days ago" => "fa %d dies",
+"_%n day go_::_%n days ago_" => array("fa %n dia","fa %n dies"),
"last month" => "el mes passat",
-"%d months ago" => "fa %d mesos",
+"_%n month ago_::_%n months ago_" => array("fa %n mes","fa %n mesos"),
"last year" => "l'any passat",
"years ago" => "anys enrere",
-"Caused by:" => "Provocat per:",
-"Could not find category \"%s\"" => "No s'ha trobat la categoria \"%s\""
+"Caused by:" => "Provocat per:"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/cs_CZ.php b/lib/l10n/cs_CZ.php
index 354c61f6a12..96d3660c473 100644
--- a/lib/l10n/cs_CZ.php
+++ b/lib/l10n/cs_CZ.php
@@ -1,20 +1,34 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "Aplikace \"%s\" nemůže být nainstalována, protože není kompatibilní s touto verzí ownCloud.",
+"No app name specified" => "Nebyl zadan název aplikace",
"Help" => "Nápověda",
"Personal" => "Osobní",
"Settings" => "Nastavení",
"Users" => "Uživatelé",
-"Apps" => "Aplikace",
"Admin" => "Administrace",
"Failed to upgrade \"%s\"." => "Selhala aktualizace verze \"%s\".",
+"Unknown filetype" => "Neznámý typ souboru",
+"Invalid image" => "Chybný obrázek",
"web services under your control" => "webové služby pod Vaší kontrolou",
"cannot open \"%s\"" => "nelze otevřít \"%s\"",
"ZIP download is turned off." => "Stahování v ZIPu je vypnuto.",
"Files need to be downloaded one by one." => "Soubory musí být stahovány jednotlivě.",
"Back to Files" => "Zpět k souborům",
"Selected files too large to generate zip file." => "Vybrané soubory jsou příliš velké pro vytvoření ZIP souboru.",
-"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Stáhněte soubory po menších částech, samostatně, nebo se obraťte na správce.",
-"couldn't be determined" => "nelze zjistit",
+"Please download the files separately in smaller chunks or kindly ask your administrator." => "Prosím stáhněte soubory odděleně po menších množstvích nebo požádejte vašeho správce.",
+"No source specified when installing app" => "Nebyl zadán zdroj při instalaci aplikace",
+"No href specified when installing app from http" => "Nebyl zadán odkaz pro instalaci aplikace z HTTP",
+"No path specified when installing app from local file" => "Nebyla zadána cesta pro instalaci aplikace z místního souboru",
+"Archives of type %s are not supported" => "Archivy typu %s nejsou podporovány",
+"Failed to open archive when installing app" => "Chyba při otevírání archivu během instalace aplikace",
+"App does not provide an info.xml file" => "Aplikace neposkytuje soubor info.xml",
+"App can't be installed because of not allowed code in the App" => "Aplikace nemůže být nainstalována, protože obsahuje nepovolený kód",
+"App can't be installed because it is not compatible with this version of ownCloud" => "Aplikace nemůže být nainstalována, protože není kompatibilní s touto verzí ownCloud",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Aplikace nemůže být nainstalována, protože obsahuje značku\n<shipped>\n\ntrue\n</shipped>\n\ncož není povoleno pro nedodávané aplikace",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Aplikace nemůže být nainstalována, protože verze uvedená v info.xml/version nesouhlasí s verzí oznámenou z úložiště aplikací.",
+"App directory already exists" => "Adresář aplikace již existuje",
+"Can't create app folder. Please fix permissions. %s" => "Nelze vytvořit složku aplikace. Opravte práva souborů. %s",
"Application is not enabled" => "Aplikace není povolena",
"Authentication error" => "Chyba ověření",
"Token expired. Please reload page." => "Token vypršel. Obnovte prosím stránku.",
@@ -41,19 +55,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "Zadejte heslo správce.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Váš webový server není správně nastaven pro umožnění synchronizace, rozhraní WebDAV se zdá být rozbité.",
"Please double check the <a href='%s'>installation guides</a>." => "Zkonzultujte, prosím, <a href='%s'>průvodce instalací</a>.",
+"Could not find category \"%s\"" => "Nelze nalézt kategorii \"%s\"",
"seconds ago" => "před pár sekundami",
-"1 minute ago" => "před minutou",
-"%d minutes ago" => "před %d minutami",
-"1 hour ago" => "před hodinou",
-"%d hours ago" => "před %d hodinami",
+"_%n minute ago_::_%n minutes ago_" => array("před %n minutou","před %n minutami","před %n minutami"),
+"_%n hour ago_::_%n hours ago_" => array("před %n hodinou","před %n hodinami","před %n hodinami"),
"today" => "dnes",
"yesterday" => "včera",
-"%d days ago" => "před %d dny",
+"_%n day go_::_%n days ago_" => array("před %n dnem","před %n dny","před %n dny"),
"last month" => "minulý měsíc",
-"%d months ago" => "před %d měsíci",
+"_%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",
-"Caused by:" => "Příčina:",
-"Could not find category \"%s\"" => "Nelze nalézt kategorii \"%s\""
+"Caused by:" => "Příčina:"
);
$PLURAL_FORMS = "nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;";
diff --git a/lib/l10n/cy_GB.php b/lib/l10n/cy_GB.php
index 7ba8378cb41..0a52f5df776 100644
--- a/lib/l10n/cy_GB.php
+++ b/lib/l10n/cy_GB.php
@@ -4,14 +4,12 @@ $TRANSLATIONS = array(
"Personal" => "Personol",
"Settings" => "Gosodiadau",
"Users" => "Defnyddwyr",
-"Apps" => "Pecynnau",
"Admin" => "Gweinyddu",
"web services under your control" => "gwasanaethau gwe a reolir gennych",
"ZIP download is turned off." => "Mae llwytho ZIP wedi ei ddiffodd.",
"Files need to be downloaded one by one." => "Mae angen llwytho ffeiliau i lawr fesul un.",
"Back to Files" => "Nôl i Ffeiliau",
"Selected files too large to generate zip file." => "Mae'r ffeiliau ddewiswyd yn rhy fawr i gynhyrchu ffeil zip.",
-"couldn't be determined" => "methwyd pennu",
"Application is not enabled" => "Nid yw'r pecyn wedi'i alluogi",
"Authentication error" => "Gwall dilysu",
"Token expired. Please reload page." => "Tocyn wedi dod i ben. Ail-lwythwch y dudalen.",
@@ -37,18 +35,16 @@ $TRANSLATIONS = array(
"Set an admin password." => "Gosod cyfrinair y gweinyddwr.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Nid yw eich gweinydd wedi'i gyflunio eto i ganiatáu cydweddu ffeiliau oherwydd bod y rhyngwyneb WebDAV wedi torri.",
"Please double check the <a href='%s'>installation guides</a>." => "Gwiriwch y <a href='%s'>canllawiau gosod</a> eto.",
+"Could not find category \"%s\"" => "Methu canfod categori \"%s\"",
"seconds ago" => "eiliad yn ôl",
-"1 minute ago" => "1 munud yn ôl",
-"%d minutes ago" => "%d munud yn ôl",
-"1 hour ago" => "1 awr yn ôl",
-"%d hours ago" => "%d awr yn ôl",
+"_%n minute ago_::_%n minutes ago_" => array("","","",""),
+"_%n hour ago_::_%n hours ago_" => array("","","",""),
"today" => "heddiw",
"yesterday" => "ddoe",
-"%d days ago" => "%d diwrnod yn ôl",
+"_%n day go_::_%n days ago_" => array("","","",""),
"last month" => "mis diwethaf",
-"%d months ago" => "%d mis yn ôl",
+"_%n month ago_::_%n months ago_" => array("","","",""),
"last year" => "y llynedd",
-"years ago" => "blwyddyn yn ôl",
-"Could not find category \"%s\"" => "Methu canfod categori \"%s\""
+"years ago" => "blwyddyn yn ôl"
);
$PLURAL_FORMS = "nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;";
diff --git a/lib/l10n/da.php b/lib/l10n/da.php
index aa5bb74bd31..f95aa30d7a0 100644
--- a/lib/l10n/da.php
+++ b/lib/l10n/da.php
@@ -1,20 +1,33 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "App'en \"%s\" kan ikke blive installeret, da den ikke er kompatibel med denne version af ownCloud.",
+"No app name specified" => "Intet app-navn angivet",
"Help" => "Hjælp",
"Personal" => "Personligt",
"Settings" => "Indstillinger",
"Users" => "Brugere",
-"Apps" => "Apps",
"Admin" => "Admin",
"Failed to upgrade \"%s\"." => "Upgradering af \"%s\" fejlede",
+"Unknown filetype" => "Ukendt filtype",
+"Invalid image" => "Ugyldigt billede",
"web services under your control" => "Webtjenester under din kontrol",
"cannot open \"%s\"" => "Kan ikke åbne \"%s\"",
"ZIP download is turned off." => "ZIP-download er slået fra.",
"Files need to be downloaded one by one." => "Filer skal downloades en for en.",
"Back to Files" => "Tilbage til Filer",
"Selected files too large to generate zip file." => "De markerede filer er for store til at generere en ZIP-fil.",
-"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Download filerne i små bider, seperat, eller kontakt venligst din administrator.",
-"couldn't be determined" => "kunne ikke fastslås",
+"No source specified when installing app" => "Ingen kilde angivet under installation af app",
+"No href specified when installing app from http" => "Ingen href angivet under installation af app via http",
+"No path specified when installing app from local file" => "Ingen sti angivet under installation af app fra lokal fil",
+"Archives of type %s are not supported" => "Arkiver af type %s understøttes ikke",
+"Failed to open archive when installing app" => "Kunne ikke åbne arkiv under installation af appen",
+"App does not provide an info.xml file" => "Der følger ingen info.xml-fil med appen",
+"App can't be installed because of not allowed code in the App" => "Appen kan ikke installeres, da den indeholder ikke-tilladt kode",
+"App can't be installed because it is not compatible with this version of ownCloud" => "Appen kan ikke installeres, da den ikke er kompatibel med denne version af ownCloud.",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Appen kan ikke installeres, da den indeholder taget\n<shipped>\n\ntrue\n</shipped>\n\nhvilket ikke er tilladt for ikke-medfølgende apps",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "App kan ikke installeres, da versionen i info.xml/version ikke er den samme som versionen rapporteret fra app-storen",
+"App directory already exists" => "App-mappe findes allerede",
+"Can't create app folder. Please fix permissions. %s" => "Kan ikke oprette app-mappe. Ret tilladelser. %s",
"Application is not enabled" => "Programmet er ikke aktiveret",
"Authentication error" => "Adgangsfejl",
"Token expired. Please reload page." => "Adgang er udløbet. Genindlæs siden.",
@@ -41,19 +54,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "Angiv et admin kodeord.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Din webserver er endnu ikke sat op til at tillade fil synkronisering fordi WebDAV grænsefladen virker ødelagt.",
"Please double check the <a href='%s'>installation guides</a>." => "Dobbelttjek venligst <a href='%s'>installations vejledningerne</a>.",
+"Could not find category \"%s\"" => "Kunne ikke finde kategorien \"%s\"",
"seconds ago" => "sekunder siden",
-"1 minute ago" => "1 minut siden",
-"%d minutes ago" => "%d minutter siden",
-"1 hour ago" => "1 time siden",
-"%d hours ago" => "%d timer siden",
+"_%n minute ago_::_%n minutes ago_" => array("%n minut siden","%n minutter siden"),
+"_%n hour ago_::_%n hours ago_" => array("%n time siden","%n timer siden"),
"today" => "i dag",
"yesterday" => "i går",
-"%d days ago" => "%d dage siden",
+"_%n day go_::_%n days ago_" => array("%n dag siden","%n dage siden"),
"last month" => "sidste måned",
-"%d months ago" => "%d måneder siden",
+"_%n month ago_::_%n months ago_" => array("%n måned siden","%n måneder siden"),
"last year" => "sidste år",
"years ago" => "år siden",
-"Caused by:" => "Forårsaget af:",
-"Could not find category \"%s\"" => "Kunne ikke finde kategorien \"%s\""
+"Caused by:" => "Forårsaget af:"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/de.php b/lib/l10n/de.php
index 5dcbea4e022..8ee4cb71d30 100644
--- a/lib/l10n/de.php
+++ b/lib/l10n/de.php
@@ -1,20 +1,34 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "Applikation \"%s\" kann nicht installiert werden, da sie mit dieser ownCloud Version nicht kompatibel ist.",
+"No app name specified" => "Es wurde kein Applikation-Name angegeben",
"Help" => "Hilfe",
"Personal" => "Persönlich",
"Settings" => "Einstellungen",
"Users" => "Benutzer",
-"Apps" => "Apps",
"Admin" => "Administration",
"Failed to upgrade \"%s\"." => "Konnte \"%s\" nicht aktualisieren.",
+"Unknown filetype" => "Unbekannter Dateityp",
+"Invalid image" => "Ungültiges Bild",
"web services under your control" => "Web-Services unter Deiner Kontrolle",
"cannot open \"%s\"" => "Öffnen von \"%s\" fehlgeschlagen",
"ZIP download is turned off." => "Der ZIP-Download ist deaktiviert.",
"Files need to be downloaded one by one." => "Die Dateien müssen einzeln heruntergeladen werden.",
"Back to Files" => "Zurück zu \"Dateien\"",
"Selected files too large to generate zip file." => "Die gewählten Dateien sind zu groß, um eine ZIP-Datei zu erstellen.",
-"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Lade die Dateien in kleineren, separaten, Stücken herunter oder bitte deinen Administrator.",
-"couldn't be determined" => "konnte nicht festgestellt werden",
+"Please download the files separately in smaller chunks or kindly ask your administrator." => "Bitte lade die Dateien einzeln in kleineren Teilen herunter oder bitte Deinen Administrator.",
+"No source specified when installing app" => "Für die Installation der Applikation wurde keine Quelle angegeben",
+"No href specified when installing app from http" => "Für die Installation der Applikation über http wurde keine Quelle (href) angegeben",
+"No path specified when installing app from local file" => "Bei der Installation der Applikation aus einer lokalen Datei wurde kein Pfad angegeben",
+"Archives of type %s are not supported" => "Archive vom Typ %s werden nicht unterstützt",
+"Failed to open archive when installing app" => "Das Archiv konnte bei der Installation der Applikation nicht geöffnet werden",
+"App does not provide an info.xml file" => "Die Applikation enthält keine info,xml Datei",
+"App can't be installed because of not allowed code in the App" => "Die Applikation kann auf Grund von unerlaubtem Code nicht installiert werden",
+"App can't be installed because it is not compatible with this version of ownCloud" => "Die Anwendung konnte nicht installiert werden, weil Sie nicht mit dieser Version von ownCloud kompatibel ist.",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Die Applikation konnte nicht installiert werden, da diese das <shipped>true</shipped> Tag beinhaltet und dieses, bei nicht mitausgelieferten Applikationen, nicht erlaubt ist",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Die Applikation konnte nicht installiert werden, da die Version in der info.xml nicht die gleiche Version wie im App-Store ist",
+"App directory already exists" => "Das Applikationsverzeichnis existiert bereits",
+"Can't create app folder. Please fix permissions. %s" => "Es kann kein Applikationsordner erstellt werden. Bitte passe die Berechtigungen an. %s",
"Application is not enabled" => "Die Anwendung ist nicht aktiviert",
"Authentication error" => "Fehler bei der Anmeldung",
"Token expired. Please reload page." => "Token abgelaufen. Bitte lade die Seite neu.",
@@ -41,19 +55,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "Setze Administrator Passwort",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Dein Web-Server ist noch nicht für Datei-Synchronisation bereit, weil die WebDAV-Schnittstelle vermutlich defekt ist.",
"Please double check the <a href='%s'>installation guides</a>." => "Bitte prüfe die <a href='%s'>Installationsanleitungen</a>.",
+"Could not find category \"%s\"" => "Die Kategorie \"%s\" konnte nicht gefunden werden.",
"seconds ago" => "Gerade eben",
-"1 minute ago" => "vor einer Minute",
-"%d minutes ago" => "Vor %d Minuten",
-"1 hour ago" => "Vor einer Stunde",
-"%d hours ago" => "Vor %d Stunden",
+"_%n minute ago_::_%n minutes ago_" => array("Vor %n Minute","Vor %n Minuten"),
+"_%n hour ago_::_%n hours ago_" => array("Vor %n Stunde","Vor %n Stunden"),
"today" => "Heute",
"yesterday" => "Gestern",
-"%d days ago" => "Vor %d Tag(en)",
+"_%n day go_::_%n days ago_" => array("Vor %n Tag","Vor %n Tagen"),
"last month" => "Letzten Monat",
-"%d months ago" => "Vor %d Monaten",
+"_%n month ago_::_%n months ago_" => array("Vor %n Monat","Vor %n Monaten"),
"last year" => "Letztes Jahr",
"years ago" => "Vor Jahren",
-"Caused by:" => "Verursacht durch:",
-"Could not find category \"%s\"" => "Die Kategorie \"%s\" konnte nicht gefunden werden."
+"Caused by:" => "Verursacht durch:"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/de_AT.php b/lib/l10n/de_AT.php
new file mode 100644
index 00000000000..15f78e0bce6
--- /dev/null
+++ b/lib/l10n/de_AT.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/de_CH.php b/lib/l10n/de_CH.php
index 2dbf22b9a7d..502791ff578 100644
--- a/lib/l10n/de_CH.php
+++ b/lib/l10n/de_CH.php
@@ -1,10 +1,11 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "Anwendung \"%s\" kann nicht installiert werden, da sie mit dieser Version von ownCloud nicht kompatibel ist.",
+"No app name specified" => "Kein App-Name spezifiziert",
"Help" => "Hilfe",
"Personal" => "Persönlich",
"Settings" => "Einstellungen",
"Users" => "Benutzer",
-"Apps" => "Apps",
"Admin" => "Administrator",
"Failed to upgrade \"%s\"." => "Konnte \"%s\" nicht aktualisieren.",
"web services under your control" => "Web-Services unter Ihrer Kontrolle",
@@ -13,8 +14,8 @@ $TRANSLATIONS = array(
"Files need to be downloaded one by one." => "Die Dateien müssen einzeln heruntergeladen werden.",
"Back to Files" => "Zurück zu \"Dateien\"",
"Selected files too large to generate zip file." => "Die gewählten Dateien sind zu gross, um eine ZIP-Datei zu erstellen.",
-"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Laden Sie die Dateien in kleineren, separaten, Stücken herunter oder bitten Sie Ihren Administrator.",
-"couldn't be determined" => "konnte nicht ermittelt werden",
+"App can't be installed because of not allowed code in the App" => "Anwendung kann wegen nicht erlaubten Codes nicht installiert werden",
+"App directory already exists" => "Anwendungsverzeichnis existiert bereits",
"Application is not enabled" => "Die Anwendung ist nicht aktiviert",
"Authentication error" => "Authentifizierungs-Fehler",
"Token expired. Please reload page." => "Token abgelaufen. Bitte laden Sie die Seite neu.",
@@ -41,19 +42,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "Setze Administrator Passwort",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Ihr Web-Server ist noch nicht für eine Datei-Synchronisation konfiguriert, weil die WebDAV-Schnittstelle vermutlich defekt ist.",
"Please double check the <a href='%s'>installation guides</a>." => "Bitte prüfen Sie die <a href='%s'>Installationsanleitungen</a>.",
+"Could not find category \"%s\"" => "Die Kategorie «%s» konnte nicht gefunden werden.",
"seconds ago" => "Gerade eben",
-"1 minute ago" => "Vor 1 Minute",
-"%d minutes ago" => "Vor %d Minuten",
-"1 hour ago" => "Vor einer Stunde",
-"%d hours ago" => "Vor %d Stunden",
+"_%n minute ago_::_%n minutes ago_" => array("","Vor %n Minuten"),
+"_%n hour ago_::_%n hours ago_" => array("","Vor %n Stunden"),
"today" => "Heute",
"yesterday" => "Gestern",
-"%d days ago" => "Vor %d Tag(en)",
+"_%n day go_::_%n days ago_" => array("","Vor %n Tagen"),
"last month" => "Letzten Monat",
-"%d months ago" => "Vor %d Monaten",
+"_%n month ago_::_%n months ago_" => array("","Vor %n Monaten"),
"last year" => "Letztes Jahr",
"years ago" => "Vor Jahren",
-"Caused by:" => "Verursacht durch:",
-"Could not find category \"%s\"" => "Die Kategorie «%s» konnte nicht gefunden werden."
+"Caused by:" => "Verursacht durch:"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/de_DE.php b/lib/l10n/de_DE.php
index 91731585d48..e76718b4117 100644
--- a/lib/l10n/de_DE.php
+++ b/lib/l10n/de_DE.php
@@ -1,20 +1,34 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "Applikation \"%s\" kann nicht installiert werden, da sie mit dieser ownCloud Version nicht kompatibel ist.",
+"No app name specified" => "Es wurde kein Applikation-Name angegeben",
"Help" => "Hilfe",
"Personal" => "Persönlich",
"Settings" => "Einstellungen",
"Users" => "Benutzer",
-"Apps" => "Apps",
"Admin" => "Administrator",
"Failed to upgrade \"%s\"." => "Konnte \"%s\" nicht aktualisieren.",
+"Unknown filetype" => "Unbekannter Dateityp",
+"Invalid image" => "Ungültiges Bild",
"web services under your control" => "Web-Services unter Ihrer Kontrolle",
"cannot open \"%s\"" => "Öffnen von \"%s\" fehlgeschlagen",
"ZIP download is turned off." => "Der ZIP-Download ist deaktiviert.",
"Files need to be downloaded one by one." => "Die Dateien müssen einzeln heruntergeladen werden.",
"Back to Files" => "Zurück zu \"Dateien\"",
"Selected files too large to generate zip file." => "Die gewählten Dateien sind zu groß, um eine ZIP-Datei zu erstellen.",
-"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Laden Sie die Dateien in kleineren, separaten, Stücken herunter oder bitten Sie Ihren Administrator.",
-"couldn't be determined" => "konnte nicht ermittelt werden",
+"Please download the files separately in smaller chunks or kindly ask your administrator." => "Bitte laden Sie die Dateien einzeln in kleineren Teilen herunter oder bitten Sie Ihren Administrator.",
+"No source specified when installing app" => "Für die Installation der Applikation wurde keine Quelle angegeben",
+"No href specified when installing app from http" => "Der Link (href) wurde nicht angegeben um die Applikation per http zu installieren",
+"No path specified when installing app from local file" => "Bei der Installation der Applikation aus einer lokalen Datei wurde kein Pfad angegeben",
+"Archives of type %s are not supported" => "Archive des Typs %s werden nicht unterstützt.",
+"Failed to open archive when installing app" => "Das Archiv konnte bei der Installation der Applikation nicht geöffnet werden",
+"App does not provide an info.xml file" => "Die Applikation enthält keine info,xml Datei",
+"App can't be installed because of not allowed code in the App" => "Die Applikation kann auf Grund von unerlaubten Code nicht installiert werden",
+"App can't be installed because it is not compatible with this version of ownCloud" => "Die Anwendung konnte nicht installiert werden, weil Sie nicht mit dieser Version von ownCloud kompatibel ist.",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Die Applikation konnte nicht installiert werden, da diese das <shipped>true</shipped> Tag beinhaltet und dieses, bei nicht mitausgelieferten Applikationen, nicht erlaubt ist ist",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Die Applikation konnte nicht installiert werden, da die Version in der info.xml nicht die gleiche Version wie im App-Store ist",
+"App directory already exists" => "Der Ordner für die Anwendung existiert bereits.",
+"Can't create app folder. Please fix permissions. %s" => "Der Ordner für die Anwendung konnte nicht angelegt werden. Bitte überprüfen Sie die Ordner- und Dateirechte und passen Sie diese entsprechend an. %s",
"Application is not enabled" => "Die Anwendung ist nicht aktiviert",
"Authentication error" => "Authentifizierungs-Fehler",
"Token expired. Please reload page." => "Token abgelaufen. Bitte laden Sie die Seite neu.",
@@ -41,19 +55,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "Setze Administrator Passwort",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Ihr Web-Server ist noch nicht für eine Datei-Synchronisation konfiguriert, weil die WebDAV-Schnittstelle vermutlich defekt ist.",
"Please double check the <a href='%s'>installation guides</a>." => "Bitte prüfen Sie die <a href='%s'>Installationsanleitungen</a>.",
+"Could not find category \"%s\"" => "Die Kategorie \"%s\" konnte nicht gefunden werden.",
"seconds ago" => "Gerade eben",
-"1 minute ago" => "Vor 1 Minute",
-"%d minutes ago" => "Vor %d Minuten",
-"1 hour ago" => "Vor einer Stunde",
-"%d hours ago" => "Vor %d Stunden",
+"_%n minute ago_::_%n minutes ago_" => array("Vor %n Minute","Vor %n Minuten"),
+"_%n hour ago_::_%n hours ago_" => array("Vor %n Stunde","Vor %n Stunden"),
"today" => "Heute",
"yesterday" => "Gestern",
-"%d days ago" => "Vor %d Tag(en)",
+"_%n day go_::_%n days ago_" => array("Vor %n Tag","Vor %n Tagen"),
"last month" => "Letzten Monat",
-"%d months ago" => "Vor %d Monaten",
+"_%n month ago_::_%n months ago_" => array("Vor %n Monat","Vor %n Monaten"),
"last year" => "Letztes Jahr",
"years ago" => "Vor Jahren",
-"Caused by:" => "Verursacht durch:",
-"Could not find category \"%s\"" => "Die Kategorie \"%s\" konnte nicht gefunden werden."
+"Caused by:" => "Verursacht durch:"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/el.php b/lib/l10n/el.php
index 9989fc967b1..d536b699a9e 100644
--- a/lib/l10n/el.php
+++ b/lib/l10n/el.php
@@ -4,17 +4,16 @@ $TRANSLATIONS = array(
"Personal" => "Προσωπικά",
"Settings" => "Ρυθμίσεις",
"Users" => "Χρήστες",
-"Apps" => "Εφαρμογές",
"Admin" => "Διαχειριστής",
"Failed to upgrade \"%s\"." => "Αποτυχία αναβάθμισης του \"%s\".",
+"Unknown filetype" => "Άγνωστος τύπος αρχείου",
+"Invalid image" => "Μη έγκυρη εικόνα",
"web services under your control" => "υπηρεσίες δικτύου υπό τον έλεγχό σας",
"cannot open \"%s\"" => "αδυναμία ανοίγματος \"%s\"",
"ZIP download is turned off." => "Η λήψη ZIP απενεργοποιήθηκε.",
"Files need to be downloaded one by one." => "Τα αρχεία πρέπει να ληφθούν ένα-ένα.",
"Back to Files" => "Πίσω στα Αρχεία",
"Selected files too large to generate zip file." => "Τα επιλεγμένα αρχεία είναι μεγάλα ώστε να δημιουργηθεί αρχείο zip.",
-"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Λήψη των αρχείων σε μικρότερα κομμάτια, χωριστά ή ρωτήστε τον διαχειριστή σας.",
-"couldn't be determined" => "δεν μπορούσε να προσδιορισθεί",
"Application is not enabled" => "Δεν ενεργοποιήθηκε η εφαρμογή",
"Authentication error" => "Σφάλμα πιστοποίησης",
"Token expired. Please reload page." => "Το αναγνωριστικό έληξε. Παρακαλώ φορτώστε ξανά την σελίδα.",
@@ -41,19 +40,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "Εισάγετε συνθηματικό διαχειριστή.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Ο διακομιστής σας δεν έχει ρυθμιστεί κατάλληλα ώστε να επιτρέπει τον συγχρονισμό αρχείων γιατί η διεπαφή WebDAV πιθανόν να είναι κατεστραμμένη.",
"Please double check the <a href='%s'>installation guides</a>." => "Ελέγξτε ξανά τις <a href='%s'>οδηγίες εγκατάστασης</a>.",
+"Could not find category \"%s\"" => "Αδυναμία εύρεσης κατηγορίας \"%s\"",
"seconds ago" => "δευτερόλεπτα πριν",
-"1 minute ago" => "1 λεπτό πριν",
-"%d minutes ago" => "%d λεπτά πριν",
-"1 hour ago" => "1 ώρα πριν",
-"%d hours ago" => "%d ώρες πριν",
+"_%n minute ago_::_%n minutes ago_" => array("","%n λεπτά πριν"),
+"_%n hour ago_::_%n hours ago_" => array("",""),
"today" => "σήμερα",
"yesterday" => "χτες",
-"%d days ago" => "%d ημέρες πριν",
+"_%n day go_::_%n days ago_" => array("",""),
"last month" => "τελευταίο μήνα",
-"%d months ago" => "%d μήνες πριν",
+"_%n month ago_::_%n months ago_" => array("",""),
"last year" => "τελευταίο χρόνο",
"years ago" => "χρόνια πριν",
-"Caused by:" => "Προκλήθηκε από:",
-"Could not find category \"%s\"" => "Αδυναμία εύρεσης κατηγορίας \"%s\""
+"Caused by:" => "Προκλήθηκε από:"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/en@pirate.php b/lib/l10n/en@pirate.php
index a86492d2a93..a8175b1400f 100644
--- a/lib/l10n/en@pirate.php
+++ b/lib/l10n/en@pirate.php
@@ -1,5 +1,9 @@
<?php
$TRANSLATIONS = array(
-"web services under your control" => "web services under your control"
+"web services under your control" => "web services under your control",
+"_%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/en_GB.php b/lib/l10n/en_GB.php
new file mode 100644
index 00000000000..295700d234a
--- /dev/null
+++ b/lib/l10n/en_GB.php
@@ -0,0 +1,71 @@
+<?php
+$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "App \"%s\" can't be installed because it is not compatible with this version of ownCloud.",
+"No app name specified" => "No app name specified",
+"Help" => "Help",
+"Personal" => "Personal",
+"Settings" => "Settings",
+"Users" => "Users",
+"Admin" => "Admin",
+"Failed to upgrade \"%s\"." => "Failed to upgrade \"%s\".",
+"Unknown filetype" => "Unknown filetype",
+"Invalid image" => "Invalid image",
+"web services under your control" => "web services under your control",
+"cannot open \"%s\"" => "cannot open \"%s\"",
+"ZIP download is turned off." => "ZIP download is turned off.",
+"Files need to be downloaded one by one." => "Files need to be downloaded one by one.",
+"Back to Files" => "Back to Files",
+"Selected files too large to generate zip file." => "Selected files too large to generate zip file.",
+"Please download the files separately in smaller chunks or kindly ask your administrator." => "Please download the files separately in smaller chunks or kindly ask your administrator.",
+"No source specified when installing app" => "No source specified when installing app",
+"No href specified when installing app from http" => "No href specified when installing app from http",
+"No path specified when installing app from local file" => "No path specified when installing app from local file",
+"Archives of type %s are not supported" => "Archives of type %s are not supported",
+"Failed to open archive when installing app" => "Failed to open archive when installing app",
+"App does not provide an info.xml file" => "App does not provide an info.xml file",
+"App can't be installed because of not allowed code in the App" => "App can't be installed because of unallowed code in the App",
+"App can't be installed because it is not compatible with this version of ownCloud" => "App can't be installed because it is not compatible with this version of ownCloud",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "App can't be installed because the version in info.xml/version is not the same as the version reported from the app store",
+"App directory already exists" => "App directory already exists",
+"Can't create app folder. Please fix permissions. %s" => "Can't create app folder. Please fix permissions. %s",
+"Application is not enabled" => "Application is not enabled",
+"Authentication error" => "Authentication error",
+"Token expired. Please reload page." => "Token expired. Please reload page.",
+"Files" => "Files",
+"Text" => "Text",
+"Images" => "Images",
+"%s enter the database username." => "%s enter the database username.",
+"%s enter the database name." => "%s enter the database name.",
+"%s you may not use dots in the database name" => "%s you may not use dots in the database name",
+"MS SQL username and/or password not valid: %s" => "MS SQL username and/or password not valid: %s",
+"You need to enter either an existing account or the administrator." => "You need to enter either an existing account or the administrator.",
+"MySQL username and/or password not valid" => "MySQL username and/or password not valid",
+"DB Error: \"%s\"" => "DB Error: \"%s\"",
+"Offending command was: \"%s\"" => "Offending command was: \"%s\"",
+"MySQL user '%s'@'localhost' exists already." => "MySQL user '%s'@'localhost' exists already.",
+"Drop this user from MySQL" => "Drop this user from MySQL",
+"MySQL user '%s'@'%%' already exists" => "MySQL user '%s'@'%%' already exists",
+"Drop this user from MySQL." => "Drop this user from MySQL.",
+"Oracle connection could not be established" => "Oracle connection could not be established",
+"Oracle username and/or password not valid" => "Oracle username and/or password not valid",
+"Offending command was: \"%s\", name: %s, password: %s" => "Offending command was: \"%s\", name: %s, password: %s",
+"PostgreSQL username and/or password not valid" => "PostgreSQL username and/or password not valid",
+"Set an admin username." => "Set an admin username.",
+"Set an admin password." => "Set an admin password.",
+"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Your web server is not yet properly setup to allow files synchronisation because the WebDAV interface seems to be broken.",
+"Please double check the <a href='%s'>installation guides</a>." => "Please double check the <a href='%s'>installation guides</a>.",
+"Could not find category \"%s\"" => "Could not find category \"%s\"",
+"seconds ago" => "seconds ago",
+"_%n minute ago_::_%n minutes ago_" => array("%n minute ago","%n minutes ago"),
+"_%n hour ago_::_%n hours ago_" => array("%n hour ago","%n hours ago"),
+"today" => "today",
+"yesterday" => "yesterday",
+"_%n day go_::_%n days ago_" => array("%n day go","%n days ago"),
+"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",
+"Caused by:" => "Caused by:"
+);
+$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/eo.php b/lib/l10n/eo.php
index 6ccc2025382..53d1ec1854d 100644
--- a/lib/l10n/eo.php
+++ b/lib/l10n/eo.php
@@ -4,7 +4,6 @@ $TRANSLATIONS = array(
"Personal" => "Persona",
"Settings" => "Agordo",
"Users" => "Uzantoj",
-"Apps" => "Aplikaĵoj",
"Admin" => "Administranto",
"web services under your control" => "TTT-servoj regataj de vi",
"ZIP download is turned off." => "ZIP-elŝuto estas malkapabligita.",
@@ -34,18 +33,16 @@ $TRANSLATIONS = array(
"Set an admin password." => "Starigi administran pasvorton.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Via TTT-servilo ankoraŭ ne ĝuste agordiĝis por permesi sinkronigi dosierojn ĉar la WebDAV-interfaco ŝajnas rompita.",
"Please double check the <a href='%s'>installation guides</a>." => "Bonvolu duoble kontroli la <a href='%s'>gvidilon por instalo</a>.",
+"Could not find category \"%s\"" => "Ne troviĝis kategorio “%s”",
"seconds ago" => "sekundoj antaŭe",
-"1 minute ago" => "antaŭ 1 minuto",
-"%d minutes ago" => "antaŭ %d minutoj",
-"1 hour ago" => "antaŭ 1 horo",
-"%d hours ago" => "antaŭ %d horoj",
+"_%n minute ago_::_%n minutes ago_" => array("",""),
+"_%n hour ago_::_%n hours ago_" => array("",""),
"today" => "hodiaŭ",
"yesterday" => "hieraŭ",
-"%d days ago" => "antaŭ %d tagoj",
+"_%n day go_::_%n days ago_" => array("",""),
"last month" => "lastamonate",
-"%d months ago" => "antaŭ %d monatoj",
+"_%n month ago_::_%n months ago_" => array("",""),
"last year" => "lastajare",
-"years ago" => "jaroj antaŭe",
-"Could not find category \"%s\"" => "Ne troviĝis kategorio “%s”"
+"years ago" => "jaroj antaŭe"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/es.php b/lib/l10n/es.php
index e30e4d711e7..1412d49c2f5 100644
--- a/lib/l10n/es.php
+++ b/lib/l10n/es.php
@@ -1,20 +1,34 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión de ownCloud",
+"No app name specified" => "No se ha especificado nombre de la aplicación",
"Help" => "Ayuda",
"Personal" => "Personal",
"Settings" => "Ajustes",
"Users" => "Usuarios",
-"Apps" => "Aplicaciones",
"Admin" => "Administración",
"Failed to upgrade \"%s\"." => "Falló la actualización \"%s\".",
+"Unknown filetype" => "Tipo de archivo desconocido",
+"Invalid image" => "Imagen inválida",
"web services under your control" => "Servicios web bajo su control",
"cannot open \"%s\"" => "No se puede abrir \"%s\"",
"ZIP download is turned off." => "La descarga en ZIP está desactivada.",
"Files need to be downloaded one by one." => "Los archivos deben ser descargados uno por uno.",
"Back to Files" => "Volver a Archivos",
"Selected files too large to generate zip file." => "Los archivos seleccionados son demasiado grandes para generar el archivo zip.",
-"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Descargue los archivos en trozos más pequeños, por separado o solicítelos amablemente su administrador.",
-"couldn't be determined" => "no pudo ser determinado",
+"Please download the files separately in smaller chunks or kindly ask your administrator." => "Descargue los archivos en trozos más pequeños, por separado o solicítelos amablemente a su administrador.",
+"No source specified when installing app" => "No se ha especificado origen cuando se ha instalado la aplicación",
+"No href specified when installing app from http" => "No href especificado cuando se ha instalado la aplicación",
+"No path specified when installing app from local file" => "Sin path especificado cuando se ha instalado la aplicación desde el fichero local",
+"Archives of type %s are not supported" => "Ficheros de tipo %s no son soportados",
+"Failed to open archive when installing app" => "Fallo de apertura de fichero mientras se instala la aplicación",
+"App does not provide an info.xml file" => "La aplicación no suministra un fichero info.xml",
+"App can't be installed because of not allowed code in the App" => "La aplicación no puede ser instalada por tener código no autorizado en la aplicación",
+"App can't be installed because it is not compatible with this version of ownCloud" => "La aplicación no se puede instalar porque no es compatible con esta versión de ownCloud",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "La aplicación no se puede instalar porque contiene la etiqueta\n<shipped>\ntrue\n</shipped>\nque no está permitida para aplicaciones no distribuidas",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "La aplicación no puede ser instalada por que la versión en info.xml/version no es la misma que la establecida en la app store",
+"App directory already exists" => "El directorio de la aplicación ya existe",
+"Can't create app folder. Please fix permissions. %s" => "No se puede crear la carpeta de la aplicación. Corrija los permisos. %s",
"Application is not enabled" => "La aplicación no está habilitada",
"Authentication error" => "Error de autenticación",
"Token expired. Please reload page." => "Token expirado. Por favor, recarga la página.",
@@ -23,7 +37,7 @@ $TRANSLATIONS = array(
"Images" => "Imágenes",
"%s enter the database username." => "%s ingresar el usuario de la base de datos.",
"%s enter the database name." => "%s ingresar el nombre de la base de datos",
-"%s you may not use dots in the database name" => "%s no se puede utilizar puntos en el nombre de la base de datos",
+"%s you may not use dots in the database name" => "%s puede utilizar puntos en el nombre de la base de datos",
"MS SQL username and/or password not valid: %s" => "Usuario y/o contraseña de MS SQL no válidos: %s",
"You need to enter either an existing account or the administrator." => "Tiene que ingresar una cuenta existente o la del administrador.",
"MySQL username and/or password not valid" => "Usuario y/o contraseña de MySQL no válidos",
@@ -41,19 +55,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "Configurar la contraseña del administrador.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Su servidor web aún no está configurado adecuadamente para permitir sincronización de archivos ya que la interfaz WebDAV parece no estar funcionando.",
"Please double check the <a href='%s'>installation guides</a>." => "Por favor, vuelva a comprobar las <a href='%s'>guías de instalación</a>.",
+"Could not find category \"%s\"" => "No puede encontrar la categoria \"%s\"",
"seconds ago" => "hace segundos",
-"1 minute ago" => "hace 1 minuto",
-"%d minutes ago" => "hace %d minutos",
-"1 hour ago" => "Hace 1 hora",
-"%d hours ago" => "Hace %d horas",
+"_%n minute ago_::_%n minutes ago_" => array("Hace %n minuto","Hace %n minutos"),
+"_%n hour ago_::_%n hours ago_" => array("Hace %n hora","Hace %n horas"),
"today" => "hoy",
"yesterday" => "ayer",
-"%d days ago" => "hace %d días",
+"_%n day go_::_%n days ago_" => array("Hace %n día","Hace %n días"),
"last month" => "mes pasado",
-"%d months ago" => "Hace %d meses",
+"_%n month ago_::_%n months ago_" => array("Hace %n mes","Hace %n meses"),
"last year" => "año pasado",
"years ago" => "hace años",
-"Caused by:" => "Causado por:",
-"Could not find category \"%s\"" => "No puede encontrar la categoria \"%s\""
+"Caused by:" => "Causado por:"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/es_AR.php b/lib/l10n/es_AR.php
index 3f1c098dbf5..e2c771d47ad 100644
--- a/lib/l10n/es_AR.php
+++ b/lib/l10n/es_AR.php
@@ -1,20 +1,33 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "La app \"%s\" no puede ser instalada porque no es compatible con esta versión de ownCloud",
+"No app name specified" => "No fue especificado el nombre de la app",
"Help" => "Ayuda",
"Personal" => "Personal",
"Settings" => "Configuración",
"Users" => "Usuarios",
-"Apps" => "Apps",
"Admin" => "Administración",
"Failed to upgrade \"%s\"." => "No se pudo actualizar \"%s\".",
+"Unknown filetype" => "Tipo de archivo desconocido",
+"Invalid image" => "Imagen inválida",
"web services under your control" => "servicios web sobre los que tenés control",
"cannot open \"%s\"" => "no se puede abrir \"%s\"",
"ZIP download is turned off." => "La descarga en ZIP está desactivada.",
"Files need to be downloaded one by one." => "Los archivos deben ser descargados de a uno.",
"Back to Files" => "Volver a Archivos",
"Selected files too large to generate zip file." => "Los archivos seleccionados son demasiado grandes para generar el archivo zip.",
-"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Descargá los archivos en partes más chicas, de forma separada, o pedíselos al administrador",
-"couldn't be determined" => "no se pudo determinar",
+"No source specified when installing app" => "No se especificó el origen al instalar la app",
+"No href specified when installing app from http" => "No se especificó href al instalar la app",
+"No path specified when installing app from local file" => "No se especificó PATH al instalar la app desde el archivo local",
+"Archives of type %s are not supported" => "No hay soporte para archivos de tipo %s",
+"Failed to open archive when installing app" => "Error al abrir archivo mientras se instalaba la app",
+"App does not provide an info.xml file" => "La app no suministra un archivo info.xml",
+"App can't be installed because of not allowed code in the App" => "No puede ser instalada la app por tener código no autorizado",
+"App can't be installed because it is not compatible with this version of ownCloud" => "No se puede instalar la app porque no es compatible con esta versión de ownCloud",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "La app no se puede instalar porque contiene la etiqueta <shipped>true</shipped> que no está permitida para apps no distribuidas",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "La app no puede ser instalada porque la versión en info.xml/version no es la misma que la establecida en el app store",
+"App directory already exists" => "El directorio de la app ya existe",
+"Can't create app folder. Please fix permissions. %s" => "No se puede crear el directorio para la app. Corregí los permisos. %s",
"Application is not enabled" => "La aplicación no está habilitada",
"Authentication error" => "Error al autenticar",
"Token expired. Please reload page." => "Token expirado. Por favor, recargá la página.",
@@ -41,19 +54,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "Configurar una contraseña de administrador.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Tu servidor web no está configurado todavía para permitir sincronización de archivos porque la interfaz WebDAV parece no funcionar.",
"Please double check the <a href='%s'>installation guides</a>." => "Por favor, comprobá nuevamente la <a href='%s'>guía de instalación</a>.",
+"Could not find category \"%s\"" => "No fue posible encontrar la categoría \"%s\"",
"seconds ago" => "segundos atrás",
-"1 minute ago" => "hace 1 minuto",
-"%d minutes ago" => "hace %d minutos",
-"1 hour ago" => "hace 1 hora",
-"%d hours ago" => "hace %d horas",
+"_%n minute ago_::_%n minutes ago_" => array("Hace %n minuto","Hace %n minutos"),
+"_%n hour ago_::_%n hours ago_" => array("Hace %n hora","Hace %n horas"),
"today" => "hoy",
"yesterday" => "ayer",
-"%d days ago" => "hace %d días",
+"_%n day go_::_%n days ago_" => array("Hace %n día","Hace %n días"),
"last month" => "el mes pasado",
-"%d months ago" => "hace %d meses",
+"_%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",
-"Caused by:" => "Provocado por:",
-"Could not find category \"%s\"" => "No fue posible encontrar la categoría \"%s\""
+"Caused by:" => "Provocado por:"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/es_MX.php b/lib/l10n/es_MX.php
new file mode 100644
index 00000000000..15f78e0bce6
--- /dev/null
+++ b/lib/l10n/es_MX.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/et_EE.php b/lib/l10n/et_EE.php
index 403f0871c53..7340ee72c28 100644
--- a/lib/l10n/et_EE.php
+++ b/lib/l10n/et_EE.php
@@ -1,20 +1,34 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "Rakendit \"%s\" ei saa paigaldada, kuna see pole ühilduv selle ownCloud versiooniga.",
+"No app name specified" => "Ühegi rakendi nime pole määratletud",
"Help" => "Abiinfo",
"Personal" => "Isiklik",
"Settings" => "Seaded",
"Users" => "Kasutajad",
-"Apps" => "Rakendused",
"Admin" => "Admin",
"Failed to upgrade \"%s\"." => "Ebaõnnestunud uuendus \"%s\".",
+"Unknown filetype" => "Tundmatu failitüüp",
+"Invalid image" => "Vigane pilt",
"web services under your control" => "veebitenused sinu kontrolli all",
"cannot open \"%s\"" => "ei suuda avada \"%s\"",
"ZIP download is turned off." => "ZIP-ina allalaadimine on välja lülitatud.",
"Files need to be downloaded one by one." => "Failid tuleb alla laadida ükshaaval.",
"Back to Files" => "Tagasi failide juurde",
"Selected files too large to generate zip file." => "Valitud failid on ZIP-faili loomiseks liiga suured.",
-"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Laadi failid alla eraldi väiksemate osadena või küsi nõu oma süsteemiadminstraatorilt.",
-"couldn't be determined" => "ei suudetud tuvastada",
+"Please download the files separately in smaller chunks or kindly ask your administrator." => "Palun laadi failid alla eraldi väiksemate osadena või palu abi oma süsteemihaldurilt.",
+"No source specified when installing app" => "Ühegi lähteallikat pole rakendi paigalduseks määratletud",
+"No href specified when installing app from http" => "Ühtegi aadressi pole määratletud rakendi paigalduseks veebist",
+"No path specified when installing app from local file" => "Ühtegi teed pole määratletud paigaldamaks rakendit kohalikust failist",
+"Archives of type %s are not supported" => "%s tüüpi arhiivid pole toetatud",
+"Failed to open archive when installing app" => "Arhiivi avamine ebaõnnestus rakendi paigalduse käigus",
+"App does not provide an info.xml file" => "Rakend ei paku ühtegi info.xml faili",
+"App can't be installed because of not allowed code in the App" => "Rakendit ei saa paigaldada, kuna sisaldab lubamatud koodi",
+"App can't be installed because it is not compatible with this version of ownCloud" => "Rakendit ei saa paigaldada, kuna see pole ühilduv selle ownCloud versiooniga.",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Rakendit ei saa paigaldada, kuna see sisaldab \n<shipped>\n\ntrue\n</shipped>\nmärgendit, mis pole lubatud mitte veetud (non shipped) rakendites",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Rakendit ei saa paigaldada, kuna selle versioon info.xml/version pole sama, mis on märgitud rakendite laos.",
+"App directory already exists" => "Rakendi kataloog on juba olemas",
+"Can't create app folder. Please fix permissions. %s" => "Ei saa luua rakendi kataloogi. Palun korrigeeri õigusi. %s",
"Application is not enabled" => "Rakendus pole sisse lülitatud",
"Authentication error" => "Autentimise viga",
"Token expired. Please reload page." => "Kontrollkood aegus. Paelun lae leht uuesti.",
@@ -41,19 +55,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "Määra admini parool.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Veebiserveri ei ole veel korralikult seadistatud võimaldamaks failide sünkroniseerimist, kuna WebDAV liides näib olevat mittetoimiv.",
"Please double check the <a href='%s'>installation guides</a>." => "Palun tutvu veelkord <a href='%s'>paigalduse juhenditega</a>.",
+"Could not find category \"%s\"" => "Ei leia kategooriat \"%s\"",
"seconds ago" => "sekundit tagasi",
-"1 minute ago" => "1 minut tagasi",
-"%d minutes ago" => "%d minutit tagasi",
-"1 hour ago" => "1 tund tagasi",
-"%d hours ago" => "%d tundi tagasi",
+"_%n minute ago_::_%n minutes ago_" => array("","%n minutit tagasi"),
+"_%n hour ago_::_%n hours ago_" => array("","%n tundi tagasi"),
"today" => "täna",
"yesterday" => "eile",
-"%d days ago" => "%d päeva tagasi",
+"_%n day go_::_%n days ago_" => array("","%n päeva tagasi"),
"last month" => "viimasel kuul",
-"%d months ago" => "%d kuud tagasi",
+"_%n month ago_::_%n months ago_" => array("","%n kuud tagasi"),
"last year" => "viimasel aastal",
"years ago" => "aastat tagasi",
-"Caused by:" => "Põhjustaja:",
-"Could not find category \"%s\"" => "Ei leia kategooriat \"%s\""
+"Caused by:" => "Põhjustaja:"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/eu.php b/lib/l10n/eu.php
index 0d9a8860a09..67a80d90caa 100644
--- a/lib/l10n/eu.php
+++ b/lib/l10n/eu.php
@@ -1,20 +1,34 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "\"%s\" Aplikazioa ezin da instalatu ownCloud bertsio honekin bateragarria ez delako",
+"No app name specified" => "Ez da aplikazioaren izena zehaztu",
"Help" => "Laguntza",
"Personal" => "Pertsonala",
"Settings" => "Ezarpenak",
"Users" => "Erabiltzaileak",
-"Apps" => "Aplikazioak",
"Admin" => "Admin",
"Failed to upgrade \"%s\"." => "Ezin izan da \"%s\" eguneratu.",
+"Unknown filetype" => "Fitxategi mota ezezaguna",
+"Invalid image" => "Baliogabeko irudia",
"web services under your control" => "web zerbitzuak zure kontrolpean",
"cannot open \"%s\"" => "ezin da \"%s\" ireki",
"ZIP download is turned off." => "ZIP deskarga ez dago gaituta.",
"Files need to be downloaded one by one." => "Fitxategiak banan-banan deskargatu behar dira.",
"Back to Files" => "Itzuli fitxategietara",
"Selected files too large to generate zip file." => "Hautatuko fitxategiak oso handiak dira zip fitxategia sortzeko.",
-"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Deskargatu fitzategiak zati txikiagoetan, banan-banan edo eskatu mesedez zure administradoreari",
-"couldn't be determined" => "ezin izan da zehaztu",
+"Please download the files separately in smaller chunks or kindly ask your administrator." => "Mesedez deskargatu fitzategiak zati txikiagoetan, banan-banan edo eskatu mesedez zure administradoreari.",
+"No source specified when installing app" => "Ez da jatorririk zehaztu aplikazioa instalatzerakoan",
+"No href specified when installing app from http" => "Ez da href parametrorik zehaztu http bidez aplikazioa instalatzerakoan",
+"No path specified when installing app from local file" => "Ez da kokalekurik zehaztu fitxategi lokal moduan aplikazioa instalatzerakoan",
+"Archives of type %s are not supported" => "%s motako fitxategiak ez dira onartzen",
+"Failed to open archive when installing app" => "Fitxategia irekitzeak huts egin du aplikazioa instalatzerakoan",
+"App does not provide an info.xml file" => "Aplikazioak ez du info.xml fitxategia",
+"App can't be installed because of not allowed code in the App" => "Aplikazioa ezin da instalatu bertan duen baimendu gabeko kodea dela eta",
+"App can't be installed because it is not compatible with this version of ownCloud" => "Aplikazioa ezin da instalatu ownCloud bertsio honekin bateragarria ez delako",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Aplikazioa ezin da instalatu <shipped>true</shipped> etiketa duelako eta etiketa hau ez da onartzen banaketan ez datozen aplikazioetan",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Aplikazioa ezin da instalatu info.xml/version bertsioa ez delako \"app store\"an jartzen duenaren berdina",
+"App directory already exists" => "Aplikazioaren karpeta dagoeneko existitzen da",
+"Can't create app folder. Please fix permissions. %s" => "Ezin izan da aplikazioaren karpeta sortu. Mesdez konpondu baimenak. %s",
"Application is not enabled" => "Aplikazioa ez dago gaituta",
"Authentication error" => "Autentifikazio errorea",
"Token expired. Please reload page." => "Tokena iraungitu da. Mesedez birkargatu orria.",
@@ -41,19 +55,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "Ezarri administraziorako pasahitza.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Zure web zerbitzaria ez dago oraindik ongi konfiguratuta fitxategien sinkronizazioa egiteko, WebDAV interfazea ongi ez dagoela dirudi.",
"Please double check the <a href='%s'>installation guides</a>." => "Mesedez begiratu <a href='%s'>instalazio gidak</a>.",
+"Could not find category \"%s\"" => "Ezin da \"%s\" kategoria aurkitu",
"seconds ago" => "segundu",
-"1 minute ago" => "orain dela minutu 1",
-"%d minutes ago" => "orain dela %d minutu",
-"1 hour ago" => "orain dela ordu bat",
-"%d hours ago" => "orain dela %d ordu",
+"_%n minute ago_::_%n minutes ago_" => array("orain dela minutu %n","orain dela %n minutu"),
+"_%n hour ago_::_%n hours ago_" => array("orain dela ordu %n","orain dela %n ordu"),
"today" => "gaur",
"yesterday" => "atzo",
-"%d days ago" => "orain dela %d egun",
+"_%n day go_::_%n days ago_" => array("orain dela egun %n","orain dela %n egun"),
"last month" => "joan den hilabetean",
-"%d months ago" => "orain dela %d hilabete",
+"_%n month ago_::_%n months ago_" => array("orain dela hilabete %n","orain dela %n hilabete"),
"last year" => "joan den urtean",
"years ago" => "urte",
-"Caused by:" => "Honek eraginda:",
-"Could not find category \"%s\"" => "Ezin da \"%s\" kategoria aurkitu"
+"Caused by:" => "Honek eraginda:"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/fa.php b/lib/l10n/fa.php
index fa886531bba..788b3703966 100644
--- a/lib/l10n/fa.php
+++ b/lib/l10n/fa.php
@@ -4,14 +4,12 @@ $TRANSLATIONS = array(
"Personal" => "شخصی",
"Settings" => "تنظیمات",
"Users" => "کاربران",
-"Apps" => " برنامه ها",
"Admin" => "مدیر",
"web services under your control" => "سرویس های تحت وب در کنترل شما",
"ZIP download is turned off." => "دانلود به صورت فشرده غیر فعال است",
"Files need to be downloaded one by one." => "فایل ها باید به صورت یکی یکی دانلود شوند",
"Back to Files" => "بازگشت به فایل ها",
"Selected files too large to generate zip file." => "فایل های انتخاب شده بزرگتر از آن هستند که بتوان یک فایل فشرده تولید کرد",
-"couldn't be determined" => "نمیتواند مشخص شود",
"Application is not enabled" => "برنامه فعال نشده است",
"Authentication error" => "خطا در اعتبار سنجی",
"Token expired. Please reload page." => "رمز منقضی شده است. لطفا دوباره صفحه را بارگذاری نمایید.",
@@ -38,18 +36,16 @@ $TRANSLATIONS = array(
"Set an admin password." => "یک رمزعبور برای مدیر تنظیم نمایید.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "احتمالاً وب سرور شما طوری تنظیم نشده است که اجازه ی همگام سازی فایلها را بدهد زیرا به نظر میرسد رابط WebDAV از کار افتاده است.",
"Please double check the <a href='%s'>installation guides</a>." => "لطفاً دوباره <a href='%s'>راهنمای نصب</a>را بررسی کنید.",
+"Could not find category \"%s\"" => "دسته بندی %s یافت نشد",
"seconds ago" => "ثانیه‌ها پیش",
-"1 minute ago" => "1 دقیقه پیش",
-"%d minutes ago" => "%d دقیقه پیش",
-"1 hour ago" => "1 ساعت پیش",
-"%d hours ago" => "%d ساعت پیش",
+"_%n minute ago_::_%n minutes ago_" => array(""),
+"_%n hour ago_::_%n hours ago_" => array(""),
"today" => "امروز",
"yesterday" => "دیروز",
-"%d days ago" => "%d روز پیش",
+"_%n day go_::_%n days ago_" => array(""),
"last month" => "ماه قبل",
-"%d months ago" => "%dماه پیش",
+"_%n month ago_::_%n months ago_" => array(""),
"last year" => "سال قبل",
-"years ago" => "سال‌های قبل",
-"Could not find category \"%s\"" => "دسته بندی %s یافت نشد"
+"years ago" => "سال‌های قبل"
);
$PLURAL_FORMS = "nplurals=1; plural=0;";
diff --git a/lib/l10n/fi_FI.php b/lib/l10n/fi_FI.php
index 5892a968d5b..68f51d34441 100644
--- a/lib/l10n/fi_FI.php
+++ b/lib/l10n/fi_FI.php
@@ -1,17 +1,28 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "Sovellusta \"%s\" ei voi asentaa, koska se ei ole yhteensopiva käytössä olevan ownCloud-version kanssa.",
+"No app name specified" => "Sovelluksen nimeä ei määritelty",
"Help" => "Ohje",
"Personal" => "Henkilökohtainen",
"Settings" => "Asetukset",
"Users" => "Käyttäjät",
-"Apps" => "Sovellukset",
"Admin" => "Ylläpitäjä",
+"Failed to upgrade \"%s\"." => "Kohteen \"%s\" päivitys epäonnistui.",
+"Unknown filetype" => "Tuntematon tiedostotyyppi",
+"Invalid image" => "Virheellinen kuva",
"web services under your control" => "verkkopalvelut hallinnassasi",
"ZIP download is turned off." => "ZIP-lataus on poistettu käytöstä.",
"Files need to be downloaded one by one." => "Tiedostot on ladattava yksittäin.",
"Back to Files" => "Takaisin tiedostoihin",
"Selected files too large to generate zip file." => "Valitut tiedostot ovat liian suurikokoisia mahtuakseen zip-tiedostoon.",
-"couldn't be determined" => "ei voitu määrittää",
+"No source specified when installing app" => "Lähdettä ei määritelty sovellusta asennettaessa",
+"No path specified when installing app from local file" => "Polkua ei määritelty sovellusta asennettaessa paikallisesta tiedostosta",
+"Archives of type %s are not supported" => "Tyypin %s arkistot eivät ole tuettuja",
+"App does not provide an info.xml file" => "Sovellus ei sisällä info.xml-tiedostoa",
+"App can't be installed because of not allowed code in the App" => "Sovellusta ei voi asentaa, koska sovellus sisältää kiellettyä koodia",
+"App can't be installed because it is not compatible with this version of ownCloud" => "Sovellusta ei voi asentaa, koska se ei ole yhteensopiva käytössä olevan ownCloud-version kanssa",
+"App directory already exists" => "Sovelluskansio on jo olemassa",
+"Can't create app folder. Please fix permissions. %s" => "Sovelluskansion luominen ei onnistu. Korjaa käyttöoikeudet. %s",
"Application is not enabled" => "Sovellusta ei ole otettu käyttöön",
"Authentication error" => "Tunnistautumisvirhe",
"Token expired. Please reload page." => "Valtuutus vanheni. Lataa sivu uudelleen.",
@@ -34,18 +45,17 @@ $TRANSLATIONS = array(
"Set an admin username." => "Aseta ylläpitäjän käyttäjätunnus.",
"Set an admin password." => "Aseta ylläpitäjän salasana.",
"Please double check the <a href='%s'>installation guides</a>." => "Lue tarkasti <a href='%s'>asennusohjeet</a>.",
+"Could not find category \"%s\"" => "Luokkaa \"%s\" ei löytynyt",
"seconds ago" => "sekuntia sitten",
-"1 minute ago" => "1 minuutti sitten",
-"%d minutes ago" => "%d minuuttia sitten",
-"1 hour ago" => "1 tunti sitten",
-"%d hours ago" => "%d tuntia sitten",
+"_%n minute ago_::_%n minutes ago_" => array("%n minuutti sitten","%n minuuttia sitten"),
+"_%n hour ago_::_%n hours ago_" => array("%n tunti sitten","%n tuntia sitten"),
"today" => "tänään",
"yesterday" => "eilen",
-"%d days ago" => "%d päivää sitten",
+"_%n day go_::_%n days ago_" => array("%n päivä sitten","%n päivää sitten"),
"last month" => "viime kuussa",
-"%d months ago" => "%d kuukautta sitten",
+"_%n month ago_::_%n months ago_" => array("%n kuukausi sitten","%n kuukautta sitten"),
"last year" => "viime vuonna",
"years ago" => "vuotta sitten",
-"Could not find category \"%s\"" => "Luokkaa \"%s\" ei löytynyt"
+"Caused by:" => "Aiheuttaja:"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/fr.php b/lib/l10n/fr.php
index 18fbe55270f..82d5739e540 100644
--- a/lib/l10n/fr.php
+++ b/lib/l10n/fr.php
@@ -1,17 +1,34 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "L'application \"%s\" ne peut être installée car elle n'est pas compatible avec cette version de ownCloud.",
+"No app name specified" => "Aucun nom d'application spécifié",
"Help" => "Aide",
"Personal" => "Personnel",
"Settings" => "Paramètres",
"Users" => "Utilisateurs",
-"Apps" => "Applications",
"Admin" => "Administration",
+"Failed to upgrade \"%s\"." => "Echec de la mise à niveau \"%s\".",
+"Unknown filetype" => "Type de fichier inconnu",
+"Invalid image" => "Image invalide",
"web services under your control" => "services web sous votre contrôle",
+"cannot open \"%s\"" => "impossible d'ouvrir \"%s\"",
"ZIP download is turned off." => "Téléchargement ZIP désactivé.",
"Files need to be downloaded one by one." => "Les fichiers nécessitent d'être téléchargés un par un.",
"Back to Files" => "Retour aux Fichiers",
"Selected files too large to generate zip file." => "Les fichiers sélectionnés sont trop volumineux pour être compressés.",
-"couldn't be determined" => "impossible à déterminer",
+"Please download the files separately in smaller chunks or kindly ask your administrator." => "Merci de télécharger les fichiers séparément en parties plus petites, ou demandez aimablement à votre administrateur.",
+"No source specified when installing app" => "Aucune source spécifiée pour installer l'application",
+"No href specified when installing app from http" => "Aucun href spécifié pour installer l'application par http",
+"No path specified when installing app from local file" => "Aucun chemin spécifié pour installer l'application depuis un fichier local",
+"Archives of type %s are not supported" => "Les archives de type %s ne sont pas supportées",
+"Failed to open archive when installing app" => "Échec de l'ouverture de l'archive lors de l'installation de l'application",
+"App does not provide an info.xml file" => "L'application ne fournit pas de fichier info.xml",
+"App can't be installed because of not allowed code in the App" => "L'application ne peut être installée car elle contient du code non-autorisé",
+"App can't be installed because it is not compatible with this version of ownCloud" => "L'application ne peut être installée car elle n'est pas compatible avec cette version de ownCloud",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "L'application ne peut être installée car elle contient la balise <shipped>true</shipped> qui n'est pas autorisée pour les applications non-diffusées",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "L'application ne peut être installée car la version de info.xml/version n'est identique à celle indiquée sur l'app store",
+"App directory already exists" => "Le dossier de l'application existe déjà",
+"Can't create app folder. Please fix permissions. %s" => "Impossible de créer le dossier de l'application. Corrigez les droits d'accès. %s",
"Application is not enabled" => "L'application n'est pas activée",
"Authentication error" => "Erreur d'authentification",
"Token expired. Please reload page." => "La session a expiré. Veuillez recharger la page.",
@@ -38,18 +55,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "Spécifiez un mot de passe administrateur.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Votre serveur web, n'est pas correctement configuré pour permettre la synchronisation des fichiers, car l'interface WebDav ne fonctionne pas comme il faut.",
"Please double check the <a href='%s'>installation guides</a>." => "Veuillez vous référer au <a href='%s'>guide d'installation</a>.",
+"Could not find category \"%s\"" => "Impossible de trouver la catégorie \"%s\"",
"seconds ago" => "il y a quelques secondes",
-"1 minute ago" => "il y a une minute",
-"%d minutes ago" => "il y a %d minutes",
-"1 hour ago" => "Il y a une heure",
-"%d hours ago" => "Il y a %d heures",
+"_%n minute ago_::_%n minutes ago_" => array("","il y a %n minutes"),
+"_%n hour ago_::_%n hours ago_" => array("","Il y a %n heures"),
"today" => "aujourd'hui",
"yesterday" => "hier",
-"%d days ago" => "il y a %d jours",
+"_%n day go_::_%n days ago_" => array("","il y a %n jours"),
"last month" => "le mois dernier",
-"%d months ago" => "Il y a %d mois",
+"_%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",
-"Could not find category \"%s\"" => "Impossible de trouver la catégorie \"%s\""
+"Caused by:" => "Causé par :"
);
$PLURAL_FORMS = "nplurals=2; plural=(n > 1);";
diff --git a/lib/l10n/fr_CA.php b/lib/l10n/fr_CA.php
new file mode 100644
index 00000000000..406ff5f5a26
--- /dev/null
+++ b/lib/l10n/fr_CA.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/gl.php b/lib/l10n/gl.php
index f5cda20e135..cf13408b2cd 100644
--- a/lib/l10n/gl.php
+++ b/lib/l10n/gl.php
@@ -1,20 +1,34 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "Non é posíbel instalar o aplicativo «%s» por non seren compatíbel con esta versión do ownCloud.",
+"No app name specified" => "Non se especificou o nome do aplicativo",
"Help" => "Axuda",
"Personal" => "Persoal",
"Settings" => "Axustes",
"Users" => "Usuarios",
-"Apps" => "Aplicativos",
"Admin" => "Administración",
"Failed to upgrade \"%s\"." => "Non foi posíbel anovar «%s».",
+"Unknown filetype" => "Tipo de ficheiro descoñecido",
+"Invalid image" => "Imaxe incorrecta",
"web services under your control" => "servizos web baixo o seu control",
"cannot open \"%s\"" => "non foi posíbel abrir «%s»",
"ZIP download is turned off." => "As descargas ZIP están desactivadas.",
"Files need to be downloaded one by one." => "Os ficheiros necesitan seren descargados dun en un.",
"Back to Files" => "Volver aos ficheiros",
"Selected files too large to generate zip file." => "Os ficheiros seleccionados son demasiado grandes como para xerar un ficheiro zip.",
-"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Descargue os ficheiros en cachos máis pequenos e por separado, ou pídallos amabelmente ao seu administrador.",
-"couldn't be determined" => "non foi posíbel determinalo",
+"Please download the files separately in smaller chunks or kindly ask your administrator." => "Descargue os ficheiros en fragmentos máis pequenos e por separado, ou pídallos amabelmente ao seu administrador.",
+"No source specified when installing app" => "Non foi especificada ningunha orixe ao instalar aplicativos",
+"No href specified when installing app from http" => "Non foi especificada ningunha href ao instalar aplicativos",
+"No path specified when installing app from local file" => "Non foi especificada ningunha ruta ao instalar aplicativos desde un ficheiro local",
+"Archives of type %s are not supported" => "Os arquivos do tipo %s non están admitidos",
+"Failed to open archive when installing app" => "Non foi posíbel abrir o arquivo ao instalar aplicativos",
+"App does not provide an info.xml file" => "O aplicativo non fornece un ficheiro info.xml",
+"App can't be installed because of not allowed code in the App" => "Non é posíbel instalar o aplicativo por mor de conter código non permitido",
+"App can't be installed because it is not compatible with this version of ownCloud" => "Non é posíbel instalar o aplicativo por non seren compatíbel con esta versión do ownCloud.",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Non é posíbel instalar o aplicativo por conter a etiqueta\n<shipped>\n\ntrue\n</shipped>\nque non está permitida para os aplicativos non enviados",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Non é posíbel instalar o aplicativo xa que a versión en info.xml/version non é a mesma que a versión informada desde a App Store",
+"App directory already exists" => "Xa existe o directorio do aplicativo",
+"Can't create app folder. Please fix permissions. %s" => "Non é posíbel crear o cartafol de aplicativos. Corrixa os permisos. %s",
"Application is not enabled" => "O aplicativo non está activado",
"Authentication error" => "Produciuse un erro de autenticación",
"Token expired. Please reload page." => "Testemuña caducada. Recargue a páxina.",
@@ -41,19 +55,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "Estabeleza un contrasinal de administrador",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "O seu servidor web non está aínda configurado adecuadamente para permitir a sincronización de ficheiros xa que semella que a interface WebDAV non está a funcionar.",
"Please double check the <a href='%s'>installation guides</a>." => "Volva comprobar as <a href='%s'>guías de instalación</a>",
+"Could not find category \"%s\"" => "Non foi posíbel atopar a categoría «%s»",
"seconds ago" => "segundos atrás",
-"1 minute ago" => "hai 1 minuto",
-"%d minutes ago" => "hai %d minutos",
-"1 hour ago" => "Vai 1 hora",
-"%d hours ago" => "Vai %d horas",
+"_%n minute ago_::_%n minutes ago_" => array("hai %n minuto","hai %n minutos"),
+"_%n hour ago_::_%n hours ago_" => array("hai %n hora","hai %n horas"),
"today" => "hoxe",
"yesterday" => "onte",
-"%d days ago" => "hai %d días",
+"_%n day go_::_%n days ago_" => array("hai %n día","hai %n días"),
"last month" => "último mes",
-"%d months ago" => "Vai %d meses",
+"_%n month ago_::_%n months ago_" => array("hai %n mes","hai %n meses"),
"last year" => "último ano",
"years ago" => "anos atrás",
-"Caused by:" => "Causado por:",
-"Could not find category \"%s\"" => "Non foi posíbel atopar a categoría «%s»"
+"Caused by:" => "Causado por:"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/he.php b/lib/l10n/he.php
index fa597dadea7..5bbfffe9ae9 100644
--- a/lib/l10n/he.php
+++ b/lib/l10n/he.php
@@ -4,7 +4,6 @@ $TRANSLATIONS = array(
"Personal" => "אישי",
"Settings" => "הגדרות",
"Users" => "משתמשים",
-"Apps" => "יישומים",
"Admin" => "מנהל",
"web services under your control" => "שירותי רשת תחת השליטה שלך",
"ZIP download is turned off." => "הורדת ZIP כבויה",
@@ -19,18 +18,16 @@ $TRANSLATIONS = array(
"Images" => "תמונות",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "שרת האינטרנט שלך אינו מוגדר לצורכי סנכרון קבצים עדיין כיוון שמנשק ה־WebDAV כנראה אינו תקין.",
"Please double check the <a href='%s'>installation guides</a>." => "נא לעיין שוב ב<a href='%s'>מדריכי ההתקנה</a>.",
+"Could not find category \"%s\"" => "לא ניתן למצוא את הקטגוריה „%s“",
"seconds ago" => "שניות",
-"1 minute ago" => "לפני דקה אחת",
-"%d minutes ago" => "לפני %d דקות",
-"1 hour ago" => "לפני שעה",
-"%d hours ago" => "לפני %d שעות",
+"_%n minute ago_::_%n minutes ago_" => array("","לפני %n דקות"),
+"_%n hour ago_::_%n hours ago_" => array("","לפני %n שעות"),
"today" => "היום",
"yesterday" => "אתמול",
-"%d days ago" => "לפני %d ימים",
+"_%n day go_::_%n days ago_" => array("","לפני %n ימים"),
"last month" => "חודש שעבר",
-"%d months ago" => "לפני %d חודשים",
+"_%n month ago_::_%n months ago_" => array("","לפני %n חודשים"),
"last year" => "שנה שעברה",
-"years ago" => "שנים",
-"Could not find category \"%s\"" => "לא ניתן למצוא את הקטגוריה „%s“"
+"years ago" => "שנים"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/hi.php b/lib/l10n/hi.php
index 7986b3b6b7f..039dfa4465d 100644
--- a/lib/l10n/hi.php
+++ b/lib/l10n/hi.php
@@ -4,6 +4,9 @@ $TRANSLATIONS = array(
"Personal" => "यक्तिगत",
"Settings" => "सेटिंग्स",
"Users" => "उपयोगकर्ता",
-"Apps" => "Apps"
+"_%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/hr.php b/lib/l10n/hr.php
index 9c158447729..d217f924099 100644
--- a/lib/l10n/hr.php
+++ b/lib/l10n/hr.php
@@ -4,16 +4,19 @@ $TRANSLATIONS = array(
"Personal" => "Osobno",
"Settings" => "Postavke",
"Users" => "Korisnici",
-"Apps" => "Aplikacije",
"Admin" => "Administrator",
"web services under your control" => "web usluge pod vašom kontrolom",
"Authentication error" => "Greška kod autorizacije",
"Files" => "Datoteke",
"Text" => "Tekst",
"seconds ago" => "sekundi prije",
+"_%n minute ago_::_%n minutes ago_" => array("","",""),
+"_%n hour ago_::_%n hours ago_" => array("","",""),
"today" => "danas",
"yesterday" => "jučer",
+"_%n day go_::_%n days ago_" => array("","",""),
"last month" => "prošli mjesec",
+"_%n month ago_::_%n months ago_" => array("","",""),
"last year" => "prošlu godinu",
"years ago" => "godina"
);
diff --git a/lib/l10n/hu_HU.php b/lib/l10n/hu_HU.php
index 422c7266680..0d91b70b51a 100644
--- a/lib/l10n/hu_HU.php
+++ b/lib/l10n/hu_HU.php
@@ -1,20 +1,33 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "A(z) \"%s\" alkalmazást nem lehet telepíteni, mert nem kompatibilis az ownCloud telepített verziójával.",
+"No app name specified" => "Nincs az alkalmazás név megadva.",
"Help" => "Súgó",
"Personal" => "Személyes",
"Settings" => "Beállítások",
"Users" => "Felhasználók",
-"Apps" => "Alkalmazások",
"Admin" => "Adminsztráció",
"Failed to upgrade \"%s\"." => "Sikertelen Frissítés \"%s\".",
+"Unknown filetype" => "Ismeretlen file tipús",
+"Invalid image" => "Hibás kép",
"web services under your control" => "webszolgáltatások saját kézben",
"cannot open \"%s\"" => "nem sikerült megnyitni \"%s\"",
"ZIP download is turned off." => "A ZIP-letöltés nincs engedélyezve.",
"Files need to be downloaded one by one." => "A fájlokat egyenként kell letölteni.",
"Back to Files" => "Vissza a Fájlokhoz",
"Selected files too large to generate zip file." => "A kiválasztott fájlok túl nagyok a zip tömörítéshez.",
-"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Tölts le a fileokat kisebb chunkokban, kölün vagy kérj segitséget a rendszergazdádtól.",
-"couldn't be determined" => "nem határozható meg",
+"No source specified when installing app" => "Az alkalmazás telepítéséhez nincs forrás megadva",
+"No href specified when installing app from http" => "Az alkalmazás http-n keresztül történő telepítéséhez nincs href hivetkozás megadva",
+"No path specified when installing app from local file" => "Az alkalmazás helyi telepítéséhez nincs útvonal (mappa) megadva",
+"Archives of type %s are not supported" => "A(z) %s típusú tömörített állomány nem támogatott",
+"Failed to open archive when installing app" => "Nem sikerült megnyitni a tömörített állományt a telepítés során",
+"App does not provide an info.xml file" => "Az alkalmazás nem szolgáltatott info.xml file-t",
+"App can't be installed because of not allowed code in the App" => "Az alkalmazást nem lehet telepíteni, mert abban nem engedélyezett programkód szerepel",
+"App can't be installed because it is not compatible with this version of ownCloud" => "Az alalmazás nem telepíthető, mert nem kompatibilis az ownClod ezzel a verziójával.",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Az alkalmazást nem lehet telepíteni, mert tartalmazza a \n<shipped>\ntrue\n</shipped>\ncímkét, ami a nem szállított alkalmazások esetén nem engedélyezett",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Az alkalmazást nem lehet telepíteni, mert az info.xml/version-ben megadott verzió nem egyezik az alkalmazás-áruházban feltüntetett verzióval.",
+"App directory already exists" => "Az alkalmazás mappája már létezik",
+"Can't create app folder. Please fix permissions. %s" => "Nem lehetett létrehozni az alkalmzás mappáját. Kérlek ellenőrizd a jogosultásgokat. %s",
"Application is not enabled" => "Az alkalmazás nincs engedélyezve",
"Authentication error" => "Azonosítási hiba",
"Token expired. Please reload page." => "A token lejárt. Frissítse az oldalt.",
@@ -41,19 +54,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "Állítson be egy jelszót az adminisztrációhoz.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Az Ön webkiszolgálója nincs megfelelően beállítva az állományok szinkronizálásához, mert a WebDAV-elérés úgy tűnik, nem működik.",
"Please double check the <a href='%s'>installation guides</a>." => "Kérjük tüzetesen tanulmányozza át a <a href='%s'>telepítési útmutatót</a>.",
+"Could not find category \"%s\"" => "Ez a kategória nem található: \"%s\"",
"seconds ago" => "pár másodperce",
-"1 minute ago" => "1 perce",
-"%d minutes ago" => "%d perce",
-"1 hour ago" => "1 órája",
-"%d hours ago" => "%d órája",
+"_%n minute ago_::_%n minutes ago_" => array("","%n perccel ezelőtt"),
+"_%n hour ago_::_%n hours ago_" => array("%n órával ezelőtt","%n órával ezelőtt"),
"today" => "ma",
"yesterday" => "tegnap",
-"%d days ago" => "%d napja",
+"_%n day go_::_%n days ago_" => array("%n nappal ezelőtt","%n nappal ezelőtt"),
"last month" => "múlt hónapban",
-"%d months ago" => "%d hónapja",
+"_%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",
-"Caused by:" => "Okozta:",
-"Could not find category \"%s\"" => "Ez a kategória nem található: \"%s\""
+"Caused by:" => "Okozta:"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/hy.php b/lib/l10n/hy.php
new file mode 100644
index 00000000000..15f78e0bce6
--- /dev/null
+++ b/lib/l10n/hy.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/ia.php b/lib/l10n/ia.php
index 50ebf20c591..34f43bc424a 100644
--- a/lib/l10n/ia.php
+++ b/lib/l10n/ia.php
@@ -4,10 +4,13 @@ $TRANSLATIONS = array(
"Personal" => "Personal",
"Settings" => "Configurationes",
"Users" => "Usatores",
-"Apps" => "Applicationes",
"Admin" => "Administration",
"web services under your control" => "servicios web sub tu controlo",
"Files" => "Files",
-"Text" => "Texto"
+"Text" => "Texto",
+"_%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/id.php b/lib/l10n/id.php
index 0881f5349bc..0cbcddcc6dd 100644
--- a/lib/l10n/id.php
+++ b/lib/l10n/id.php
@@ -4,14 +4,12 @@ $TRANSLATIONS = array(
"Personal" => "Pribadi",
"Settings" => "Setelan",
"Users" => "Pengguna",
-"Apps" => "Aplikasi",
"Admin" => "Admin",
"web services under your control" => "layanan web dalam kontrol Anda",
"ZIP download is turned off." => "Pengunduhan ZIP dimatikan.",
"Files need to be downloaded one by one." => "Berkas harus diunduh satu persatu.",
"Back to Files" => "Kembali ke Daftar Berkas",
"Selected files too large to generate zip file." => "Berkas yang dipilih terlalu besar untuk dibuat berkas zip-nya.",
-"couldn't be determined" => "tidak dapat ditentukan",
"Application is not enabled" => "Aplikasi tidak diaktifkan",
"Authentication error" => "Galat saat autentikasi",
"Token expired. Please reload page." => "Token kedaluwarsa. Silakan muat ulang halaman.",
@@ -37,18 +35,16 @@ $TRANSLATIONS = array(
"Set an admin password." => "Setel sandi admin.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Web server Anda belum dikonfigurasikan dengan baik untuk mengizinkan sinkronisasi berkas karena tampaknya antarmuka WebDAV rusak.",
"Please double check the <a href='%s'>installation guides</a>." => "Silakan periksa ulang <a href='%s'>panduan instalasi</a>.",
+"Could not find category \"%s\"" => "Tidak dapat menemukan kategori \"%s\"",
"seconds ago" => "beberapa detik yang lalu",
-"1 minute ago" => "1 menit yang lalu",
-"%d minutes ago" => "%d menit yang lalu",
-"1 hour ago" => "1 jam yang lalu",
-"%d hours ago" => "%d jam yang lalu",
+"_%n minute ago_::_%n minutes ago_" => array(""),
+"_%n hour ago_::_%n hours ago_" => array(""),
"today" => "hari ini",
"yesterday" => "kemarin",
-"%d days ago" => "%d hari yang lalu",
+"_%n day go_::_%n days ago_" => array(""),
"last month" => "bulan kemarin",
-"%d months ago" => "%d bulan yang lalu",
+"_%n month ago_::_%n months ago_" => array(""),
"last year" => "tahun kemarin",
-"years ago" => "beberapa tahun lalu",
-"Could not find category \"%s\"" => "Tidak dapat menemukan kategori \"%s\""
+"years ago" => "beberapa tahun lalu"
);
$PLURAL_FORMS = "nplurals=1; plural=0;";
diff --git a/lib/l10n/is.php b/lib/l10n/is.php
index 5ccb20882ad..032289fd304 100644
--- a/lib/l10n/is.php
+++ b/lib/l10n/is.php
@@ -4,7 +4,6 @@ $TRANSLATIONS = array(
"Personal" => "Um mig",
"Settings" => "Stillingar",
"Users" => "Notendur",
-"Apps" => "Forrit",
"Admin" => "Stjórnun",
"web services under your control" => "vefþjónusta undir þinni stjórn",
"ZIP download is turned off." => "Slökkt á ZIP niðurhali.",
@@ -17,18 +16,16 @@ $TRANSLATIONS = array(
"Files" => "Skrár",
"Text" => "Texti",
"Images" => "Myndir",
+"Could not find category \"%s\"" => "Fann ekki flokkinn \"%s\"",
"seconds ago" => "sek.",
-"1 minute ago" => "Fyrir 1 mínútu",
-"%d minutes ago" => "fyrir %d mínútum",
-"1 hour ago" => "Fyrir 1 klst.",
-"%d hours ago" => "fyrir %d klst.",
+"_%n minute ago_::_%n minutes ago_" => array("",""),
+"_%n hour ago_::_%n hours ago_" => array("",""),
"today" => "í dag",
"yesterday" => "í gær",
-"%d days ago" => "fyrir %d dögum",
+"_%n day go_::_%n days ago_" => array("",""),
"last month" => "síðasta mánuði",
-"%d months ago" => "fyrir %d mánuðum",
+"_%n month ago_::_%n months ago_" => array("",""),
"last year" => "síðasta ári",
-"years ago" => "einhverjum árum",
-"Could not find category \"%s\"" => "Fann ekki flokkinn \"%s\""
+"years ago" => "einhverjum árum"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/it.php b/lib/l10n/it.php
index c85ba08f4cd..b1259a0a874 100644
--- a/lib/l10n/it.php
+++ b/lib/l10n/it.php
@@ -1,20 +1,34 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "L'applicazione \"%s\" non può essere installata poiché non è compatibile con questa versione di ownCloud.",
+"No app name specified" => "Il nome dell'applicazione non è specificato",
"Help" => "Aiuto",
"Personal" => "Personale",
"Settings" => "Impostazioni",
"Users" => "Utenti",
-"Apps" => "Applicazioni",
"Admin" => "Admin",
"Failed to upgrade \"%s\"." => "Aggiornamento non riuscito \"%s\".",
+"Unknown filetype" => "Tipo di file sconosciuto",
+"Invalid image" => "Immagine non valida",
"web services under your control" => "servizi web nelle tue mani",
"cannot open \"%s\"" => "impossibile aprire \"%s\"",
"ZIP download is turned off." => "Lo scaricamento in formato ZIP è stato disabilitato.",
"Files need to be downloaded one by one." => "I file devono essere scaricati uno alla volta.",
"Back to Files" => "Torna ai file",
"Selected files too large to generate zip file." => "I file selezionati sono troppo grandi per generare un file zip.",
-"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Scarica i file in blocchi più piccoli, separatamente o chiedi al tuo amministratore.",
-"couldn't be determined" => "non può essere determinato",
+"Please download the files separately in smaller chunks or kindly ask your administrator." => "Scarica i file separatamente in blocchi più piccoli o chiedi al tuo amministratore.",
+"No source specified when installing app" => "Nessuna fonte specificata durante l'installazione dell'applicazione",
+"No href specified when installing app from http" => "Nessun href specificato durante l'installazione dell'applicazione da http",
+"No path specified when installing app from local file" => "Nessun percorso specificato durante l'installazione dell'applicazione da file locale",
+"Archives of type %s are not supported" => "Gli archivi di tipo %s non sono supportati",
+"Failed to open archive when installing app" => "Apertura archivio non riuscita durante l'installazione dell'applicazione",
+"App does not provide an info.xml file" => "L'applicazione non fornisce un file info.xml",
+"App can't be installed because of not allowed code in the App" => "L'applicazione non può essere installata a causa di codice non consentito al suo interno",
+"App can't be installed because it is not compatible with this version of ownCloud" => "L'applicazione non può essere installata poiché non è compatibile con questa versione di ownCloud",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "L'applicazione non può essere installata poiché contiene il tag <shipped>true<shipped> che non è permesso alle applicazioni non shipped",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "L'applicazione non può essere installata poiché la versione in info.xml/version non è la stessa riportata dall'app store",
+"App directory already exists" => "La cartella dell'applicazione esiste già",
+"Can't create app folder. Please fix permissions. %s" => "Impossibile creare la cartella dell'applicazione. Correggi i permessi. %s",
"Application is not enabled" => "L'applicazione non è abilitata",
"Authentication error" => "Errore di autenticazione",
"Token expired. Please reload page." => "Token scaduto. Ricarica la pagina.",
@@ -41,19 +55,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "Imposta una password di amministrazione.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Il tuo server web non è configurato correttamente per consentire la sincronizzazione dei file poiché l'interfaccia WebDAV sembra essere danneggiata.",
"Please double check the <a href='%s'>installation guides</a>." => "Leggi attentamente le <a href='%s'>guide d'installazione</a>.",
+"Could not find category \"%s\"" => "Impossibile trovare la categoria \"%s\"",
"seconds ago" => "secondi fa",
-"1 minute ago" => "Un minuto fa",
-"%d minutes ago" => "%d minuti fa",
-"1 hour ago" => "1 ora fa",
-"%d hours ago" => "%d ore fa",
+"_%n minute ago_::_%n minutes ago_" => array("%n minuto fa","%n minuti fa"),
+"_%n hour ago_::_%n hours ago_" => array("%n ora fa","%n ore fa"),
"today" => "oggi",
"yesterday" => "ieri",
-"%d days ago" => "%d giorni fa",
+"_%n day go_::_%n days ago_" => array("%n giorno fa","%n giorni fa"),
"last month" => "mese scorso",
-"%d months ago" => "%d mesi fa",
+"_%n month ago_::_%n months ago_" => array("%n mese fa","%n mesi fa"),
"last year" => "anno scorso",
"years ago" => "anni fa",
-"Caused by:" => "Causato da:",
-"Could not find category \"%s\"" => "Impossibile trovare la categoria \"%s\""
+"Caused by:" => "Causato da:"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/ja_JP.php b/lib/l10n/ja_JP.php
index 716db8706f0..d7baf176a14 100644
--- a/lib/l10n/ja_JP.php
+++ b/lib/l10n/ja_JP.php
@@ -1,20 +1,34 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => " \"%s\" アプリは、このバージョンのownCloudと互換性がない為、インストールできません。",
+"No app name specified" => "アプリ名が未指定",
"Help" => "ヘルプ",
"Personal" => "個人",
"Settings" => "設定",
"Users" => "ユーザ",
-"Apps" => "アプリ",
"Admin" => "管理",
"Failed to upgrade \"%s\"." => "\"%s\" へのアップグレードに失敗しました。",
+"Unknown filetype" => "不明なファイルタイプ",
+"Invalid image" => "無効な画像",
"web services under your control" => "管理下のウェブサービス",
"cannot open \"%s\"" => "\"%s\" が開けません",
"ZIP download is turned off." => "ZIPダウンロードは無効です。",
"Files need to be downloaded one by one." => "ファイルは1つずつダウンロードする必要があります。",
"Back to Files" => "ファイルに戻る",
"Selected files too large to generate zip file." => "選択したファイルはZIPファイルの生成には大きすぎます。",
-"Download the files in smaller chunks, seperately or kindly ask your administrator." => "ファイルは、小さいファイルに分割されてダウンロードされます。もしくは、管理者にお尋ねください。",
-"couldn't be determined" => "測定できませんでした",
+"Please download the files separately in smaller chunks or kindly ask your administrator." => "少しずつに分けてファイルをダウンロードするか、管理者に問い合わせてください。",
+"No source specified when installing app" => "アプリインストール時のソースが未指定",
+"No href specified when installing app from http" => "アプリインストール時のhttpの URL が未指定",
+"No path specified when installing app from local file" => "アプリインストール時のローカルファイルのパスが未指定",
+"Archives of type %s are not supported" => "\"%s\"タイプのアーカイブ形式は未サポート",
+"Failed to open archive when installing app" => "アプリをインストール中にアーカイブファイルを開けませんでした。",
+"App does not provide an info.xml file" => "アプリにinfo.xmlファイルが入っていません",
+"App can't be installed because of not allowed code in the App" => "アプリで許可されないコードが入っているのが原因でアプリがインストールできません",
+"App can't be installed because it is not compatible with this version of ownCloud" => "アプリは、このバージョンのownCloudと互換性がない為、インストールできません。",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "非shippedアプリには許可されない<shipped>true</shipped>タグが含まれているためにアプリをインストール出来ません。",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "info.xml/versionのバージョンがアプリストアのバージョンと合っていない為、アプリはインストールされません",
+"App directory already exists" => "アプリディレクトリは既に存在します",
+"Can't create app folder. Please fix permissions. %s" => "アプリフォルダを作成出来ませんでした。%s のパーミッションを修正してください。",
"Application is not enabled" => "アプリケーションは無効です",
"Authentication error" => "認証エラー",
"Token expired. Please reload page." => "トークンが無効になりました。ページを再読込してください。",
@@ -41,19 +55,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "管理者のパスワードを設定。",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "WebDAVインタフェースが動作していないと考えられるため、あなたのWEBサーバはまだファイルの同期を許可するように適切な設定がされていません。",
"Please double check the <a href='%s'>installation guides</a>." => "<a href='%s'>インストールガイド</a>をよく確認してください。",
+"Could not find category \"%s\"" => "カテゴリ \"%s\" が見つかりませんでした",
"seconds ago" => "数秒前",
-"1 minute ago" => "1 分前",
-"%d minutes ago" => "%d 分前",
-"1 hour ago" => "1 時間前",
-"%d hours ago" => "%d 時間前",
+"_%n minute ago_::_%n minutes ago_" => array("%n 分前"),
+"_%n hour ago_::_%n hours ago_" => array("%n 時間前"),
"today" => "今日",
"yesterday" => "昨日",
-"%d days ago" => "%d 日前",
+"_%n day go_::_%n days ago_" => array("%n 日前"),
"last month" => "一月前",
-"%d months ago" => "%d 分前",
+"_%n month ago_::_%n months ago_" => array("%n ヶ月前"),
"last year" => "一年前",
"years ago" => "年前",
-"Caused by:" => "原因は以下:",
-"Could not find category \"%s\"" => "カテゴリ \"%s\" が見つかりませんでした"
+"Caused by:" => "原因:"
);
$PLURAL_FORMS = "nplurals=1; plural=0;";
diff --git a/lib/l10n/ka.php b/lib/l10n/ka.php
index b6e06997638..04fefe8bdf1 100644
--- a/lib/l10n/ka.php
+++ b/lib/l10n/ka.php
@@ -7,11 +7,11 @@ $TRANSLATIONS = array(
"ZIP download is turned off." => "ZIP გადმოწერა გამორთულია",
"Files" => "ფაილები",
"seconds ago" => "წამის წინ",
-"1 minute ago" => "1 წუთის წინ",
-"%d minutes ago" => "%d წუთის წინ",
-"1 hour ago" => "1 საათის წინ",
+"_%n minute ago_::_%n minutes ago_" => array(""),
+"_%n hour ago_::_%n hours ago_" => array(""),
"today" => "დღეს",
"yesterday" => "გუშინ",
-"%d days ago" => "%d დღის წინ"
+"_%n day go_::_%n days ago_" => array(""),
+"_%n month ago_::_%n months ago_" => array("")
);
$PLURAL_FORMS = "nplurals=1; plural=0;";
diff --git a/lib/l10n/ka_GE.php b/lib/l10n/ka_GE.php
index 5001eee0c27..0cf6ab333e8 100644
--- a/lib/l10n/ka_GE.php
+++ b/lib/l10n/ka_GE.php
@@ -4,14 +4,12 @@ $TRANSLATIONS = array(
"Personal" => "პირადი",
"Settings" => "პარამეტრები",
"Users" => "მომხმარებელი",
-"Apps" => "აპლიკაციები",
"Admin" => "ადმინისტრატორი",
"web services under your control" => "web services under your control",
"ZIP download is turned off." => "ZIP download–ი გათიშულია",
"Files need to be downloaded one by one." => "ფაილები უნდა გადმოიტვირთოს სათითაოდ.",
"Back to Files" => "უკან ფაილებში",
"Selected files too large to generate zip file." => "არჩეული ფაილები ძალიან დიდია zip ფაილის გენერაციისთვის.",
-"couldn't be determined" => "ვერ განისაზღვრა",
"Application is not enabled" => "აპლიკაცია არ არის აქტიური",
"Authentication error" => "ავთენტიფიკაციის შეცდომა",
"Token expired. Please reload page." => "Token–ს ვადა გაუვიდა. გთხოვთ განაახლოთ გვერდი.",
@@ -37,18 +35,16 @@ $TRANSLATIONS = array(
"Set an admin password." => "დააყენეთ ადმინისტრატორის პაროლი.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "თქვენი web სერვერი არ არის კონფიგურირებული ფაილ სინქრონიზაციისთვის, რადგან WebDAV ინტერფეისი შეიძლება იყოს გატეხილი.",
"Please double check the <a href='%s'>installation guides</a>." => "გთხოვთ გადაათვალიეროთ <a href='%s'>ინსტალაციის გზამკვლევი</a>.",
+"Could not find category \"%s\"" => "\"%s\" კატეგორიის მოძებნა ვერ მოხერხდა",
"seconds ago" => "წამის წინ",
-"1 minute ago" => "1 წუთის წინ",
-"%d minutes ago" => "%d წუთის წინ",
-"1 hour ago" => "1 საათის წინ",
-"%d hours ago" => "%d საათის წინ",
+"_%n minute ago_::_%n minutes ago_" => array(""),
+"_%n hour ago_::_%n hours ago_" => array(""),
"today" => "დღეს",
"yesterday" => "გუშინ",
-"%d days ago" => "%d დღის წინ",
+"_%n day go_::_%n days ago_" => array(""),
"last month" => "გასულ თვეში",
-"%d months ago" => "%d თვის წინ",
+"_%n month ago_::_%n months ago_" => array(""),
"last year" => "ბოლო წელს",
-"years ago" => "წლის წინ",
-"Could not find category \"%s\"" => "\"%s\" კატეგორიის მოძებნა ვერ მოხერხდა"
+"years ago" => "წლის წინ"
);
$PLURAL_FORMS = "nplurals=1; plural=0;";
diff --git a/lib/l10n/km.php b/lib/l10n/km.php
new file mode 100644
index 00000000000..e7b09649a24
--- /dev/null
+++ b/lib/l10n/km.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=1; plural=0;";
diff --git a/lib/l10n/kn.php b/lib/l10n/kn.php
new file mode 100644
index 00000000000..e7b09649a24
--- /dev/null
+++ b/lib/l10n/kn.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=1; plural=0;";
diff --git a/lib/l10n/ko.php b/lib/l10n/ko.php
index c163d8c9fa4..102bf9f978d 100644
--- a/lib/l10n/ko.php
+++ b/lib/l10n/ko.php
@@ -1,17 +1,33 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "현재 ownCloud 버전과 호환되지 않기 때문에 \"%s\" 앱을 설치할 수 없습니다.",
+"No app name specified" => "앱 이름이 지정되지 않았습니다.",
"Help" => "도움말",
"Personal" => "개인",
"Settings" => "설정",
"Users" => "사용자",
-"Apps" => "앱",
"Admin" => "관리자",
+"Failed to upgrade \"%s\"." => "\"%s\" 업그레이드에 실패했습니다.",
+"Unknown filetype" => "알수없는 파일형식",
+"Invalid image" => "잘못된 그림",
"web services under your control" => "내가 관리하는 웹 서비스",
+"cannot open \"%s\"" => "\"%s\"을(를) 열 수 없습니다.",
"ZIP download is turned off." => "ZIP 다운로드가 비활성화되었습니다.",
"Files need to be downloaded one by one." => "파일을 개별적으로 다운로드해야 합니다.",
"Back to Files" => "파일로 돌아가기",
"Selected files too large to generate zip file." => "선택한 파일들은 ZIP 파일을 생성하기에 너무 큽니다.",
-"couldn't be determined" => "결정할 수 없음",
+"No source specified when installing app" => "앱을 설치할 때 소스가 지정되지 않았습니다.",
+"No href specified when installing app from http" => "http에서 앱을 설치할 대 href가 지정되지 않았습니다.",
+"No path specified when installing app from local file" => "로컬 파일에서 앱을 설치할 때 경로가 지정되지 않았습니다.",
+"Archives of type %s are not supported" => "%s 타입 아카이브는 지원되지 않습니다.",
+"Failed to open archive when installing app" => "앱을 설치할 때 아카이브를 열지 못했습니다.",
+"App does not provide an info.xml file" => "앱에서 info.xml 파일이 제공되지 않았습니다.",
+"App can't be installed because of not allowed code in the App" => "앱에 허용되지 않는 코드가 있어서 앱을 설치할 수 없습니다. ",
+"App can't be installed because it is not compatible with this version of ownCloud" => "현재 ownCloud 버전과 호환되지 않기 때문에 앱을 설치할 수 없습니다.",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "출하되지 않은 앱에 허용되지 않는 <shipped>true</shipped> 태그를 포함하고 있기 때문에 앱을 설치할 수 없습니다.",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "info.xml/version에 포함된 버전과 앱 스토어에 보고된 버전이 같지 않아서 앱을 설치할 수 없습니다. ",
+"App directory already exists" => "앱 디렉토리가 이미 존재합니다. ",
+"Can't create app folder. Please fix permissions. %s" => "앱 폴더를 만들 수 없습니다. 권한을 수정하십시오. %s ",
"Application is not enabled" => "앱이 활성화되지 않았습니다",
"Authentication error" => "인증 오류",
"Token expired. Please reload page." => "토큰이 만료되었습니다. 페이지를 새로 고치십시오.",
@@ -21,24 +37,34 @@ $TRANSLATIONS = array(
"%s enter the database username." => "데이터베이스 사용자 명을 %s 에 입력해주십시오",
"%s enter the database name." => "데이터베이스 명을 %s 에 입력해주십시오",
"%s you may not use dots in the database name" => "%s 에 적으신 데이터베이스 이름에는 점을 사용할수 없습니다",
+"MS SQL username and/or password not valid: %s" => "MS SQL 사용자 이름이나 암호가 잘못되었습니다: %s",
+"You need to enter either an existing account or the administrator." => "기존 계정이나 administrator(관리자)를 입력해야 합니다.",
+"MySQL username and/or password not valid" => "MySQL 사용자 이름이나 암호가 잘못되었습니다.",
"DB Error: \"%s\"" => "DB 오류: \"%s\"",
+"Offending command was: \"%s\"" => "잘못된 명령: \"%s\"",
+"MySQL user '%s'@'localhost' exists already." => "MySQL 사용자 '%s'@'localhost'이(가) 이미 존재합니다.",
+"Drop this user from MySQL" => "이 사용자를 MySQL에서 뺍니다.",
+"MySQL user '%s'@'%%' already exists" => "MySQL 사용자 '%s'@'%%'이(가) 이미 존재합니다. ",
+"Drop this user from MySQL." => "이 사용자를 MySQL에서 뺍니다.",
+"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",
"PostgreSQL username and/or password not valid" => "PostgreSQL의 사용자 명 혹은 비밀번호가 잘못되었습니다",
"Set an admin username." => "관리자 이름 설정",
"Set an admin password." => "관리자 비밀번호 설정",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "WebDAV 인터페이스가 제대로 작동하지 않습니다. 웹 서버에서 파일 동기화를 사용할 수 있도록 설정이 제대로 되지 않은 것 같습니다.",
"Please double check the <a href='%s'>installation guides</a>." => "<a href='%s'>설치 가이드</a>를 다시 한 번 확인하십시오.",
+"Could not find category \"%s\"" => "분류 \"%s\"을(를) 찾을 수 없습니다.",
"seconds ago" => "초 전",
-"1 minute ago" => "1분 전",
-"%d minutes ago" => "%d분 전",
-"1 hour ago" => "1시간 전",
-"%d hours ago" => "%d시간 전",
+"_%n minute ago_::_%n minutes ago_" => array("%n분 전 "),
+"_%n hour ago_::_%n hours ago_" => array("%n시간 전 "),
"today" => "오늘",
"yesterday" => "어제",
-"%d days ago" => "%d일 전",
+"_%n day go_::_%n days ago_" => array("%n일 전 "),
"last month" => "지난 달",
-"%d months ago" => "%d개월 전",
+"_%n month ago_::_%n months ago_" => array("%n달 전 "),
"last year" => "작년",
"years ago" => "년 전",
-"Could not find category \"%s\"" => "분류 \"%s\"을(를) 찾을 수 없습니다."
+"Caused by:" => "원인: "
);
$PLURAL_FORMS = "nplurals=1; plural=0;";
diff --git a/lib/l10n/ku_IQ.php b/lib/l10n/ku_IQ.php
index 05959b89cff..c99f9dd2a12 100644
--- a/lib/l10n/ku_IQ.php
+++ b/lib/l10n/ku_IQ.php
@@ -3,8 +3,11 @@ $TRANSLATIONS = array(
"Help" => "یارمەتی",
"Settings" => "ده‌ستكاری",
"Users" => "به‌كارهێنه‌ر",
-"Apps" => "به‌رنامه‌كان",
"Admin" => "به‌ڕێوه‌به‌ری سه‌ره‌كی",
-"web services under your control" => "ڕاژه‌ی وێب له‌ژێر چاودێریت دایه"
+"web services under your control" => "ڕاژه‌ی وێب له‌ژێر چاودێریت دایه",
+"_%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/lb.php b/lib/l10n/lb.php
index 11552bcce82..629d5b11c30 100644
--- a/lib/l10n/lb.php
+++ b/lib/l10n/lb.php
@@ -4,18 +4,21 @@ $TRANSLATIONS = array(
"Personal" => "Perséinlech",
"Settings" => "Astellungen",
"Users" => "Benotzer",
-"Apps" => "Applikatiounen",
"Admin" => "Admin",
+"Unknown filetype" => "Onbekannten Fichier Typ",
+"Invalid image" => "Ongülteg d'Bild",
"web services under your control" => "Web-Servicer ënnert denger Kontroll",
"Authentication error" => "Authentifikatioun's Fehler",
"Files" => "Dateien",
"Text" => "SMS",
"seconds ago" => "Sekonnen hir",
-"1 minute ago" => "1 Minutt hir",
-"1 hour ago" => "vrun 1 Stonn",
+"_%n minute ago_::_%n minutes ago_" => array("","%n Minutten hir"),
+"_%n hour ago_::_%n hours ago_" => array("",""),
"today" => "haut",
"yesterday" => "gëschter",
+"_%n day go_::_%n days ago_" => array("",""),
"last month" => "Läschte Mount",
+"_%n month ago_::_%n months ago_" => array("",""),
"last year" => "Läscht Joer",
"years ago" => "Joren hier"
);
diff --git a/lib/l10n/lt_LT.php b/lib/l10n/lt_LT.php
index e35f3bee16b..17bbb856e43 100644
--- a/lib/l10n/lt_LT.php
+++ b/lib/l10n/lt_LT.php
@@ -1,33 +1,71 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "Programa „%s“ negali būti įdiegta, nes yra nesuderinama su šia ownCloud versija.",
+"No app name specified" => "Nenurodytas programos pavadinimas",
"Help" => "Pagalba",
"Personal" => "Asmeniniai",
"Settings" => "Nustatymai",
"Users" => "Vartotojai",
-"Apps" => "Programos",
"Admin" => "Administravimas",
+"Failed to upgrade \"%s\"." => "Nepavyko pakelti „%s“ versijos.",
+"Unknown filetype" => "Nežinomas failo tipas",
+"Invalid image" => "Netinkamas paveikslėlis",
"web services under your control" => "jūsų valdomos web paslaugos",
+"cannot open \"%s\"" => "nepavyksta atverti „%s“",
"ZIP download is turned off." => "ZIP atsisiuntimo galimybė yra išjungta.",
"Files need to be downloaded one by one." => "Failai turi būti parsiunčiami vienas po kito.",
"Back to Files" => "Atgal į Failus",
"Selected files too large to generate zip file." => "Pasirinkti failai per dideli archyvavimui į ZIP.",
+"Please download the files separately in smaller chunks or kindly ask your administrator." => "Prašome atsisiųsti failus mažesnėmis dalimis atskirai, arba mandagiai prašykite savo administratoriaus.",
+"No source specified when installing app" => "Nenurodytas šaltinis diegiant programą",
+"No href specified when installing app from http" => "Nenurodytas href diegiant programą iš http",
+"No path specified when installing app from local file" => "Nenurodytas kelias diegiant programą iš vietinio failo",
+"Archives of type %s are not supported" => "%s tipo archyvai nepalaikomi",
+"Failed to open archive when installing app" => "Nepavyko atverti archyvo diegiant programą",
+"App does not provide an info.xml file" => "Programa nepateikia info.xml failo",
+"App can't be installed because of not allowed code in the App" => "Programa negali būti įdiegta, nes turi neleistiną kodą",
+"App can't be installed because it is not compatible with this version of ownCloud" => "Programa negali būti įdiegta, nes yra nesuderinama su šia ownCloud versija",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Programa negali būti įdiegta, nes turi <shipped>true</shipped> žymę, kuri yra neleistina ne kartu platinamoms programoms",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Programa negali būti įdiegta, nes versija pateikta info.xml/version nesutampa su versija deklaruota programų saugykloje",
+"App directory already exists" => "Programos aplankas jau egzistuoja",
+"Can't create app folder. Please fix permissions. %s" => "Nepavyksta sukurti aplanko. Prašome pataisyti leidimus. %s",
"Application is not enabled" => "Programa neįjungta",
"Authentication error" => "Autentikacijos klaida",
"Token expired. Please reload page." => "Sesija baigėsi. Prašome perkrauti puslapį.",
"Files" => "Failai",
"Text" => "Žinučių",
"Images" => "Paveikslėliai",
+"%s enter the database username." => "%s įrašykite duombazės naudotojo vardą.",
+"%s enter the database name." => "%s įrašykite duombazės pavadinimą.",
+"%s you may not use dots in the database name" => "%s negalite naudoti taškų duombazės pavadinime",
+"MS SQL username and/or password not valid: %s" => "MS SQL naudotojo vardas ir/arba slaptažodis netinka: %s",
+"You need to enter either an existing account or the administrator." => "Turite prisijungti su egzistuojančia paskyra arba su administratoriumi.",
+"MySQL username and/or password not valid" => "Neteisingas MySQL naudotojo vardas ir/arba slaptažodis",
+"DB Error: \"%s\"" => "DB klaida: \"%s\"",
+"Offending command was: \"%s\"" => "Vykdyta komanda buvo: \"%s\"",
+"MySQL user '%s'@'localhost' exists already." => "MySQL naudotojas '%s'@'localhost' jau egzistuoja.",
+"Drop this user from MySQL" => "Pašalinti šį naudotoją iš MySQL",
+"MySQL user '%s'@'%%' already exists" => "MySQL naudotojas '%s'@'%%' jau egzistuoja",
+"Drop this user from MySQL." => "Pašalinti šį naudotoją iš MySQL.",
+"Oracle connection could not be established" => "Nepavyko sukurti Oracle ryšio",
+"Oracle username and/or password not valid" => "Neteisingas Oracle naudotojo vardas ir/arba slaptažodis",
+"Offending command was: \"%s\", name: %s, password: %s" => "Vykdyta komanda buvo: \"%s\", name: %s, password: %s",
+"PostgreSQL username and/or password not valid" => "Neteisingas PostgreSQL naudotojo vardas ir/arba slaptažodis",
+"Set an admin username." => "Nustatyti administratoriaus naudotojo vardą.",
+"Set an admin password." => "Nustatyti administratoriaus slaptažodį.",
+"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Jūsų serveris nėra tvarkingai nustatytas leisti failų sinchronizaciją, nes WebDAV sąsaja panašu, kad yra sugadinta.",
+"Please double check the <a href='%s'>installation guides</a>." => "Prašome pažiūrėkite dar kartą <a href='%s'>diegimo instrukcijas</a>.",
+"Could not find category \"%s\"" => "Nepavyko rasti kategorijos „%s“",
"seconds ago" => "prieš sekundę",
-"1 minute ago" => "Prieš 1 minutę",
-"%d minutes ago" => "prieš %d minučių",
-"1 hour ago" => "prieš 1 valandą",
-"%d hours ago" => "prieš %d valandų",
+"_%n minute ago_::_%n minutes ago_" => array("prieš %n min.","Prieš % minutes","Prieš %n minučių"),
+"_%n hour ago_::_%n hours ago_" => array("Prieš %n valandą","Prieš %n valandas","Prieš %n valandų"),
"today" => "šiandien",
"yesterday" => "vakar",
-"%d days ago" => "prieš %d dienų",
+"_%n day go_::_%n days ago_" => array("Prieš %n dieną","Prieš %n dienas","Prieš %n dienų"),
"last month" => "praeitą mėnesį",
-"%d months ago" => "prieš %d mėnesių",
+"_%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",
+"Caused by:" => "Iššaukė:"
);
$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 0dfaf6b6780..ef5fd2d5ca8 100644
--- a/lib/l10n/lv.php
+++ b/lib/l10n/lv.php
@@ -4,14 +4,14 @@ $TRANSLATIONS = array(
"Personal" => "Personīgi",
"Settings" => "Iestatījumi",
"Users" => "Lietotāji",
-"Apps" => "Lietotnes",
"Admin" => "Administratori",
+"Failed to upgrade \"%s\"." => "Kļūda atjauninot \"%s\"",
"web services under your control" => "tīmekļa servisi tavā varā",
+"cannot open \"%s\"" => "Nevar atvērt \"%s\"",
"ZIP download is turned off." => "ZIP lejupielādēšana ir izslēgta.",
"Files need to be downloaded one by one." => "Datnes var lejupielādēt tikai katru atsevišķi.",
"Back to Files" => "Atpakaļ pie datnēm",
"Selected files too large to generate zip file." => "Izvēlētās datnes ir pārāk lielas, lai izveidotu zip datni.",
-"couldn't be determined" => "nevarēja noteikt",
"Application is not enabled" => "Lietotne nav aktivēta",
"Authentication error" => "Autentifikācijas kļūda",
"Token expired. Please reload page." => "Pilnvarai ir beidzies termiņš. Lūdzu, pārlādējiet lapu.",
@@ -30,6 +30,7 @@ $TRANSLATIONS = array(
"Drop this user from MySQL" => "Izmest šo lietotāju no MySQL",
"MySQL user '%s'@'%%' already exists" => "MySQL lietotājs '%s'@'%%' jau eksistē",
"Drop this user from MySQL." => "Izmest šo lietotāju no MySQL.",
+"Oracle connection could not be established" => "Nevar izveidot savienojumu ar Oracle",
"Oracle username and/or password not valid" => "Nav derīga Oracle parole un/vai lietotājvārds",
"Offending command was: \"%s\", name: %s, password: %s" => "Vainīgā komanda bija \"%s\", vārds: %s, parole: %s",
"PostgreSQL username and/or password not valid" => "Nav derīga PostgreSQL parole un/vai lietotājvārds",
@@ -37,18 +38,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "Iestatiet administratora paroli.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Jūsu serveris vēl nav pareizi iestatīts, lai ļautu sinhronizēt datnes, jo izskatās, ka WebDAV saskarne ir salauzta.",
"Please double check the <a href='%s'>installation guides</a>." => "Lūdzu, vēlreiz pārbaudiet <a href='%s'>instalēšanas palīdzību</a>.",
+"Could not find category \"%s\"" => "Nevarēja atrast kategoriju “%s”",
"seconds ago" => "sekundes atpakaļ",
-"1 minute ago" => "pirms 1 minūtes",
-"%d minutes ago" => "pirms %d minūtēm",
-"1 hour ago" => "pirms 1 stundas",
-"%d hours ago" => "pirms %d stundām",
+"_%n minute ago_::_%n minutes ago_" => array("","","Pirms %n minūtēm"),
+"_%n hour ago_::_%n hours ago_" => array("","","Pirms %n stundām"),
"today" => "šodien",
"yesterday" => "vakar",
-"%d days ago" => "pirms %d dienām",
+"_%n day go_::_%n days ago_" => array("","","Pirms %n dienām"),
"last month" => "pagājušajā mēnesī",
-"%d months ago" => "pirms %d mēnešiem",
+"_%n month ago_::_%n months ago_" => array("","","Pirms %n mēnešiem"),
"last year" => "gājušajā gadā",
"years ago" => "gadus atpakaļ",
-"Could not find category \"%s\"" => "Nevarēja atrast kategoriju “%s”"
+"Caused by:" => "Cēlonis:"
);
$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 eeece35ea6d..deaf1bc8d05 100644
--- a/lib/l10n/mk.php
+++ b/lib/l10n/mk.php
@@ -4,8 +4,9 @@ $TRANSLATIONS = array(
"Personal" => "Лично",
"Settings" => "Подесувања",
"Users" => "Корисници",
-"Apps" => "Аппликации",
"Admin" => "Админ",
+"Unknown filetype" => "Непознат тип на датотека",
+"Invalid image" => "Невалидна фотографија",
"web services under your control" => "веб сервиси под Ваша контрола",
"ZIP download is turned off." => "Преземање во ZIP е исклучено",
"Files need to be downloaded one by one." => "Датотеките треба да се симнат една по една.",
@@ -17,18 +18,16 @@ $TRANSLATIONS = array(
"Files" => "Датотеки",
"Text" => "Текст",
"Images" => "Слики",
+"Could not find category \"%s\"" => "Не можам да најдам категорија „%s“",
"seconds ago" => "пред секунди",
-"1 minute ago" => "пред 1 минута",
-"%d minutes ago" => "пред %d минути",
-"1 hour ago" => "пред 1 час",
-"%d hours ago" => "пред %d часови",
+"_%n minute ago_::_%n minutes ago_" => array("",""),
+"_%n hour ago_::_%n hours ago_" => array("",""),
"today" => "денеска",
"yesterday" => "вчера",
-"%d days ago" => "пред %d денови",
+"_%n day go_::_%n days ago_" => array("",""),
"last month" => "минатиот месец",
-"%d months ago" => "пред %d месеци",
+"_%n month ago_::_%n months ago_" => array("",""),
"last year" => "минатата година",
-"years ago" => "пред години",
-"Could not find category \"%s\"" => "Не можам да најдам категорија „%s“"
+"years ago" => "пред години"
);
$PLURAL_FORMS = "nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;";
diff --git a/lib/l10n/ml_IN.php b/lib/l10n/ml_IN.php
new file mode 100644
index 00000000000..15f78e0bce6
--- /dev/null
+++ b/lib/l10n/ml_IN.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/ms_MY.php b/lib/l10n/ms_MY.php
index 5de0eb95991..17ef07f83dd 100644
--- a/lib/l10n/ms_MY.php
+++ b/lib/l10n/ms_MY.php
@@ -4,11 +4,14 @@ $TRANSLATIONS = array(
"Personal" => "Peribadi",
"Settings" => "Tetapan",
"Users" => "Pengguna",
-"Apps" => "Aplikasi",
"Admin" => "Admin",
"web services under your control" => "Perkhidmatan web di bawah kawalan anda",
"Authentication error" => "Ralat pengesahan",
"Files" => "Fail-fail",
-"Text" => "Teks"
+"Text" => "Teks",
+"_%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;";
diff --git a/lib/l10n/my_MM.php b/lib/l10n/my_MM.php
index 731aa33d576..7fdf0d0285d 100644
--- a/lib/l10n/my_MM.php
+++ b/lib/l10n/my_MM.php
@@ -2,30 +2,26 @@
$TRANSLATIONS = array(
"Help" => "အကူအညီ",
"Users" => "သုံးစွဲသူ",
-"Apps" => "Apps",
"Admin" => "အက်ဒမင်",
"web services under your control" => "သင်၏ထိန်းချုပ်မှု့အောက်တွင်ရှိသော Web services",
"ZIP download is turned off." => "ZIP ဒေါင်းလုတ်ကိုပိတ်ထားသည်",
"Files need to be downloaded one by one." => "ဖိုင်များသည် တစ်ခုပြီး တစ်ခုဒေါင်းလုတ်ချရန်လိုအပ်သည်",
"Back to Files" => "ဖိုင်သို့ပြန်သွားမည်",
"Selected files too large to generate zip file." => "zip ဖိုင်အဖြစ်ပြုလုပ်ရန် ရွေးချယ်ထားသောဖိုင်များသည် အရမ်းကြီးလွန်းသည်",
-"couldn't be determined" => "မဆုံးဖြတ်နိုင်ပါ။",
"Authentication error" => "ခွင့်ပြုချက်မအောင်မြင်",
"Files" => "ဖိုင်များ",
"Text" => "စာသား",
"Images" => "ပုံရိပ်များ",
+"Could not find category \"%s\"" => "\"%s\"ခေါင်းစဉ်ကို ရှာမတွေ့ပါ",
"seconds ago" => "စက္ကန့်အနည်းငယ်က",
-"1 minute ago" => "၁ မိနစ်အရင်က",
-"%d minutes ago" => "%d မိနစ်အရင်က",
-"1 hour ago" => "၁ နာရီ အရင်က",
-"%d hours ago" => "%d နာရီအရင်က",
+"_%n minute ago_::_%n minutes ago_" => array(""),
+"_%n hour ago_::_%n hours ago_" => array(""),
"today" => "ယနေ့",
"yesterday" => "မနေ့က",
-"%d days ago" => "%d ရက် အရင်က",
+"_%n day go_::_%n days ago_" => array(""),
"last month" => "ပြီးခဲ့သောလ",
-"%d months ago" => "%d လအရင်က",
+"_%n month ago_::_%n months ago_" => array(""),
"last year" => "မနှစ်က",
-"years ago" => "နှစ် အရင်က",
-"Could not find category \"%s\"" => "\"%s\"ခေါင်းစဉ်ကို ရှာမတွေ့ပါ"
+"years ago" => "နှစ် အရင်က"
);
$PLURAL_FORMS = "nplurals=1; plural=0;";
diff --git a/lib/l10n/nb_NO.php b/lib/l10n/nb_NO.php
index 42a43bfd98f..eb5e8d766fd 100644
--- a/lib/l10n/nb_NO.php
+++ b/lib/l10n/nb_NO.php
@@ -4,7 +4,6 @@ $TRANSLATIONS = array(
"Personal" => "Personlig",
"Settings" => "Innstillinger",
"Users" => "Brukere",
-"Apps" => "Apper",
"Admin" => "Admin",
"web services under your control" => "web tjenester du kontrollerer",
"ZIP download is turned off." => "ZIP-nedlasting av avslått",
@@ -19,18 +18,16 @@ $TRANSLATIONS = array(
"Images" => "Bilder",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Din nettservev er ikke konfigurert korrekt for filsynkronisering. WebDAV ser ut til å ikke funkere.",
"Please double check the <a href='%s'>installation guides</a>." => "Vennligst dobbelsjekk <a href='%s'>installasjonsguiden</a>.",
+"Could not find category \"%s\"" => "Kunne ikke finne kategori \"%s\"",
"seconds ago" => "sekunder siden",
-"1 minute ago" => "1 minutt siden",
-"%d minutes ago" => "%d minutter siden",
-"1 hour ago" => "1 time siden",
-"%d hours ago" => "%d timer siden",
+"_%n minute ago_::_%n minutes ago_" => array("",""),
+"_%n hour ago_::_%n hours ago_" => array("",""),
"today" => "i dag",
"yesterday" => "i går",
-"%d days ago" => "%d dager siden",
+"_%n day go_::_%n days ago_" => array("",""),
"last month" => "forrige måned",
-"%d months ago" => "%d måneder siden",
+"_%n month ago_::_%n months ago_" => array("",""),
"last year" => "forrige år",
-"years ago" => "år siden",
-"Could not find category \"%s\"" => "Kunne ikke finne kategori \"%s\""
+"years ago" => "år siden"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/nds.php b/lib/l10n/nds.php
new file mode 100644
index 00000000000..15f78e0bce6
--- /dev/null
+++ b/lib/l10n/nds.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/ne.php b/lib/l10n/ne.php
new file mode 100644
index 00000000000..15f78e0bce6
--- /dev/null
+++ b/lib/l10n/ne.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/nl.php b/lib/l10n/nl.php
index 8983aa81bfd..0254ce81886 100644
--- a/lib/l10n/nl.php
+++ b/lib/l10n/nl.php
@@ -1,20 +1,34 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "App \"%s\" kan niet worden geïnstalleerd omdat die niet compatible is met deze versie van ownCloud.",
+"No app name specified" => "De app naam is niet gespecificeerd.",
"Help" => "Help",
"Personal" => "Persoonlijk",
"Settings" => "Instellingen",
"Users" => "Gebruikers",
-"Apps" => "Apps",
"Admin" => "Beheerder",
"Failed to upgrade \"%s\"." => "Upgrade \"%s\" mislukt.",
+"Unknown filetype" => "Onbekend bestandsformaat",
+"Invalid image" => "Ongeldige afbeelding",
"web services under your control" => "Webdiensten in eigen beheer",
"cannot open \"%s\"" => "Kon \"%s\" niet openen",
"ZIP download is turned off." => "ZIP download is uitgeschakeld.",
"Files need to be downloaded one by one." => "Bestanden moeten één voor één worden gedownload.",
"Back to Files" => "Terug naar bestanden",
"Selected files too large to generate zip file." => "De geselecteerde bestanden zijn te groot om een zip bestand te maken.",
-"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Download de bestanden in kleinere brokken, appart of vraag uw administrator.",
-"couldn't be determined" => "kon niet worden vastgesteld",
+"Please download the files separately in smaller chunks or kindly ask your administrator." => "Download de bestanden afzonderlijk in kleinere porties of vraag het uw beheerder,",
+"No source specified when installing app" => "Geen bron opgegeven bij installatie van de app",
+"No href specified when installing app from http" => "Geen href opgegeven bij installeren van de app vanaf http",
+"No path specified when installing app from local file" => "Geen pad opgegeven bij installeren van de app vanaf een lokaal bestand",
+"Archives of type %s are not supported" => "Archiefbestanden van type %s niet ondersteund",
+"Failed to open archive when installing app" => "Kon archiefbestand bij installatie van de app niet openen",
+"App does not provide an info.xml file" => "De app heeft geen info.xml bestand",
+"App can't be installed because of not allowed code in the App" => "De app kan niet worden geïnstalleerd wegens onjuiste code in de app",
+"App can't be installed because it is not compatible with this version of ownCloud" => "De app kan niet worden geïnstalleerd omdat die niet compatible is met deze versie van ownCloud",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "De app kan niet worden geïnstallerd omdat het de <shipped>true</shipped> tag bevat die niet is toegestaan voor niet gepubliceerde apps",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "De app kan niet worden geïnstalleerd omdat de versie in info.xml/version niet dezelfde is als de versie zoals die in de app store staat vermeld",
+"App directory already exists" => "App directory bestaat al",
+"Can't create app folder. Please fix permissions. %s" => "Kan de app map niet aanmaken, Herstel de permissies. %s",
"Application is not enabled" => "De applicatie is niet actief",
"Authentication error" => "Authenticatie fout",
"Token expired. Please reload page." => "Token verlopen. Herlaad de pagina.",
@@ -41,19 +55,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "Stel een beheerderswachtwoord in.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Uw webserver is nog niet goed ingesteld voor bestandssynchronisatie omdat de WebDAV interface verbroken lijkt.",
"Please double check the <a href='%s'>installation guides</a>." => "Controleer de <a href='%s'>installatiehandleiding</a> goed.",
+"Could not find category \"%s\"" => "Kon categorie \"%s\" niet vinden",
"seconds ago" => "seconden geleden",
-"1 minute ago" => "1 minuut geleden",
-"%d minutes ago" => "%d minuten geleden",
-"1 hour ago" => "1 uur geleden",
-"%d hours ago" => "%d uren geleden",
+"_%n minute ago_::_%n minutes ago_" => array("%n minuut geleden","%n minuten geleden"),
+"_%n hour ago_::_%n hours ago_" => array("%n uur geleden","%n uur geleden"),
"today" => "vandaag",
"yesterday" => "gisteren",
-"%d days ago" => "%d dagen geleden",
+"_%n day go_::_%n days ago_" => array("%n dag terug","%n dagen geleden"),
"last month" => "vorige maand",
-"%d months ago" => "%d maanden geleden",
+"_%n month ago_::_%n months ago_" => array("%n maand geleden","%n maanden geleden"),
"last year" => "vorig jaar",
"years ago" => "jaar geleden",
-"Caused by:" => "Gekomen door:",
-"Could not find category \"%s\"" => "Kon categorie \"%s\" niet vinden"
+"Caused by:" => "Gekomen door:"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/nn_NO.php b/lib/l10n/nn_NO.php
index 3cbd0159bc2..e8bf8dfdef4 100644
--- a/lib/l10n/nn_NO.php
+++ b/lib/l10n/nn_NO.php
@@ -4,20 +4,23 @@ $TRANSLATIONS = array(
"Personal" => "Personleg",
"Settings" => "Innstillingar",
"Users" => "Brukarar",
-"Apps" => "Program",
"Admin" => "Administrer",
+"Unknown filetype" => "Ukjend filtype",
+"Invalid image" => "Ugyldig bilete",
"web services under your control" => "Vev tjenester under din kontroll",
"Authentication error" => "Feil i autentisering",
"Files" => "Filer",
"Text" => "Tekst",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Tenaren din er ikkje enno rett innstilt til å tilby filsynkronisering sidan WebDAV-grensesnittet ser ut til å vera øydelagt.",
-"Please double check the <a href='%s'>installation guides</a>." => "Ver vennleg og dobbeltsjekk <a href='%s'>installasjonsrettleiinga</a>.",
+"Please double check the <a href='%s'>installation guides</a>." => "Ver venleg og dobbeltsjekk <a href='%s'>installasjonsrettleiinga</a>.",
"seconds ago" => "sekund sidan",
-"1 minute ago" => "1 minutt sidan",
-"1 hour ago" => "1 time sidan",
+"_%n minute ago_::_%n minutes ago_" => array("","%n minutt sidan"),
+"_%n hour ago_::_%n hours ago_" => array("","%n timar sidan"),
"today" => "i dag",
"yesterday" => "i går",
+"_%n day go_::_%n days ago_" => array("","%n dagar sidan"),
"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"
);
diff --git a/lib/l10n/nqo.php b/lib/l10n/nqo.php
new file mode 100644
index 00000000000..e7b09649a24
--- /dev/null
+++ b/lib/l10n/nqo.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=1; plural=0;";
diff --git a/lib/l10n/oc.php b/lib/l10n/oc.php
index 6f0645bf77a..40a527cc76c 100644
--- a/lib/l10n/oc.php
+++ b/lib/l10n/oc.php
@@ -4,7 +4,6 @@ $TRANSLATIONS = array(
"Personal" => "Personal",
"Settings" => "Configuracion",
"Users" => "Usancièrs",
-"Apps" => "Apps",
"Admin" => "Admin",
"web services under your control" => "Services web jos ton contraròtle",
"ZIP download is turned off." => "Avalcargar los ZIP es inactiu.",
@@ -13,12 +12,13 @@ $TRANSLATIONS = array(
"Authentication error" => "Error d'autentificacion",
"Files" => "Fichièrs",
"seconds ago" => "segonda a",
-"1 minute ago" => "1 minuta a",
-"%d minutes ago" => "%d minutas a",
+"_%n minute ago_::_%n minutes ago_" => array("",""),
+"_%n hour ago_::_%n hours ago_" => array("",""),
"today" => "uèi",
"yesterday" => "ièr",
-"%d days ago" => "%d jorns a",
+"_%n day go_::_%n days ago_" => array("",""),
"last month" => "mes passat",
+"_%n month ago_::_%n months ago_" => array("",""),
"last year" => "an passat",
"years ago" => "ans a"
);
diff --git a/lib/l10n/pa.php b/lib/l10n/pa.php
new file mode 100644
index 00000000000..069fea6e710
--- /dev/null
+++ b/lib/l10n/pa.php
@@ -0,0 +1,16 @@
+<?php
+$TRANSLATIONS = array(
+"Settings" => "ਸੈਟਿੰਗ",
+"Files" => "ਫਾਇਲਾਂ",
+"seconds ago" => "ਸਕਿੰਟ ਪਹਿਲਾਂ",
+"_%n minute ago_::_%n minutes ago_" => array("",""),
+"_%n hour ago_::_%n hours ago_" => array("",""),
+"today" => "ਅੱਜ",
+"yesterday" => "ਕੱਲ੍ਹ",
+"_%n day go_::_%n days ago_" => array("",""),
+"last month" => "ਪਿਛਲੇ ਮਹੀਨੇ",
+"_%n month ago_::_%n months ago_" => array("",""),
+"last year" => "ਪਿਛਲੇ ਸਾਲ",
+"years ago" => "ਸਾਲਾਂ ਪਹਿਲਾਂ"
+);
+$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/pl.php b/lib/l10n/pl.php
index bd24614751a..e520509920a 100644
--- a/lib/l10n/pl.php
+++ b/lib/l10n/pl.php
@@ -1,20 +1,34 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "Aplikacja \"%s\" nie może zostać zainstalowana, ponieważ nie jest zgodna z tą wersją ownCloud.",
+"No app name specified" => "Nie określono nazwy aplikacji",
"Help" => "Pomoc",
"Personal" => "Osobiste",
"Settings" => "Ustawienia",
"Users" => "Użytkownicy",
-"Apps" => "Aplikacje",
"Admin" => "Administrator",
"Failed to upgrade \"%s\"." => "Błąd przy aktualizacji \"%s\".",
+"Unknown filetype" => "Nieznany typ pliku",
+"Invalid image" => "Błędne zdjęcie",
"web services under your control" => "Kontrolowane serwisy",
"cannot open \"%s\"" => "Nie można otworzyć \"%s\"",
"ZIP download is turned off." => "Pobieranie ZIP jest wyłączone.",
"Files need to be downloaded one by one." => "Pliki muszą zostać pobrane pojedynczo.",
"Back to Files" => "Wróć do plików",
"Selected files too large to generate zip file." => "Wybrane pliki są zbyt duże, aby wygenerować plik zip.",
-"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Pobierz pliki w mniejszy kawałkach, oddzielnie lub poproś administratora o zwiększenie limitu.",
-"couldn't be determined" => "nie może zostać znaleziony",
+"Please download the files separately in smaller chunks or kindly ask your administrator." => "Proszę ściągać pliki osobno w mniejszych paczkach lub poprosić administratora.",
+"No source specified when installing app" => "Nie określono źródła podczas instalacji aplikacji",
+"No href specified when installing app from http" => "Nie określono linku skąd aplikacja ma być zainstalowana",
+"No path specified when installing app from local file" => "Nie określono lokalnego pliku z którego miała być instalowana aplikacja",
+"Archives of type %s are not supported" => "Typ archiwum %s nie jest obsługiwany",
+"Failed to open archive when installing app" => "Nie udało się otworzyć archiwum podczas instalacji aplikacji",
+"App does not provide an info.xml file" => "Aplikacja nie posiada pliku info.xml",
+"App can't be installed because of not allowed code in the App" => "Aplikacja nie może być zainstalowany ponieważ nie dopuszcza kod w aplikacji",
+"App can't be installed because it is not compatible with this version of ownCloud" => "Aplikacja nie może zostać zainstalowana ponieważ jest niekompatybilna z tą wersja ownCloud",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Aplikacja nie może być zainstalowana ponieważ true tag nie jest <shipped>true</shipped> , co nie jest dozwolone dla aplikacji nie wysłanych",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Nie można zainstalować aplikacji, ponieważ w wersji info.xml/version nie jest taka sama, jak wersja z app store",
+"App directory already exists" => "Katalog aplikacji już isnieje",
+"Can't create app folder. Please fix permissions. %s" => "Nie mogę utworzyć katalogu aplikacji. Proszę popraw uprawnienia. %s",
"Application is not enabled" => "Aplikacja nie jest włączona",
"Authentication error" => "Błąd uwierzytelniania",
"Token expired. Please reload page." => "Token wygasł. Proszę ponownie załadować stronę.",
@@ -41,19 +55,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "Ustaw hasło administratora.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Serwer internetowy nie jest jeszcze poprawnie skonfigurowany, aby umożliwić synchronizację plików, ponieważ interfejs WebDAV wydaje się być uszkodzony.",
"Please double check the <a href='%s'>installation guides</a>." => "Sprawdź ponownie <a href='%s'>przewodniki instalacji</a>.",
+"Could not find category \"%s\"" => "Nie można odnaleźć kategorii \"%s\"",
"seconds ago" => "sekund temu",
-"1 minute ago" => "1 minutę temu",
-"%d minutes ago" => "%d minut temu",
-"1 hour ago" => "1 godzinę temu",
-"%d hours ago" => "%d godzin temu",
+"_%n minute ago_::_%n minutes ago_" => array("%n minute temu","%n minut temu","%n minut temu"),
+"_%n hour ago_::_%n hours ago_" => array("%n godzinę temu","%n godzin temu","%n godzin temu"),
"today" => "dziś",
"yesterday" => "wczoraj",
-"%d days ago" => "%d dni temu",
+"_%n day go_::_%n days ago_" => array("%n dzień temu","%n dni temu","%n dni temu"),
"last month" => "w zeszłym miesiącu",
-"%d months ago" => "%d miesiecy temu",
+"_%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",
-"Caused by:" => "Spowodowane przez:",
-"Could not find category \"%s\"" => "Nie można odnaleźć kategorii \"%s\""
+"Caused by:" => "Spowodowane przez:"
);
$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 cae6107b9e8..d6912f07110 100644
--- a/lib/l10n/pt_BR.php
+++ b/lib/l10n/pt_BR.php
@@ -1,20 +1,34 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "O aplicativo \"%s\" não pode ser instalado porque não é compatível com esta versão do ownCloud.",
+"No app name specified" => "O nome do aplicativo não foi especificado.",
"Help" => "Ajuda",
"Personal" => "Pessoal",
"Settings" => "Ajustes",
"Users" => "Usuários",
-"Apps" => "Aplicações",
"Admin" => "Admin",
"Failed to upgrade \"%s\"." => "Falha na atualização de \"%s\".",
+"Unknown filetype" => "Tipo de arquivo desconhecido",
+"Invalid image" => "Imagem inválida",
"web services under your control" => "serviços web sob seu controle",
"cannot open \"%s\"" => "não pode abrir \"%s\"",
"ZIP download is turned off." => "Download ZIP está desligado.",
"Files need to be downloaded one by one." => "Arquivos precisam ser baixados um de cada vez.",
"Back to Files" => "Voltar para Arquivos",
"Selected files too large to generate zip file." => "Arquivos selecionados são muito grandes para gerar arquivo zip.",
-"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Baixe os arquivos em pedaços menores, separadamente ou solicite educadamente ao seu administrador.",
-"couldn't be determined" => "não pôde ser determinado",
+"Please download the files separately in smaller chunks or kindly ask your administrator." => "Por favor baixe os arquivos separadamente em pedaços ou educadamente pergunte ao seu administrador.",
+"No source specified when installing app" => "Nenhuma fonte foi especificada enquanto instalava o aplicativo",
+"No href specified when installing app from http" => "Nenhuma href foi especificada enquanto instalava o aplicativo de httml",
+"No path specified when installing app from local file" => "Nenhum caminho foi especificado enquanto instalava o aplicativo do arquivo local",
+"Archives of type %s are not supported" => "Arquivos do tipo %s não são suportados",
+"Failed to open archive when installing app" => "Falha para abrir o arquivo enquanto instalava o aplicativo",
+"App does not provide an info.xml file" => "O aplicativo não fornece um arquivo info.xml",
+"App can't be installed because of not allowed code in the App" => "O aplicativo não pode ser instalado por causa do código não permitido no Aplivativo",
+"App can't be installed because it is not compatible with this version of ownCloud" => "O aplicativo não pode ser instalado porque não é compatível com esta versão do ownCloud",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "O aplicativo não pode ser instalado porque ele contém a marca <shipped>verdadeiro</shipped> que não é permitido para aplicações não embarcadas",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "O aplicativo não pode ser instalado porque a versão em info.xml /versão não é a mesma que a versão relatada na App Store",
+"App directory already exists" => "Diretório App já existe",
+"Can't create app folder. Please fix permissions. %s" => "Não é possível criar pasta app. Corrija as permissões. %s",
"Application is not enabled" => "Aplicação não está habilitada",
"Authentication error" => "Erro de autenticação",
"Token expired. Please reload page." => "Token expirou. Por favor recarregue a página.",
@@ -41,19 +55,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "Defina uma senha de administrador.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Seu servidor web não está configurado corretamente para permitir sincronização de arquivos porque a interface WebDAV parece estar quebrada.",
"Please double check the <a href='%s'>installation guides</a>." => "Por favor, confira os <a href='%s'>guias de instalação</a>.",
+"Could not find category \"%s\"" => "Impossível localizar categoria \"%s\"",
"seconds ago" => "segundos atrás",
-"1 minute ago" => "1 minuto atrás",
-"%d minutes ago" => "%d minutos atrás",
-"1 hour ago" => "1 hora atrás",
-"%d hours ago" => "%d horas atrás",
+"_%n minute ago_::_%n minutes ago_" => array("","ha %n minutos"),
+"_%n hour ago_::_%n hours ago_" => array("","ha %n horas"),
"today" => "hoje",
"yesterday" => "ontem",
-"%d days ago" => "%d dias atrás",
+"_%n day go_::_%n days ago_" => array("","ha %n dias"),
"last month" => "último mês",
-"%d months ago" => "%d meses atrás",
+"_%n month ago_::_%n months ago_" => array("","ha %n meses"),
"last year" => "último ano",
"years ago" => "anos atrás",
-"Caused by:" => "Causados ​​por:",
-"Could not find category \"%s\"" => "Impossível localizar categoria \"%s\""
+"Caused by:" => "Causados ​​por:"
);
$PLURAL_FORMS = "nplurals=2; plural=(n > 1);";
diff --git a/lib/l10n/pt_PT.php b/lib/l10n/pt_PT.php
index cb8bc99096c..55845cf2ae9 100644
--- a/lib/l10n/pt_PT.php
+++ b/lib/l10n/pt_PT.php
@@ -1,20 +1,34 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "A aplicação \"%s\" não pode ser instaladas por não ser compatível com esta versão da ownCloud.",
+"No app name specified" => "O nome da aplicação não foi especificado",
"Help" => "Ajuda",
"Personal" => "Pessoal",
"Settings" => "Configurações",
"Users" => "Utilizadores",
-"Apps" => "Aplicações",
"Admin" => "Admin",
"Failed to upgrade \"%s\"." => "A actualização \"%s\" falhou.",
+"Unknown filetype" => "Ficheiro desconhecido",
+"Invalid image" => "Imagem inválida",
"web services under your control" => "serviços web sob o seu controlo",
"cannot open \"%s\"" => "Não foi possível abrir \"%s\"",
"ZIP download is turned off." => "Descarregamento em ZIP está desligado.",
"Files need to be downloaded one by one." => "Os ficheiros precisam de ser descarregados um por um.",
"Back to Files" => "Voltar a Ficheiros",
"Selected files too large to generate zip file." => "Os ficheiros seleccionados são grandes demais para gerar um ficheiro zip.",
-"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Descarregue os ficheiros em partes menores, separados ou peça gentilmente ao seu administrador.",
-"couldn't be determined" => "Não foi possível determinar",
+"Please download the files separately in smaller chunks or kindly ask your administrator." => "Por favor descarregue os ficheiros divididos em partes mais pequenas ou peça ajuda ao seu administrador.",
+"No source specified when installing app" => "Não foi especificada uma fonte de instalação desta aplicação",
+"No href specified when installing app from http" => "Não foi especificada uma href http para instalar esta aplicação",
+"No path specified when installing app from local file" => "Não foi especificado o caminho de instalação desta aplicação",
+"Archives of type %s are not supported" => "Arquivos do tipo %s não são suportados",
+"Failed to open archive when installing app" => "Ocorreu um erro ao abrir o ficheiro de instalação desta aplicação",
+"App does not provide an info.xml file" => "A aplicação não disponibiliza um ficheiro info.xml",
+"App can't be installed because of not allowed code in the App" => "A aplicação não pode ser instalado devido a código não permitido dentro da aplicação",
+"App can't be installed because it is not compatible with this version of ownCloud" => "A aplicação não pode ser instalada por não ser compatível com esta versão do ownCloud",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Esta aplicação não pode ser instalada por que contém o tag <shipped>true</shipped> que só é permitido para aplicações nativas",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Esta aplicação não pode ser instalada porque a versão no info.xml/version não coincide com a reportada na loja de aplicações",
+"App directory already exists" => "A directoria da aplicação já existe",
+"Can't create app folder. Please fix permissions. %s" => "Não foi possível criar a pasta da aplicação. Por favor verifique as permissões. %s",
"Application is not enabled" => "A aplicação não está activada",
"Authentication error" => "Erro na autenticação",
"Token expired. Please reload page." => "O token expirou. Por favor recarregue a página.",
@@ -41,19 +55,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "Definiar uma password de administrador",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "O seu servidor web não está configurado correctamente para autorizar sincronização de ficheiros, pois o interface WebDAV parece estar com problemas.",
"Please double check the <a href='%s'>installation guides</a>." => "Por favor verifique <a href='%s'>installation guides</a>.",
+"Could not find category \"%s\"" => "Não foi encontrado a categoria \"%s\"",
"seconds ago" => "Minutos atrás",
-"1 minute ago" => "Há 1 minuto",
-"%d minutes ago" => "há %d minutos",
-"1 hour ago" => "Há 1 horas",
-"%d hours ago" => "Há %d horas",
+"_%n minute ago_::_%n minutes ago_" => array("","%n minutos atrás"),
+"_%n hour ago_::_%n hours ago_" => array("","%n horas atrás"),
"today" => "hoje",
"yesterday" => "ontem",
-"%d days ago" => "há %d dias",
+"_%n day go_::_%n days ago_" => array("","%n dias atrás"),
"last month" => "ultímo mês",
-"%d months ago" => "Há %d meses atrás",
+"_%n month ago_::_%n months ago_" => array("","%n meses atrás"),
"last year" => "ano passado",
"years ago" => "anos atrás",
-"Caused by:" => "Causado por:",
-"Could not find category \"%s\"" => "Não foi encontrado a categoria \"%s\""
+"Caused by:" => "Causado por:"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/ro.php b/lib/l10n/ro.php
index 006e97ed865..94ff7a4326a 100644
--- a/lib/l10n/ro.php
+++ b/lib/l10n/ro.php
@@ -4,14 +4,14 @@ $TRANSLATIONS = array(
"Personal" => "Personal",
"Settings" => "Setări",
"Users" => "Utilizatori",
-"Apps" => "Aplicații",
"Admin" => "Admin",
+"Unknown filetype" => "Tip fișier necunoscut",
+"Invalid image" => "Imagine invalidă",
"web services under your control" => "servicii web controlate de tine",
"ZIP download is turned off." => "Descărcarea ZIP este dezactivată.",
"Files need to be downloaded one by one." => "Fișierele trebuie descărcate unul câte unul.",
"Back to Files" => "Înapoi la fișiere",
"Selected files too large to generate zip file." => "Fișierele selectate sunt prea mari pentru a genera un fișier zip.",
-"couldn't be determined" => "nu poate fi determinat",
"Application is not enabled" => "Aplicația nu este activată",
"Authentication error" => "Eroare la autentificare",
"Token expired. Please reload page." => "Token expirat. Te rugăm să reîncarci pagina.",
@@ -19,19 +19,17 @@ $TRANSLATIONS = array(
"Text" => "Text",
"Images" => "Imagini",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Serverul de web nu este încă setat corespunzător pentru a permite sincronizarea fișierelor deoarece interfața WebDAV pare a fi întreruptă.",
-"Please double check the <a href='%s'>installation guides</a>." => "Vă rugăm să verificați <a href='%s'>ghiduri de instalare</ a>.",
+"Please double check the <a href='%s'>installation guides</a>." => "Vă rugăm să verificați <a href='%s'>ghiduri de instalare</a>.",
+"Could not find category \"%s\"" => "Cloud nu a gasit categoria \"%s\"",
"seconds ago" => "secunde în urmă",
-"1 minute ago" => "1 minut în urmă",
-"%d minutes ago" => "%d minute în urmă",
-"1 hour ago" => "Acum o ora",
-"%d hours ago" => "%d ore in urma",
+"_%n minute ago_::_%n minutes ago_" => array("","","acum %n minute"),
+"_%n hour ago_::_%n hours ago_" => array("","","acum %n ore"),
"today" => "astăzi",
"yesterday" => "ieri",
-"%d days ago" => "%d zile în urmă",
+"_%n day go_::_%n days ago_" => array("","","acum %n zile"),
"last month" => "ultima lună",
-"%d months ago" => "%d luni in urma",
+"_%n month ago_::_%n months ago_" => array("","",""),
"last year" => "ultimul an",
-"years ago" => "ani în urmă",
-"Could not find category \"%s\"" => "Cloud nu a gasit categoria \"%s\""
+"years ago" => "ani în urmă"
);
$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 544f9c9b809..baf80cbf24e 100644
--- a/lib/l10n/ru.php
+++ b/lib/l10n/ru.php
@@ -1,20 +1,34 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "Приложение \"%s\" нельзя установить, так как оно не совместимо с текущей версией ownCloud.",
+"No app name specified" => "Не выбрано имя приложения",
"Help" => "Помощь",
"Personal" => "Личное",
"Settings" => "Конфигурация",
"Users" => "Пользователи",
-"Apps" => "Приложения",
"Admin" => "Admin",
"Failed to upgrade \"%s\"." => "Не смог обновить \"%s\".",
+"Unknown filetype" => "Неизвестный тип файла",
+"Invalid image" => "Изображение повреждено",
"web services under your control" => "веб-сервисы под вашим управлением",
"cannot open \"%s\"" => "не могу открыть \"%s\"",
"ZIP download is turned off." => "ZIP-скачивание отключено.",
"Files need to be downloaded one by one." => "Файлы должны быть загружены по одному.",
"Back to Files" => "Назад к файлам",
"Selected files too large to generate zip file." => "Выбранные файлы слишком велики, чтобы создать zip файл.",
-"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Загрузите файл маленьшими порциями, раздельно или вежливо попросите Вашего администратора.",
-"couldn't be determined" => "Невозможно установить",
+"Please download the files separately in smaller chunks or kindly ask your administrator." => "Загрузите файлы раздельно маленькими частями или вежливо попросите вашего администратора.",
+"No source specified when installing app" => "Не указан источник при установке приложения",
+"No href specified when installing app from http" => "Не указан атрибут href при установке приложения через http",
+"No path specified when installing app from local file" => "Не указан путь при установке приложения из локального файла",
+"Archives of type %s are not supported" => "Архивы %s не поддерживаются",
+"Failed to open archive when installing app" => "Не возможно открыть архив при установке приложения",
+"App does not provide an info.xml file" => "Приложение не имеет файла info.xml",
+"App can't be installed because of not allowed code in the App" => "Приложение невозможно установить. В нем содержится запрещенный код.",
+"App can't be installed because it is not compatible with this version of ownCloud" => "Приложение невозможно установить. Не совместимо с текущей версией ownCloud.",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Приложение невозможно установить. Оно содержит параметр <shipped>true</shipped> который не допустим для приложений, не входящих в поставку.",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Приложение невозможно установить. Версия в info.xml/version не совпадает с версией заявленной в магазине приложений",
+"App directory already exists" => "Папка приложения уже существует",
+"Can't create app folder. Please fix permissions. %s" => "Не удалось создать директорию. Исправьте права доступа. %s",
"Application is not enabled" => "Приложение не разрешено",
"Authentication error" => "Ошибка аутентификации",
"Token expired. Please reload page." => "Токен просрочен. Перезагрузите страницу.",
@@ -41,19 +55,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "становит пароль для admin.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Ваш веб сервер до сих пор не настроен правильно для возможности синхронизации файлов, похоже что проблема в неисправности интерфейса WebDAV.",
"Please double check the <a href='%s'>installation guides</a>." => "Пожалуйста, дважды просмотрите <a href='%s'>инструкции по установке</a>.",
+"Could not find category \"%s\"" => "Категория \"%s\" не найдена",
"seconds ago" => "несколько секунд назад",
-"1 minute ago" => "1 минуту назад",
-"%d minutes ago" => "%d минут назад",
-"1 hour ago" => "час назад",
-"%d hours ago" => "%d часов назад",
+"_%n minute ago_::_%n minutes ago_" => array("%n минута назад","%n минуты назад","%n минут назад"),
+"_%n hour ago_::_%n hours ago_" => array("%n час назад","%n часа назад","%n часов назад"),
"today" => "сегодня",
"yesterday" => "вчера",
-"%d days ago" => "%d дней назад",
+"_%n day go_::_%n days ago_" => array("%n день назад","%n дня назад","%n дней назад"),
"last month" => "в прошлом месяце",
-"%d months ago" => "%d месяцев назад",
+"_%n month ago_::_%n months ago_" => array("%n месяц назад","%n месяца назад","%n месяцев назад"),
"last year" => "в прошлом году",
"years ago" => "несколько лет назад",
-"Caused by:" => "Вызвано:",
-"Could not find category \"%s\"" => "Категория \"%s\" не найдена"
+"Caused by:" => "Вызвано:"
);
$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/ru_RU.php b/lib/l10n/ru_RU.php
index 1761c1ebf3b..23e900721e8 100644
--- a/lib/l10n/ru_RU.php
+++ b/lib/l10n/ru_RU.php
@@ -1,6 +1,12 @@
<?php
$TRANSLATIONS = array(
+"Help" => "Помощь",
"Settings" => "Настройки",
-"Text" => "Текст"
+"Files" => "Файлы",
+"Text" => "Текст",
+"_%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=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/si_LK.php b/lib/l10n/si_LK.php
index 36e7b19ba97..d10804cae69 100644
--- a/lib/l10n/si_LK.php
+++ b/lib/l10n/si_LK.php
@@ -4,7 +4,6 @@ $TRANSLATIONS = array(
"Personal" => "පෞද්ගලික",
"Settings" => "සිටුවම්",
"Users" => "පරිශීලකයන්",
-"Apps" => "යෙදුම්",
"Admin" => "පරිපාලක",
"web services under your control" => "ඔබට පාලනය කළ හැකි වෙබ් සේවාවන්",
"ZIP download is turned off." => "ZIP භාගත කිරීම් අක්‍රියයි",
@@ -18,12 +17,13 @@ $TRANSLATIONS = array(
"Text" => "පෙළ",
"Images" => "අනු රූ",
"seconds ago" => "තත්පරයන්ට පෙර",
-"1 minute ago" => "1 මිනිත්තුවකට පෙර",
-"%d minutes ago" => "%d මිනිත්තුවන්ට පෙර",
+"_%n minute ago_::_%n minutes ago_" => array("",""),
+"_%n hour ago_::_%n hours ago_" => array("",""),
"today" => "අද",
"yesterday" => "ඊයේ",
-"%d days ago" => "%d දිනකට පෙර",
+"_%n day go_::_%n days ago_" => array("",""),
"last month" => "පෙර මාසයේ",
+"_%n month ago_::_%n months ago_" => array("",""),
"last year" => "පෙර අවුරුද්දේ",
"years ago" => "අවුරුදු කීපයකට පෙර"
);
diff --git a/lib/l10n/sk.php b/lib/l10n/sk.php
new file mode 100644
index 00000000000..54812b15a6f
--- /dev/null
+++ b/lib/l10n/sk.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=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;";
diff --git a/lib/l10n/sk_SK.php b/lib/l10n/sk_SK.php
index 93699439ee2..18b455780d1 100644
--- a/lib/l10n/sk_SK.php
+++ b/lib/l10n/sk_SK.php
@@ -1,27 +1,41 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "Aplikácia \"%s\" nemôže byť nainštalovaná kvôli nekompatibilite z touto verziou ownCloudu.",
+"No app name specified" => "Nešpecifikované meno aplikácie",
"Help" => "Pomoc",
"Personal" => "Osobné",
"Settings" => "Nastavenia",
"Users" => "Používatelia",
-"Apps" => "Aplikácie",
"Admin" => "Administrátor",
"Failed to upgrade \"%s\"." => "Zlyhala aktualizácia \"%s\".",
+"Unknown filetype" => "Neznámy typ súboru",
+"Invalid image" => "Chybný obrázok",
"web services under your control" => "webové služby pod Vašou kontrolou",
"cannot open \"%s\"" => "nemožno otvoriť \"%s\"",
"ZIP download is turned off." => "Sťahovanie súborov ZIP je vypnuté.",
"Files need to be downloaded one by one." => "Súbory musia byť nahrávané jeden za druhým.",
"Back to Files" => "Späť na súbory",
"Selected files too large to generate zip file." => "Zvolené súbory sú príliš veľké na vygenerovanie zip súboru.",
-"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Stiahnite súbory po menších častiach, samostatne, alebo sa obráťte na správcu.",
-"couldn't be determined" => "nedá sa zistiť",
+"Please download the files separately in smaller chunks or kindly ask your administrator." => "Prosím, stiahnite si súbory samostatne v menších blokoch alebo sa obráťte na správcu.",
+"No source specified when installing app" => "Nešpecifikovaný zdroj pri inštalácii aplikácie",
+"No href specified when installing app from http" => "Nešpecifikovaný atribút \"href\" pri inštalácii aplikácie pomocou protokolu \"http\"",
+"No path specified when installing app from local file" => "Nešpecifikovaná cesta pri inštalácii aplikácie z lokálneho súboru",
+"Archives of type %s are not supported" => "Tento typ archívu %s nie je podporovaný",
+"Failed to open archive when installing app" => "Zlyhanie pri otváraní archívu počas inštalácie aplikácie",
+"App does not provide an info.xml file" => "Aplikácia neposkytuje súbor info.xml",
+"App can't be installed because of not allowed code in the App" => "Aplikácia nemôže byť nainštalovaná pre nepovolený kód v aplikácii",
+"App can't be installed because it is not compatible with this version of ownCloud" => "Aplikácia nemôže byť nainštalovaná pre nekompatibilitu z touto verziou ownCloudu",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Aplikácia nemôže byť nainštalovaná pretože obsahuje <shipped>pravý</shipped> štítok, ktorý nie je povolený pre zaslané \"shipped\" aplikácie",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Aplikácia nemôže byť nainštalovaná pretože verzia v info.xml/version nezodpovedá verzii špecifikovanej v obchode s aplikáciami",
+"App directory already exists" => "Aplikačný priečinok už existuje",
+"Can't create app folder. Please fix permissions. %s" => "Nemožno vytvoriť aplikačný priečinok. Prosím upravte povolenia. %s",
"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.",
"Files" => "Súbory",
"Text" => "Text",
"Images" => "Obrázky",
-"%s enter the database username." => "Zadajte používateľské meno %s databázy..",
+"%s enter the database username." => "Zadajte používateľské meno %s databázy.",
"%s enter the database name." => "Zadajte názov databázy pre %s databázy.",
"%s you may not use dots in the database name" => "V názve databázy %s nemôžete používať bodky",
"MS SQL username and/or password not valid: %s" => "Používateľské meno, alebo heslo MS SQL nie je platné: %s",
@@ -41,19 +55,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "Zadajte heslo administrátora.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Váš webový server nie je správne nastavený na synchronizáciu, pretože rozhranie WebDAV je poškodené.",
"Please double check the <a href='%s'>installation guides</a>." => "Prosím skontrolujte <a href='%s'>inštalačnú príručku</a>.",
+"Could not find category \"%s\"" => "Nemožno nájsť danú kategóriu \"%s\"",
"seconds ago" => "pred sekundami",
-"1 minute ago" => "pred minútou",
-"%d minutes ago" => "pred %d minútami",
-"1 hour ago" => "Pred 1 hodinou",
-"%d hours ago" => "Pred %d hodinami.",
+"_%n minute ago_::_%n minutes ago_" => array("pred %n minútou","pred %n minútami","pred %n minútami"),
+"_%n hour ago_::_%n hours ago_" => array("pred %n hodinou","pred %n hodinami","pred %n hodinami"),
"today" => "dnes",
"yesterday" => "včera",
-"%d days ago" => "pred %d dňami",
+"_%n day go_::_%n days ago_" => array("pred %n dňom","pred %n dňami","pred %n dňami"),
"last month" => "minulý mesiac",
-"%d months ago" => "Pred %d mesiacmi.",
+"_%n month ago_::_%n months ago_" => array("pred %n mesiacom","pred %n mesiacmi","pred %n mesiacmi"),
"last year" => "minulý rok",
"years ago" => "pred rokmi",
-"Caused by:" => "Príčina:",
-"Could not find category \"%s\"" => "Nemožno nájsť danú kategóriu \"%s\""
+"Caused by:" => "Príčina:"
);
$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 bffc6d5929b..69067c2691f 100644
--- a/lib/l10n/sl.php
+++ b/lib/l10n/sl.php
@@ -1,19 +1,36 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "Programa \"%s\" ni mogoče namestiti, ker ni skladen s trenutno nameščeno različico oblaka ownCloud.",
+"No app name specified" => "Ni podanega imena programa",
"Help" => "Pomoč",
"Personal" => "Osebno",
"Settings" => "Nastavitve",
"Users" => "Uporabniki",
-"Apps" => "Programi",
"Admin" => "Skrbništvo",
+"Failed to upgrade \"%s\"." => "Posodabljanje \"%s\" je spodletelo.",
+"Unknown filetype" => "Neznana vrsta datoteke",
+"Invalid image" => "Neveljavna slika",
"web services under your control" => "spletne storitve pod vašim nadzorom",
+"cannot open \"%s\"" => "ni mogoče odpreti \"%s\"",
"ZIP download is turned off." => "Prejemanje datotek v paketu ZIP je onemogočeno.",
"Files need to be downloaded one by one." => "Datoteke je mogoče prejeti le posamično.",
"Back to Files" => "Nazaj na datoteke",
"Selected files too large to generate zip file." => "Izbrane datoteke so prevelike za ustvarjanje datoteke arhiva zip.",
-"couldn't be determined" => "ni mogoče določiti",
+"Please download the files separately in smaller chunks or kindly ask your administrator." => "Datoteke je treba prejeti ločeno v manjših paketih, ali pa je treba za pomoč prositi skrbnika.",
+"No source specified when installing app" => "Ni podanega vira med nameščenjem programa",
+"No href specified when installing app from http" => "Ni podanega podatka naslova HREF med nameščenjem programa preko protokola HTTP.",
+"No path specified when installing app from local file" => "Ni podane poti med nameščenjem programa iz krajevne datoteke",
+"Archives of type %s are not supported" => "Arhivi vrste %s niso podprti",
+"Failed to open archive when installing app" => "Odpiranje arhiva je med nameščanjem spodletelo",
+"App does not provide an info.xml file" => "Program je brez datoteke info.xml",
+"App can't be installed because of not allowed code in the App" => "Programa ni mogoče namestiti zaradi nedovoljene programske kode.",
+"App can't be installed because it is not compatible with this version of ownCloud" => "Programa ni mogoče namestiti, ker ni skladen z trenutno nameščeno različico oblaka ownCloud.",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Programa ni mogoče namestiti, ker vsebuje oznako <shipped>potrditve</shipped>, ki pa ni dovoljena za javne programe.",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Program ni mogoče namestiti zaradi neustrezne različice datoteke info.xml. Ta ni enaka različici programa.",
+"App directory already exists" => "Programska mapa že obstaja",
+"Can't create app folder. Please fix permissions. %s" => "Programske mape ni mogoče ustvariti. Ni ustreznih dovoljenj. %s",
"Application is not enabled" => "Program ni omogočen",
-"Authentication error" => "Napaka pri overjanju",
+"Authentication error" => "Napaka overjanja",
"Token expired. Please reload page." => "Žeton je potekel. Stran je treba ponovno naložiti.",
"Files" => "Datoteke",
"Text" => "Besedilo",
@@ -27,10 +44,10 @@ $TRANSLATIONS = array(
"DB Error: \"%s\"" => "Napaka podatkovne zbirke: \"%s\"",
"Offending command was: \"%s\"" => "Napačni ukaz je: \"%s\"",
"MySQL user '%s'@'localhost' exists already." => "Uporabnik MySQL '%s'@'localhost' že obstaja.",
-"Drop this user from MySQL" => "Odstrani uporabnika s podatkovne zbirke MySQL",
+"Drop this user from MySQL" => "Odstrani uporabnika iz podatkovne zbirke MySQL",
"MySQL user '%s'@'%%' already exists" => "Uporabnik MySQL '%s'@'%%' že obstaja.",
-"Drop this user from MySQL." => "Odstrani uporabnika s podatkovne zbirke MySQL",
-"Oracle connection could not be established" => "Povezava z bazo Oracle ni uspela.",
+"Drop this user from MySQL." => "Odstrani uporabnika iz podatkovne zbirke MySQL",
+"Oracle connection could not be established" => "Povezave s sistemom Oracle ni mogoče vzpostaviti.",
"Oracle username and/or password not valid" => "Uporabniško ime ali geslo Oracle ni veljavno",
"Offending command was: \"%s\", name: %s, password: %s" => "Napačni ukaz je: \"%s\", ime: %s, geslo: %s",
"PostgreSQL username and/or password not valid" => "Uporabniško ime ali geslo PostgreSQL ni veljavno",
@@ -38,18 +55,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "Nastavi geslo skrbnika.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Spletni stražnik še ni ustrezno nastavljen in ne omogoča usklajevanja, saj je nastavitev WebDAV okvarjena.",
"Please double check the <a href='%s'>installation guides</a>." => "Preverite <a href='%s'>navodila namestitve</a>.",
+"Could not find category \"%s\"" => "Kategorije \"%s\" ni mogoče najti.",
"seconds ago" => "pred nekaj sekundami",
-"1 minute ago" => "pred minuto",
-"%d minutes ago" => "pred %d minutami",
-"1 hour ago" => "Pred 1 uro",
-"%d hours ago" => "Pred %d urami",
+"_%n minute ago_::_%n minutes ago_" => array("pred %n minuto","pred %n minutama","pred %n minutami","pred %n minutami"),
+"_%n hour ago_::_%n hours ago_" => array("pred %n uro","pred %n urama","pred %n urami","pred %n urami"),
"today" => "danes",
"yesterday" => "včeraj",
-"%d days ago" => "pred %d dnevi",
+"_%n day go_::_%n days ago_" => array("pred %n dnevom","pred %n dnevoma","pred %n dnevi","pred %n dnevi"),
"last month" => "zadnji mesec",
-"%d months ago" => "Pred %d meseci",
+"_%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",
-"Could not find category \"%s\"" => "Kategorije \"%s\" ni mogoče najti."
+"Caused by:" => "Vzrok:"
);
$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 9a332bc671e..b36aa4ceefc 100644
--- a/lib/l10n/sq.php
+++ b/lib/l10n/sq.php
@@ -4,14 +4,12 @@ $TRANSLATIONS = array(
"Personal" => "Personale",
"Settings" => "Parametra",
"Users" => "Përdoruesit",
-"Apps" => "App",
"Admin" => "Admin",
"web services under your control" => "shërbime web nën kontrollin tënd",
"ZIP download is turned off." => "Shkarimi i skedarëve ZIP është i çaktivizuar.",
"Files need to be downloaded one by one." => "Skedarët duhet të shkarkohen një nga një.",
"Back to Files" => "Kthehu tek skedarët",
"Selected files too large to generate zip file." => "Skedarët e selektuar janë shumë të mëdhenj për të krijuar një skedar ZIP.",
-"couldn't be determined" => "nuk u vendos dot",
"Application is not enabled" => "Programi nuk është i aktivizuar.",
"Authentication error" => "Veprim i gabuar gjatë vërtetimit të identitetit",
"Token expired. Please reload page." => "Përmbajtja ka skaduar. Ju lutemi ringarkoni faqen.",
@@ -37,18 +35,16 @@ $TRANSLATIONS = array(
"Set an admin password." => "Cakto kodin e administratorit.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Serveri web i juaji nuk është konfiguruar akoma për të lejuar sinkronizimin e skedarëve sepse ndërfaqja WebDAV mund të jetë e dëmtuar.",
"Please double check the <a href='%s'>installation guides</a>." => "Ju lutemi kontrolloni mirë <a href='%s'>shoqëruesin e instalimit</a>.",
+"Could not find category \"%s\"" => "Kategoria \"%s\" nuk u gjet",
"seconds ago" => "sekonda më parë",
-"1 minute ago" => "1 minutë më parë",
-"%d minutes ago" => "%d minuta më parë",
-"1 hour ago" => "1 orë më parë",
-"%d hours ago" => "%d orë më parë",
+"_%n minute ago_::_%n minutes ago_" => array("","%n minuta më parë"),
+"_%n hour ago_::_%n hours ago_" => array("","%n orë më parë"),
"today" => "sot",
"yesterday" => "dje",
-"%d days ago" => "%d ditë më parë",
+"_%n day go_::_%n days ago_" => array("","%n ditë më parë"),
"last month" => "muajin e shkuar",
-"%d months ago" => "%d muaj më parë",
+"_%n month ago_::_%n months ago_" => array("","%n muaj më parë"),
"last year" => "vitin e shkuar",
-"years ago" => "vite më parë",
-"Could not find category \"%s\"" => "Kategoria \"%s\" nuk u gjet"
+"years ago" => "vite më parë"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/sr.php b/lib/l10n/sr.php
index a42df978b4d..47a84803683 100644
--- a/lib/l10n/sr.php
+++ b/lib/l10n/sr.php
@@ -4,14 +4,12 @@ $TRANSLATIONS = array(
"Personal" => "Лично",
"Settings" => "Поставке",
"Users" => "Корисници",
-"Apps" => "Апликације",
"Admin" => "Администратор",
"web services under your control" => "веб сервиси под контролом",
"ZIP download is turned off." => "Преузимање ZIP-а је искључено.",
"Files need to be downloaded one by one." => "Датотеке морате преузимати једну по једну.",
"Back to Files" => "Назад на датотеке",
"Selected files too large to generate zip file." => "Изабране датотеке су превелике да бисте направили ZIP датотеку.",
-"couldn't be determined" => "није одређено",
"Application is not enabled" => "Апликација није омогућена",
"Authentication error" => "Грешка при провери идентитета",
"Token expired. Please reload page." => "Жетон је истекао. Поново учитајте страницу.",
@@ -20,18 +18,16 @@ $TRANSLATIONS = array(
"Images" => "Слике",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Ваш веб сервер тренутно не подржава синхронизацију датотека јер се чини да је WebDAV сучеље неисправно.",
"Please double check the <a href='%s'>installation guides</a>." => "Погледајте <a href='%s'>водиче за инсталацију</a>.",
+"Could not find category \"%s\"" => "Не могу да пронађем категорију „%s“.",
"seconds ago" => "пре неколико секунди",
-"1 minute ago" => "пре 1 минут",
-"%d minutes ago" => "пре %d минута",
-"1 hour ago" => "Пре једног сата",
-"%d hours ago" => "пре %d сата/и",
+"_%n minute ago_::_%n minutes ago_" => array("","",""),
+"_%n hour ago_::_%n hours ago_" => array("","",""),
"today" => "данас",
"yesterday" => "јуче",
-"%d days ago" => "пре %d дана",
+"_%n day go_::_%n days ago_" => array("","",""),
"last month" => "прошлог месеца",
-"%d months ago" => "пре %d месеца/и",
+"_%n month ago_::_%n months ago_" => array("","",""),
"last year" => "прошле године",
-"years ago" => "година раније",
-"Could not find category \"%s\"" => "Не могу да пронађем категорију „%s“."
+"years ago" => "година раније"
);
$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/sr@latin.php b/lib/l10n/sr@latin.php
index a0c46c2487b..d8fa9289221 100644
--- a/lib/l10n/sr@latin.php
+++ b/lib/l10n/sr@latin.php
@@ -4,10 +4,19 @@ $TRANSLATIONS = array(
"Personal" => "Lično",
"Settings" => "Podešavanja",
"Users" => "Korisnici",
-"Apps" => "Programi",
"Admin" => "Adninistracija",
"Authentication error" => "Greška pri autentifikaciji",
"Files" => "Fajlovi",
-"Text" => "Tekst"
+"Text" => "Tekst",
+"seconds ago" => "Pre par sekundi",
+"_%n minute ago_::_%n minutes ago_" => array("","",""),
+"_%n hour ago_::_%n hours ago_" => array("","",""),
+"today" => "Danas",
+"yesterday" => "juče",
+"_%n day go_::_%n days ago_" => array("","",""),
+"last month" => "prošlog meseca",
+"_%n month ago_::_%n months ago_" => array("","",""),
+"last year" => "prošle godine",
+"years ago" => "pre nekoliko godina"
);
$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 72e2d18654a..4f04cbe3159 100644
--- a/lib/l10n/sv.php
+++ b/lib/l10n/sv.php
@@ -1,20 +1,34 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "Appen \"%s\" kan inte installeras eftersom att den inte är kompatibel med denna version av ownCloud.",
+"No app name specified" => "Inget appnamn angivet",
"Help" => "Hjälp",
"Personal" => "Personligt",
"Settings" => "Inställningar",
"Users" => "Användare",
-"Apps" => "Program",
"Admin" => "Admin",
"Failed to upgrade \"%s\"." => "Misslyckades med att uppgradera \"%s\".",
+"Unknown filetype" => "Okänd filtyp",
+"Invalid image" => "Ogiltig bild",
"web services under your control" => "webbtjänster under din kontroll",
"cannot open \"%s\"" => "Kan inte öppna \"%s\"",
"ZIP download is turned off." => "Nerladdning av ZIP är avstängd.",
"Files need to be downloaded one by one." => "Filer laddas ner en åt gången.",
"Back to Files" => "Tillbaka till Filer",
"Selected files too large to generate zip file." => "Valda filer är för stora för att skapa zip-fil.",
-"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Ladda ner filerna i mindre bitar, separat eller fråga din administratör.",
-"couldn't be determined" => "kunde inte bestämmas",
+"Please download the files separately in smaller chunks or kindly ask your administrator." => "Ladda ner filerna i mindre bitar, separat eller fråga din administratör.",
+"No source specified when installing app" => "Ingen källa angiven vid installation av app ",
+"No href specified when installing app from http" => "Ingen href angiven vid installation av app från http",
+"No path specified when installing app from local file" => "Ingen sökväg angiven vid installation av app från lokal fil",
+"Archives of type %s are not supported" => "Arkiv av typen %s stöds ej",
+"Failed to open archive when installing app" => "Kunde inte öppna arkivet när appen skulle installeras",
+"App does not provide an info.xml file" => "Appen har ingen info.xml fil",
+"App can't be installed because of not allowed code in the App" => "Appen kan inte installeras eftersom att den innehåller otillåten kod",
+"App can't be installed because it is not compatible with this version of ownCloud" => "Appen kan inte installeras eftersom att den inte är kompatibel med denna version av ownCloud",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Appen kan inte installeras eftersom att den innehåller etiketten <shipped>true</shipped> vilket inte är tillåtet för icke inkluderade appar",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Appen kan inte installeras eftersom versionen i info.xml inte är samma som rapporteras från app store",
+"App directory already exists" => "Appens mapp finns redan",
+"Can't create app folder. Please fix permissions. %s" => "Kan inte skapa appens mapp. Var god åtgärda rättigheterna. %s",
"Application is not enabled" => "Applikationen är inte aktiverad",
"Authentication error" => "Fel vid autentisering",
"Token expired. Please reload page." => "Ogiltig token. Ladda om sidan.",
@@ -41,19 +55,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "Ange ett administratörslösenord.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Din webbserver är inte korrekt konfigurerad för att tillåta filsynkronisering eftersom WebDAV inte verkar fungera.",
"Please double check the <a href='%s'>installation guides</a>." => "Var god kontrollera <a href='%s'>installationsguiden</a>.",
+"Could not find category \"%s\"" => "Kunde inte hitta kategorin \"%s\"",
"seconds ago" => "sekunder sedan",
-"1 minute ago" => "1 minut sedan",
-"%d minutes ago" => "%d minuter sedan",
-"1 hour ago" => "1 timme sedan",
-"%d hours ago" => "%d timmar sedan",
+"_%n minute ago_::_%n minutes ago_" => array("%n minut sedan","%n minuter sedan"),
+"_%n hour ago_::_%n hours ago_" => array("%n timme sedan","%n timmar sedan"),
"today" => "i dag",
"yesterday" => "i går",
-"%d days ago" => "%d dagar sedan",
+"_%n day go_::_%n days ago_" => array("%n dag sedan","%n dagar sedan"),
"last month" => "förra månaden",
-"%d months ago" => "%d månader sedan",
+"_%n month ago_::_%n months ago_" => array("%n månad sedan","%n månader sedan"),
"last year" => "förra året",
"years ago" => "år sedan",
-"Caused by:" => "Orsakad av:",
-"Could not find category \"%s\"" => "Kunde inte hitta kategorin \"%s\""
+"Caused by:" => "Orsakad av:"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/sw_KE.php b/lib/l10n/sw_KE.php
new file mode 100644
index 00000000000..15f78e0bce6
--- /dev/null
+++ b/lib/l10n/sw_KE.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/ta_LK.php b/lib/l10n/ta_LK.php
index 88b9de5f7d1..f761ccab0e2 100644
--- a/lib/l10n/ta_LK.php
+++ b/lib/l10n/ta_LK.php
@@ -4,7 +4,6 @@ $TRANSLATIONS = array(
"Personal" => "தனிப்பட்ட",
"Settings" => "அமைப்புகள்",
"Users" => "பயனாளர்",
-"Apps" => "செயலிகள்",
"Admin" => "நிர்வாகம்",
"web services under your control" => "வலைய சேவைகள் உங்களுடைய கட்டுப்பாட்டின் கீழ் உள்ளது",
"ZIP download is turned off." => "வீசொலிப் பூட்டு பதிவிறக்கம் நிறுத்தப்பட்டுள்ளது.",
@@ -17,18 +16,16 @@ $TRANSLATIONS = array(
"Files" => "கோப்புகள்",
"Text" => "உரை",
"Images" => "படங்கள்",
+"Could not find category \"%s\"" => "பிரிவு \"%s\" ஐ கண்டுப்பிடிக்க முடியவில்லை",
"seconds ago" => "செக்கன்களுக்கு முன்",
-"1 minute ago" => "1 நிமிடத்திற்கு முன் ",
-"%d minutes ago" => "%d நிமிடங்களுக்கு முன்",
-"1 hour ago" => "1 மணித்தியாலத்திற்கு முன்",
-"%d hours ago" => "%d மணித்தியாலத்திற்கு முன்",
+"_%n minute ago_::_%n minutes ago_" => array("",""),
+"_%n hour ago_::_%n hours ago_" => array("",""),
"today" => "இன்று",
"yesterday" => "நேற்று",
-"%d days ago" => "%d நாட்களுக்கு முன்",
+"_%n day go_::_%n days ago_" => array("",""),
"last month" => "கடந்த மாதம்",
-"%d months ago" => "%d மாதத்திற்கு முன்",
+"_%n month ago_::_%n months ago_" => array("",""),
"last year" => "கடந்த வருடம்",
-"years ago" => "வருடங்களுக்கு முன்",
-"Could not find category \"%s\"" => "பிரிவு \"%s\" ஐ கண்டுப்பிடிக்க முடியவில்லை"
+"years ago" => "வருடங்களுக்கு முன்"
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
diff --git a/lib/l10n/te.php b/lib/l10n/te.php
index e7d9d921e5e..524ea0c6024 100644
--- a/lib/l10n/te.php
+++ b/lib/l10n/te.php
@@ -4,11 +4,13 @@ $TRANSLATIONS = array(
"Settings" => "అమరికలు",
"Users" => "వాడుకరులు",
"seconds ago" => "క్షణాల క్రితం",
-"1 minute ago" => "1 నిమిషం క్రితం",
-"1 hour ago" => "1 గంట క్రితం",
+"_%n minute ago_::_%n minutes ago_" => array("",""),
+"_%n hour ago_::_%n hours ago_" => array("",""),
"today" => "ఈరోజు",
"yesterday" => "నిన్న",
+"_%n day go_::_%n days ago_" => array("",""),
"last month" => "పోయిన నెల",
+"_%n month ago_::_%n months ago_" => array("",""),
"last year" => "పోయిన సంవత్సరం",
"years ago" => "సంవత్సరాల క్రితం"
);
diff --git a/lib/l10n/th_TH.php b/lib/l10n/th_TH.php
index 25c2d8f1f2a..173d0f2856b 100644
--- a/lib/l10n/th_TH.php
+++ b/lib/l10n/th_TH.php
@@ -4,32 +4,28 @@ $TRANSLATIONS = array(
"Personal" => "ส่วนตัว",
"Settings" => "ตั้งค่า",
"Users" => "ผู้ใช้งาน",
-"Apps" => "แอปฯ",
"Admin" => "ผู้ดูแล",
"web services under your control" => "เว็บเซอร์วิสที่คุณควบคุมการใช้งานได้",
"ZIP download is turned off." => "คุณสมบัติการดาวน์โหลด zip ถูกปิดการใช้งานไว้",
"Files need to be downloaded one by one." => "ไฟล์สามารถดาวน์โหลดได้ทีละครั้งเท่านั้น",
"Back to Files" => "กลับไปที่ไฟล์",
"Selected files too large to generate zip file." => "ไฟล์ที่เลือกมีขนาดใหญ่เกินกว่าที่จะสร้างเป็นไฟล์ zip",
-"couldn't be determined" => "ไม่สามารถกำหนดได้",
"Application is not enabled" => "แอพพลิเคชั่นดังกล่าวยังไม่ได้เปิดใช้งาน",
"Authentication error" => "เกิดข้อผิดพลาดในสิทธิ์การเข้าใช้งาน",
"Token expired. Please reload page." => "รหัสยืนยันความถูกต้องหมดอายุแล้ว กรุณาโหลดหน้าเว็บใหม่อีกครั้ง",
"Files" => "ไฟล์",
"Text" => "ข้อความ",
"Images" => "รูปภาพ",
+"Could not find category \"%s\"" => "ไม่พบหมวดหมู่ \"%s\"",
"seconds ago" => "วินาที ก่อนหน้านี้",
-"1 minute ago" => "1 นาทีก่อนหน้านี้",
-"%d minutes ago" => "%d นาทีที่ผ่านมา",
-"1 hour ago" => "1 ชั่วโมงก่อนหน้านี้",
-"%d hours ago" => "%d ชั่วโมงก่อนหน้านี้",
+"_%n minute ago_::_%n minutes ago_" => array(""),
+"_%n hour ago_::_%n hours ago_" => array(""),
"today" => "วันนี้",
"yesterday" => "เมื่อวานนี้",
-"%d days ago" => "%d วันที่ผ่านมา",
+"_%n day go_::_%n days ago_" => array(""),
"last month" => "เดือนที่แล้ว",
-"%d months ago" => "%d เดือนมาแล้ว",
+"_%n month ago_::_%n months ago_" => array(""),
"last year" => "ปีที่แล้ว",
-"years ago" => "ปี ที่ผ่านมา",
-"Could not find category \"%s\"" => "ไม่พบหมวดหมู่ \"%s\""
+"years ago" => "ปี ที่ผ่านมา"
);
$PLURAL_FORMS = "nplurals=1; plural=0;";
diff --git a/lib/l10n/tr.php b/lib/l10n/tr.php
index 233b99e6373..093984bb952 100644
--- a/lib/l10n/tr.php
+++ b/lib/l10n/tr.php
@@ -1,25 +1,42 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "ownCloud yazılımının bu sürümü ile uyumlu olmadığı için \"%s\" uygulaması kurulamaz.",
+"No app name specified" => "Uygulama adı belirtimedli",
"Help" => "Yardım",
"Personal" => "Kişisel",
"Settings" => "Ayarlar",
"Users" => "Kullanıcılar",
-"Apps" => "Uygulamalar",
"Admin" => "Yönetici",
+"Failed to upgrade \"%s\"." => "\"%s\" yükseltme başarısız oldu.",
+"Unknown filetype" => "Bilinmeyen dosya türü",
+"Invalid image" => "Geçersiz resim",
"web services under your control" => "Bilgileriniz güvenli ve şifreli",
+"cannot open \"%s\"" => "\"%s\" açılamıyor",
"ZIP download is turned off." => "ZIP indirmeleri kapatılmıştır.",
"Files need to be downloaded one by one." => "Dosyaların birer birer indirilmesi gerekmektedir.",
"Back to Files" => "Dosyalara dön",
"Selected files too large to generate zip file." => "Seçilen dosyalar bir zip dosyası oluşturmak için fazla büyüktür.",
-"couldn't be determined" => "tespit edilemedi",
+"Please download the files separately in smaller chunks or kindly ask your administrator." => "Dosyaları ayrı ayrı, küçük parçalar halinde indirin veya yöneticinizden yardım isteyin. ",
+"No source specified when installing app" => "Uygulama kurulurken bir kaynak belirtilmedi",
+"No href specified when installing app from http" => "Uygulama kuruluyorken http'de href belirtilmedi",
+"No path specified when installing app from local file" => "Uygulama yerel dosyadan kuruluyorken dosya yolu belirtilmedi",
+"Archives of type %s are not supported" => "%s arşiv türü desteklenmiyor",
+"Failed to open archive when installing app" => "Uygulama kuruluyorken arşiv dosyası açılamadı",
+"App does not provide an info.xml file" => "Uygulama info.xml dosyası sağlamıyor",
+"App can't be installed because of not allowed code in the App" => "Uygulama, izin verilmeyen kodlar barındırdığından kurulamıyor.",
+"App can't be installed because it is not compatible with this version of ownCloud" => "ownCloud sürümünüz ile uyumsuz olduğu için uygulama kurulamıyor.",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Uygulama kurulamıyor. Çünkü \"birlikte gelmeyen\" uygulamalar için <shipped>true</shipped> etiketi içeriyor",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Uygulama kurulamıyor çünkü info.xml/version ile uygulama markette belirtilen sürüm aynı değil",
+"App directory already exists" => "Uygulama dizini zaten mevcut",
+"Can't create app folder. Please fix permissions. %s" => "Uygulama dizini oluşturulamıyor. Lütfen izinleri düzeltin. %s",
"Application is not enabled" => "Uygulama etkinleştirilmedi",
"Authentication error" => "Kimlik doğrulama hatası",
"Token expired. Please reload page." => "Jetonun süresi geçti. Lütfen sayfayı yenileyin.",
"Files" => "Dosyalar",
"Text" => "Metin",
"Images" => "Resimler",
-"%s enter the database username." => "%s veritabanı kullanıcı adını gir.",
-"%s enter the database name." => "%s veritabanı adını gir.",
+"%s enter the database username." => "%s veritabanı kullanıcı adını girin.",
+"%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. ",
@@ -29,7 +46,7 @@ $TRANSLATIONS = array(
"MySQL user '%s'@'localhost' exists already." => "MySQL kullanici '%s @local host zatan var. ",
"Drop this user from MySQL" => "Bu kullanici MySQLden list disari koymak. ",
"MySQL user '%s'@'%%' already exists" => "MySQL kullanici '%s @ % % zaten var (zaten yazili)",
-"Drop this user from MySQL." => "Bu kulanıcıyı MySQL veritabanından kaldır",
+"Drop this user from MySQL." => "Bu kullanıcıyı MySQL veritabanından kaldır",
"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. ",
"Offending command was: \"%s\", name: %s, password: %s" => "Hatalı komut: \"%s\", ad: %s, parola: %s",
@@ -38,18 +55,17 @@ $TRANSLATIONS = array(
"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.",
"Please double check the <a href='%s'>installation guides</a>." => "Lütfen <a href='%s'>kurulum kılavuzlarını</a> iki kez kontrol edin.",
+"Could not find category \"%s\"" => "\"%s\" kategorisi bulunamadı",
"seconds ago" => "saniye önce",
-"1 minute ago" => "1 dakika önce",
-"%d minutes ago" => "%d dakika önce",
-"1 hour ago" => "1 saat önce",
-"%d hours ago" => "%d saat önce",
+"_%n minute ago_::_%n minutes ago_" => array("","%n dakika önce"),
+"_%n hour ago_::_%n hours ago_" => array("","%n saat önce"),
"today" => "bugün",
"yesterday" => "dün",
-"%d days ago" => "%d gün önce",
+"_%n day go_::_%n days ago_" => array("","%n gün önce"),
"last month" => "geçen ay",
-"%d months ago" => "%d ay önce",
+"_%n month ago_::_%n months ago_" => array("","%n ay önce"),
"last year" => "geçen yıl",
"years ago" => "yıl önce",
-"Could not find category \"%s\"" => "\"%s\" kategorisi bulunamadı"
+"Caused by:" => "Neden olan:"
);
$PLURAL_FORMS = "nplurals=2; plural=(n > 1);";
diff --git a/lib/l10n/tzm.php b/lib/l10n/tzm.php
new file mode 100644
index 00000000000..3120c509265
--- /dev/null
+++ b/lib/l10n/tzm.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 == 0 || n == 1 || (n > 10 && n < 100) ? 0 : 1;";
diff --git a/lib/l10n/ug.php b/lib/l10n/ug.php
index cf460cd3024..e2cf38ecc8c 100644
--- a/lib/l10n/ug.php
+++ b/lib/l10n/ug.php
@@ -4,18 +4,16 @@ $TRANSLATIONS = array(
"Personal" => "شەخسىي",
"Settings" => "تەڭشەكلەر",
"Users" => "ئىشلەتكۈچىلەر",
-"Apps" => "ئەپلەر",
"Authentication error" => "سالاھىيەت دەلىللەش خاتالىقى",
"Files" => "ھۆججەتلەر",
"Text" => "قىسقا ئۇچۇر",
"Images" => "سۈرەتلەر",
-"1 minute ago" => "1 مىنۇت ئىلگىرى",
-"%d minutes ago" => "%d مىنۇت ئىلگىرى",
-"1 hour ago" => "1 سائەت ئىلگىرى",
-"%d hours ago" => "%d سائەت ئىلگىرى",
+"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "سىزنىڭ تور مۇلازىمېتىرىڭىز ھۆججەت قەدەمداشلاشقا يول قويىدىغان قىلىپ توغرا تەڭشەلمەپتۇ، چۈنكى WebDAV نىڭ ئېغىزى بۇزۇلغاندەك تۇرىدۇ.",
+"_%n minute ago_::_%n minutes ago_" => array(""),
+"_%n hour ago_::_%n hours ago_" => array(""),
"today" => "بۈگۈن",
"yesterday" => "تۈنۈگۈن",
-"%d days ago" => "%d كۈن ئىلگىرى",
-"%d months ago" => "%d ئاي ئىلگىرى"
+"_%n day go_::_%n days ago_" => array(""),
+"_%n month ago_::_%n months ago_" => array("")
);
$PLURAL_FORMS = "nplurals=1; plural=0;";
diff --git a/lib/l10n/uk.php b/lib/l10n/uk.php
index c52aa5dfc77..32e010f1d40 100644
--- a/lib/l10n/uk.php
+++ b/lib/l10n/uk.php
@@ -4,14 +4,14 @@ $TRANSLATIONS = array(
"Personal" => "Особисте",
"Settings" => "Налаштування",
"Users" => "Користувачі",
-"Apps" => "Додатки",
"Admin" => "Адмін",
+"Unknown filetype" => "Невідомий тип файлу",
+"Invalid image" => "Невірне зображення",
"web services under your control" => "підконтрольні Вам веб-сервіси",
"ZIP download is turned off." => "ZIP завантаження вимкнено.",
"Files need to be downloaded one by one." => "Файли повинні бути завантаженні послідовно.",
"Back to Files" => "Повернутися до файлів",
"Selected files too large to generate zip file." => "Вибрані фали завеликі для генерування zip файлу.",
-"couldn't be determined" => "не може бути визначено",
"Application is not enabled" => "Додаток не увімкнений",
"Authentication error" => "Помилка автентифікації",
"Token expired. Please reload page." => "Строк дії токена скінчився. Будь ласка, перезавантажте сторінку.",
@@ -37,18 +37,16 @@ $TRANSLATIONS = array(
"Set an admin password." => "Встановіть пароль адміністратора.",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Ваш Web-сервер ще не налаштований належним чином для того, щоб дозволити синхронізацію файлів, через те що інтерфейс WebDAV, здається, зламаний.",
"Please double check the <a href='%s'>installation guides</a>." => "Будь ласка, перевірте <a href='%s'>інструкції по встановленню</a>.",
+"Could not find category \"%s\"" => "Не вдалося знайти категорію \"%s\"",
"seconds ago" => "секунди тому",
-"1 minute ago" => "1 хвилину тому",
-"%d minutes ago" => "%d хвилин тому",
-"1 hour ago" => "1 годину тому",
-"%d hours ago" => "%d годин тому",
+"_%n minute ago_::_%n minutes ago_" => array("","","%n хвилин тому"),
+"_%n hour ago_::_%n hours ago_" => array("","","%n годин тому"),
"today" => "сьогодні",
"yesterday" => "вчора",
-"%d days ago" => "%d днів тому",
+"_%n day go_::_%n days ago_" => array("","","%n днів тому"),
"last month" => "минулого місяця",
-"%d months ago" => "%d місяців тому",
+"_%n month ago_::_%n months ago_" => array("","","%n місяців тому"),
"last year" => "минулого року",
-"years ago" => "роки тому",
-"Could not find category \"%s\"" => "Не вдалося знайти категорію \"%s\""
+"years ago" => "роки тому"
);
$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/ur_PK.php b/lib/l10n/ur_PK.php
index 57f77d46059..7dc967ccd93 100644
--- a/lib/l10n/ur_PK.php
+++ b/lib/l10n/ur_PK.php
@@ -4,8 +4,11 @@ $TRANSLATIONS = array(
"Personal" => "ذاتی",
"Settings" => "سیٹینگز",
"Users" => "یوزرز",
-"Apps" => "ایپز",
"Admin" => "ایڈمن",
-"web services under your control" => "آپ کے اختیار میں ویب سروسیز"
+"web services under your control" => "آپ کے اختیار میں ویب سروسیز",
+"_%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/uz.php b/lib/l10n/uz.php
new file mode 100644
index 00000000000..e7b09649a24
--- /dev/null
+++ b/lib/l10n/uz.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=1; plural=0;";
diff --git a/lib/l10n/vi.php b/lib/l10n/vi.php
index c3ec50b41f9..5840283110e 100644
--- a/lib/l10n/vi.php
+++ b/lib/l10n/vi.php
@@ -4,32 +4,28 @@ $TRANSLATIONS = array(
"Personal" => "Cá nhân",
"Settings" => "Cài đặt",
"Users" => "Người dùng",
-"Apps" => "Ứng dụng",
"Admin" => "Quản trị",
"web services under your control" => "dịch vụ web dưới sự kiểm soát của bạn",
"ZIP download is turned off." => "Tải về ZIP đã bị tắt.",
"Files need to be downloaded one by one." => "Tập tin cần phải được tải về từng người một.",
"Back to Files" => "Trở lại tập tin",
"Selected files too large to generate zip file." => "Tập tin được chọn quá lớn để tạo tập tin ZIP.",
-"couldn't be determined" => "không thể phát hiện được",
"Application is not enabled" => "Ứng dụng không được BẬT",
"Authentication error" => "Lỗi xác thực",
"Token expired. Please reload page." => "Mã Token đã hết hạn. Hãy tải lại trang.",
"Files" => "Tập tin",
"Text" => "Văn bản",
"Images" => "Hình ảnh",
+"Could not find category \"%s\"" => "không thể tìm thấy mục \"%s\"",
"seconds ago" => "vài giây trước",
-"1 minute ago" => "1 phút trước",
-"%d minutes ago" => "%d phút trước",
-"1 hour ago" => "1 giờ trước",
-"%d hours ago" => "%d giờ trước",
+"_%n minute ago_::_%n minutes ago_" => array(""),
+"_%n hour ago_::_%n hours ago_" => array(""),
"today" => "hôm nay",
"yesterday" => "hôm qua",
-"%d days ago" => "%d ngày trước",
+"_%n day go_::_%n days ago_" => array(""),
"last month" => "tháng trước",
-"%d months ago" => "%d tháng trước",
+"_%n month ago_::_%n months ago_" => array(""),
"last year" => "năm trước",
-"years ago" => "năm trước",
-"Could not find category \"%s\"" => "không thể tìm thấy mục \"%s\""
+"years ago" => "năm trước"
);
$PLURAL_FORMS = "nplurals=1; plural=0;";
diff --git a/lib/l10n/zh_CN.GB2312.php b/lib/l10n/zh_CN.GB2312.php
deleted file mode 100644
index 9d7237bd198..00000000000
--- a/lib/l10n/zh_CN.GB2312.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-$TRANSLATIONS = array(
-"Help" => "帮助",
-"Personal" => "私人",
-"Settings" => "设置",
-"Users" => "用户",
-"Apps" => "程序",
-"Admin" => "管理员",
-"web services under your control" => "您控制的网络服务",
-"ZIP download is turned off." => "ZIP 下载已关闭",
-"Files need to be downloaded one by one." => "需要逐个下载文件。",
-"Back to Files" => "返回到文件",
-"Selected files too large to generate zip file." => "选择的文件太大而不能生成 zip 文件。",
-"Application is not enabled" => "应用未启用",
-"Authentication error" => "验证错误",
-"Token expired. Please reload page." => "会话过期。请刷新页面。",
-"Files" => "文件",
-"Text" => "文本",
-"Images" => "图片",
-"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "因WebDAV接口故障,您的网络服务器好像并未允许文件同步。",
-"Please double check the <a href='%s'>installation guides</a>." => "请双击<a href='%s'>安装向导</a>。",
-"seconds ago" => "秒前",
-"1 minute ago" => "1 分钟前",
-"%d minutes ago" => "%d 分钟前",
-"1 hour ago" => "1小时前",
-"today" => "今天",
-"yesterday" => "昨天",
-"%d days ago" => "%d 天前",
-"last month" => "上个月",
-"last year" => "去年",
-"years ago" => "年前"
-);
-$PLURAL_FORMS = "nplurals=1; plural=0;";
diff --git a/lib/l10n/zh_CN.php b/lib/l10n/zh_CN.php
index 4469f0fb1e4..ae9243cf412 100644
--- a/lib/l10n/zh_CN.php
+++ b/lib/l10n/zh_CN.php
@@ -4,14 +4,15 @@ $TRANSLATIONS = array(
"Personal" => "个人",
"Settings" => "设置",
"Users" => "用户",
-"Apps" => "应用",
"Admin" => "管理",
+"Unknown filetype" => "未知的文件类型",
+"Invalid image" => "无效的图像",
"web services under your control" => "您控制的web服务",
"ZIP download is turned off." => "ZIP 下载已经关闭",
"Files need to be downloaded one by one." => "需要逐一下载文件",
"Back to Files" => "回到文件",
"Selected files too large to generate zip file." => "选择的文件太大,无法生成 zip 文件。",
-"couldn't be determined" => "无法确定",
+"App does not provide an info.xml file" => "应用未提供 info.xml 文件",
"Application is not enabled" => "应用程序未启用",
"Authentication error" => "认证出错",
"Token expired. Please reload page." => "Token 过期,请刷新页面。",
@@ -38,18 +39,16 @@ $TRANSLATIONS = array(
"Set an admin password." => "请设置一个管理员密码。",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "您的Web服务器尚未正确设置以允许文件同步, 因为WebDAV的接口似乎已损坏.",
"Please double check the <a href='%s'>installation guides</a>." => "请认真检查<a href='%s'>安装指南</a>.",
+"Could not find category \"%s\"" => "无法找到分类 \"%s\"",
"seconds ago" => "秒前",
-"1 minute ago" => "一分钟前",
-"%d minutes ago" => "%d 分钟前",
-"1 hour ago" => "1小时前",
-"%d hours ago" => "%d小时前",
+"_%n minute ago_::_%n minutes ago_" => array("%n 分钟前"),
+"_%n hour ago_::_%n hours ago_" => array("%n 小时前"),
"today" => "今天",
"yesterday" => "昨天",
-"%d days ago" => "%d 天前",
+"_%n day go_::_%n days ago_" => array("%n 天前"),
"last month" => "上月",
-"%d months ago" => "%d 月前",
+"_%n month ago_::_%n months ago_" => array("%n 月前"),
"last year" => "去年",
-"years ago" => "年前",
-"Could not find category \"%s\"" => "无法找到分类 \"%s\""
+"years ago" => "年前"
);
$PLURAL_FORMS = "nplurals=1; plural=0;";
diff --git a/lib/l10n/zh_HK.php b/lib/l10n/zh_HK.php
index f5fc48366ff..ca3e6d504e7 100644
--- a/lib/l10n/zh_HK.php
+++ b/lib/l10n/zh_HK.php
@@ -4,12 +4,15 @@ $TRANSLATIONS = array(
"Personal" => "個人",
"Settings" => "設定",
"Users" => "用戶",
-"Apps" => "軟件",
"Admin" => "管理",
"Files" => "文件",
"Text" => "文字",
+"_%n minute ago_::_%n minutes ago_" => array(""),
+"_%n hour ago_::_%n hours ago_" => array(""),
"today" => "今日",
"yesterday" => "昨日",
-"last month" => "前一月"
+"_%n day go_::_%n days ago_" => array(""),
+"last month" => "前一月",
+"_%n month ago_::_%n months ago_" => array("")
);
$PLURAL_FORMS = "nplurals=1; plural=0;";
diff --git a/lib/l10n/zh_TW.php b/lib/l10n/zh_TW.php
index 81b66b93296..187d40e540e 100644
--- a/lib/l10n/zh_TW.php
+++ b/lib/l10n/zh_TW.php
@@ -1,17 +1,33 @@
<?php
$TRANSLATIONS = array(
+"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "無法安裝應用程式 %s 因為它和此版本的 ownCloud 不相容。",
+"No app name specified" => "沒有指定應用程式名稱",
"Help" => "說明",
"Personal" => "個人",
"Settings" => "設定",
"Users" => "使用者",
-"Apps" => "應用程式",
"Admin" => "管理",
+"Failed to upgrade \"%s\"." => "升級失敗:%s",
+"Unknown filetype" => "未知的檔案類型",
+"Invalid image" => "無效的圖片",
"web services under your control" => "由您控制的網路服務",
+"cannot open \"%s\"" => "無法開啓 %s",
"ZIP download is turned off." => "ZIP 下載已關閉。",
"Files need to be downloaded one by one." => "檔案需要逐一下載。",
"Back to Files" => "回到檔案列表",
"Selected files too large to generate zip file." => "選擇的檔案太大以致於無法產生壓縮檔。",
-"couldn't be determined" => "無法判斷",
+"No source specified when installing app" => "沒有指定應用程式安裝來源",
+"No href specified when installing app from http" => "從 http 安裝應用程式,找不到 href 屬性",
+"No path specified when installing app from local file" => "從本地檔案安裝應用程式時沒有指定路徑",
+"Archives of type %s are not supported" => "不支援 %s 格式的壓縮檔",
+"Failed to open archive when installing app" => "安裝應用程式時無法開啓壓縮檔",
+"App does not provide an info.xml file" => "應用程式沒有提供 info.xml 檔案",
+"App can't be installed because of not allowed code in the App" => "無法安裝應用程式因為在當中找到危險的代碼",
+"App can't be installed because it is not compatible with this version of ownCloud" => "無法安裝應用程式因為它和此版本的 ownCloud 不相容。",
+"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "無法安裝應用程式,因為它包含了 <shipped>true</shipped> 標籤,在未發行的應用程式當中這是不允許的",
+"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "無法安裝應用程式,因為它在 info.xml/version 宣告的版本與 app store 當中記載的版本不同",
+"App directory already exists" => "應用程式目錄已經存在",
+"Can't create app folder. Please fix permissions. %s" => "無法建立應用程式目錄,請檢查權限:%s",
"Application is not enabled" => "應用程式未啟用",
"Authentication error" => "認證錯誤",
"Token expired. Please reload page." => "Token 過期,請重新整理頁面。",
@@ -38,18 +54,17 @@ $TRANSLATIONS = array(
"Set an admin password." => "設定管理員密碼。",
"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "您的網頁伺服器尚未被正確設定來進行檔案同步,因為您的 WebDAV 界面似乎無法使用。",
"Please double check the <a href='%s'>installation guides</a>." => "請參考<a href='%s'>安裝指南</a>。",
+"Could not find category \"%s\"" => "找不到分類:\"%s\"",
"seconds ago" => "幾秒前",
-"1 minute ago" => "1 分鐘前",
-"%d minutes ago" => "%d 分鐘前",
-"1 hour ago" => "1 小時之前",
-"%d hours ago" => "%d 小時之前",
+"_%n minute ago_::_%n minutes ago_" => array("%n 分鐘前"),
+"_%n hour ago_::_%n hours ago_" => array("%n 小時前"),
"today" => "今天",
"yesterday" => "昨天",
-"%d days ago" => "%d 天前",
+"_%n day go_::_%n days ago_" => array("%n 天前"),
"last month" => "上個月",
-"%d months ago" => "%d 個月之前",
+"_%n month ago_::_%n months ago_" => array("%n 個月前"),
"last year" => "去年",
"years ago" => "幾年前",
-"Could not find category \"%s\"" => "找不到分類:\"%s\""
+"Caused by:" => "原因:"
);
$PLURAL_FORMS = "nplurals=1; plural=0;";
diff --git a/lib/ocs/activity.php b/lib/ocs/activity.php
deleted file mode 100644
index c30e21018d3..00000000000
--- a/lib/ocs/activity.php
+++ /dev/null
@@ -1,28 +0,0 @@
-<?php
-/**
-* ownCloud
-*
-* @author Frank Karlitschek
-* @copyright 2012 Frank Karlitschek frank@owncloud.org
-*
-* 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/>.
-*
-*/
-
-class OC_OCS_Activity {
-
- public static function activityGet($parameters){
- // TODO
- }
-}
diff --git a/lib/ocs/privatedata.php b/lib/ocs/privatedata.php
deleted file mode 100644
index 4dfd0a6e66e..00000000000
--- a/lib/ocs/privatedata.php
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-/**
-* ownCloud
-*
-* @author Frank Karlitschek
-* @author Tom Needham
-* @copyright 2012 Frank Karlitschek frank@owncloud.org
-* @copyright 2012 Tom Needham tom@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/>.
-*
-*/
-
-class OC_OCS_Privatedata {
-
- public static function get($parameters) {
- OC_Util::checkLoggedIn();
- $user = OC_User::getUser();
- $app = addslashes(strip_tags($parameters['app']));
- $key = addslashes(strip_tags($parameters['key']));
- $result = OC_OCS::getData($user, $app, $key);
- $xml = array();
- foreach($result as $i=>$log) {
- $xml[$i]['key']=$log['key'];
- $xml[$i]['app']=$log['app'];
- $xml[$i]['value']=$log['value'];
- }
- return new OC_OCS_Result($xml);
- //TODO: replace 'privatedata' with 'attribute' once a new libattice has been released that works with it
- }
-
- public static function set($parameters) {
- OC_Util::checkLoggedIn();
- $user = OC_User::getUser();
- $app = addslashes(strip_tags($parameters['app']));
- $key = addslashes(strip_tags($parameters['key']));
- $value = OC_OCS::readData('post', 'value', 'text');
- if(OC_Preferences::setValue($user, $app, $key, $value)) {
- return new OC_OCS_Result(null, 100);
- }
- }
-
- public static function delete($parameters) {
- OC_Util::checkLoggedIn();
- $user = OC_User::getUser();
- $app = addslashes(strip_tags($parameters['app']));
- $key = addslashes(strip_tags($parameters['key']));
- if($key==="" or $app==="") {
- return new OC_OCS_Result(null, 101); //key and app are NOT optional here
- }
- if(OC_Preferences::deleteKey($user, $app, $key)) {
- return new OC_OCS_Result(null, 100);
- }
- }
-}
diff --git a/lib/private/activitymanager.php b/lib/private/activitymanager.php
new file mode 100755
index 00000000000..7e7e2257874
--- /dev/null
+++ b/lib/private/activitymanager.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * Copyright (c) 2013 Thomas Müller thomas.mueller@tmit.eu
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ *
+ */
+namespace OC;
+
+
+use OCP\Activity\IConsumer;
+use OCP\Activity\IManager;
+
+class ActivityManager implements IManager {
+
+ private $consumers = array();
+
+ /**
+ * @param $app
+ * @param $subject
+ * @param $subjectParams
+ * @param $message
+ * @param $messageParams
+ * @param $file
+ * @param $link
+ * @param $affectedUser
+ * @param $type
+ * @param $priority
+ * @return mixed
+ */
+ function publishActivity($app, $subject, $subjectParams, $message, $messageParams, $file, $link, $affectedUser, $type, $priority) {
+ foreach($this->consumers as $consumer) {
+ $c = $consumer();
+ if ($c instanceof IConsumer) {
+ try {
+ $c->receive(
+ $app,
+ $subject,
+ $subjectParams,
+ $message,
+ $messageParams,
+ $file,
+ $link,
+ $affectedUser,
+ $type,
+ $priority);
+ } catch (\Exception $ex) {
+ // TODO: log the excepetion
+ }
+ }
+
+ }
+ }
+
+ /**
+ * In order to improve lazy loading a closure can be registered which will be called in case
+ * activity consumers are actually requested
+ *
+ * $callable has to return an instance of OCA\Activity\IConsumer
+ *
+ * @param string $key
+ * @param \Closure $callable
+ */
+ function registerConsumer(\Closure $callable) {
+ array_push($this->consumers, $callable);
+ }
+
+}
diff --git a/lib/private/allconfig.php b/lib/private/allconfig.php
new file mode 100644
index 00000000000..72aabf60793
--- /dev/null
+++ b/lib/private/allconfig.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ *
+ */
+
+namespace OC;
+
+/**
+ * Class to combine all the configuration options ownCloud offers
+ */
+class AllConfig implements \OCP\IConfig {
+ /**
+ * Sets a new system wide value
+ * @param string $key the key of the value, under which will be saved
+ * @param string $value the value that should be stored
+ * @todo need a use case for this
+ */
+// public function setSystemValue($key, $value) {
+// \OCP\Config::setSystemValue($key, $value);
+// }
+
+ /**
+ * Looks up a system wide defined value
+ * @param string $key the key of the value, under which it was saved
+ * @return string the saved value
+ */
+ public function getSystemValue($key) {
+ return \OCP\Config::getSystemValue($key, '');
+ }
+
+
+ /**
+ * Writes a new app wide value
+ * @param string $appName the appName that we want to store the value under
+ * @param string $key the key of the value, under which will be saved
+ * @param string $value the value that should be stored
+ */
+ public function setAppValue($appName, $key, $value) {
+ \OCP\Config::setAppValue($appName, $key, $value);
+ }
+
+ /**
+ * Looks up an app wide defined value
+ * @param string $appName the appName that we stored the value under
+ * @param string $key the key of the value, under which it was saved
+ * @return string the saved value
+ */
+ public function getAppValue($appName, $key) {
+ return \OCP\Config::getAppValue($appName, $key, '');
+ }
+
+
+ /**
+ * Set a user defined value
+ * @param string $userId the userId of the user that we want to store the value under
+ * @param string $appName the appName that we want to store the value under
+ * @param string $key the key under which the value is being stored
+ * @param string $value the value that you want to store
+ */
+ public function setUserValue($userId, $appName, $key, $value) {
+ \OCP\Config::setUserValue($userId, $appName, $key, $value);
+ }
+
+ /**
+ * Shortcut for getting a user defined value
+ * @param string $userId the userId of the user that we want to store the value under
+ * @param string $appName the appName that we stored the value under
+ * @param string $key the key under which the value is being stored
+ */
+ public function getUserValue($userId, $appName, $key){
+ return \OCP\Config::getUserValue($userId, $appName, $key);
+ }
+}
diff --git a/lib/api.php b/lib/private/api.php
index 31f3f968d9b..03d7b7382a5 100644
--- a/lib/api.php
+++ b/lib/private/api.php
@@ -46,6 +46,7 @@ class OC_API {
* api actions
*/
protected static $actions = array();
+ private static $logoutRequired = false;
/**
* registers an api call
@@ -95,6 +96,7 @@ class OC_API {
$responses[] = array(
'app' => $action['app'],
'response' => new OC_OCS_Result(null, OC_API::RESPOND_UNAUTHORISED, 'Unauthorised'),
+ 'shipped' => OC_App::isShipped($action['app']),
);
continue;
}
@@ -102,6 +104,7 @@ class OC_API {
$responses[] = array(
'app' => $action['app'],
'response' => new OC_OCS_Result(null, OC_API::RESPOND_NOT_FOUND, 'Api method not found'),
+ 'shipped' => OC_App::isShipped($action['app']),
);
continue;
}
@@ -109,13 +112,16 @@ class OC_API {
$responses[] = array(
'app' => $action['app'],
'response' => call_user_func($action['action'], $parameters),
+ 'shipped' => OC_App::isShipped($action['app']),
);
}
$response = self::mergeResponses($responses);
$formats = array('json', 'xml');
$format = !empty($_GET['format']) && in_array($_GET['format'], $formats) ? $_GET['format'] : 'xml';
- OC_User::logout();
+ if (self::$logoutRequired) {
+ OC_User::logout();
+ }
self::respond($response, $format);
}
@@ -124,7 +130,7 @@ class OC_API {
* merge the returned result objects into one response
* @param array $responses
*/
- private static function mergeResponses($responses) {
+ public static function mergeResponses($responses) {
$response = array();
// Sort into shipped and thirdparty
$shipped = array(
@@ -137,50 +143,76 @@ class OC_API {
);
foreach($responses as $response) {
- if(OC_App::isShipped($response['app']) || ($response['app'] === 'core')) {
+ if($response['shipped'] || ($response['app'] === 'core')) {
if($response['response']->succeeded()) {
- $shipped['succeeded'][$response['app']] = $response['response'];
+ $shipped['succeeded'][$response['app']] = $response;
} else {
- $shipped['failed'][$response['app']] = $response['response'];
+ $shipped['failed'][$response['app']] = $response;
}
} else {
if($response['response']->succeeded()) {
- $thirdparty['succeeded'][$response['app']] = $response['response'];
+ $thirdparty['succeeded'][$response['app']] = $response;
} else {
- $thirdparty['failed'][$response['app']] = $response['response'];
+ $thirdparty['failed'][$response['app']] = $response;
}
}
}
// Remove any error responses if there is one shipped response that succeeded
- if(!empty($shipped['succeeded'])) {
- $responses = array_merge($shipped['succeeded'], $thirdparty['succeeded']);
- } else if(!empty($shipped['failed'])) {
+ if(!empty($shipped['failed'])) {
// Which shipped response do we use if they all failed?
// They may have failed for different reasons (different status codes)
// Which reponse code should we return?
// Maybe any that are not OC_API::RESPOND_SERVER_ERROR
- $response = reset($shipped['failed']);
+ // Merge failed responses if more than one
+ $data = array();
+ $meta = array();
+ foreach($shipped['failed'] as $failure) {
+ $data = array_merge_recursive($data, $failure['response']->getData());
+ }
+ $picked = reset($shipped['failed']);
+ $code = $picked['response']->getStatusCode();
+ $response = new OC_OCS_Result($data, $code);
return $response;
+ } elseif(!empty($shipped['succeeded'])) {
+ $responses = array_merge($shipped['succeeded'], $thirdparty['succeeded']);
} elseif(!empty($thirdparty['failed'])) {
- // Return the third party failure result
- $response = reset($thirdparty['failed']);
+ // Merge failed responses if more than one
+ $data = array();
+ $meta = array();
+ foreach($thirdparty['failed'] as $failure) {
+ $data = array_merge_recursive($data, $failure['response']->getData());
+ }
+ $picked = reset($thirdparty['failed']);
+ $code = $picked['response']->getStatusCode();
+ $response = new OC_OCS_Result($data, $code);
return $response;
} else {
- $responses = array_merge($shipped['succeeded'], $thirdparty['succeeded']);
+ $responses = $thirdparty['succeeded'];
}
// Merge the successful responses
$meta = array();
$data = array();
foreach($responses as $app => $response) {
- if(OC_App::isShipped($app)) {
- $data = array_merge_recursive($response->getData(), $data);
+ if($response['shipped']) {
+ $data = array_merge_recursive($response['response']->getData(), $data);
} else {
- $data = array_merge_recursive($data, $response->getData());
+ $data = array_merge_recursive($data, $response['response']->getData());
+ }
+ $codes[] = $response['response']->getStatusCode();
+ }
+
+ // Use any non 100 status codes
+ $statusCode = 100;
+ foreach($codes as $code) {
+ if($code != 100) {
+ $statusCode = $code;
+ break;
}
}
- $result = new OC_OCS_Result($data, 100);
+
+ $result = new OC_OCS_Result($data, $statusCode);
return $result;
}
@@ -235,10 +267,32 @@ class OC_API {
* http basic auth
* @return string|false (username, or false on failure)
*/
- private static function loginUser(){
+ private static function loginUser(){
+ // basic auth
$authUser = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : '';
$authPw = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : '';
- return OC_User::login($authUser, $authPw) ? $authUser : false;
+ $return = OC_User::login($authUser, $authPw);
+ if ($return === true) {
+ self::$logoutRequired = true;
+
+ // initialize the user's filesystem
+ \OC_Util::setUpFS(\OC_User::getUser());
+
+ return $authUser;
+ }
+
+ // reuse existing login
+ $loggedIn = OC_User::isLoggedIn();
+ $ocsApiRequest = isset($_SERVER['HTTP_OCS_APIREQUEST']) ? $_SERVER['HTTP_OCS_APIREQUEST'] === 'true' : false;
+ if ($loggedIn === true && $ocsApiRequest) {
+
+ // initialize the user's filesystem
+ \OC_Util::setUpFS(\OC_User::getUser());
+
+ return OC_User::getUser();
+ }
+
+ return false;
}
/**
diff --git a/lib/app.php b/lib/private/app.php
index 5fa650044f3..eca40a81cc1 100644
--- a/lib/app.php
+++ b/lib/private/app.php
@@ -27,8 +27,6 @@
* upgrading and removing apps.
*/
class OC_App{
- static private $activeapp = '';
- static private $navigation = array();
static private $settingsForms = array();
static private $adminForms = array();
static private $personalForms = array();
@@ -73,11 +71,11 @@ class OC_App{
if (!defined('DEBUG') || !DEBUG) {
if (is_null($types)
- && empty(OC_Util::$core_scripts)
- && empty(OC_Util::$core_styles)) {
- OC_Util::$core_scripts = OC_Util::$scripts;
+ && empty(OC_Util::$coreScripts)
+ && empty(OC_Util::$coreStyles)) {
+ OC_Util::$coreScripts = OC_Util::$scripts;
OC_Util::$scripts = array();
- OC_Util::$core_styles = OC_Util::$styles;
+ OC_Util::$coreStyles = OC_Util::$styles;
OC_Util::$styles = array();
}
}
@@ -167,10 +165,14 @@ class OC_App{
/**
* get all enabled apps
*/
+ private static $enabledAppsCache = array();
public static function getEnabledApps() {
if(!OC_Config::getValue('installed', false)) {
return array();
}
+ if(!empty(self::$enabledAppsCache)) {
+ return self::$enabledAppsCache;
+ }
$apps=array('files');
$sql = 'SELECT `appid` FROM `*PREFIX*appconfig`'
.' WHERE `configkey` = \'enabled\' AND `configvalue`=\'yes\'';
@@ -189,6 +191,7 @@ class OC_App{
$apps[]=$row['appid'];
}
}
+ self::$enabledAppsCache = $apps;
return $apps;
}
@@ -200,21 +203,23 @@ class OC_App{
* This function checks whether or not an app is enabled.
*/
public static function isEnabled( $app ) {
- if( 'files'==$app or ('yes' == OC_Appconfig::getValue( $app, 'enabled' ))) {
+ if('files' == $app) {
return true;
}
-
- return false;
+ $enabledApps = self::getEnabledApps();
+ return in_array($app, $enabledApps);
}
/**
* @brief enables an app
* @param mixed $app app
- * @return bool
+ * @throws \Exception
+ * @return void
*
* This function set an app as enabled in appconfig.
*/
public static function enable( $app ) {
+ self::$enabledAppsCache = array(); // flush
if(!OC_Installer::isInstalled($app)) {
// check if app is a shipped app or not. OCS apps have an integer as id, shipped apps use a string
if(!is_numeric($app)) {
@@ -228,25 +233,26 @@ class OC_App{
}
}
}
+ $l = OC_L10N::get('core');
if($app!==false) {
// check if the app is compatible with this version of ownCloud
$info=OC_App::getAppInfo($app);
$version=OC_Util::getVersion();
if(!isset($info['require']) or !self::isAppVersionCompatible($version, $info['require'])) {
- OC_Log::write('core',
- 'App "'.$info['name'].'" can\'t be installed because it is'
- .' not compatible with this version of ownCloud',
- OC_Log::ERROR);
- return false;
+ throw new \Exception(
+ $l->t("App \"%s\" can't be installed because it is not compatible with this version of ownCloud.",
+ array($info['name'])
+ )
+ );
}else{
OC_Appconfig::setValue( $app, 'enabled', 'yes' );
if(isset($appdata['id'])) {
OC_Appconfig::setValue( $app, 'ocsid', $appdata['id'] );
}
- return true;
+ \OC_Hook::emit('OC_App', 'post_enable', array('app' => $app));
}
}else{
- return false;
+ throw new \Exception($l->t("No app name specified"));
}
}
@@ -258,6 +264,7 @@ class OC_App{
* This function set an app as disabled in appconfig.
*/
public static function disable( $app ) {
+ self::$enabledAppsCache = array(); // flush
// check if app is a shipped app or not. if not delete
\OC_Hook::emit('OC_App', 'pre_disable', array('app' => $app));
OC_Appconfig::setValue( $app, 'enabled', 'no' );
@@ -270,7 +277,7 @@ class OC_App{
/**
* @brief adds an entry to the navigation
- * @param string $data array containing the data
+ * @param array $data array containing the data
* @return bool
*
* This function adds a new entry to the navigation visible to users. $data
@@ -286,11 +293,7 @@ class OC_App{
* the navigation. Lower values come first.
*/
public static function addNavigationEntry( $data ) {
- $data['active']=false;
- if(!isset($data['icon'])) {
- $data['icon']='';
- }
- OC_App::$navigation[] = $data;
+ OC::$server->getNavigationManager()->add($data);
return true;
}
@@ -304,9 +307,7 @@ class OC_App{
* highlighting the current position of the user.
*/
public static function setActiveNavigationEntry( $id ) {
- // load all the apps, to make sure we have all the navigation entries
- self::loadApps();
- self::$activeapp = $id;
+ OC::$server->getNavigationManager()->setActiveEntry($id);
return true;
}
@@ -314,15 +315,14 @@ class OC_App{
* @brief Get the navigation entries for the $app
* @param string $app app
* @return array of the $data added with addNavigationEntry
+ *
+ * Warning: destroys the existing entries
*/
public static function getAppNavigationEntries($app) {
if(is_file(self::getAppPath($app).'/appinfo/app.php')) {
- $save = self::$navigation;
- self::$navigation = array();
+ OC::$server->getNavigationManager()->clear();
require $app.'/appinfo/app.php';
- $app_entries = self::$navigation;
- self::$navigation = $save;
- return $app_entries;
+ return OC::$server->getNavigationManager()->getAll();
}
return array();
}
@@ -335,7 +335,7 @@ class OC_App{
* setActiveNavigationEntry
*/
public static function getActiveNavigationEntry() {
- return self::$activeapp;
+ return OC::$server->getNavigationManager()->getActiveEntry();
}
/**
@@ -418,8 +418,9 @@ class OC_App{
// This is private as well. It simply works, so don't ask for more details
private static function proceedNavigation( $list ) {
+ $activeapp = OC::$server->getNavigationManager()->getActiveEntry();
foreach( $list as &$naventry ) {
- if( $naventry['id'] == self::$activeapp ) {
+ if( $naventry['id'] == $activeapp ) {
$naventry['active'] = true;
}
else{
@@ -571,7 +572,8 @@ class OC_App{
* - active: boolean, signals if the user is on this navigation entry
*/
public static function getNavigation() {
- $navigation = self::proceedNavigation( self::$navigation );
+ $entries = OC::$server->getNavigationManager()->getAll();
+ $navigation = self::proceedNavigation( $entries );
return $navigation;
}
@@ -666,14 +668,16 @@ class OC_App{
}
$dh = opendir( $apps_dir['path'] );
- while( $file = readdir( $dh ) ) {
+ if(is_resource($dh)) {
+ while (($file = readdir($dh)) !== false) {
- if ($file[0] != '.' and is_file($apps_dir['path'].'/'.$file.'/appinfo/app.php')) {
+ if ($file[0] != '.' and is_file($apps_dir['path'].'/'.$file.'/appinfo/app.php')) {
- $apps[] = $file;
+ $apps[] = $file;
- }
+ }
+ }
}
}
@@ -749,10 +753,43 @@ class OC_App{
} else {
$combinedApps = $appList;
}
+ // bring the apps into the right order with a custom sort funtion
+ usort( $combinedApps, '\OC_App::customSort' );
+
return $combinedApps;
}
/**
+ * @brief: Internal custom sort funtion to bring the app into the right order. Should only be called by listAllApps
+ * @return array
+ */
+ private static function customSort($a, $b) {
+
+ // prio 1: active
+ if ($a['active'] != $b['active']) {
+ return $b['active'] - $a['active'];
+ }
+
+ // prio 2: shipped
+ $ashipped = (array_key_exists('shipped', $a) && $a['shipped'] === 'true') ? 1 : 0;
+ $bshipped = (array_key_exists('shipped', $b) && $b['shipped'] === 'true') ? 1 : 0;
+ if ($ashipped !== $bshipped) {
+ return ($bshipped - $ashipped);
+ }
+
+ // prio 3: recommended
+ if ($a['internalclass'] != $b['internalclass']) {
+ $atemp = ($a['internalclass'] == 'recommendedapp' ? 1 : 0);
+ $btemp = ($b['internalclass'] == 'recommendedapp' ? 1 : 0);
+ return ($btemp - $atemp);
+ }
+
+ // prio 4: alphabetical
+ return strcasecmp($a['name'], $b['name']);
+
+ }
+
+ /**
* @brief: get a list of all apps on apps.owncloud.com
* @return array, multi-dimensional array of apps.
* Keys: id, name, type, typename, personid, license, detailpage, preview, changed, description
@@ -867,10 +904,10 @@ class OC_App{
/**
- * Compares the app version with the owncloud version to see if the app
+ * Compares the app version with the owncloud version to see if the app
* requires a newer version than the currently active one
* @param array $owncloudVersions array with 3 entries: major minor bugfix
- * @param string $appRequired the required version from the xml
+ * @param string $appRequired the required version from the xml
* major.minor.bugfix
* @return boolean true if compatible, otherwise false
*/
diff --git a/lib/appconfig.php b/lib/private/appconfig.php
index e615d838173..4f170e054e9 100644
--- a/lib/appconfig.php
+++ b/lib/private/appconfig.php
@@ -134,6 +134,12 @@ class OC_Appconfig{
.' WHERE `appid` = ? AND `configkey` = ?' );
$query->execute( array( $value, $app, $key ));
}
+ // TODO where should this be documented?
+ \OC_Hook::emit('OC_Appconfig', 'post_set_value', array(
+ 'app' => $app,
+ 'key' => $key,
+ 'value' => $value
+ ));
}
/**
diff --git a/lib/private/appframework/app.php b/lib/private/appframework/app.php
new file mode 100644
index 00000000000..b835188661a
--- /dev/null
+++ b/lib/private/appframework/app.php
@@ -0,0 +1,99 @@
+<?php
+
+/**
+ * ownCloud - App Framework
+ *
+ * @author Bernhard Posselt
+ * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+namespace OC\AppFramework;
+
+use OC\AppFramework\DependencyInjection\DIContainer;
+use OCP\AppFramework\IAppContainer;
+
+
+/**
+ * Entry point for every request in your app. You can consider this as your
+ * public static void main() method
+ *
+ * Handles all the dependency injection, controllers and output flow
+ */
+class App {
+
+
+ /**
+ * Shortcut for calling a controller method and printing the result
+ * @param string $controllerName the name of the controller under which it is
+ * stored in the DI container
+ * @param string $methodName the method that you want to call
+ * @param DIContainer $container an instance of a pimple container.
+ * @param array $urlParams list of URL parameters (optional)
+ */
+ public static function main($controllerName, $methodName, DIContainer $container, array $urlParams = null) {
+ if (!is_null($urlParams)) {
+ $container['urlParams'] = $urlParams;
+ }
+ $controller = $container[$controllerName];
+
+ // initialize the dispatcher and run all the middleware before the controller
+ $dispatcher = $container['Dispatcher'];
+
+ list($httpHeaders, $responseHeaders, $output) =
+ $dispatcher->dispatch($controller, $methodName);
+
+ if(!is_null($httpHeaders)) {
+ header($httpHeaders);
+ }
+
+ foreach($responseHeaders as $name => $value) {
+ header($name . ': ' . $value);
+ }
+
+ if(!is_null($output)) {
+ header('Content-Length: ' . strlen($output));
+ print($output);
+ }
+
+ }
+
+ /**
+ * Shortcut for calling a controller method and printing the result.
+ * Similar to App:main except that no headers will be sent.
+ * This should be used for example when registering sections via
+ * \OC\AppFramework\Core\API::registerAdmin()
+ *
+ * @param string $controllerName the name of the controller under which it is
+ * stored in the DI container
+ * @param string $methodName the method that you want to call
+ * @param array $urlParams an array with variables extracted from the routes
+ * @param DIContainer $container an instance of a pimple container.
+ */
+ public static function part($controllerName, $methodName, array $urlParams,
+ DIContainer $container){
+
+ $container['urlParams'] = $urlParams;
+ $controller = $container[$controllerName];
+
+ $dispatcher = $container['Dispatcher'];
+
+ list(, , $output) = $dispatcher->dispatch($controller, $methodName);
+ return $output;
+ }
+
+}
diff --git a/lib/private/appframework/core/api.php b/lib/private/appframework/core/api.php
new file mode 100644
index 00000000000..e7269373bb0
--- /dev/null
+++ b/lib/private/appframework/core/api.php
@@ -0,0 +1,184 @@
+<?php
+
+/**
+ * ownCloud - App Framework
+ *
+ * @author Bernhard Posselt
+ * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+namespace OC\AppFramework\Core;
+use OCP\AppFramework\IApi;
+
+
+/**
+ * This is used to wrap the owncloud static api calls into an object to make the
+ * code better abstractable for use in the dependency injection container
+ *
+ * Should you find yourself in need for more methods, simply inherit from this
+ * class and add your methods
+ */
+class API implements IApi{
+
+ private $appName;
+
+ /**
+ * constructor
+ * @param string $appName the name of your application
+ */
+ public function __construct($appName){
+ $this->appName = $appName;
+ }
+
+
+ /**
+ * Gets the userid of the current user
+ * @return string the user id of the current user
+ */
+ public function getUserId(){
+ return \OCP\User::getUser();
+ }
+
+
+ /**
+ * Adds a new javascript file
+ * @param string $scriptName the name of the javascript in js/ without the suffix
+ * @param string $appName the name of the app, defaults to the current one
+ */
+ public function addScript($scriptName, $appName=null){
+ if($appName === null){
+ $appName = $this->appName;
+ }
+ \OCP\Util::addScript($appName, $scriptName);
+ }
+
+
+ /**
+ * Adds a new css file
+ * @param string $styleName the name of the css file in css/without the suffix
+ * @param string $appName the name of the app, defaults to the current one
+ */
+ public function addStyle($styleName, $appName=null){
+ if($appName === null){
+ $appName = $this->appName;
+ }
+ \OCP\Util::addStyle($appName, $styleName);
+ }
+
+
+ /**
+ * shorthand for addScript for files in the 3rdparty directory
+ * @param string $name the name of the file without the suffix
+ */
+ public function add3rdPartyScript($name){
+ \OCP\Util::addScript($this->appName . '/3rdparty', $name);
+ }
+
+
+ /**
+ * shorthand for addStyle for files in the 3rdparty directory
+ * @param string $name the name of the file without the suffix
+ */
+ public function add3rdPartyStyle($name){
+ \OCP\Util::addStyle($this->appName . '/3rdparty', $name);
+ }
+
+
+ /**
+ * Checks if an app is enabled
+ * @param string $appName the name of an app
+ * @return bool true if app is enabled
+ */
+ public function isAppEnabled($appName){
+ return \OCP\App::isEnabled($appName);
+ }
+
+
+ /**
+ * used to return and open a new eventsource
+ * @return \OC_EventSource a new open EventSource class
+ */
+ public function openEventSource(){
+ # TODO: use public api
+ return new \OC_EventSource();
+ }
+
+ /**
+ * @brief connects a function to a hook
+ * @param string $signalClass class name of emitter
+ * @param string $signalName name of signal
+ * @param string $slotClass class name of slot
+ * @param string $slotName name of slot, in another word, this is the
+ * name of the method that will be called when registered
+ * signal is emitted.
+ * @return bool, always true
+ */
+ public function connectHook($signalClass, $signalName, $slotClass, $slotName) {
+ return \OCP\Util::connectHook($signalClass, $signalName, $slotClass, $slotName);
+ }
+
+ /**
+ * @brief Emits a signal. To get data from the slot use references!
+ * @param string $signalClass class name of emitter
+ * @param string $signalName name of signal
+ * @param array $params defautl: array() array with additional data
+ * @return bool, true if slots exists or false if not
+ */
+ public function emitHook($signalClass, $signalName, $params = array()) {
+ return \OCP\Util::emitHook($signalClass, $signalName, $params);
+ }
+
+ /**
+ * @brief clear hooks
+ * @param string $signalClass
+ * @param string $signalName
+ */
+ public function clearHook($signalClass=false, $signalName=false) {
+ if ($signalClass) {
+ \OC_Hook::clear($signalClass, $signalName);
+ }
+ }
+
+
+ /**
+ * Register a backgroundjob task
+ * @param string $className full namespace and class name of the class
+ * @param string $methodName the name of the static method that should be
+ * called
+ */
+ public function addRegularTask($className, $methodName) {
+ \OCP\Backgroundjob::addRegularTask($className, $methodName);
+ }
+
+
+ /**
+ * Tells ownCloud to include a template in the admin overview
+ * @param string $mainPath the path to the main php file without the php
+ * suffix, relative to your apps directory! not the template directory
+ * @param string $appName the name of the app, defaults to the current one
+ */
+ public function registerAdmin($mainPath, $appName=null) {
+ if($appName === null){
+ $appName = $this->appName;
+ }
+
+ \OCP\App::registerAdmin($appName, $mainPath);
+ }
+
+
+}
diff --git a/lib/private/appframework/dependencyinjection/dicontainer.php b/lib/private/appframework/dependencyinjection/dicontainer.php
new file mode 100644
index 00000000000..e2ea974e104
--- /dev/null
+++ b/lib/private/appframework/dependencyinjection/dicontainer.php
@@ -0,0 +1,196 @@
+<?php
+
+/**
+ * ownCloud - App Framework
+ *
+ * @author Bernhard Posselt
+ * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+namespace OC\AppFramework\DependencyInjection;
+
+use OC\AppFramework\Http;
+use OC\AppFramework\Http\Request;
+use OC\AppFramework\Http\Dispatcher;
+use OC\AppFramework\Core\API;
+use OC\AppFramework\Middleware\MiddlewareDispatcher;
+use OC\AppFramework\Middleware\Security\SecurityMiddleware;
+use OC\AppFramework\Utility\SimpleContainer;
+use OC\AppFramework\Utility\TimeFactory;
+use OCP\AppFramework\IApi;
+use OCP\AppFramework\IAppContainer;
+use OCP\AppFramework\IMiddleWare;
+use OCP\AppFramework\Middleware;
+use OCP\IServerContainer;
+
+
+class DIContainer extends SimpleContainer implements IAppContainer{
+
+ /**
+ * @var array
+ */
+ private $middleWares = array();
+
+ /**
+ * Put your class dependencies in here
+ * @param string $appName the name of the app
+ */
+ public function __construct($appName, $urlParams = array()){
+
+ $this['AppName'] = $appName;
+ $this['urlParams'] = $urlParams;
+
+ $this->registerParameter('ServerContainer', \OC::$server);
+
+ $this['API'] = $this->share(function($c){
+ return new API($c['AppName']);
+ });
+
+ /**
+ * Http
+ */
+ $this['Request'] = $this->share(function($c) {
+ /** @var $c SimpleContainer */
+ /** @var $server IServerContainer */
+ $server = $c->query('ServerContainer');
+ $server->registerParameter('urlParams', $c['urlParams']);
+ return $server->getRequest();
+ });
+
+ $this['Protocol'] = $this->share(function($c){
+ if(isset($_SERVER['SERVER_PROTOCOL'])) {
+ return new Http($_SERVER, $_SERVER['SERVER_PROTOCOL']);
+ } else {
+ return new Http($_SERVER);
+ }
+ });
+
+ $this['Dispatcher'] = $this->share(function($c) {
+ return new Dispatcher($c['Protocol'], $c['MiddlewareDispatcher']);
+ });
+
+
+ /**
+ * Middleware
+ */
+ $app = $this;
+ $this['SecurityMiddleware'] = $this->share(function($c) use ($app){
+ return new SecurityMiddleware($app, $c['Request']);
+ });
+
+ $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);
+ }
+
+ return $dispatcher;
+ });
+
+
+ /**
+ * Utilities
+ */
+ $this['TimeFactory'] = $this->share(function($c){
+ return new TimeFactory();
+ });
+
+
+ }
+
+
+ /**
+ * @return IApi
+ */
+ function getCoreApi()
+ {
+ return $this->query('API');
+ }
+
+ /**
+ * @return \OCP\IServerContainer
+ */
+ function getServer()
+ {
+ return $this->query('ServerContainer');
+ }
+
+ /**
+ * @param Middleware $middleWare
+ * @return boolean
+ */
+ function registerMiddleWare(Middleware $middleWare) {
+ array_push($this->middleWares, $middleWare);
+ }
+
+ /**
+ * used to return the appname of the set application
+ * @return string the name of your application
+ */
+ function getAppName() {
+ return $this->query('AppName');
+ }
+
+ /**
+ * @return boolean
+ */
+ function isLoggedIn() {
+ return \OC_User::isLoggedIn();
+ }
+
+ /**
+ * @return boolean
+ */
+ function isAdminUser() {
+ $uid = $this->getUserId();
+ return \OC_User::isAdminUser($uid);
+ }
+
+ private function getUserId() {
+ return \OC::$session->get('user_id');
+ }
+
+ /**
+ * @param $message
+ * @param $level
+ * @return mixed
+ */
+ function log($message, $level) {
+ switch($level){
+ case 'debug':
+ $level = \OCP\Util::DEBUG;
+ break;
+ case 'info':
+ $level = \OCP\Util::INFO;
+ break;
+ case 'warn':
+ $level = \OCP\Util::WARN;
+ break;
+ case 'fatal':
+ $level = \OCP\Util::FATAL;
+ break;
+ default:
+ $level = \OCP\Util::ERROR;
+ break;
+ }
+ \OCP\Util::writeLog($this->getAppName(), $message, $level);
+ }
+}
diff --git a/lib/private/appframework/http.php b/lib/private/appframework/http.php
new file mode 100644
index 00000000000..41fc0db6b38
--- /dev/null
+++ b/lib/private/appframework/http.php
@@ -0,0 +1,149 @@
+<?php
+
+/**
+ * ownCloud - App Framework
+ *
+ * @author Bernhard Posselt, Thomas Tanghus, Bart Visscher
+ * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+namespace OC\AppFramework;
+
+use OCP\AppFramework\Http as BaseHttp;
+
+class Http extends BaseHttp {
+
+ private $server;
+ private $protocolVersion;
+ protected $headers;
+
+ /**
+ * @param $_SERVER $server
+ * @param string $protocolVersion the http version to use defaults to HTTP/1.1
+ */
+ public function __construct($server, $protocolVersion='HTTP/1.1') {
+ $this->server = $server;
+ $this->protocolVersion = $protocolVersion;
+
+ $this->headers = array(
+ self::STATUS_CONTINUE => 'Continue',
+ self::STATUS_SWITCHING_PROTOCOLS => 'Switching Protocols',
+ self::STATUS_PROCESSING => 'Processing',
+ self::STATUS_OK => 'OK',
+ self::STATUS_CREATED => 'Created',
+ self::STATUS_ACCEPTED => 'Accepted',
+ self::STATUS_NON_AUTHORATIVE_INFORMATION => 'Non-Authorative Information',
+ self::STATUS_NO_CONTENT => 'No Content',
+ self::STATUS_RESET_CONTENT => 'Reset Content',
+ self::STATUS_PARTIAL_CONTENT => 'Partial Content',
+ self::STATUS_MULTI_STATUS => 'Multi-Status', // RFC 4918
+ self::STATUS_ALREADY_REPORTED => 'Already Reported', // RFC 5842
+ self::STATUS_IM_USED => 'IM Used', // RFC 3229
+ self::STATUS_MULTIPLE_CHOICES => 'Multiple Choices',
+ self::STATUS_MOVED_PERMANENTLY => 'Moved Permanently',
+ self::STATUS_FOUND => 'Found',
+ self::STATUS_SEE_OTHER => 'See Other',
+ self::STATUS_NOT_MODIFIED => 'Not Modified',
+ self::STATUS_USE_PROXY => 'Use Proxy',
+ self::STATUS_RESERVED => 'Reserved',
+ self::STATUS_TEMPORARY_REDIRECT => 'Temporary Redirect',
+ self::STATUS_BAD_REQUEST => 'Bad request',
+ self::STATUS_UNAUTHORIZED => 'Unauthorized',
+ self::STATUS_PAYMENT_REQUIRED => 'Payment Required',
+ self::STATUS_FORBIDDEN => 'Forbidden',
+ self::STATUS_NOT_FOUND => 'Not Found',
+ self::STATUS_METHOD_NOT_ALLOWED => 'Method Not Allowed',
+ self::STATUS_NOT_ACCEPTABLE => 'Not Acceptable',
+ self::STATUS_PROXY_AUTHENTICATION_REQUIRED => 'Proxy Authentication Required',
+ self::STATUS_REQUEST_TIMEOUT => 'Request Timeout',
+ self::STATUS_CONFLICT => 'Conflict',
+ self::STATUS_GONE => 'Gone',
+ self::STATUS_LENGTH_REQUIRED => 'Length Required',
+ self::STATUS_PRECONDITION_FAILED => 'Precondition failed',
+ self::STATUS_REQUEST_ENTITY_TOO_LARGE => 'Request Entity Too Large',
+ self::STATUS_REQUEST_URI_TOO_LONG => 'Request-URI Too Long',
+ self::STATUS_UNSUPPORTED_MEDIA_TYPE => 'Unsupported Media Type',
+ self::STATUS_REQUEST_RANGE_NOT_SATISFIABLE => 'Requested Range Not Satisfiable',
+ self::STATUS_EXPECTATION_FAILED => 'Expectation Failed',
+ self::STATUS_IM_A_TEAPOT => 'I\'m a teapot', // RFC 2324
+ self::STATUS_UNPROCESSABLE_ENTITY => 'Unprocessable Entity', // RFC 4918
+ self::STATUS_LOCKED => 'Locked', // RFC 4918
+ self::STATUS_FAILED_DEPENDENCY => 'Failed Dependency', // RFC 4918
+ self::STATUS_UPGRADE_REQUIRED => 'Upgrade required',
+ self::STATUS_PRECONDITION_REQUIRED => 'Precondition required', // draft-nottingham-http-new-status
+ self::STATUS_TOO_MANY_REQUESTS => 'Too Many Requests', // draft-nottingham-http-new-status
+ self::STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE => 'Request Header Fields Too Large', // draft-nottingham-http-new-status
+ self::STATUS_INTERNAL_SERVER_ERROR => 'Internal Server Error',
+ self::STATUS_NOT_IMPLEMENTED => 'Not Implemented',
+ self::STATUS_BAD_GATEWAY => 'Bad Gateway',
+ self::STATUS_SERVICE_UNAVAILABLE => 'Service Unavailable',
+ self::STATUS_GATEWAY_TIMEOUT => 'Gateway Timeout',
+ self::STATUS_HTTP_VERSION_NOT_SUPPORTED => 'HTTP Version not supported',
+ self::STATUS_VARIANT_ALSO_NEGOTIATES => 'Variant Also Negotiates',
+ self::STATUS_INSUFFICIENT_STORAGE => 'Insufficient Storage', // RFC 4918
+ self::STATUS_LOOP_DETECTED => 'Loop Detected', // RFC 5842
+ self::STATUS_BANDWIDTH_LIMIT_EXCEEDED => 'Bandwidth Limit Exceeded', // non-standard
+ self::STATUS_NOT_EXTENDED => 'Not extended',
+ self::STATUS_NETWORK_AUTHENTICATION_REQUIRED => 'Network Authentication Required', // draft-nottingham-http-new-status
+ );
+ }
+
+
+ /**
+ * Gets the correct header
+ * @param Http::CONSTANT $status the constant from the Http class
+ * @param \DateTime $lastModified formatted last modified date
+ * @param string $Etag the etag
+ */
+ public function getStatusHeader($status, \DateTime $lastModified=null,
+ $ETag=null) {
+
+ if(!is_null($lastModified)) {
+ $lastModified = $lastModified->format(\DateTime::RFC2822);
+ }
+
+ // if etag or lastmodified have not changed, return a not modified
+ if ((isset($this->server['HTTP_IF_NONE_MATCH'])
+ && trim($this->server['HTTP_IF_NONE_MATCH']) === $ETag)
+
+ ||
+
+ (isset($this->server['HTTP_IF_MODIFIED_SINCE'])
+ && trim($this->server['HTTP_IF_MODIFIED_SINCE']) ===
+ $lastModified)) {
+
+ $status = self::STATUS_NOT_MODIFIED;
+ }
+
+ // we have one change currently for the http 1.0 header that differs
+ // from 1.1: STATUS_TEMPORARY_REDIRECT should be STATUS_FOUND
+ // if this differs any more, we want to create childclasses for this
+ if($status === self::STATUS_TEMPORARY_REDIRECT
+ && $this->protocolVersion === 'HTTP/1.0') {
+
+ $status = self::STATUS_FOUND;
+ }
+
+ return $this->protocolVersion . ' ' . $status . ' ' .
+ $this->headers[$status];
+ }
+
+
+}
+
+
diff --git a/lib/private/appframework/http/dispatcher.php b/lib/private/appframework/http/dispatcher.php
new file mode 100644
index 00000000000..a2afb53f0fa
--- /dev/null
+++ b/lib/private/appframework/http/dispatcher.php
@@ -0,0 +1,101 @@
+<?php
+
+/**
+ * ownCloud - App Framework
+ *
+ * @author Bernhard Posselt, Thomas Tanghus, Bart Visscher
+ * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+namespace OC\AppFramework\Http;
+
+use \OC\AppFramework\Middleware\MiddlewareDispatcher;
+use \OC\AppFramework\Http;
+use OCP\AppFramework\Controller;
+
+
+/**
+ * Class to dispatch the request to the middleware dispatcher
+ */
+class Dispatcher {
+
+ private $middlewareDispatcher;
+ private $protocol;
+
+
+ /**
+ * @param Http $protocol the http protocol with contains all status headers
+ * @param MiddlewareDispatcher $middlewareDispatcher the dispatcher which
+ * runs the middleware
+ */
+ public function __construct(Http $protocol,
+ MiddlewareDispatcher $middlewareDispatcher) {
+ $this->protocol = $protocol;
+ $this->middlewareDispatcher = $middlewareDispatcher;
+ }
+
+
+ /**
+ * Handles a request and calls the dispatcher on the controller
+ * @param Controller $controller the controller which will be called
+ * @param string $methodName the method name which will be called on
+ * the controller
+ * @return array $array[0] contains a string with the http main header,
+ * $array[1] contains headers in the form: $key => value, $array[2] contains
+ * the response output
+ */
+ public function dispatch(Controller $controller, $methodName) {
+ $out = array(null, array(), null);
+
+ try {
+
+ $this->middlewareDispatcher->beforeController($controller,
+ $methodName);
+ $response = $controller->$methodName();
+
+ // if an exception appears, the middleware checks if it can handle the
+ // exception and creates a response. If no response is created, it is
+ // assumed that theres no middleware who can handle it and the error is
+ // thrown again
+ } catch(\Exception $exception){
+ $response = $this->middlewareDispatcher->afterException(
+ $controller, $methodName, $exception);
+ if (is_null($response)) {
+ throw $exception;
+ }
+ }
+
+ $response = $this->middlewareDispatcher->afterController(
+ $controller, $methodName, $response);
+
+ // get the output which should be printed and run the after output
+ // middleware to modify the response
+ $output = $response->render();
+ $out[2] = $this->middlewareDispatcher->beforeOutput(
+ $controller, $methodName, $output);
+
+ // depending on the cache object the headers need to be changed
+ $out[0] = $this->protocol->getStatusHeader($response->getStatus(),
+ $response->getLastModified(), $response->getETag());
+ $out[1] = $response->getHeaders();
+
+ return $out;
+ }
+
+
+}
diff --git a/lib/private/appframework/http/downloadresponse.php b/lib/private/appframework/http/downloadresponse.php
new file mode 100644
index 00000000000..67b9542dba6
--- /dev/null
+++ b/lib/private/appframework/http/downloadresponse.php
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * ownCloud - App Framework
+ *
+ * @author Bernhard Posselt
+ * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+namespace OC\AppFramework\Http;
+
+
+/**
+ * Prompts the user to download the a file
+ */
+class DownloadResponse extends \OCP\AppFramework\Http\Response {
+
+ private $filename;
+ private $contentType;
+
+ /**
+ * Creates a response that prompts the user to download the file
+ * @param string $filename the name that the downloaded file should have
+ * @param string $contentType the mimetype that the downloaded file should have
+ */
+ public function __construct($filename, $contentType) {
+ $this->filename = $filename;
+ $this->contentType = $contentType;
+
+ $this->addHeader('Content-Disposition', 'attachment; filename="' . $filename . '"');
+ $this->addHeader('Content-Type', $contentType);
+ }
+
+
+}
diff --git a/lib/private/appframework/http/redirectresponse.php b/lib/private/appframework/http/redirectresponse.php
new file mode 100644
index 00000000000..c4e21059480
--- /dev/null
+++ b/lib/private/appframework/http/redirectresponse.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * ownCloud - App Framework
+ *
+ * @author Bernhard Posselt
+ * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+namespace OC\AppFramework\Http;
+
+use OCP\AppFramework\Http\Response,
+ OCP\AppFramework\Http;
+
+
+/**
+ * Redirects to a different URL
+ */
+class RedirectResponse extends Response {
+
+ private $redirectURL;
+
+ /**
+ * Creates a response that redirects to a url
+ * @param string $redirectURL the url to redirect to
+ */
+ public function __construct($redirectURL) {
+ $this->redirectURL = $redirectURL;
+ $this->setStatus(Http::STATUS_TEMPORARY_REDIRECT);
+ $this->addHeader('Location', $redirectURL);
+ }
+
+
+ /**
+ * @return string the url to redirect
+ */
+ public function getRedirectURL() {
+ return $this->redirectURL;
+ }
+
+
+}
diff --git a/lib/private/appframework/http/request.php b/lib/private/appframework/http/request.php
new file mode 100644
index 00000000000..3e1f4ff87ed
--- /dev/null
+++ b/lib/private/appframework/http/request.php
@@ -0,0 +1,389 @@
+<?php
+/**
+ * ownCloud - Request
+ *
+ * @author Thomas Tanghus
+ * @copyright 2013 Thomas Tanghus (thomas@tanghus.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\AppFramework\Http;
+
+use OCP\IRequest;
+
+/**
+ * Class for accessing variables in the request.
+ * This class provides an immutable object with request variables.
+ */
+
+class Request implements \ArrayAccess, \Countable, IRequest {
+
+ protected $inputStream;
+ protected $content;
+ protected $items = array();
+ protected $allowedKeys = array(
+ 'get',
+ 'post',
+ 'files',
+ 'server',
+ 'env',
+ 'cookies',
+ 'urlParams',
+ 'parameters',
+ 'method',
+ 'requesttoken',
+ );
+
+ /**
+ * @param array $vars An associative array with the following optional values:
+ * @param array 'urlParams' the parameters which were matched from the URL
+ * @param array 'get' the $_GET array
+ * @param array|string 'post' the $_POST array or JSON string
+ * @param array 'files' the $_FILES array
+ * @param array 'server' the $_SERVER array
+ * @param array 'env' the $_ENV array
+ * @param array 'cookies' the $_COOKIE array
+ * @param string 'method' the request method (GET, POST etc)
+ * @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()) {
+
+ foreach($this->allowedKeys as $name) {
+ $this->items[$name] = isset($vars[$name])
+ ? $vars[$name]
+ : 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);
+ }
+
+ $this->items['parameters'] = array_merge(
+ $this->items['get'],
+ $this->items['post'],
+ $this->items['urlParams']
+ );
+
+ }
+
+ // Countable method.
+ public function count() {
+ return count(array_keys($this->items['parameters']));
+ }
+
+ /**
+ * ArrayAccess methods
+ *
+ * Gives access to the combined GET, POST and urlParams arrays
+ *
+ * Examples:
+ *
+ * $var = $request['myvar'];
+ *
+ * or
+ *
+ * if(!isset($request['myvar']) {
+ * // Do something
+ * }
+ *
+ * $request['myvar'] = 'something'; // This throws an exception.
+ *
+ * @param string $offset The key to lookup
+ * @return string|null
+ */
+ public function offsetExists($offset) {
+ return isset($this->items['parameters'][$offset]);
+ }
+
+ /**
+ * @see offsetExists
+ */
+ public function offsetGet($offset) {
+ return isset($this->items['parameters'][$offset])
+ ? $this->items['parameters'][$offset]
+ : null;
+ }
+
+ /**
+ * @see offsetExists
+ */
+ public function offsetSet($offset, $value) {
+ throw new \RuntimeException('You cannot change the contents of the request object');
+ }
+
+ /**
+ * @see offsetExists
+ */
+ public function offsetUnset($offset) {
+ throw new \RuntimeException('You cannot change the contents of the request object');
+ }
+
+ // Magic property accessors
+ public function __set($name, $value) {
+ throw new \RuntimeException('You cannot change the contents of the request object');
+ }
+
+ /**
+ * Access request variables by method and name.
+ * Examples:
+ *
+ * $request->post['myvar']; // Only look for POST variables
+ * $request->myvar; or $request->{'myvar'}; or $request->{$myvar}
+ * Looks in the combined GET, POST and urlParams array.
+ *
+ * If you access e.g. ->post but the current HTTP request method
+ * is GET a \LogicException will be thrown.
+ *
+ * @param string $name The key to look for.
+ * @throws \LogicException
+ * @return mixed|null
+ */
+ public function __get($name) {
+ switch($name) {
+ case 'put':
+ case 'patch':
+ case 'get':
+ case 'post':
+ if($this->method !== strtoupper($name)) {
+ throw new \LogicException(sprintf('%s cannot be accessed in a %s request.', $name, $this->method));
+ }
+ case 'files':
+ case 'server':
+ case 'env':
+ case 'cookies':
+ case 'parameters':
+ case 'params':
+ case 'urlParams':
+ if(in_array($name, array('put', 'patch'))) {
+ return $this->getContent($name);
+ } else {
+ return isset($this->items[$name])
+ ? $this->items[$name]
+ : null;
+ }
+ break;
+ case 'method':
+ return $this->items['method'];
+ break;
+ default;
+ return isset($this[$name])
+ ? $this[$name]
+ : null;
+ break;
+ }
+ }
+
+
+ public function __isset($name) {
+ return isset($this->items['parameters'][$name]);
+ }
+
+
+ public function __unset($id) {
+ throw new \RunTimeException('You cannot change the contents of the request object');
+ }
+
+ /**
+ * Returns the value for a specific http header.
+ *
+ * This method returns null if the header did not exist.
+ *
+ * @param string $name
+ * @return string
+ */
+ public function getHeader($name) {
+
+ $name = strtoupper(str_replace(array('-'),array('_'),$name));
+ if (isset($this->server['HTTP_' . $name])) {
+ return $this->server['HTTP_' . $name];
+ }
+
+ // There's a few headers that seem to end up in the top-level
+ // server array.
+ switch($name) {
+ case 'CONTENT_TYPE' :
+ case 'CONTENT_LENGTH' :
+ if (isset($this->server[$name])) {
+ return $this->server[$name];
+ }
+ break;
+
+ }
+
+ return null;
+ }
+
+ /**
+ * Lets you access post and get parameters by the index
+ * In case of json requests the encoded json body is accessed
+ *
+ * @param string $key the key which you want to access in the URL Parameter
+ * placeholder, $_POST or $_GET array.
+ * The priority how they're returned is the following:
+ * 1. URL parameters
+ * 2. POST parameters
+ * 3. GET parameters
+ * @param mixed $default If the key is not found, this value will be returned
+ * @return mixed the content of the array
+ */
+ public function getParam($key, $default = null) {
+ return isset($this->parameters[$key])
+ ? $this->parameters[$key]
+ : $default;
+ }
+
+ /**
+ * Returns all params that were received, be it from the request
+ * (as GET or POST) or throuh the URL by the route
+ * @return array the array with all parameters
+ */
+ public function getParams() {
+ return $this->parameters;
+ }
+
+ /**
+ * Returns the method of the request
+ * @return string the method of the request (POST, GET, etc)
+ */
+ public function getMethod() {
+ return $this->method;
+ }
+
+ /**
+ * Shortcut for accessing an uploaded file through the $_FILES array
+ * @param string $key the key that will be taken from the $_FILES array
+ * @return array the file in the $_FILES element
+ */
+ public function getUploadedFile($key) {
+ return isset($this->files[$key]) ? $this->files[$key] : null;
+ }
+
+ /**
+ * Shortcut for getting env variables
+ * @param string $key the key that will be taken from the $_ENV array
+ * @return array the value in the $_ENV element
+ */
+ public function getEnv($key) {
+ return isset($this->env[$key]) ? $this->env[$key] : null;
+ }
+
+ /**
+ * Shortcut for getting cookie variables
+ * @param string $key the key that will be taken from the $_COOKIE array
+ * @return array the value in the $_COOKIE element
+ */
+ function getCookie($key) {
+ return isset($this->cookies[$key]) ? $this->cookies[$key] : null;
+ }
+
+ /**
+ * Returns the request body content.
+ *
+ * If the HTTP request method is PUT and the body
+ * not application/x-www-form-urlencoded or application/json a stream
+ * resource is returned, otherwise an array.
+ *
+ * @return array|string|resource The request body content or a resource to read the body stream.
+ *
+ * @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
+ ) {
+ $this->content = false;
+ return fopen($this->inputStream, 'rb');
+ }
+
+ 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;
+ }
+
+ /**
+ * Checks if the CSRF check was correct
+ * @return bool true if CSRF check passed
+ * @see OC_Util::$callLifespan
+ * @see OC_Util::callRegister()
+ */
+ public function passesCSRFCheck() {
+ if($this->items['requesttoken'] === false) {
+ return false;
+ }
+
+ if (isset($this->items['get']['requesttoken'])) {
+ $token = $this->items['get']['requesttoken'];
+ } elseif (isset($this->items['post']['requesttoken'])) {
+ $token = $this->items['post']['requesttoken'];
+ } elseif (isset($this->items['server']['HTTP_REQUESTTOKEN'])) {
+ $token = $this->items['server']['HTTP_REQUESTTOKEN'];
+ } else {
+ //no token found.
+ return false;
+ }
+
+ // Check if the token is valid
+ if($token !== $this->items['requesttoken']) {
+ // Not valid
+ return false;
+ } else {
+ // Valid token
+ return true;
+ }
+ }}
diff --git a/lib/private/appframework/middleware/middlewaredispatcher.php b/lib/private/appframework/middleware/middlewaredispatcher.php
new file mode 100644
index 00000000000..681140c2242
--- /dev/null
+++ b/lib/private/appframework/middleware/middlewaredispatcher.php
@@ -0,0 +1,159 @@
+<?php
+
+/**
+ * ownCloud - App Framework
+ *
+ * @author Bernhard Posselt
+ * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+namespace OC\AppFramework\Middleware;
+
+use OCP\AppFramework\Controller;
+use OCP\AppFramework\Http\Response;
+use OCP\AppFramework\MiddleWare;
+
+/**
+ * This class is used to store and run all the middleware in correct order
+ */
+class MiddlewareDispatcher {
+
+ /**
+ * @var array array containing all the middlewares
+ */
+ private $middlewares;
+
+ /**
+ * @var int counter which tells us what middlware was executed once an
+ * exception occurs
+ */
+ private $middlewareCounter;
+
+
+ /**
+ * Constructor
+ */
+ public function __construct(){
+ $this->middlewares = array();
+ $this->middlewareCounter = 0;
+ }
+
+
+ /**
+ * Adds a new middleware
+ * @param Middleware $middleware the middleware which will be added
+ */
+ public function registerMiddleware(Middleware $middleWare){
+ array_push($this->middlewares, $middleWare);
+ }
+
+
+ /**
+ * returns an array with all middleware elements
+ * @return array the middlewares
+ */
+ public function getMiddlewares(){
+ return $this->middlewares;
+ }
+
+
+ /**
+ * This is being run in normal order before the controller is being
+ * called which allows several modifications and checks
+ *
+ * @param Controller $controller the controller that is being called
+ * @param string $methodName the name of the method that will be called on
+ * the controller
+ */
+ public function beforeController(Controller $controller, $methodName){
+ // we need to count so that we know which middlewares we have to ask in
+ // case theres an exception
+ for($i=0; $i<count($this->middlewares); $i++){
+ $this->middlewareCounter++;
+ $middleware = $this->middlewares[$i];
+ $middleware->beforeController($controller, $methodName);
+ }
+ }
+
+
+ /**
+ * This is being run when either the beforeController method or the
+ * controller method itself is throwing an exception. The middleware is asked
+ * in reverse order to handle the exception and to return a response.
+ * If the response is null, it is assumed that the exception could not be
+ * handled and the error will be thrown again
+ *
+ * @param Controller $controller the controller that is being called
+ * @param string $methodName the name of the method that will be called on
+ * the controller
+ * @param \Exception $exception the thrown exception
+ * @return Response a Response object if the middleware can handle the
+ * exception
+ * @throws \Exception the passed in exception if it cant handle it
+ */
+ public function afterException(Controller $controller, $methodName, \Exception $exception){
+ for($i=$this->middlewareCounter-1; $i>=0; $i--){
+ $middleware = $this->middlewares[$i];
+ try {
+ return $middleware->afterException($controller, $methodName, $exception);
+ } catch(\Exception $exception){
+ continue;
+ }
+ }
+ throw $exception;
+ }
+
+
+ /**
+ * This is being run after a successful controllermethod call and allows
+ * the manipulation of a Response object. The middleware is run in reverse order
+ *
+ * @param Controller $controller the controller that is being called
+ * @param string $methodName the name of the method that will be called on
+ * the controller
+ * @param Response $response the generated response from the controller
+ * @return Response a Response object
+ */
+ public function afterController(Controller $controller, $methodName, Response $response){
+ for($i=count($this->middlewares)-1; $i>=0; $i--){
+ $middleware = $this->middlewares[$i];
+ $response = $middleware->afterController($controller, $methodName, $response);
+ }
+ return $response;
+ }
+
+
+ /**
+ * This is being run after the response object has been rendered and
+ * allows the manipulation of the output. The middleware is run in reverse order
+ *
+ * @param Controller $controller the controller that is being called
+ * @param string $methodName the name of the method that will be called on
+ * the controller
+ * @param string $output the generated output from a response
+ * @return string the output that should be printed
+ */
+ public function beforeOutput(Controller $controller, $methodName, $output){
+ for($i=count($this->middlewares)-1; $i>=0; $i--){
+ $middleware = $this->middlewares[$i];
+ $output = $middleware->beforeOutput($controller, $methodName, $output);
+ }
+ return $output;
+ }
+
+}
diff --git a/lib/private/appframework/middleware/security/securityexception.php b/lib/private/appframework/middleware/security/securityexception.php
new file mode 100644
index 00000000000..b32a2769ff5
--- /dev/null
+++ b/lib/private/appframework/middleware/security/securityexception.php
@@ -0,0 +1,41 @@
+<?php
+
+/**
+ * ownCloud - App Framework
+ *
+ * @author Bernhard Posselt
+ * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+namespace OC\AppFramework\Middleware\Security;
+
+
+/**
+ * Thrown when the security middleware encounters a security problem
+ */
+class SecurityException extends \Exception {
+
+ /**
+ * @param string $msg the security error message
+ * @param bool $ajax true if it resulted because of an ajax request
+ */
+ public function __construct($msg, $code = 0) {
+ parent::__construct($msg, $code);
+ }
+
+}
diff --git a/lib/private/appframework/middleware/security/securitymiddleware.php b/lib/private/appframework/middleware/security/securitymiddleware.php
new file mode 100644
index 00000000000..c3143754823
--- /dev/null
+++ b/lib/private/appframework/middleware/security/securitymiddleware.php
@@ -0,0 +1,140 @@
+<?php
+
+/**
+ * ownCloud - App Framework
+ *
+ * @author Bernhard Posselt
+ * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+namespace OC\AppFramework\Middleware\Security;
+
+use OC\AppFramework\Http;
+use OC\AppFramework\Http\RedirectResponse;
+use OC\AppFramework\Utility\MethodAnnotationReader;
+use OCP\AppFramework\Middleware;
+use OCP\AppFramework\Http\Response;
+use OCP\AppFramework\Http\JSONResponse;
+use OCP\AppFramework\IAppContainer;
+use OCP\IRequest;
+
+
+/**
+ * Used to do all the authentication and checking stuff for a controller method
+ * It reads out the annotations of a controller method and checks which if
+ * security things should be checked and also handles errors in case a security
+ * check fails
+ */
+class SecurityMiddleware extends Middleware {
+
+ /**
+ * @var \OCP\AppFramework\IAppContainer
+ */
+ private $app;
+
+ /**
+ * @var \OCP\IRequest
+ */
+ private $request;
+
+ /**
+ * @param IAppContainer $app
+ * @param IRequest $request
+ */
+ public function __construct(IAppContainer $app, IRequest $request){
+ $this->app = $app;
+ $this->request = $request;
+ }
+
+
+ /**
+ * This runs all the security checks before a method call. The
+ * security checks are determined by inspecting the controller method
+ * annotations
+ * @param string/Controller $controller the controllername or string
+ * @param string $methodName the name of the method
+ * @throws SecurityException when a security check fails
+ */
+ public function beforeController($controller, $methodName){
+
+ // get annotations from comments
+ $annotationReader = new MethodAnnotationReader($controller, $methodName);
+
+ // this will set the current navigation entry of the app, use this only
+ // for normal HTML requests and not for AJAX requests
+ $this->app->getServer()->getNavigationManager()->setActiveEntry($this->app->getAppName());
+
+ // security checks
+ $isPublicPage = $annotationReader->hasAnnotation('PublicPage');
+ if(!$isPublicPage) {
+ if(!$this->app->isLoggedIn()) {
+ throw new SecurityException('Current user is not logged in', Http::STATUS_UNAUTHORIZED);
+ }
+
+ if(!$annotationReader->hasAnnotation('NoAdminRequired')) {
+ if(!$this->app->isAdminUser()) {
+ throw new SecurityException('Logged in user must be an admin', Http::STATUS_FORBIDDEN);
+ }
+ }
+ }
+
+ if(!$annotationReader->hasAnnotation('NoCSRFRequired')) {
+ if(!$this->request->passesCSRFCheck()) {
+ throw new SecurityException('CSRF check failed', Http::STATUS_PRECONDITION_FAILED);
+ }
+ }
+
+ }
+
+
+ /**
+ * If an SecurityException is being caught, ajax requests return a JSON error
+ * response and non ajax requests redirect to the index
+ * @param Controller $controller the controller that is being called
+ * @param string $methodName the name of the method that will be called on
+ * the controller
+ * @param \Exception $exception the thrown exception
+ * @throws \Exception the passed in exception if it cant handle it
+ * @return Response a Response object or null in case that the exception could not be handled
+ */
+ public function afterException($controller, $methodName, \Exception $exception){
+ if($exception instanceof SecurityException){
+
+ if (stripos($this->request->getHeader('Accept'),'html')===false) {
+
+ $response = new JSONResponse(
+ array('message' => $exception->getMessage()),
+ $exception->getCode()
+ );
+ $this->app->log($exception->getMessage(), 'debug');
+ } else {
+
+ // TODO: replace with link to route
+ $url = $this->app->getServer()->getURLGenerator()->getAbsoluteURL('index.php');
+ $response = new RedirectResponse($url);
+ $this->app->log($exception->getMessage(), 'debug');
+ }
+
+ return $response;
+
+ }
+
+ throw $exception;
+ }
+
+}
diff --git a/lib/private/appframework/routing/routeactionhandler.php b/lib/private/appframework/routing/routeactionhandler.php
new file mode 100644
index 00000000000..2b9dc38dc43
--- /dev/null
+++ b/lib/private/appframework/routing/routeactionhandler.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ * ownCloud - App Framework
+ *
+ * @author Thomas Müller
+ * @copyright 2013 Thomas Müller thomas.mueller@tmit.eu
+ *
+ * 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\AppFramework\routing;
+
+use \OC\AppFramework\App;
+use \OC\AppFramework\DependencyInjection\DIContainer;
+
+class RouteActionHandler {
+ private $controllerName;
+ private $actionName;
+ private $container;
+
+ public function __construct(DIContainer $container, $controllerName, $actionName) {
+ $this->controllerName = $controllerName;
+ $this->actionName = $actionName;
+ $this->container = $container;
+ }
+
+ public function __invoke($params) {
+ App::main($this->controllerName, $this->actionName, $this->container, $params);
+ }
+}
diff --git a/lib/private/appframework/routing/routeconfig.php b/lib/private/appframework/routing/routeconfig.php
new file mode 100644
index 00000000000..53ab11bf2f5
--- /dev/null
+++ b/lib/private/appframework/routing/routeconfig.php
@@ -0,0 +1,186 @@
+<?php
+/**
+ * ownCloud - App Framework
+ *
+ * @author Thomas Müller
+ * @copyright 2013 Thomas Müller thomas.mueller@tmit.eu
+ *
+ * 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\AppFramework\routing;
+
+use OC\AppFramework\DependencyInjection\DIContainer;
+
+/**
+ * Class RouteConfig
+ * @package OC\AppFramework\routing
+ */
+class RouteConfig {
+ private $container;
+ private $router;
+ private $routes;
+ private $appName;
+
+ /**
+ * @param \OC\AppFramework\DependencyInjection\DIContainer $container
+ * @param \OC_Router $router
+ * @param string $pathToYml
+ * @internal param $appName
+ */
+ public function __construct(DIContainer $container, \OC_Router $router, $routes) {
+ $this->routes = $routes;
+ $this->container = $container;
+ $this->router = $router;
+ $this->appName = $container['AppName'];
+ }
+
+ /**
+ * The routes and resource will be registered to the \OC_Router
+ */
+ public function register() {
+
+ // parse simple
+ $this->processSimpleRoutes($this->routes);
+
+ // parse resources
+ $this->processResources($this->routes);
+ }
+
+ /**
+ * Creates one route base on the give configuration
+ * @param $routes
+ * @throws \UnexpectedValueException
+ */
+ private function processSimpleRoutes($routes)
+ {
+ $simpleRoutes = isset($routes['routes']) ? $routes['routes'] : array();
+ foreach ($simpleRoutes as $simpleRoute) {
+ $name = $simpleRoute['name'];
+ $url = $simpleRoute['url'];
+ $verb = isset($simpleRoute['verb']) ? strtoupper($simpleRoute['verb']) : 'GET';
+
+ $split = explode('#', $name, 2);
+ if (count($split) != 2) {
+ throw new \UnexpectedValueException('Invalid route name');
+ }
+ $controller = $split[0];
+ $action = $split[1];
+
+ $controllerName = $this->buildControllerName($controller);
+ $actionName = $this->buildActionName($action);
+
+ // register the route
+ $handler = new RouteActionHandler($this->container, $controllerName, $actionName);
+ $this->router->create($this->appName.'.'.$controller.'.'.$action, $url)->method($verb)->action($handler);
+ }
+ }
+
+ /**
+ * For a given name and url restful routes are created:
+ * - index
+ * - show
+ * - new
+ * - create
+ * - update
+ * - destroy
+ *
+ * @param $routes
+ */
+ private function processResources($routes)
+ {
+ // declaration of all restful actions
+ $actions = array(
+ array('name' => 'index', 'verb' => 'GET', 'on-collection' => true),
+ array('name' => 'show', 'verb' => 'GET'),
+ array('name' => 'create', 'verb' => 'POST', 'on-collection' => true),
+ array('name' => 'update', 'verb' => 'PUT'),
+ array('name' => 'destroy', 'verb' => 'DELETE'),
+ );
+
+ $resources = isset($routes['resources']) ? $routes['resources'] : array();
+ foreach ($resources as $resource => $config) {
+
+ // the url parameter used as id to the resource
+ $resourceId = $this->buildResourceId($resource);
+ foreach($actions as $action) {
+ $url = $config['url'];
+ $method = $action['name'];
+ $verb = isset($action['verb']) ? strtoupper($action['verb']) : 'GET';
+ $collectionAction = isset($action['on-collection']) ? $action['on-collection'] : false;
+ if (!$collectionAction) {
+ $url = $url . '/' . $resourceId;
+ }
+ if (isset($action['url-postfix'])) {
+ $url = $url . '/' . $action['url-postfix'];
+ }
+
+ $controller = $resource;
+
+ $controllerName = $this->buildControllerName($controller);
+ $actionName = $this->buildActionName($method);
+
+ $routeName = $this->appName . '.' . strtolower($resource) . '.' . strtolower($method);
+
+ $this->router->create($routeName, $url)->method($verb)->action(
+ new RouteActionHandler($this->container, $controllerName, $actionName)
+ );
+ }
+ }
+ }
+
+ /**
+ * Based on a given route name the controller name is generated
+ * @param $controller
+ * @return string
+ */
+ private function buildControllerName($controller)
+ {
+ return $this->underScoreToCamelCase(ucfirst($controller)) . 'Controller';
+ }
+
+ /**
+ * Based on the action part of the route name the controller method name is generated
+ * @param $action
+ * @return string
+ */
+ private function buildActionName($action) {
+ return $this->underScoreToCamelCase($action);
+ }
+
+ /**
+ * Generates the id used in the url part o the route url
+ * @param $resource
+ * @return string
+ */
+ private function buildResourceId($resource) {
+ return '{'.$this->underScoreToCamelCase(rtrim($resource, 's')).'Id}';
+ }
+
+ /**
+ * Underscored strings are converted to camel case strings
+ * @param $str string
+ * @return string
+ */
+ private function underScoreToCamelCase($str) {
+ $pattern = "/_[a-z]?/";
+ return preg_replace_callback(
+ $pattern,
+ function ($matches) {
+ return strtoupper(ltrim($matches[0], "_"));
+ },
+ $str);
+ }
+}
diff --git a/lib/private/appframework/utility/methodannotationreader.php b/lib/private/appframework/utility/methodannotationreader.php
new file mode 100644
index 00000000000..42060a08529
--- /dev/null
+++ b/lib/private/appframework/utility/methodannotationreader.php
@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * ownCloud - App Framework
+ *
+ * @author Bernhard Posselt
+ * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+namespace OC\AppFramework\Utility;
+
+
+/**
+ * Reads and parses annotations from doc comments
+ */
+class MethodAnnotationReader {
+
+ private $annotations;
+
+ /**
+ * @param object $object an object or classname
+ * @param string $method the method which we want to inspect for annotations
+ */
+ public function __construct($object, $method){
+ $this->annotations = array();
+
+ $reflection = new \ReflectionMethod($object, $method);
+ $docs = $reflection->getDocComment();
+
+ // extract everything prefixed by @ and first letter uppercase
+ preg_match_all('/@([A-Z]\w+)/', $docs, $matches);
+ $this->annotations = $matches[1];
+ }
+
+
+ /**
+ * Check if a method contains an annotation
+ * @param string $name the name of the annotation
+ * @return bool true if the annotation is found
+ */
+ public function hasAnnotation($name){
+ return in_array($name, $this->annotations);
+ }
+
+
+}
diff --git a/lib/private/appframework/utility/simplecontainer.php b/lib/private/appframework/utility/simplecontainer.php
new file mode 100644
index 00000000000..7e4db63bde5
--- /dev/null
+++ b/lib/private/appframework/utility/simplecontainer.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace OC\AppFramework\Utility;
+
+// register 3rdparty autoloaders
+require_once __DIR__ . '/../../../../3rdparty/Pimple/Pimple.php';
+
+/**
+ * Class SimpleContainer
+ *
+ * SimpleContainer is a simple implementation of IContainer on basis of \Pimple
+ */
+class SimpleContainer extends \Pimple implements \OCP\IContainer {
+
+ /**
+ * @param string $name name of the service to query for
+ * @return object registered service for the given $name
+ */
+ public function query($name) {
+ return $this->offsetGet($name);
+ }
+
+ function registerParameter($name, $value)
+ {
+ $this[$name] = $value;
+ }
+
+ /**
+ * The given closure is call the first time the given service is queried.
+ * The closure has to return the instance for the given service.
+ * Created instance will be cached in case $shared is true.
+ *
+ * @param string $name name of the service to register another backend for
+ * @param callable $closure the closure to be called on service creation
+ */
+ function registerService($name, \Closure $closure, $shared = true)
+ {
+ if ($shared) {
+ $this[$name] = \Pimple::share($closure);
+ } else {
+ $this[$name] = $closure;
+ }
+ }
+}
diff --git a/lib/private/appframework/utility/timefactory.php b/lib/private/appframework/utility/timefactory.php
new file mode 100644
index 00000000000..2c3dd6cf5e3
--- /dev/null
+++ b/lib/private/appframework/utility/timefactory.php
@@ -0,0 +1,42 @@
+<?php
+
+/**
+ * ownCloud - App Framework
+ *
+ * @author Bernhard Posselt
+ * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+namespace OC\AppFramework\Utility;
+
+
+/**
+ * Needed to mock calls to time()
+ */
+class TimeFactory {
+
+
+ /**
+ * @return int the result of a call to time()
+ */
+ public function getTime() {
+ return time();
+ }
+
+
+}
diff --git a/lib/private/apphelper.php b/lib/private/apphelper.php
new file mode 100644
index 00000000000..bd02f3aabfa
--- /dev/null
+++ b/lib/private/apphelper.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ *
+ */
+
+namespace OC;
+
+/**
+ * TODO: Description
+ */
+class AppHelper implements \OCP\IHelper {
+ /**
+ * Gets the content of an URL by using CURL or a fallback if it is not
+ * installed
+ * @param string $url the url that should be fetched
+ * @return string the content of the webpage
+ */
+ public function getUrlContent($url) {
+ return \OC_Util::getUrlContent($url);
+ }
+}
diff --git a/lib/archive.php b/lib/private/archive.php
index 70615db714e..85bfae57295 100644
--- a/lib/archive.php
+++ b/lib/private/archive.php
@@ -119,9 +119,10 @@ abstract class OC_Archive{
* @return bool
*/
function addRecursive($path, $source) {
- if($dh=opendir($source)) {
+ $dh = opendir($source);
+ if(is_resource($dh)) {
$this->addFolder($path);
- while($file=readdir($dh)) {
+ while (($file = readdir($dh)) !== false) {
if($file=='.' or $file=='..') {
continue;
}
diff --git a/lib/archive/tar.php b/lib/private/archive/tar.php
index a1c0535b1c3..a1c0535b1c3 100644
--- a/lib/archive/tar.php
+++ b/lib/private/archive/tar.php
diff --git a/lib/archive/zip.php b/lib/private/archive/zip.php
index 8a866716a79..8a866716a79 100644
--- a/lib/archive/zip.php
+++ b/lib/private/archive/zip.php
diff --git a/lib/arrayparser.php b/lib/private/arrayparser.php
index 3bb394a5163..3bb394a5163 100644
--- a/lib/arrayparser.php
+++ b/lib/private/arrayparser.php
diff --git a/lib/private/avatar.php b/lib/private/avatar.php
new file mode 100644
index 00000000000..e97f55eecaf
--- /dev/null
+++ b/lib/private/avatar.php
@@ -0,0 +1,91 @@
+<?php
+/**
+ * Copyright (c) 2013 Christopher Schäpers <christopher@schaepers.it>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+/**
+ * This class gets and sets users avatars.
+ */
+
+class OC_Avatar implements \OCP\IAvatar {
+
+ private $view;
+
+ /**
+ * @brief constructor
+ * @param $user string user to do avatar-management with
+ */
+ public function __construct ($user) {
+ $this->view = new \OC\Files\View('/'.$user);
+ }
+
+ /**
+ * @brief get the users avatar
+ * @param $size integer size in px of the avatar, avatars are square, defaults to 64
+ * @return boolean|\OC_Image containing the avatar or false if there's no image
+ */
+ public function get ($size = 64) {
+ if ($this->view->file_exists('avatar.jpg')) {
+ $ext = 'jpg';
+ } elseif ($this->view->file_exists('avatar.png')) {
+ $ext = 'png';
+ } else {
+ return false;
+ }
+
+ $avatar = new OC_Image();
+ $avatar->loadFromData($this->view->file_get_contents('avatar.'.$ext));
+ $avatar->resize($size);
+ return $avatar;
+ }
+
+ /**
+ * @brief sets the users avatar
+ * @param $data mixed OC_Image, imagedata or path to set a new avatar
+ * @throws Exception if the provided file is not a jpg or png image
+ * @throws Exception if the provided image is not valid
+ * @throws \OC\NotSquareException if the image is not square
+ * @return void
+ */
+ public function set ($data) {
+ if($data instanceOf OC_Image) {
+ $img = $data;
+ $data = $img->data();
+ } else {
+ $img = new OC_Image($data);
+ }
+ $type = substr($img->mimeType(), -3);
+ if ($type === 'peg') {
+ $type = 'jpg';
+ }
+ if ($type !== 'jpg' && $type !== 'png') {
+ $l = \OC_L10N::get('lib');
+ throw new \Exception($l->t("Unknown filetype"));
+ }
+
+ if (!$img->valid()) {
+ $l = \OC_L10N::get('lib');
+ throw new \Exception($l->t("Invalid image"));
+ }
+
+ if (!($img->height() === $img->width())) {
+ throw new \OC\NotSquareException();
+ }
+
+ $this->view->unlink('avatar.jpg');
+ $this->view->unlink('avatar.png');
+ $this->view->file_put_contents('avatar.'.$type, $data);
+ }
+
+ /**
+ * @brief remove the users avatar
+ * @return void
+ */
+ public function remove () {
+ $this->view->unlink('avatar.jpg');
+ $this->view->unlink('avatar.png');
+ }
+}
diff --git a/lib/private/avatarmanager.php b/lib/private/avatarmanager.php
new file mode 100644
index 00000000000..3ca46868ea6
--- /dev/null
+++ b/lib/private/avatarmanager.php
@@ -0,0 +1,26 @@
+<?php
+/**
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC;
+
+use OCP\IAvatarManager;
+
+/*
+ * This class implements methods to access Avatar functionality
+ */
+class AvatarManager implements IAvatarManager {
+
+ /**
+ * @brief return a user specific instance of \OCP\IAvatar
+ * @see \OCP\IAvatar
+ * @param $user string the ownCloud user id
+ * @return \OCP\IAvatar
+ */
+ function getAvatar($user) {
+ return new \OC_Avatar($user);
+ }
+}
diff --git a/lib/backgroundjob.php b/lib/private/backgroundjob.php
index 9619dcb732c..9619dcb732c 100644
--- a/lib/backgroundjob.php
+++ b/lib/private/backgroundjob.php
diff --git a/lib/backgroundjob/job.php b/lib/private/backgroundjob/job.php
index 49fbffbd684..92bd0f8fdbd 100644
--- a/lib/backgroundjob/job.php
+++ b/lib/private/backgroundjob/job.php
@@ -9,16 +9,35 @@
namespace OC\BackgroundJob;
abstract class Job {
+ /**
+ * @var int $id
+ */
protected $id;
+
+ /**
+ * @var int $lastRun
+ */
protected $lastRun;
+
+ /**
+ * @var mixed $argument
+ */
protected $argument;
/**
* @param JobList $jobList
+ * @param \OC\Log $logger
*/
- public function execute($jobList) {
+ public function execute($jobList, $logger = null) {
$jobList->setLastRun($this);
- $this->run($this->argument);
+ try {
+ $this->run($this->argument);
+ } catch (\Exception $e) {
+ if ($logger) {
+ $logger->error('Error while running background job: ' . $e->getMessage());
+ }
+ $jobList->remove($this, $this->argument);
+ }
}
abstract protected function run($argument);
diff --git a/lib/backgroundjob/joblist.php b/lib/private/backgroundjob/joblist.php
index cc803dd9b5f..99743a70c77 100644
--- a/lib/backgroundjob/joblist.php
+++ b/lib/private/backgroundjob/joblist.php
@@ -138,7 +138,7 @@ class JobList {
$job = new $class();
$job->setId($row['id']);
$job->setLastRun($row['last_run']);
- $job->setArgument(json_decode($row['argument']));
+ $job->setArgument(json_decode($row['argument'], true));
return $job;
}
diff --git a/lib/backgroundjob/legacy/queuedjob.php b/lib/private/backgroundjob/legacy/queuedjob.php
index 2bc001103b8..2bc001103b8 100644
--- a/lib/backgroundjob/legacy/queuedjob.php
+++ b/lib/private/backgroundjob/legacy/queuedjob.php
diff --git a/lib/backgroundjob/legacy/regularjob.php b/lib/private/backgroundjob/legacy/regularjob.php
index d4cfa348cea..d4cfa348cea 100644
--- a/lib/backgroundjob/legacy/regularjob.php
+++ b/lib/private/backgroundjob/legacy/regularjob.php
diff --git a/lib/backgroundjob/queuedjob.php b/lib/private/backgroundjob/queuedjob.php
index 1714182820d..799eac47848 100644
--- a/lib/backgroundjob/queuedjob.php
+++ b/lib/private/backgroundjob/queuedjob.php
@@ -20,9 +20,10 @@ abstract class QueuedJob extends Job {
* run the job, then remove it from the joblist
*
* @param JobList $jobList
+ * @param \OC\Log $logger
*/
- public function execute($jobList) {
+ public function execute($jobList, $logger = null) {
$jobList->remove($this);
- $this->run($this->argument);
+ parent::execute($jobList, $logger);
}
}
diff --git a/lib/backgroundjob/timedjob.php b/lib/private/backgroundjob/timedjob.php
index ae9f33505ab..09e05f1d846 100644
--- a/lib/backgroundjob/timedjob.php
+++ b/lib/private/backgroundjob/timedjob.php
@@ -31,11 +31,11 @@ abstract class TimedJob extends Job {
* run the job if
*
* @param JobList $jobList
+ * @param \OC\Log $logger
*/
- public function execute($jobList) {
+ public function execute($jobList, $logger = null) {
if ((time() - $this->lastRun) > $this->interval) {
- $jobList->setLastRun($this);
- $this->run($this->argument);
+ parent::execute($jobList, $logger);
}
}
}
diff --git a/lib/cache.php b/lib/private/cache.php
index 48b9964ba9d..a311f10a00f 100644
--- a/lib/cache.php
+++ b/lib/private/cache.php
@@ -6,34 +6,36 @@
* See the COPYING-README file.
*/
-class OC_Cache {
+namespace OC;
+
+class Cache {
/**
- * @var OC_Cache $user_cache
+ * @var Cache $user_cache
*/
static protected $user_cache;
/**
- * @var OC_Cache $global_cache
+ * @var Cache $global_cache
*/
static protected $global_cache;
/**
* get the global cache
- * @return OC_Cache
+ * @return Cache
*/
static public function getGlobalCache() {
if (!self::$global_cache) {
- self::$global_cache = new OC_Cache_FileGlobal();
+ self::$global_cache = new Cache\FileGlobal();
}
return self::$global_cache;
}
/**
* get the user cache
- * @return OC_Cache
+ * @return Cache
*/
static public function getUserCache() {
if (!self::$user_cache) {
- self::$user_cache = new OC_Cache_File();
+ self::$user_cache = new Cache\File();
}
return self::$user_cache;
}
@@ -85,7 +87,7 @@ class OC_Cache {
/**
* clear the user cache of all entries starting with a prefix
- * @param string prefix (optional)
+ * @param string $prefix (optional)
* @return bool
*/
static public function clear($prefix='') {
@@ -93,6 +95,11 @@ class OC_Cache {
return $user_cache->clear($prefix);
}
+ /**
+ * creates cache key based on the files given
+ * @param $files
+ * @return string
+ */
static public function generateCacheKeyFromFiles($files) {
$key = '';
sort($files);
diff --git a/lib/cache/broker.php b/lib/private/cache/broker.php
index a161dbfa3bb..9b7e837e1bc 100644
--- a/lib/cache/broker.php
+++ b/lib/private/cache/broker.php
@@ -6,8 +6,18 @@
* See the COPYING-README file.
*/
-class OC_Cache_Broker {
+namespace OC\Cache;
+
+class Broker {
+
+ /**
+ * @var \OC\Cache
+ */
protected $fast_cache;
+
+ /**
+ * @var \OC\Cache
+ */
protected $slow_cache;
public function __construct($fast_cache, $slow_cache) {
diff --git a/lib/cache/file.php b/lib/private/cache/file.php
index ba3dedaf8f3..b0738d2a92b 100644
--- a/lib/cache/file.php
+++ b/lib/private/cache/file.php
@@ -6,24 +6,25 @@
* See the COPYING-README file.
*/
+namespace OC\Cache;
-class OC_Cache_File{
+class File {
protected $storage;
protected function getStorage() {
if (isset($this->storage)) {
return $this->storage;
}
- if(OC_User::isLoggedIn()) {
- \OC\Files\Filesystem::initMountPoints(OC_User::getUser());
+ if(\OC_User::isLoggedIn()) {
+ \OC\Files\Filesystem::initMountPoints(\OC_User::getUser());
$subdir = 'cache';
- $view = new \OC\Files\View('/'.OC_User::getUser());
+ $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().'/'.$subdir);
return $this->storage;
}else{
- OC_Log::write('core', 'Can\'t get cache storage, user not logged in', OC_Log::ERROR);
+ \OC_Log::write('core', 'Can\'t get cache storage, user not logged in', \OC_Log::ERROR);
return false;
}
}
@@ -40,6 +41,24 @@ class OC_Cache_File{
return $result;
}
+ /**
+ * Returns the size of the stored/cached data
+ *
+ * @param $key
+ * @return int
+ */
+ public function size($key) {
+ $result = 0;
+ $proxyStatus = \OC_FileProxy::$enabled;
+ \OC_FileProxy::$enabled = false;
+ if ($this->hasKey($key)) {
+ $storage = $this->getStorage();
+ $result = $storage->filesize($key);
+ }
+ \OC_FileProxy::$enabled = $proxyStatus;
+ return $result;
+ }
+
public function set($key, $value, $ttl=0) {
$storage = $this->getStorage();
$result = false;
@@ -80,9 +99,11 @@ class OC_Cache_File{
$storage = $this->getStorage();
if($storage and $storage->is_dir('/')) {
$dh=$storage->opendir('/');
- while($file=readdir($dh)) {
- if($file!='.' and $file!='..' and ($prefix==='' || strpos($file, $prefix) === 0)) {
- $storage->unlink('/'.$file);
+ if(is_resource($dh)) {
+ while (($file = readdir($dh)) !== false) {
+ if($file!='.' and $file!='..' and ($prefix==='' || strpos($file, $prefix) === 0)) {
+ $storage->unlink('/'.$file);
+ }
}
}
}
@@ -94,7 +115,10 @@ class OC_Cache_File{
if($storage and $storage->is_dir('/')) {
$now = time();
$dh=$storage->opendir('/');
- while($file=readdir($dh)) {
+ if(!is_resource($dh)) {
+ return null;
+ }
+ while (($file = readdir($dh)) !== false) {
if($file!='.' and $file!='..') {
$mtime = $storage->filemtime('/'.$file);
if ($mtime < $now) {
diff --git a/lib/cache/fileglobal.php b/lib/private/cache/fileglobal.php
index 6d01964e185..bd049bba4d0 100644
--- a/lib/cache/fileglobal.php
+++ b/lib/private/cache/fileglobal.php
@@ -6,10 +6,11 @@
* See the COPYING-README file.
*/
+namespace OC\Cache;
-class OC_Cache_FileGlobal{
+class FileGlobal {
static protected function getCacheDir() {
- $cache_dir = get_temp_dir().'/owncloud-'.OC_Util::getInstanceId().'/';
+ $cache_dir = get_temp_dir().'/owncloud-' . \OC_Util::getInstanceId().'/';
if (!is_dir($cache_dir)) {
mkdir($cache_dir);
}
@@ -69,30 +70,34 @@ class OC_Cache_FileGlobal{
$prefix = $this->fixKey($prefix);
if($cache_dir and is_dir($cache_dir)) {
$dh=opendir($cache_dir);
- while($file=readdir($dh)) {
- if($file!='.' and $file!='..' and ($prefix==='' || strpos($file, $prefix) === 0)) {
- unlink($cache_dir.$file);
+ if(is_resource($dh)) {
+ while (($file = readdir($dh)) !== false) {
+ if($file!='.' and $file!='..' and ($prefix==='' || strpos($file, $prefix) === 0)) {
+ unlink($cache_dir.$file);
+ }
}
}
}
}
static public function gc() {
- $last_run = OC_AppConfig::getValue('core', 'global_cache_gc_lastrun', 0);
+ $last_run = \OC_AppConfig::getValue('core', 'global_cache_gc_lastrun', 0);
$now = time();
if (($now - $last_run) < 300) {
// only do cleanup every 5 minutes
return;
}
- OC_AppConfig::setValue('core', 'global_cache_gc_lastrun', $now);
+ \OC_AppConfig::setValue('core', 'global_cache_gc_lastrun', $now);
$cache_dir = self::getCacheDir();
if($cache_dir and is_dir($cache_dir)) {
$dh=opendir($cache_dir);
- while($file=readdir($dh)) {
- if($file!='.' and $file!='..') {
- $mtime = filemtime($cache_dir.$file);
- if ($mtime < $now) {
- unlink($cache_dir.$file);
+ if(is_resource($dh)) {
+ while (($file = readdir($dh)) !== false) {
+ if($file!='.' and $file!='..') {
+ $mtime = filemtime($cache_dir.$file);
+ if ($mtime < $now) {
+ unlink($cache_dir.$file);
+ }
}
}
}
diff --git a/lib/private/cache/fileglobalgc.php b/lib/private/cache/fileglobalgc.php
new file mode 100644
index 00000000000..399dd5e6f94
--- /dev/null
+++ b/lib/private/cache/fileglobalgc.php
@@ -0,0 +1,9 @@
+<?php
+
+namespace OC\Cache;
+
+class FileGlobalGC extends \OC\BackgroundJob\Job{
+ public function run($argument){
+ FileGlobal::gc();
+ }
+}
diff --git a/lib/private/cache/usercache.php b/lib/private/cache/usercache.php
new file mode 100644
index 00000000000..baa8820700b
--- /dev/null
+++ b/lib/private/cache/usercache.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * Copyright (c) 2013 Thomas Tanghus (thomas@tanghus.net)
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+namespace OC\Cache;
+
+/**
+ * This interface defines method for accessing the file based user cache.
+ */
+class UserCache implements \OCP\ICache {
+
+ /**
+ * @var \OC\Cache\File $userCache
+ */
+ protected $userCache;
+
+ public function __construct() {
+ $this->userCache = new File();
+ }
+
+ /**
+ * Get a value from the user cache
+ *
+ * @param string $key
+ * @return mixed
+ */
+ public function get($key) {
+ return $this->userCache->get($key);
+ }
+
+ /**
+ * Set a value in the user cache
+ *
+ * @param string $key
+ * @param mixed $value
+ * @param int $ttl Time To Live in seconds. Defaults to 60*60*24
+ * @return bool
+ */
+ public function set($key, $value, $ttl = 0) {
+ if (empty($key)) {
+ return false;
+ }
+ return $this->userCache->set($key, $value, $ttl);
+ }
+
+ /**
+ * Check if a value is set in the user cache
+ *
+ * @param string $key
+ * @return bool
+ */
+ public function hasKey($key) {
+ return $this->userCache->hasKey($key);
+ }
+
+ /**
+ * Remove an item from the user cache
+ *
+ * @param string $key
+ * @return bool
+ */
+ public function remove($key) {
+ return $this->userCache->remove($key);
+ }
+
+ /**
+ * clear the user cache of all entries starting with a prefix
+ * @param string $prefix (optional)
+ * @return bool
+ */
+ public function clear($prefix = '') {
+ return $this->userCache->clear($prefix);
+ }
+}
diff --git a/lib/config.php b/lib/private/config.php
index e773e6e2eb0..caf7b1d7066 100644
--- a/lib/config.php
+++ b/lib/private/config.php
@@ -160,7 +160,6 @@ class Config {
*/
private function writeData() {
// Create a php file ...
- $defaults = new \OC_Defaults;
$content = "<?php\n";
if ($this->debugMode) {
$content .= "define('DEBUG',true);\n";
@@ -172,7 +171,8 @@ class Config {
// Write the file
$result = @file_put_contents($this->configFilename, $content);
if (!$result) {
- $url = $defaults->getDocBaseUrl() . '/server/5.0/admin_manual/installation/installation_source.html#set-the-directory-permissions';
+ $defaults = new \OC_Defaults;
+ $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/connector/sabre/ServiceUnavailable.php b/lib/private/connector/sabre/ServiceUnavailable.php
index c1cc815c989..c1cc815c989 100644
--- a/lib/connector/sabre/ServiceUnavailable.php
+++ b/lib/private/connector/sabre/ServiceUnavailable.php
diff --git a/lib/private/connector/sabre/aborteduploaddetectionplugin.php b/lib/private/connector/sabre/aborteduploaddetectionplugin.php
new file mode 100644
index 00000000000..10cca647e8d
--- /dev/null
+++ b/lib/private/connector/sabre/aborteduploaddetectionplugin.php
@@ -0,0 +1,107 @@
+<?php
+/**
+ * Copyright (c) 2013 Thomas Müller <thomas.mueller@tmit.eu>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+/**
+ * Class OC_Connector_Sabre_AbortedUploadDetectionPlugin
+ *
+ * This plugin will verify if the uploaded data has been stored completely.
+ * This is done by comparing the content length of the request with the file size on storage.
+ */
+class OC_Connector_Sabre_AbortedUploadDetectionPlugin extends Sabre_DAV_ServerPlugin {
+
+ /**
+ * Reference to main server object
+ *
+ * @var Sabre_DAV_Server
+ */
+ private $server;
+
+ /**
+ * is kept public to allow overwrite for unit testing
+ *
+ * @var \OC\Files\View
+ */
+ public $fileView;
+
+ /**
+ * This initializes the plugin.
+ *
+ * This function is called by Sabre_DAV_Server, after
+ * addPlugin is called.
+ *
+ * This method should set up the requires event subscriptions.
+ *
+ * @param Sabre_DAV_Server $server
+ */
+ public function initialize(Sabre_DAV_Server $server) {
+
+ $this->server = $server;
+
+ $server->subscribeEvent('afterCreateFile', array($this, 'verifyContentLength'), 10);
+ $server->subscribeEvent('afterWriteContent', array($this, 'verifyContentLength'), 10);
+ }
+
+ /**
+ * @param $filePath
+ * @param Sabre_DAV_INode $node
+ * @throws Sabre_DAV_Exception_BadRequest
+ */
+ public function verifyContentLength($filePath, Sabre_DAV_INode $node = null) {
+
+ // we should only react on PUT which is used for upload
+ // e.g. with LOCK this will not work, but LOCK uses createFile() as well
+ if ($this->server->httpRequest->getMethod() !== 'PUT' ) {
+ return;
+ }
+
+ // ownCloud chunked upload will be handled in its own plugin
+ $chunkHeader = $this->server->httpRequest->getHeader('OC-Chunked');
+ if ($chunkHeader) {
+ return;
+ }
+
+ // compare expected and actual size
+ $expected = $this->getLength();
+ if (!$expected) {
+ return;
+ }
+ $actual = $this->getFileView()->filesize($filePath);
+ if ($actual != $expected) {
+ $this->getFileView()->unlink($filePath);
+ throw new Sabre_DAV_Exception_BadRequest('expected filesize ' . $expected . ' got ' . $actual);
+ }
+
+ }
+
+ /**
+ * @return string
+ */
+ public function getLength()
+ {
+ $req = $this->server->httpRequest;
+ $length = $req->getHeader('X-Expected-Entity-Length');
+ if (!$length) {
+ $length = $req->getHeader('Content-Length');
+ }
+
+ return $length;
+ }
+
+ /**
+ * @return \OC\Files\View
+ */
+ public function getFileView()
+ {
+ if (is_null($this->fileView)) {
+ // initialize fileView
+ $this->fileView = \OC\Files\Filesystem::getView();
+ }
+
+ return $this->fileView;
+ }
+}
diff --git a/lib/connector/sabre/auth.php b/lib/private/connector/sabre/auth.php
index bf3a49593cb..0c84fa6b757 100644
--- a/lib/connector/sabre/auth.php
+++ b/lib/private/connector/sabre/auth.php
@@ -72,7 +72,8 @@ class OC_Connector_Sabre_Auth extends Sabre_DAV_Auth_Backend_AbstractBasic {
* @return bool
*/
public function authenticate(Sabre_DAV_Server $server, $realm) {
- if (OC_User::isLoggedIn()) {
+
+ if (OC_User::handleApacheAuth() || OC_User::isLoggedIn()) {
$user = OC_User::getUser();
OC_Util::setupFS($user);
$this->currentUser = $user;
diff --git a/lib/connector/sabre/directory.php b/lib/private/connector/sabre/directory.php
index ed8d085462d..02d1a9f4ba2 100644
--- a/lib/connector/sabre/directory.php
+++ b/lib/private/connector/sabre/directory.php
@@ -50,58 +50,31 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
*/
public function createFile($name, $data = null) {
- if (!\OC\Files\Filesystem::isCreatable($this->path)) {
+ if ($name === 'Shared' && empty($this->path)) {
throw new \Sabre_DAV_Exception_Forbidden();
}
+ // for chunked upload also updating a existing file is a "createFile"
+ // because we create all the chunks before reasamble them to the existing file.
if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
+
+ // exit if we can't create a new file and we don't updatable existing file
$info = OC_FileChunking::decodeName($name);
- if (empty($info)) {
- throw new Sabre_DAV_Exception_NotImplemented();
- }
- $chunk_handler = new OC_FileChunking($info);
- $chunk_handler->store($info['index'], $data);
- if ($chunk_handler->isComplete()) {
- $newPath = $this->path . '/' . $info['name'];
- $chunk_handler->file_assemble($newPath);
- return OC_Connector_Sabre_Node::getETagPropertyForPath($newPath);
- }
- } else {
- $newPath = $this->path . '/' . $name;
-
- // mark file as partial while uploading (ignored by the scanner)
- $partpath = $newPath . '.part';
-
- \OC\Files\Filesystem::file_put_contents($partpath, $data);
-
- //detect aborted upload
- if (isset ($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT' ) {
- if (isset($_SERVER['CONTENT_LENGTH'])) {
- $expected = $_SERVER['CONTENT_LENGTH'];
- $actual = \OC\Files\Filesystem::filesize($partpath);
- if ($actual != $expected) {
- \OC\Files\Filesystem::unlink($partpath);
- throw new Sabre_DAV_Exception_BadRequest(
- 'expected filesize ' . $expected . ' got ' . $actual);
- }
- }
+ if (!\OC\Files\Filesystem::isCreatable($this->path) &&
+ !\OC\Files\Filesystem::isUpdatable($this->path . '/' . $info['name'])) {
+ throw new \Sabre_DAV_Exception_Forbidden();
}
- // rename to correct path
- \OC\Files\Filesystem::rename($partpath, $newPath);
-
- // allow sync clients to send the mtime along in a header
- $mtime = OC_Request::hasModificationTime();
- if ($mtime !== false) {
- if(\OC\Files\Filesystem::touch($newPath, $mtime)) {
- header('X-OC-MTime: accepted');
- }
+ } else {
+ // For non-chunked upload it is enough to check if we can create a new file
+ if (!\OC\Files\Filesystem::isCreatable($this->path)) {
+ throw new \Sabre_DAV_Exception_Forbidden();
}
-
- return OC_Connector_Sabre_Node::getETagPropertyForPath($newPath);
}
- return null;
+ $path = $this->path . '/' . $name;
+ $node = new OC_Connector_Sabre_File($path);
+ return $node->put($data);
}
/**
@@ -113,6 +86,10 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
*/
public function createDirectory($name) {
+ if ($name === 'Shared' && empty($this->path)) {
+ throw new \Sabre_DAV_Exception_Forbidden();
+ }
+
if (!\OC\Files\Filesystem::isCreatable($this->path)) {
throw new \Sabre_DAV_Exception_Forbidden();
}
@@ -218,13 +195,16 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
*/
public function delete() {
- if (!\OC\Files\Filesystem::isDeletable($this->path)) {
+ if ($this->path === 'Shared') {
throw new \Sabre_DAV_Exception_Forbidden();
}
- if ($this->path != "/Shared") {
- \OC\Files\Filesystem::rmdir($this->path);
+
+ if (!\OC\Files\Filesystem::isDeletable($this->path)) {
+ throw new \Sabre_DAV_Exception_Forbidden();
}
+ \OC\Files\Filesystem::rmdir($this->path);
+
}
/**
@@ -233,10 +213,10 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
* @return array
*/
public function getQuotaInfo() {
- $rootInfo=\OC\Files\Filesystem::getFileInfo('');
+ $storageInfo = OC_Helper::getStorageInfo($this->path);
return array(
- $rootInfo['size'],
- \OC\Files\Filesystem::free_space()
+ $storageInfo['used'],
+ $storageInfo['free']
);
}
@@ -250,14 +230,14 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
* If the array is empty, all properties should be returned
*
* @param array $properties
- * @return void
+ * @return array
*/
public function getProperties($properties) {
$props = parent::getProperties($properties);
if (in_array(self::GETETAG_PROPERTYNAME, $properties) && !isset($props[self::GETETAG_PROPERTYNAME])) {
- $props[self::GETETAG_PROPERTYNAME]
- = OC_Connector_Sabre_Node::getETagPropertyForPath($this->path);
+ $props[self::GETETAG_PROPERTYNAME] = $this->getETagPropertyForPath($this->path);
}
return $props;
}
+
}
diff --git a/lib/private/connector/sabre/exception/entitytoolarge.php b/lib/private/connector/sabre/exception/entitytoolarge.php
new file mode 100644
index 00000000000..2bda51f2f3e
--- /dev/null
+++ b/lib/private/connector/sabre/exception/entitytoolarge.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * Entity Too Large
+ *
+ * This exception is thrown whenever a user tries to upload a file which exceeds hard limitations
+ *
+ */
+class OC_Connector_Sabre_Exception_EntityTooLarge extends Sabre_DAV_Exception {
+
+ /**
+ * Returns the HTTP status code for this exception
+ *
+ * @return int
+ */
+ public function getHTTPCode() {
+
+ return 413;
+
+ }
+
+}
diff --git a/lib/private/connector/sabre/exception/unsupportedmediatype.php b/lib/private/connector/sabre/exception/unsupportedmediatype.php
new file mode 100644
index 00000000000..95d6a8cc651
--- /dev/null
+++ b/lib/private/connector/sabre/exception/unsupportedmediatype.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * Unsupported Media Type
+ *
+ * This exception is thrown whenever a user tries to upload a file which holds content which is not allowed
+ *
+ */
+class OC_Connector_Sabre_Exception_UnsupportedMediaType extends Sabre_DAV_Exception {
+
+ /**
+ * Returns the HTTP status code for this exception
+ *
+ * @return int
+ */
+ public function getHTTPCode() {
+
+ return 415;
+
+ }
+
+}
diff --git a/lib/private/connector/sabre/file.php b/lib/private/connector/sabre/file.php
new file mode 100644
index 00000000000..295575f0af6
--- /dev/null
+++ b/lib/private/connector/sabre/file.php
@@ -0,0 +1,263 @@
+<?php
+
+/**
+ * ownCloud
+ *
+ * @author Jakob Sack
+ * @copyright 2011 Jakob Sack kde@jakobsack.de
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_DAV_IFile {
+
+ /**
+ * Updates the data
+ *
+ * The data argument is a readable stream resource.
+ *
+ * After a successful put operation, you may choose to return an ETag. The
+ * etag must always be surrounded by double-quotes. These quotes must
+ * appear in the actual string you're returning.
+ *
+ * Clients may use the ETag from a PUT request to later on make sure that
+ * when they update the file, the contents haven't changed in the mean
+ * time.
+ *
+ * If you don't plan to store the file byte-by-byte, and you return a
+ * different object on a subsequent GET you are strongly recommended to not
+ * return an ETag, and just return null.
+ *
+ * @param resource $data
+ * @throws Sabre_DAV_Exception_Forbidden
+ * @return string|null
+ */
+ public function put($data) {
+
+ $fs = $this->getFS();
+
+ if ($fs->file_exists($this->path) &&
+ !$fs->isUpdatable($this->path)) {
+ throw new \Sabre_DAV_Exception_Forbidden();
+ }
+
+ // throw an exception if encryption was disabled but the files are still encrypted
+ if (\OC_Util::encryptedFiles()) {
+ throw new \Sabre_DAV_Exception_ServiceUnavailable();
+ }
+
+ // chunked handling
+ if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
+ return $this->createFileChunked($data);
+ }
+
+ // mark file as partial while uploading (ignored by the scanner)
+ $partpath = $this->path . '.part';
+
+ // if file is located in /Shared we write the part file to the users
+ // root folder because we can't create new files in /shared
+ // we extend the name with a random number to avoid overwriting a existing file
+ if (dirname($partpath) === 'Shared') {
+ $partpath = pathinfo($partpath, PATHINFO_FILENAME) . rand() . '.part';
+ }
+
+ try {
+ $putOkay = $fs->file_put_contents($partpath, $data);
+ if ($putOkay === false) {
+ \OC_Log::write('webdav', '\OC\Files\Filesystem::file_put_contents() failed', \OC_Log::ERROR);
+ $fs->unlink($partpath);
+ // because we have no clue about the cause we can only throw back a 500/Internal Server Error
+ throw new Sabre_DAV_Exception();
+ }
+ } catch (\OCP\Files\NotPermittedException $e) {
+ // a more general case - due to whatever reason the content could not be written
+ throw new Sabre_DAV_Exception_Forbidden($e->getMessage());
+
+ } catch (\OCP\Files\EntityTooLargeException $e) {
+ // the file is too big to be stored
+ throw new OC_Connector_Sabre_Exception_EntityTooLarge($e->getMessage());
+
+ } catch (\OCP\Files\InvalidContentException $e) {
+ // the file content is not permitted
+ throw new OC_Connector_Sabre_Exception_UnsupportedMediaType($e->getMessage());
+
+ } catch (\OCP\Files\InvalidPathException $e) {
+ // the path for the file was not valid
+ // TODO: find proper http status code for this case
+ throw new Sabre_DAV_Exception_Forbidden($e->getMessage());
+ }
+
+ // rename to correct path
+ $renameOkay = $fs->rename($partpath, $this->path);
+ $fileExists = $fs->file_exists($this->path);
+ if ($renameOkay === false || $fileExists === false) {
+ \OC_Log::write('webdav', '\OC\Files\Filesystem::rename() failed', \OC_Log::ERROR);
+ $fs->unlink($partpath);
+ throw new Sabre_DAV_Exception();
+ }
+
+ // allow sync clients to send the mtime along in a header
+ $mtime = OC_Request::hasModificationTime();
+ if ($mtime !== false) {
+ if($fs->touch($this->path, $mtime)) {
+ header('X-OC-MTime: accepted');
+ }
+ }
+
+ return $this->getETagPropertyForPath($this->path);
+ }
+
+ /**
+ * Returns the data
+ *
+ * @return string
+ */
+ public function get() {
+
+ //throw exception if encryption is disabled but files are still encrypted
+ if (\OC_Util::encryptedFiles()) {
+ throw new \Sabre_DAV_Exception_ServiceUnavailable();
+ } else {
+ return \OC\Files\Filesystem::fopen($this->path, 'rb');
+ }
+
+ }
+
+ /**
+ * Delete the current file
+ *
+ * @return void
+ * @throws Sabre_DAV_Exception_Forbidden
+ */
+ public function delete() {
+
+ if ($this->path === 'Shared') {
+ throw new \Sabre_DAV_Exception_Forbidden();
+ }
+
+ if (!\OC\Files\Filesystem::isDeletable($this->path)) {
+ throw new \Sabre_DAV_Exception_Forbidden();
+ }
+ \OC\Files\Filesystem::unlink($this->path);
+
+ // remove properties
+ $this->removeProperties();
+
+ }
+
+ /**
+ * Returns the size of the node, in bytes
+ *
+ * @return int
+ */
+ public function getSize() {
+ $this->getFileinfoCache();
+ if ($this->fileinfo_cache['size'] > -1) {
+ return $this->fileinfo_cache['size'];
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the ETag for a file
+ *
+ * An ETag is a unique identifier representing the current version of the
+ * file. If the file changes, the ETag MUST change. The ETag is an
+ * arbitrary string, but MUST be surrounded by double-quotes.
+ *
+ * Return null if the ETag can not effectively be determined
+ *
+ * @return mixed
+ */
+ public function getETag() {
+ $properties = $this->getProperties(array(self::GETETAG_PROPERTYNAME));
+ if (isset($properties[self::GETETAG_PROPERTYNAME])) {
+ return $properties[self::GETETAG_PROPERTYNAME];
+ }
+ return null;
+ }
+
+ /**
+ * Returns the mime-type for a file
+ *
+ * If null is returned, we'll assume application/octet-stream
+ *
+ * @return mixed
+ */
+ public function getContentType() {
+ if (isset($this->fileinfo_cache['mimetype'])) {
+ return $this->fileinfo_cache['mimetype'];
+ }
+
+ return \OC\Files\Filesystem::getMimeType($this->path);
+
+ }
+
+ private function createFileChunked($data)
+ {
+ list($path, $name) = \Sabre_DAV_URLUtil::splitPath($this->path);
+
+ $info = OC_FileChunking::decodeName($name);
+ if (empty($info)) {
+ throw new Sabre_DAV_Exception_NotImplemented();
+ }
+ $chunk_handler = new OC_FileChunking($info);
+ $bytesWritten = $chunk_handler->store($info['index'], $data);
+
+ //detect aborted upload
+ if (isset ($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT' ) {
+ if (isset($_SERVER['CONTENT_LENGTH'])) {
+ $expected = $_SERVER['CONTENT_LENGTH'];
+ if ($bytesWritten != $expected) {
+ $chunk_handler->remove($info['index']);
+ throw new Sabre_DAV_Exception_BadRequest(
+ 'expected filesize ' . $expected . ' got ' . $bytesWritten);
+ }
+ }
+ }
+
+ if ($chunk_handler->isComplete()) {
+
+ // we first assembly the target file as a part file
+ $partFile = $path . '/' . $info['name'] . '.ocTransferId' . $info['transferid'] . '.part';
+ $chunk_handler->file_assemble($partFile);
+
+ // here is the final atomic rename
+ $fs = $this->getFS();
+ $targetPath = $path . '/' . $info['name'];
+ $renameOkay = $fs->rename($partFile, $targetPath);
+ $fileExists = $fs->file_exists($targetPath);
+ if ($renameOkay === false || $fileExists === false) {
+ \OC_Log::write('webdav', '\OC\Files\Filesystem::rename() failed', \OC_Log::ERROR);
+ $fs->unlink($targetPath);
+ throw new Sabre_DAV_Exception();
+ }
+
+ // allow sync clients to send the mtime along in a header
+ $mtime = OC_Request::hasModificationTime();
+ if ($mtime !== false) {
+ if($fs->touch($targetPath, $mtime)) {
+ header('X-OC-MTime: accepted');
+ }
+ }
+
+ return OC_Connector_Sabre_Node::getETagPropertyForPath($targetPath);
+ }
+
+ return null;
+ }
+
+}
diff --git a/lib/private/connector/sabre/filesplugin.php b/lib/private/connector/sabre/filesplugin.php
new file mode 100644
index 00000000000..65231040fb5
--- /dev/null
+++ b/lib/private/connector/sabre/filesplugin.php
@@ -0,0 +1,103 @@
+<?php
+
+/**
+ * ownCloud
+ *
+ * @author Thomas Müller
+ * @copyright 2013 Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @license AGPL3
+ */
+
+class OC_Connector_Sabre_FilesPlugin extends Sabre_DAV_ServerPlugin
+{
+
+ // namespace
+ const NS_OWNCLOUD = 'http://owncloud.org/ns';
+
+ /**
+ * Reference to main server object
+ *
+ * @var Sabre_DAV_Server
+ */
+ private $server;
+
+ /**
+ * This initializes the plugin.
+ *
+ * This function is called by Sabre_DAV_Server, after
+ * addPlugin is called.
+ *
+ * This method should set up the required event subscriptions.
+ *
+ * @param Sabre_DAV_Server $server
+ * @return void
+ */
+ public function initialize(Sabre_DAV_Server $server) {
+
+ $server->xmlNamespaces[self::NS_OWNCLOUD] = 'oc';
+ $server->protectedProperties[] = '{' . self::NS_OWNCLOUD . '}id';
+
+ $this->server = $server;
+ $this->server->subscribeEvent('beforeGetProperties', array($this, 'beforeGetProperties'));
+ $this->server->subscribeEvent('afterCreateFile', array($this, 'sendFileIdHeader'));
+ $this->server->subscribeEvent('afterWriteContent', array($this, 'sendFileIdHeader'));
+ }
+
+ /**
+ * Adds all ownCloud-specific properties
+ *
+ * @param string $path
+ * @param Sabre_DAV_INode $node
+ * @param array $requestedProperties
+ * @param array $returnedProperties
+ * @return void
+ */
+ public function beforeGetProperties($path, Sabre_DAV_INode $node, array &$requestedProperties, array &$returnedProperties) {
+
+ if ($node instanceof OC_Connector_Sabre_Node) {
+
+ $fileid_propertyname = '{' . self::NS_OWNCLOUD . '}id';
+ if (array_search($fileid_propertyname, $requestedProperties)) {
+ unset($requestedProperties[array_search($fileid_propertyname, $requestedProperties)]);
+ }
+
+ /** @var $node OC_Connector_Sabre_Node */
+ $fileId = $node->getFileId();
+ if (!is_null($fileId)) {
+ $returnedProperties[200][$fileid_propertyname] = $fileId;
+ }
+
+ }
+
+ }
+
+ /**
+ * @param $filePath
+ * @param Sabre_DAV_INode $node
+ * @throws Sabre_DAV_Exception_BadRequest
+ */
+ public function sendFileIdHeader($filePath, Sabre_DAV_INode $node = null) {
+ // chunked upload handling
+ if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
+ list($path, $name) = \Sabre_DAV_URLUtil::splitPath($filePath);
+ $info = OC_FileChunking::decodeName($name);
+ if (!empty($info)) {
+ $filePath = $path . '/' . $info['name'];
+ }
+ }
+
+ // we get the node for the given $filePath here because in case of afterCreateFile $node is the parent folder
+ if (!$this->server->tree->nodeExists($filePath)) {
+ return;
+ }
+ $node = $this->server->tree->getNodeForPath($filePath);
+ if ($node instanceof OC_Connector_Sabre_Node) {
+ $fileId = $node->getFileId();
+ if (!is_null($fileId)) {
+ $this->server->httpResponse->setHeader('OC-FileId', $fileId);
+ }
+ }
+ }
+
+}
diff --git a/lib/connector/sabre/locks.php b/lib/private/connector/sabre/locks.php
index 69496c15ada..69496c15ada 100644
--- a/lib/connector/sabre/locks.php
+++ b/lib/private/connector/sabre/locks.php
diff --git a/lib/connector/sabre/maintenanceplugin.php b/lib/private/connector/sabre/maintenanceplugin.php
index 2eda269afc2..2eda269afc2 100644
--- a/lib/connector/sabre/maintenanceplugin.php
+++ b/lib/private/connector/sabre/maintenanceplugin.php
diff --git a/lib/connector/sabre/node.php b/lib/private/connector/sabre/node.php
index 0bffa58af78..993aa73faeb 100644
--- a/lib/connector/sabre/node.php
+++ b/lib/private/connector/sabre/node.php
@@ -33,11 +33,19 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
public static $ETagFunction = null;
/**
+ * is kept public to allow overwrite for unit testing
+ *
+ * @var \OC\Files\View
+ */
+ public $fileView;
+
+ /**
* The path to the current node
*
* @var string
*/
protected $path;
+
/**
* node fileinfo cache
* @var array
@@ -78,6 +86,11 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
*/
public function setName($name) {
+ // rename is only allowed if the update privilege is granted
+ if (!\OC\Files\Filesystem::isUpdatable($this->path)) {
+ throw new \Sabre_DAV_Exception_Forbidden();
+ }
+
list($parentPath, ) = Sabre_DAV_URLUtil::splitPath($this->path);
list(, $newName) = Sabre_DAV_URLUtil::splitPath($name);
@@ -179,6 +192,17 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
}
/**
+ * removes all properties for this node and user
+ */
+ public function removeProperties() {
+ $query = OC_DB::prepare( 'DELETE FROM `*PREFIX*properties`'
+ .' WHERE `userid` = ? AND `propertypath` = ?' );
+ $query->execute( array( OC_User::getUser(), $this->path));
+
+ $this->setPropertyCache(null);
+ }
+
+ /**
* @brief Returns a list of properties for this nodes.;
* @param array $properties
* @return array
@@ -188,6 +212,7 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
* properties should be returned
*/
public function getProperties($properties) {
+
if (is_null($this->property_cache)) {
$sql = 'SELECT * FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ?';
$result = OC_DB::executeAudited( $sql, array( OC_User::getUser(), $this->path ) );
@@ -196,7 +221,14 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
while( $row = $result->fetchRow()) {
$this->property_cache[$row['propertyname']] = $row['propertyvalue'];
}
- $this->property_cache[self::GETETAG_PROPERTYNAME] = $this->getETagPropertyForPath($this->path);
+
+ // Don't call the static getETagPropertyForPath, its result is not cached
+ $this->getFileinfoCache();
+ if ($this->fileinfo_cache['etag']) {
+ $this->property_cache[self::GETETAG_PROPERTYNAME] = '"'.$this->fileinfo_cache['etag'].'"';
+ } else {
+ $this->property_cache[self::GETETAG_PROPERTYNAME] = null;
+ }
}
// if the array was empty, we need to return everything
@@ -206,8 +238,11 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
$props = array();
foreach($properties as $property) {
- if (isset($this->property_cache[$property])) $props[$property] = $this->property_cache[$property];
+ if (isset($this->property_cache[$property])) {
+ $props[$property] = $this->property_cache[$property];
+ }
}
+
return $props;
}
@@ -216,12 +251,34 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
* @param string $path Path of the file
* @return string|null Returns null if the ETag can not effectively be determined
*/
- static public function getETagPropertyForPath($path) {
- $data = \OC\Files\Filesystem::getFileInfo($path);
+ protected function getETagPropertyForPath($path) {
+ $data = $this->getFS()->getFileInfo($path);
if (isset($data['etag'])) {
return '"'.$data['etag'].'"';
}
return null;
}
+ protected function getFS() {
+ if (is_null($this->fileView)) {
+ $this->fileView = \OC\Files\Filesystem::getView();
+ }
+ return $this->fileView;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getFileId()
+ {
+ $this->getFileinfoCache();
+
+ if (isset($this->fileinfo_cache['fileid'])) {
+ $instanceId = OC_Util::getInstanceId();
+ $id = sprintf('%08d', $this->fileinfo_cache['fileid']);
+ return $id . $instanceId;
+ }
+
+ return null;
+ }
}
diff --git a/lib/connector/sabre/objecttree.php b/lib/private/connector/sabre/objecttree.php
index c4ddcbecbb8..cd3f081f7cc 100644
--- a/lib/connector/sabre/objecttree.php
+++ b/lib/private/connector/sabre/objecttree.php
@@ -11,6 +11,14 @@ namespace OC\Connector\Sabre;
use OC\Files\Filesystem;
class ObjectTree extends \Sabre_DAV_ObjectTree {
+
+ /**
+ * keep this public to allow mock injection during unit test
+ *
+ * @var \OC\Files\View
+ */
+ public $fileView;
+
/**
* Returns the INode object for the requested path
*
@@ -21,14 +29,16 @@ class ObjectTree extends \Sabre_DAV_ObjectTree {
public function getNodeForPath($path) {
$path = trim($path, '/');
- if (isset($this->cache[$path])) return $this->cache[$path];
+ if (isset($this->cache[$path])) {
+ return $this->cache[$path];
+ }
// Is it the root node?
if (!strlen($path)) {
return $this->rootNode;
}
- $info = Filesystem::getFileInfo($path);
+ $info = $this->getFileView()->getFileInfo($path);
if (!$info) {
throw new \Sabre_DAV_Exception_NotFound('File with name ' . $path . ' could not be located');
@@ -64,7 +74,33 @@ class ObjectTree extends \Sabre_DAV_ObjectTree {
list($sourceDir,) = \Sabre_DAV_URLUtil::splitPath($sourcePath);
list($destinationDir,) = \Sabre_DAV_URLUtil::splitPath($destinationPath);
- Filesystem::rename($sourcePath, $destinationPath);
+ // check update privileges
+ $fs = $this->getFileView();
+ if (!$fs->isUpdatable($sourcePath)) {
+ throw new \Sabre_DAV_Exception_Forbidden();
+ }
+ if ($sourceDir !== $destinationDir) {
+ // for a full move we need update privileges on sourcePath and sourceDir as well as destinationDir
+ if (!$fs->isUpdatable($sourceDir)) {
+ throw new \Sabre_DAV_Exception_Forbidden();
+ }
+ if (!$fs->isUpdatable($destinationDir)) {
+ throw new \Sabre_DAV_Exception_Forbidden();
+ }
+ if (!$fs->isDeletable($sourcePath)) {
+ throw new \Sabre_DAV_Exception_Forbidden();
+ }
+ }
+
+ $renameOkay = $fs->rename($sourcePath, $destinationPath);
+ if (!$renameOkay) {
+ throw new \Sabre_DAV_Exception_Forbidden('');
+ }
+
+ // update properties
+ $query = \OC_DB::prepare( 'UPDATE `*PREFIX*properties` SET `propertypath` = ?'
+ .' WHERE `userid` = ? AND `propertypath` = ?' );
+ $query->execute( array( $destinationPath, \OC_User::getUser(), $sourcePath ));
$this->markDirty($sourceDir);
$this->markDirty($destinationDir);
@@ -88,15 +124,27 @@ class ObjectTree extends \Sabre_DAV_ObjectTree {
} else {
Filesystem::mkdir($destination);
$dh = Filesystem::opendir($source);
- while ($subnode = readdir($dh)) {
+ if(is_resource($dh)) {
+ while (($subnode = readdir($dh)) !== false) {
- if ($subnode == '.' || $subnode == '..') continue;
- $this->copy($source . '/' . $subnode, $destination . '/' . $subnode);
+ if ($subnode == '.' || $subnode == '..') continue;
+ $this->copy($source . '/' . $subnode, $destination . '/' . $subnode);
+ }
}
}
list($destinationDir,) = \Sabre_DAV_URLUtil::splitPath($destination);
$this->markDirty($destinationDir);
}
+
+ /**
+ * @return \OC\Files\View
+ */
+ public function getFileView() {
+ if (is_null($this->fileView)) {
+ $this->fileView = \OC\Files\Filesystem::getView();
+ }
+ return $this->fileView;
+ }
}
diff --git a/lib/connector/sabre/principal.php b/lib/private/connector/sabre/principal.php
index 16c88b96ea6..59a96797c16 100644
--- a/lib/connector/sabre/principal.php
+++ b/lib/private/connector/sabre/principal.php
@@ -66,13 +66,13 @@ class OC_Connector_Sabre_Principal implements Sabre_DAVACL_IPrincipalBackend {
*/
public function getGroupMemberSet($principal) {
// TODO: for now the group principal has only one member, the user itself
- list($prefix, $name) = Sabre_DAV_URLUtil::splitPath($principal);
-
- $principal = $this->getPrincipalByPath($prefix);
- if (!$principal) throw new Sabre_DAV_Exception('Principal not found');
+ $principal = $this->getPrincipalByPath($principal);
+ if (!$principal) {
+ throw new Sabre_DAV_Exception('Principal not found');
+ }
return array(
- $prefix
+ $principal['uri']
);
}
@@ -88,7 +88,9 @@ class OC_Connector_Sabre_Principal implements Sabre_DAVACL_IPrincipalBackend {
$group_membership = array();
if ($prefix == 'principals') {
$principal = $this->getPrincipalByPath($principal);
- if (!$principal) throw new Sabre_DAV_Exception('Principal not found');
+ if (!$principal) {
+ throw new Sabre_DAV_Exception('Principal not found');
+ }
// TODO: for now the user principal has only its own groups
return array(
diff --git a/lib/private/connector/sabre/quotaplugin.php b/lib/private/connector/sabre/quotaplugin.php
new file mode 100644
index 00000000000..ea2cb81d1f7
--- /dev/null
+++ b/lib/private/connector/sabre/quotaplugin.php
@@ -0,0 +1,97 @@
+<?php
+
+/**
+ * This plugin check user quota and deny creating files when they exceeds the quota.
+ *
+ * @author Sergio Cambra
+ * @copyright Copyright (C) 2012 entreCables S.L. All rights reserved.
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class OC_Connector_Sabre_QuotaPlugin extends Sabre_DAV_ServerPlugin {
+
+ /**
+ * Reference to main server object
+ *
+ * @var Sabre_DAV_Server
+ */
+ private $server;
+
+ /**
+ * is kept public to allow overwrite for unit testing
+ *
+ * @var \OC\Files\View
+ */
+ public $fileView;
+
+ /**
+ * This initializes the plugin.
+ *
+ * This function is called by Sabre_DAV_Server, after
+ * addPlugin is called.
+ *
+ * This method should set up the requires event subscriptions.
+ *
+ * @param Sabre_DAV_Server $server
+ * @return void
+ */
+ public function initialize(Sabre_DAV_Server $server) {
+
+ $this->server = $server;
+
+ $server->subscribeEvent('beforeWriteContent', array($this, 'checkQuota'), 10);
+ $server->subscribeEvent('beforeCreateFile', array($this, 'checkQuota'), 10);
+ }
+
+ /**
+ * This method is called before any HTTP method and validates there is enough free space to store the file
+ *
+ * @param string $method
+ * @throws Sabre_DAV_Exception
+ * @return bool
+ */
+ public function checkQuota($uri, $data = null) {
+ $length = $this->getLength();
+ if ($length) {
+ if (substr($uri, 0, 1)!=='/') {
+ $uri='/'.$uri;
+ }
+ list($parentUri, $newName) = Sabre_DAV_URLUtil::splitPath($uri);
+ $freeSpace = $this->getFreeSpace($parentUri);
+ if ($freeSpace !== \OC\Files\SPACE_UNKNOWN && $length > $freeSpace) {
+ throw new Sabre_DAV_Exception_InsufficientStorage();
+ }
+ }
+ return true;
+ }
+
+ public function getLength()
+ {
+ $req = $this->server->httpRequest;
+ $length = $req->getHeader('X-Expected-Entity-Length');
+ if (!$length) {
+ $length = $req->getHeader('Content-Length');
+ }
+
+ $ocLength = $req->getHeader('OC-Total-Length');
+ if ($length && $ocLength) {
+ return max($length, $ocLength);
+ }
+
+ return $length;
+ }
+
+ /**
+ * @param $parentUri
+ * @return mixed
+ */
+ public function getFreeSpace($parentUri)
+ {
+ if (is_null($this->fileView)) {
+ // initialize fileView
+ $this->fileView = \OC\Files\Filesystem::getView();
+ }
+
+ $freeSpace = $this->fileView->free_space($parentUri);
+ return $freeSpace;
+ }
+}
diff --git a/lib/connector/sabre/request.php b/lib/private/connector/sabre/request.php
index d70c25c4e70..d70c25c4e70 100644
--- a/lib/connector/sabre/request.php
+++ b/lib/private/connector/sabre/request.php
diff --git a/lib/private/connector/sabre/server.php b/lib/private/connector/sabre/server.php
new file mode 100644
index 00000000000..41e8885917a
--- /dev/null
+++ b/lib/private/connector/sabre/server.php
@@ -0,0 +1,235 @@
+<?php
+/**
+ * ownCloud / SabreDAV
+ *
+ * @author Markus Goetz
+ *
+ * @copyright Copyright (C) 2007-2013 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+
+/**
+ * Class OC_Connector_Sabre_Server
+ *
+ * This class reimplements some methods from @see Sabre_DAV_Server.
+ *
+ * Basically we add handling of depth: infinity.
+ *
+ * The right way to handle this would have been to submit a patch to the upstream project
+ * and grab the corresponding version one merged.
+ *
+ * Due to time constrains and the limitations where we don't want to upgrade 3rdparty code in
+ * this stage of the release cycle we did choose this approach.
+ *
+ * For ownCloud 7 we will upgrade SabreDAV and submit the patch - if needed.
+ *
+ * @see Sabre_DAV_Server
+ */
+class OC_Connector_Sabre_Server extends Sabre_DAV_Server {
+
+ /**
+ * @see Sabre_DAV_Server
+ */
+ protected function httpPropfind($uri) {
+
+ // $xml = new Sabre_DAV_XMLReader(file_get_contents('php://input'));
+ $requestedProperties = $this->parsePropFindRequest($this->httpRequest->getBody(true));
+
+ $depth = $this->getHTTPDepth(1);
+ // The only two options for the depth of a propfind is 0 or 1
+ // if ($depth!=0) $depth = 1;
+
+ $newProperties = $this->getPropertiesForPath($uri,$requestedProperties,$depth);
+
+ // This is a multi-status response
+ $this->httpResponse->sendStatus(207);
+ $this->httpResponse->setHeader('Content-Type','application/xml; charset=utf-8');
+ $this->httpResponse->setHeader('Vary','Brief,Prefer');
+
+ // Normally this header is only needed for OPTIONS responses, however..
+ // iCal seems to also depend on these being set for PROPFIND. Since
+ // this is not harmful, we'll add it.
+ $features = array('1','3', 'extended-mkcol');
+ foreach($this->plugins as $plugin) {
+ $features = array_merge($features,$plugin->getFeatures());
+ }
+
+ $this->httpResponse->setHeader('DAV',implode(', ',$features));
+
+ $prefer = $this->getHTTPPrefer();
+ $minimal = $prefer['return-minimal'];
+
+ $data = $this->generateMultiStatus($newProperties, $minimal);
+ $this->httpResponse->sendBody($data);
+
+ }
+
+ /**
+ * Small helper to support PROPFIND with DEPTH_INFINITY.
+ */
+ private function addPathNodesRecursively(&$nodes, $path) {
+ foreach($this->tree->getChildren($path) as $childNode) {
+ $nodes[$path . '/' . $childNode->getName()] = $childNode;
+ if ($childNode instanceof Sabre_DAV_ICollection)
+ $this->addPathNodesRecursively($nodes, $path . '/' . $childNode->getName());
+ }
+ }
+
+ public function getPropertiesForPath($path, $propertyNames = array(), $depth = 0) {
+
+ // if ($depth!=0) $depth = 1;
+
+ $path = rtrim($path,'/');
+
+ $returnPropertyList = array();
+
+ $parentNode = $this->tree->getNodeForPath($path);
+ $nodes = array(
+ $path => $parentNode
+ );
+ if ($depth==1 && $parentNode instanceof Sabre_DAV_ICollection) {
+ foreach($this->tree->getChildren($path) as $childNode)
+ $nodes[$path . '/' . $childNode->getName()] = $childNode;
+ } else if ($depth == self::DEPTH_INFINITY && $parentNode instanceof Sabre_DAV_ICollection) {
+ $this->addPathNodesRecursively($nodes, $path);
+ }
+
+ // If the propertyNames array is empty, it means all properties are requested.
+ // We shouldn't actually return everything we know though, and only return a
+ // sensible list.
+ $allProperties = count($propertyNames)==0;
+
+ foreach($nodes as $myPath=>$node) {
+
+ $currentPropertyNames = $propertyNames;
+
+ $newProperties = array(
+ '200' => array(),
+ '404' => array(),
+ );
+
+ if ($allProperties) {
+ // Default list of propertyNames, when all properties were requested.
+ $currentPropertyNames = array(
+ '{DAV:}getlastmodified',
+ '{DAV:}getcontentlength',
+ '{DAV:}resourcetype',
+ '{DAV:}quota-used-bytes',
+ '{DAV:}quota-available-bytes',
+ '{DAV:}getetag',
+ '{DAV:}getcontenttype',
+ );
+ }
+
+ // If the resourceType was not part of the list, we manually add it
+ // and mark it for removal. We need to know the resourcetype in order
+ // to make certain decisions about the entry.
+ // WebDAV dictates we should add a / and the end of href's for collections
+ $removeRT = false;
+ if (!in_array('{DAV:}resourcetype',$currentPropertyNames)) {
+ $currentPropertyNames[] = '{DAV:}resourcetype';
+ $removeRT = true;
+ }
+
+ $result = $this->broadcastEvent('beforeGetProperties',array($myPath, $node, &$currentPropertyNames, &$newProperties));
+ // If this method explicitly returned false, we must ignore this
+ // node as it is inaccessible.
+ if ($result===false) continue;
+
+ if (count($currentPropertyNames) > 0) {
+
+ if ($node instanceof Sabre_DAV_IProperties) {
+ $nodeProperties = $node->getProperties($currentPropertyNames);
+
+ // The getProperties method may give us too much,
+ // properties, in case the implementor was lazy.
+ //
+ // So as we loop through this list, we will only take the
+ // properties that were actually requested and discard the
+ // rest.
+ foreach($currentPropertyNames as $k=>$currentPropertyName) {
+ if (isset($nodeProperties[$currentPropertyName])) {
+ unset($currentPropertyNames[$k]);
+ $newProperties[200][$currentPropertyName] = $nodeProperties[$currentPropertyName];
+ }
+ }
+
+ }
+
+ }
+
+ foreach($currentPropertyNames as $prop) {
+
+ if (isset($newProperties[200][$prop])) continue;
+
+ switch($prop) {
+ case '{DAV:}getlastmodified' : if ($node->getLastModified()) $newProperties[200][$prop] = new Sabre_DAV_Property_GetLastModified($node->getLastModified()); break;
+ case '{DAV:}getcontentlength' :
+ if ($node instanceof Sabre_DAV_IFile) {
+ $size = $node->getSize();
+ if (!is_null($size)) {
+ $newProperties[200][$prop] = (int)$node->getSize();
+ }
+ }
+ break;
+ case '{DAV:}quota-used-bytes' :
+ if ($node instanceof Sabre_DAV_IQuota) {
+ $quotaInfo = $node->getQuotaInfo();
+ $newProperties[200][$prop] = $quotaInfo[0];
+ }
+ break;
+ case '{DAV:}quota-available-bytes' :
+ if ($node instanceof Sabre_DAV_IQuota) {
+ $quotaInfo = $node->getQuotaInfo();
+ $newProperties[200][$prop] = $quotaInfo[1];
+ }
+ break;
+ case '{DAV:}getetag' : if ($node instanceof Sabre_DAV_IFile && $etag = $node->getETag()) $newProperties[200][$prop] = $etag; break;
+ case '{DAV:}getcontenttype' : if ($node instanceof Sabre_DAV_IFile && $ct = $node->getContentType()) $newProperties[200][$prop] = $ct; break;
+ case '{DAV:}supported-report-set' :
+ $reports = array();
+ foreach($this->plugins as $plugin) {
+ $reports = array_merge($reports, $plugin->getSupportedReportSet($myPath));
+ }
+ $newProperties[200][$prop] = new Sabre_DAV_Property_SupportedReportSet($reports);
+ break;
+ case '{DAV:}resourcetype' :
+ $newProperties[200]['{DAV:}resourcetype'] = new Sabre_DAV_Property_ResourceType();
+ foreach($this->resourceTypeMapping as $className => $resourceType) {
+ if ($node instanceof $className) $newProperties[200]['{DAV:}resourcetype']->add($resourceType);
+ }
+ break;
+
+ }
+
+ // If we were unable to find the property, we will list it as 404.
+ if (!$allProperties && !isset($newProperties[200][$prop])) $newProperties[404][$prop] = null;
+
+ }
+
+ $this->broadcastEvent('afterGetProperties',array(trim($myPath,'/'),&$newProperties, $node));
+
+ $newProperties['href'] = trim($myPath,'/');
+
+ // Its is a WebDAV recommendation to add a trailing slash to collectionnames.
+ // Apple's iCal also requires a trailing slash for principals (rfc 3744), though this is non-standard.
+ if ($myPath!='' && isset($newProperties[200]['{DAV:}resourcetype'])) {
+ $rt = $newProperties[200]['{DAV:}resourcetype'];
+ if ($rt->is('{DAV:}collection') || $rt->is('{DAV:}principal')) {
+ $newProperties['href'] .='/';
+ }
+ }
+
+ // If the resourcetype property was manually added to the requested property list,
+ // we will remove it again.
+ if ($removeRT) unset($newProperties[200]['{DAV:}resourcetype']);
+
+ $returnPropertyList[] = $newProperties;
+
+ }
+
+ return $returnPropertyList;
+
+ }
+}
diff --git a/lib/private/contactsmanager.php b/lib/private/contactsmanager.php
new file mode 100644
index 00000000000..fc6745b4505
--- /dev/null
+++ b/lib/private/contactsmanager.php
@@ -0,0 +1,145 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Thomas Müller
+ * @copyright 2013 Thomas Müller thomas.mueller@tmit.eu
+ *
+ * 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 {
+
+ class ContactsManager implements \OCP\Contacts\IManager {
+
+ /**
+ * This function is used to search and find contacts within the users address books.
+ * In case $pattern is empty all contacts will be returned.
+ *
+ * @param string $pattern which should match within the $searchProperties
+ * @param array $searchProperties defines the properties within the query pattern should match
+ * @param array $options - for future use. One should always have options!
+ * @return array of contacts which are arrays of key-value-pairs
+ */
+ public function search($pattern, $searchProperties = array(), $options = array()) {
+ $result = array();
+ foreach($this->address_books as $address_book) {
+ $r = $address_book->search($pattern, $searchProperties, $options);
+ $result = array_merge($result, $r);
+ }
+
+ return $result;
+ }
+
+ /**
+ * 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
+ * @return bool successful or not
+ */
+ public function delete($id, $address_book_key) {
+ if (!array_key_exists($address_book_key, $this->address_books))
+ return null;
+
+ $address_book = $this->address_books[$address_book_key];
+ if ($address_book->getPermissions() & \OCP\PERMISSION_DELETE)
+ return null;
+
+ return $address_book->delete($id);
+ }
+
+ /**
+ * This function is used to create a new contact if 'id' is not given or not present.
+ * 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
+ * @return array representing the contact just created or updated
+ */
+ public function createOrUpdate($properties, $address_book_key) {
+
+ if (!array_key_exists($address_book_key, $this->address_books))
+ return null;
+
+ $address_book = $this->address_books[$address_book_key];
+ if ($address_book->getPermissions() & \OCP\PERMISSION_CREATE)
+ return null;
+
+ return $address_book->createOrUpdate($properties);
+ }
+
+ /**
+ * Check if contacts are available (e.g. contacts app enabled)
+ *
+ * @return bool true if enabled, false if not
+ */
+ public function isEnabled() {
+ return !empty($this->address_books);
+ }
+
+ /**
+ * @param \OCP\IAddressBook $address_book
+ */
+ public function registerAddressBook(\OCP\IAddressBook $address_book) {
+ $this->address_books[$address_book->getKey()] = $address_book;
+ }
+
+ /**
+ * @param \OCP\IAddressBook $address_book
+ */
+ public function unregisterAddressBook(\OCP\IAddressBook $address_book) {
+ unset($this->address_books[$address_book->getKey()]);
+ }
+
+ /**
+ * @return array
+ */
+ public function getAddressBooks() {
+ $result = array();
+ foreach($this->address_books as $address_book) {
+ $result[$address_book->getKey()] = $address_book->getDisplayName();
+ }
+
+ return $result;
+ }
+
+ /**
+ * removes all registered address book instances
+ */
+ public function clear() {
+ $this->address_books = array();
+ }
+
+ /**
+ * @var \OCP\IAddressBook[] which holds all registered address books
+ */
+ private $address_books = array();
+
+ /**
+ * In order to improve lazy loading a closure can be registered which will be called in case
+ * address books are actually requested
+ *
+ * @param string $key
+ * @param \Closure $callable
+ */
+ function register($key, \Closure $callable)
+ {
+ //
+ //TODO: implement me
+ //
+ }
+ }
+}
diff --git a/lib/private/davclient.php b/lib/private/davclient.php
new file mode 100644
index 00000000000..28f48f3b921
--- /dev/null
+++ b/lib/private/davclient.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Vincent Petry
+ * @copyright 2013 Vincent Petry <pvince81@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/>.
+ *
+ */
+
+/**
+ * This class extends the SabreDAV client with additional functionality
+ * like request timeout.
+ */
+
+class OC_DAVClient extends \Sabre_DAV_Client {
+
+ protected $requestTimeout;
+
+ /**
+ * @brief Sets the request timeout or 0 to disable timeout.
+ * @param int timeout in seconds or 0 to disable
+ */
+ public function setRequestTimeout($timeout) {
+ $this->requestTimeout = (int)$timeout;
+ }
+
+ protected function curlRequest($url, $settings) {
+ if ($this->requestTimeout > 0) {
+ $settings[CURLOPT_TIMEOUT] = $this->requestTimeout;
+ }
+ return parent::curlRequest($url, $settings);
+ }
+}
diff --git a/lib/db.php b/lib/private/db.php
index ebd012c72f8..562065259fa 100644
--- a/lib/db.php
+++ b/lib/private/db.php
@@ -75,6 +75,7 @@ class OC_DB {
// do nothing if the connection already has been established
if (!self::$connection) {
$config = new \Doctrine\DBAL\Configuration();
+ $eventManager = new \Doctrine\Common\EventManager();
switch($type) {
case 'sqlite':
case 'sqlite3':
@@ -86,6 +87,7 @@ class OC_DB {
'driver' => 'pdo_sqlite',
);
$connectionParams['adapter'] = '\OC\DB\AdapterSqlite';
+ $connectionParams['wrapperClass'] = 'OC\DB\Connection';
break;
case 'mysql':
$connectionParams = array(
@@ -98,6 +100,10 @@ class OC_DB {
'driver' => 'pdo_mysql',
);
$connectionParams['adapter'] = '\OC\DB\Adapter';
+ $connectionParams['wrapperClass'] = 'OC\DB\Connection';
+ // Send "SET NAMES utf8". Only required on PHP 5.3 below 5.3.6.
+ // See http://stackoverflow.com/questions/4361459/php-pdo-charset-set-names#4361485
+ $eventManager->addEventSubscriber(new \Doctrine\DBAL\Event\Listeners\MysqlSessionInit);
break;
case 'pgsql':
$connectionParams = array(
@@ -109,6 +115,7 @@ class OC_DB {
'driver' => 'pdo_pgsql',
);
$connectionParams['adapter'] = '\OC\DB\AdapterPgSql';
+ $connectionParams['wrapperClass'] = 'OC\DB\Connection';
break;
case 'oci':
$connectionParams = array(
@@ -123,6 +130,8 @@ class OC_DB {
$connectionParams['port'] = $port;
}
$connectionParams['adapter'] = '\OC\DB\AdapterOCI8';
+ $connectionParams['wrapperClass'] = 'OC\DB\OracleConnection';
+ $eventManager->addEventSubscriber(new \Doctrine\DBAL\Event\Listeners\OracleSessionInit);
break;
case 'mssql':
$connectionParams = array(
@@ -135,14 +144,14 @@ class OC_DB {
'driver' => 'pdo_sqlsrv',
);
$connectionParams['adapter'] = '\OC\DB\AdapterSQLSrv';
+ $connectionParams['wrapperClass'] = 'OC\DB\Connection';
break;
default:
return false;
}
- $connectionParams['wrapperClass'] = 'OC\DB\Connection';
$connectionParams['tablePrefix'] = OC_Config::getValue('dbtableprefix', 'oc_' );
try {
- self::$connection = \Doctrine\DBAL\DriverManager::getConnection($connectionParams, $config);
+ self::$connection = \Doctrine\DBAL\DriverManager::getConnection($connectionParams, $config, $eventManager);
if ($type === 'sqlite' || $type === 'sqlite3') {
// Sqlite doesn't handle query caching and schema changes
// TODO: find a better way to handle this
@@ -330,18 +339,6 @@ class OC_DB {
}
/**
- * @brief Disconnect
- *
- * This is good bye, good bye, yeah!
- */
- public static function disconnect() {
- // Cut connection if required
- if(self::$connection) {
- self::$connection->close();
- }
- }
-
- /**
* @brief saves database schema to xml file
* @param string $file name of file
* @param int $mode
diff --git a/lib/db/adapter.php b/lib/private/db/adapter.php
index 6b31f37dd98..6b31f37dd98 100644
--- a/lib/db/adapter.php
+++ b/lib/private/db/adapter.php
diff --git a/lib/db/adapteroci8.php b/lib/private/db/adapteroci8.php
index bc226e979ec..bc226e979ec 100644
--- a/lib/db/adapteroci8.php
+++ b/lib/private/db/adapteroci8.php
diff --git a/lib/db/adapterpgsql.php b/lib/private/db/adapterpgsql.php
index 990d71c9f29..990d71c9f29 100644
--- a/lib/db/adapterpgsql.php
+++ b/lib/private/db/adapterpgsql.php
diff --git a/lib/db/adaptersqlite.php b/lib/private/db/adaptersqlite.php
index fa6d308ae32..fa6d308ae32 100644
--- a/lib/db/adaptersqlite.php
+++ b/lib/private/db/adaptersqlite.php
diff --git a/lib/db/adaptersqlsrv.php b/lib/private/db/adaptersqlsrv.php
index d0a67af28a7..a6bc0e21052 100644
--- a/lib/db/adaptersqlsrv.php
+++ b/lib/private/db/adaptersqlsrv.php
@@ -10,13 +10,6 @@
namespace OC\DB;
class AdapterSQLSrv extends Adapter {
- public function lastInsertId($table) {
- if($table !== null) {
- $table = $this->conn->replaceTablePrefix( $table );
- }
- return $this->conn->lastInsertId($table);
- }
-
public function fixupStatement($statement) {
$statement = preg_replace( "/\`(.*?)`/", "[$1]", $statement );
$statement = str_ireplace( 'NOW()', 'CURRENT_TIMESTAMP', $statement );
diff --git a/lib/db/connection.php b/lib/private/db/connection.php
index 2581969dbd0..2581969dbd0 100644
--- a/lib/db/connection.php
+++ b/lib/private/db/connection.php
diff --git a/lib/private/db/connectionwrapper.php b/lib/private/db/connectionwrapper.php
new file mode 100644
index 00000000000..93d4fb57f74
--- /dev/null
+++ b/lib/private/db/connectionwrapper.php
@@ -0,0 +1,99 @@
+<?php
+/**
+ * Copyright (c) 2013 Thomas Müller <deepdiver@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\DB;
+
+
+class ConnectionWrapper implements \OCP\IDBConnection {
+
+ private $connection;
+
+ public function __construct(Connection $conn) {
+ $this->connection = $conn;
+ }
+
+ /**
+ * Used to the owncloud database access away
+ * @param string $sql the sql query with ? placeholder for params
+ * @param int $limit the maximum number of rows
+ * @param int $offset from which row we want to start
+ * @return \Doctrine\DBAL\Driver\Statement The prepared statement.
+ */
+ public function prepare($sql, $limit = null, $offset = null)
+ {
+ return $this->connection->prepare($sql, $limit, $offset);
+ }
+
+ /**
+ * Used to get the id of the just inserted element
+ * @param string $tableName the name of the table where we inserted the item
+ * @return int the id of the inserted element
+ */
+ public function lastInsertId($table = null)
+ {
+ return $this->connection->lastInsertId($table);
+ }
+
+ /**
+ * Insert a row if a matching row doesn't exists.
+ * @param string The table name (will replace *PREFIX*) to perform the replace on.
+ * @param array
+ *
+ * The input array if in the form:
+ *
+ * array ( 'id' => array ( 'value' => 6,
+ * 'key' => true
+ * ),
+ * 'name' => array ('value' => 'Stoyan'),
+ * 'family' => array ('value' => 'Stefanov'),
+ * 'birth_date' => array ('value' => '1975-06-20')
+ * );
+ * @return bool
+ *
+ */
+ public function insertIfNotExist($table, $input)
+ {
+ return $this->connection->insertIfNotExist($table, $input);
+ }
+
+ /**
+ * Start a transaction
+ * @return bool TRUE on success or FALSE on failure
+ */
+ public function beginTransaction()
+ {
+ return $this->connection->beginTransaction();
+ }
+
+ /**
+ * Commit the database changes done during a transaction that is in progress
+ * @return bool TRUE on success or FALSE on failure
+ */
+ public function commit()
+ {
+ return $this->connection->commit();
+ }
+
+ /**
+ * Rollback the database changes done during a transaction that is in progress
+ * @return bool TRUE on success or FALSE on failure
+ */
+ public function rollBack()
+ {
+ return $this->connection->rollBack();
+ }
+
+ /**
+ * Gets the error code and message as a string for logging
+ * @return string
+ */
+ public function getError()
+ {
+ return $this->connection->getError();
+ }
+}
diff --git a/lib/db/mdb2schemamanager.php b/lib/private/db/mdb2schemamanager.php
index 8e76f46c78f..6378c769055 100644
--- a/lib/db/mdb2schemamanager.php
+++ b/lib/private/db/mdb2schemamanager.php
@@ -19,6 +19,8 @@ class MDB2SchemaManager {
*/
public function __construct($conn) {
$this->conn = $conn;
+ $this->conn->close();
+ $this->conn->connect();
}
/**
@@ -53,7 +55,7 @@ class MDB2SchemaManager {
* @param string $file file to read structure from
* @return bool
*/
- public function updateDbFromStructure($file) {
+ public function updateDbFromStructure($file, $generateSql = false) {
$sm = $this->conn->getSchemaManager();
$fromSchema = $sm->createSchema();
@@ -61,6 +63,7 @@ class MDB2SchemaManager {
$toSchema = $schemaReader->loadSchemaFromFile($file);
// remove tables we don't know about
+ /** @var $table \Doctrine\DBAL\Schema\Table */
foreach($fromSchema->getTables() as $table) {
if (!$toSchema->hasTable($table->getName())) {
$fromSchema->dropTable($table->getName());
@@ -77,10 +80,13 @@ class MDB2SchemaManager {
$schemaDiff = $comparator->compare($fromSchema, $toSchema);
$platform = $this->conn->getDatabasePlatform();
- $tables = $schemaDiff->newTables + $schemaDiff->changedTables + $schemaDiff->removedTables;
- foreach($tables as $tableDiff) {
+ foreach($schemaDiff->changedTables as $tableDiff) {
$tableDiff->name = $platform->quoteIdentifier($tableDiff->name);
}
+
+ if ($generateSql) {
+ return $this->generateChangeScript($schemaDiff);
+ }
return $this->executeSchemaChange($schemaDiff);
}
@@ -106,6 +112,7 @@ class MDB2SchemaManager {
$schemaReader = new MDB2SchemaReader(\OC_Config::getObject(), $this->conn->getDatabasePlatform());
$fromSchema = $schemaReader->loadSchemaFromFile($file);
$toSchema = clone $fromSchema;
+ /** @var $table \Doctrine\DBAL\Schema\Table */
foreach($toSchema->getTables() as $table) {
$toSchema->dropTable($table->getName());
}
@@ -147,4 +154,20 @@ class MDB2SchemaManager {
$this->conn->commit();
return true;
}
+
+ /**
+ * @param \Doctrine\DBAL\Schema\Schema $schema
+ * @return string
+ */
+ public function generateChangeScript($schema) {
+
+ $script = '';
+ $sqls = $schema->toSql($this->conn->getDatabasePlatform());
+ foreach($sqls as $sql) {
+ $script .= $sql . ';';
+ $script .= PHP_EOL;
+ }
+
+ return $script;
+ }
}
diff --git a/lib/db/mdb2schemareader.php b/lib/private/db/mdb2schemareader.php
index b7128a2f176..511bd1c90bd 100644
--- a/lib/db/mdb2schemareader.php
+++ b/lib/private/db/mdb2schemareader.php
@@ -150,6 +150,9 @@ class MDB2SchemaReader {
case 'timestamp':
$type = 'datetime';
break;
+ case 'numeric':
+ $type = 'decimal';
+ break;
}
break;
case 'length':
@@ -186,14 +189,14 @@ class MDB2SchemaReader {
}
}
if (isset($name) && isset($type)) {
- if (empty($options['default'])) {
+ if (isset($options['default']) && empty($options['default'])) {
if (empty($options['notnull']) || !$options['notnull']) {
unset($options['default']);
$options['notnull'] = false;
} else {
$options['default'] = '';
}
- if ($type == 'integer') {
+ if ($type == 'integer' || $type == 'decimal') {
$options['default'] = 0;
} elseif ($type == 'boolean') {
$options['default'] = false;
diff --git a/lib/db/mdb2schemawriter.php b/lib/private/db/mdb2schemawriter.php
index 21b43cbfe80..21b43cbfe80 100644
--- a/lib/db/mdb2schemawriter.php
+++ b/lib/private/db/mdb2schemawriter.php
diff --git a/lib/private/db/oracleconnection.php b/lib/private/db/oracleconnection.php
new file mode 100644
index 00000000000..e2fc4644f47
--- /dev/null
+++ b/lib/private/db/oracleconnection.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\DB;
+
+class OracleConnection extends Connection {
+ /**
+ * Quote the keys of the array
+ */
+ private function quoteKeys(array $data) {
+ $return = array();
+ foreach($data as $key => $value) {
+ $return[$this->quoteIdentifier($key)] = $value;
+ }
+ return $return;
+ }
+
+ /*
+ * {@inheritDoc}
+ */
+ public function insert($tableName, array $data, array $types = array()) {
+ $tableName = $this->quoteIdentifier($tableName);
+ $data = $this->quoteKeys($data);
+ return parent::insert($tableName, $data, $types);
+ }
+
+ /*
+ * {@inheritDoc}
+ */
+ public function update($tableName, array $data, array $identifier, array $types = array()) {
+ $tableName = $this->quoteIdentifier($tableName);
+ $data = $this->quoteKeys($data);
+ $identifier = $this->quoteKeys($identifier);
+ return parent::update($tableName, $data, $identifier, $types);
+ }
+
+ /*
+ * {@inheritDoc}
+ */
+ public function delete($tableName, array $identifier) {
+ $tableName = $this->quoteIdentifier($tableName);
+ $identifier = $this->quoteKeys($identifier);
+ return parent::delete($tableName, $identifier);
+ }
+}
diff --git a/lib/db/statementwrapper.php b/lib/private/db/statementwrapper.php
index b8da1afc0e5..b8da1afc0e5 100644
--- a/lib/db/statementwrapper.php
+++ b/lib/private/db/statementwrapper.php
diff --git a/lib/defaults.php b/lib/private/defaults.php
index 10813a3e8d8..cec9a65c7f3 100644
--- a/lib/defaults.php
+++ b/lib/private/defaults.php
@@ -1,18 +1,17 @@
<?php
-/**
- * Default strings and values which differ between the enterprise and the
- * community edition. Use the get methods to always get the right strings.
- */
-
-
if (file_exists(OC::$SERVERROOT . '/themes/' . OC_Util::getTheme() . '/defaults.php')) {
require_once 'themes/' . OC_Util::getTheme() . '/defaults.php';
}
+/**
+ * Default strings and values which differ between the enterprise and the
+ * community edition. Use the get methods to always get the right strings.
+ */
class OC_Defaults {
private $theme;
+ private $l;
private $defaultEntity;
private $defaultName;
@@ -24,7 +23,7 @@ class OC_Defaults {
private $defaultLogoClaim;
function __construct() {
- $l = OC_L10N::get('core');
+ $this->l = OC_L10N::get('core');
$this->defaultEntity = "ownCloud"; /* e.g. company name, used for footers and copyright notices */
$this->defaultName = "ownCloud"; /* short name, used when referring to the software */
@@ -32,7 +31,7 @@ class OC_Defaults {
$this->defaultBaseUrl = "http://owncloud.org";
$this->defaultSyncClientUrl = " http://owncloud.org/sync-clients/";
$this->defaultDocBaseUrl = "http://doc.owncloud.org";
- $this->defaultSlogan = $l->t("web services under your control");
+ $this->defaultSlogan = $this->l->t("web services under your control");
$this->defaultLogoClaim = "";
if (class_exists("OC_Theme")) {
@@ -47,6 +46,10 @@ class OC_Defaults {
return false;
}
+ /**
+ * Returns the base URL
+ * @return string URL
+ */
public function getBaseUrl() {
if ($this->themeExist('getBaseUrl')) {
return $this->theme->getBaseUrl();
@@ -55,6 +58,10 @@ class OC_Defaults {
}
}
+ /**
+ * Returns the URL where the sync clients are listed
+ * @return string URL
+ */
public function getSyncClientUrl() {
if ($this->themeExist('getSyncClientUrl')) {
return $this->theme->getSyncClientUrl();
@@ -63,6 +70,10 @@ class OC_Defaults {
}
}
+ /**
+ * Returns the documentation URL
+ * @return string URL
+ */
public function getDocBaseUrl() {
if ($this->themeExist('getDocBaseUrl')) {
return $this->theme->getDocBaseUrl();
@@ -71,6 +82,10 @@ class OC_Defaults {
}
}
+ /**
+ * Returns the title
+ * @return string title
+ */
public function getTitle() {
if ($this->themeExist('getTitle')) {
return $this->theme->getTitle();
@@ -79,6 +94,10 @@ class OC_Defaults {
}
}
+ /**
+ * Returns the short name of the software
+ * @return string title
+ */
public function getName() {
if ($this->themeExist('getName')) {
return $this->theme->getName();
@@ -87,6 +106,10 @@ class OC_Defaults {
}
}
+ /**
+ * Returns entity (e.g. company name) - used for footer, copyright
+ * @return string entity name
+ */
public function getEntity() {
if ($this->themeExist('getEntity')) {
return $this->theme->getEntity();
@@ -95,6 +118,10 @@ class OC_Defaults {
}
}
+ /**
+ * Returns slogan
+ * @return string slogan
+ */
public function getSlogan() {
if ($this->themeExist('getSlogan')) {
return $this->theme->getSlogan();
@@ -103,6 +130,10 @@ class OC_Defaults {
}
}
+ /**
+ * Returns logo claim
+ * @return string logo claim
+ */
public function getLogoClaim() {
if ($this->themeExist('getLogoClaim')) {
return $this->theme->getLogoClaim();
@@ -111,6 +142,10 @@ class OC_Defaults {
}
}
+ /**
+ * Returns short version of the footer
+ * @return string short footer
+ */
public function getShortFooter() {
if ($this->themeExist('getShortFooter')) {
$footer = $this->theme->getShortFooter();
@@ -122,6 +157,10 @@ class OC_Defaults {
return $footer;
}
+ /**
+ * Returns long version of the footer
+ * @return string long footer
+ */
public function getLongFooter() {
if ($this->themeExist('getLongFooter')) {
$footer = $this->theme->getLongFooter();
diff --git a/lib/eventsource.php b/lib/private/eventsource.php
index a83084d9251..a83084d9251 100644
--- a/lib/eventsource.php
+++ b/lib/private/eventsource.php
diff --git a/lib/filechunking.php b/lib/private/filechunking.php
index e6d69273a44..aa4f73c7c05 100644
--- a/lib/filechunking.php
+++ b/lib/private/filechunking.php
@@ -29,15 +29,24 @@ class OC_FileChunking {
protected function getCache() {
if (!isset($this->cache)) {
- $this->cache = new OC_Cache_File();
+ $this->cache = new \OC\Cache\File();
}
return $this->cache;
}
+ /**
+ * Stores the given $data under the given $key - the number of stored bytes is returned
+ *
+ * @param $index
+ * @param $data
+ * @return int
+ */
public function store($index, $data) {
$cache = $this->getCache();
$name = $this->getPrefix().$index;
$cache->set($name, $data);
+
+ return $cache->size($name);
}
public function isComplete() {
@@ -58,12 +67,34 @@ class OC_FileChunking {
$count = 0;
for($i=0; $i < $this->info['chunkcount']; $i++) {
$chunk = $cache->get($prefix.$i);
- $cache->remove($prefix.$i);
$count += fwrite($f, $chunk);
}
+
+ $this->cleanup();
return $count;
}
+ /**
+ * Removes all chunks which belong to this transmission
+ */
+ public function cleanup() {
+ $cache = $this->getCache();
+ $prefix = $this->getPrefix();
+ for($i=0; $i < $this->info['chunkcount']; $i++) {
+ $cache->remove($prefix.$i);
+ }
+ }
+
+ /**
+ * Removes one specific chunk
+ * @param $index
+ */
+ public function remove($index) {
+ $cache = $this->getCache();
+ $prefix = $this->getPrefix();
+ $cache->remove($prefix.$index);
+ }
+
public function signature_split($orgfile, $input) {
$info = unpack('n', fread($input, 2));
$blocksize = $info[1];
diff --git a/lib/fileproxy.php b/lib/private/fileproxy.php
index 52ec79b4bdb..52ec79b4bdb 100644
--- a/lib/fileproxy.php
+++ b/lib/private/fileproxy.php
diff --git a/lib/fileproxy/fileoperations.php b/lib/private/fileproxy/fileoperations.php
index b2ff2e7e5e9..b2ff2e7e5e9 100644
--- a/lib/fileproxy/fileoperations.php
+++ b/lib/private/fileproxy/fileoperations.php
diff --git a/lib/files.php b/lib/private/files.php
index c705d2adb1a..6ffa14c0d91 100644
--- a/lib/files.php
+++ b/lib/private/files.php
@@ -28,8 +28,8 @@
class OC_Files {
static $tmpFiles = array();
- static public function getFileInfo($path){
- return \OC\Files\Filesystem::getFileInfo($path);
+ static public function getFileInfo($path, $includeMountPoints = true){
+ return \OC\Files\Filesystem::getFileInfo($path, $includeMountPoints);
}
static public function getDirectoryContent($path){
@@ -109,6 +109,9 @@ class OC_Files {
$zip = false;
$filename = $dir . '/' . $files;
$name = $files;
+ if ($xsendfile && OC_App::isEnabled('files_encryption')) {
+ $xsendfile = false;
+ }
}
OC_Util::obEnd();
if ($zip or \OC\Files\Filesystem::isReadable($filename)) {
@@ -131,9 +134,11 @@ class OC_Files {
if ($filesize > -1) {
header("Content-Length: ".$filesize);
}
- list($storage) = \OC\Files\Filesystem::resolvePath($filename);
- if ($storage instanceof \OC\Files\Storage\Local) {
- self::addSendfileHeader(\OC\Files\Filesystem::getLocalFile($filename));
+ if ($xsendfile) {
+ list($storage) = \OC\Files\Filesystem::resolvePath(\OC\Files\Filesystem::getView()->getAbsolutePath($filename));
+ if ($storage instanceof \OC\Files\Storage\Local) {
+ self::addSendfileHeader(\OC\Files\Filesystem::getLocalFile($filename));
+ }
}
}
} elseif ($zip or !\OC\Files\Filesystem::file_exists($filename)) {
@@ -251,7 +256,7 @@ class OC_Files {
header("HTTP/1.0 409 Conflict");
OC_Template::printErrorPage(
$l->t('Selected files too large to generate zip file.'),
- $l->t('Download the files in smaller chunks, seperately or kindly ask your administrator.')
+ $l->t('Please download the files separately in smaller chunks or kindly ask your administrator.')
.'<br/><a href="javascript:history.back()">'
. $l->t('Back to Files') . '</a>'
);
diff --git a/lib/files/cache/backgroundwatcher.php b/lib/private/files/cache/backgroundwatcher.php
index 923804f48d0..923804f48d0 100644
--- a/lib/files/cache/backgroundwatcher.php
+++ b/lib/private/files/cache/backgroundwatcher.php
diff --git a/lib/files/cache/cache.php b/lib/private/files/cache/cache.php
index 39e36684b7b..8e682a96b75 100644
--- a/lib/files/cache/cache.php
+++ b/lib/private/files/cache/cache.php
@@ -34,8 +34,8 @@ class Cache {
*/
private $storageCache;
- private $mimetypeIds = array();
- private $mimetypes = array();
+ private static $mimetypeIds = array();
+ private static $mimetypes = array();
/**
* @param \OC\Files\Storage\Storage|string $storage
@@ -64,30 +64,45 @@ class Cache {
* @return int
*/
public function getMimetypeId($mime) {
- if (!isset($this->mimetypeIds[$mime])) {
- $result = \OC_DB::executeAudited('SELECT `id` FROM `*PREFIX*mimetypes` WHERE `mimetype` = ?', array($mime));
- if ($row = $result->fetchRow()) {
- $this->mimetypeIds[$mime] = $row['id'];
- } else {
+ if (empty($mime)) {
+ // Can not insert empty string into Oracle NOT NULL column.
+ $mime = 'application/octet-stream';
+ }
+ if (empty(self::$mimetypeIds)) {
+ $this->loadMimetypes();
+ }
+
+ if (!isset(self::$mimetypeIds[$mime])) {
+ try{
$result = \OC_DB::executeAudited('INSERT INTO `*PREFIX*mimetypes`(`mimetype`) VALUES(?)', array($mime));
- $this->mimetypeIds[$mime] = \OC_DB::insertid('*PREFIX*mimetypes');
+ self::$mimetypeIds[$mime] = \OC_DB::insertid('*PREFIX*mimetypes');
+ self::$mimetypes[self::$mimetypeIds[$mime]] = $mime;
}
- $this->mimetypes[$this->mimetypeIds[$mime]] = $mime;
- }
- return $this->mimetypeIds[$mime];
+ catch (\Doctrine\DBAL\DBALException $e){
+ \OC_Log::write('core', 'Exception during mimetype insertion: ' . $e->getmessage(), \OC_Log::DEBUG);
+ return -1;
+ }
+ }
+
+ return self::$mimetypeIds[$mime];
}
public function getMimetype($id) {
- if (!isset($this->mimetypes[$id])) {
- $sql = 'SELECT `mimetype` FROM `*PREFIX*mimetypes` WHERE `id` = ?';
- $result = \OC_DB::executeAudited($sql, array($id));
- if ($row = $result->fetchRow()) {
- $this->mimetypes[$id] = $row['mimetype'];
- } else {
- return null;
- }
+ if (empty(self::$mimetypes)) {
+ $this->loadMimetypes();
}
- return $this->mimetypes[$id];
+
+ return isset(self::$mimetypes[$id]) ? self::$mimetypes[$id] : null;
+ }
+
+ public function loadMimetypes(){
+ $result = \OC_DB::executeAudited('SELECT `id`, `mimetype` FROM `*PREFIX*mimetypes`', array());
+ if ($result) {
+ while ($row = $result->fetchRow()) {
+ self::$mimetypeIds[$row['mimetype']] = $row['id'];
+ self::$mimetypes[$row['id']] = $row['mimetype'];
+ }
+ }
}
/**
@@ -129,6 +144,7 @@ class Cache {
$data['fileid'] = (int)$data['fileid'];
$data['size'] = (int)$data['size'];
$data['mtime'] = (int)$data['mtime'];
+ $data['storage_mtime'] = (int)$data['storage_mtime'];
$data['encrypted'] = (bool)$data['encrypted'];
$data['unencrypted_size'] = (int)$data['unencrypted_size'];
$data['storage'] = $this->storageId;
@@ -162,6 +178,10 @@ class Cache {
if ($file['storage_mtime'] == 0) {
$file['storage_mtime'] = $file['mtime'];
}
+ if ($file['encrypted']) {
+ $file['encrypted_size'] = $file['size'];
+ $file['size'] = $file['unencrypted_size'];
+ }
}
return $files;
} else {
@@ -201,7 +221,6 @@ class Cache {
$data['path'] = $file;
$data['parent'] = $this->getParentId($file);
$data['name'] = \OC_Util::basename($file);
- $data['encrypted'] = isset($data['encrypted']) ? ((int)$data['encrypted']) : 0;
list($queryParts, $params) = $this->buildParts($data);
$queryParts[] = '`storage`';
@@ -265,6 +284,9 @@ class Cache {
$params[] = $value;
$queryParts[] = '`mtime`';
}
+ } elseif ($name === 'encrypted') {
+ // Boolean to integer conversion
+ $value = $value ? 1 : 0;
}
$params[] = $value;
$queryParts[] = '`' . $name . '`';
@@ -489,7 +511,7 @@ class Cache {
$entry = $this->get($path);
if ($entry && $entry['mimetype'] === 'httpd/unix-directory') {
$id = $entry['fileid'];
- $sql = 'SELECT SUM(`size`), MIN(`size`) FROM `*PREFIX*filecache` '.
+ $sql = 'SELECT SUM(`size`) AS f1, MIN(`size`) AS f2 FROM `*PREFIX*filecache` '.
'WHERE `parent` = ? AND `storage` = ?';
$result = \OC_DB::executeAudited($sql, array($id, $this->getNumericStorageId()));
if ($row = $result->fetchRow()) {
diff --git a/lib/private/files/cache/homecache.php b/lib/private/files/cache/homecache.php
new file mode 100644
index 00000000000..18dfbfe3191
--- /dev/null
+++ b/lib/private/files/cache/homecache.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Files\Cache;
+
+class HomeCache extends Cache {
+ /**
+ * get the size of a folder and set it in the cache
+ *
+ * @param string $path
+ * @return int
+ */
+ public function calculateFolderSize($path) {
+ if ($path !== '/' and $path !== '') {
+ return parent::calculateFolderSize($path);
+ }
+
+ $totalSize = 0;
+ $entry = $this->get($path);
+ if ($entry && $entry['mimetype'] === 'httpd/unix-directory') {
+ $id = $entry['fileid'];
+ $sql = 'SELECT SUM(`size`) FROM `*PREFIX*filecache` ' .
+ 'WHERE `parent` = ? AND `storage` = ? AND `size` >= 0';
+ $result = \OC_DB::executeAudited($sql, array($id, $this->getNumericStorageId()));
+ if ($row = $result->fetchRow()) {
+ list($sum) = array_values($row);
+ $totalSize = (int)$sum;
+ if ($entry['size'] !== $totalSize) {
+ $this->update($id, array('size' => $totalSize));
+ }
+ }
+ }
+ return $totalSize;
+ }
+
+ public function get($path) {
+ $data = parent::get($path);
+ if ($path === '' or $path === '/') {
+ // only the size of the "files" dir counts
+ $filesData = parent::get('files');
+
+ if (isset($filesData['size'])) {
+ $data['size'] = $filesData['size'];
+ }
+ }
+ return $data;
+ }
+}
diff --git a/lib/files/cache/legacy.php b/lib/private/files/cache/legacy.php
index 8eed1f67a5d..8eed1f67a5d 100644
--- a/lib/files/cache/legacy.php
+++ b/lib/private/files/cache/legacy.php
diff --git a/lib/files/cache/permissions.php b/lib/private/files/cache/permissions.php
index 2e2bdb20b78..2e2bdb20b78 100644
--- a/lib/files/cache/permissions.php
+++ b/lib/private/files/cache/permissions.php
diff --git a/lib/files/cache/scanner.php b/lib/private/files/cache/scanner.php
index adecc2bb901..a8c069ee99f 100644
--- a/lib/files/cache/scanner.php
+++ b/lib/private/files/cache/scanner.php
@@ -17,6 +17,8 @@ use OC\Hooks\BasicEmitter;
* Hooks available in scope \OC\Files\Cache\Scanner:
* - scanFile(string $path, string $storageId)
* - scanFolder(string $path, string $storageId)
+ * - postScanFile(string $path, string $storageId)
+ * - postScanFolder(string $path, string $storageId)
*
* @package OC\Files\Cache
*/
@@ -36,6 +38,11 @@ class Scanner extends BasicEmitter {
*/
private $cache;
+ /**
+ * @var \OC\Files\Cache\Permissions $permissionsCache
+ */
+ private $permissionsCache;
+
const SCAN_RECURSIVE = true;
const SCAN_SHALLOW = false;
@@ -46,6 +53,7 @@ class Scanner extends BasicEmitter {
$this->storage = $storage;
$this->storageId = $this->storage->getId();
$this->cache = $storage->getCache();
+ $this->permissionsCache = $storage->getPermissionsCache();
}
/**
@@ -56,8 +64,12 @@ class Scanner extends BasicEmitter {
* @return array with metadata of the file
*/
public function getData($path) {
+ if (!$this->storage->isReadable($path)) {
+ //cant read, nothing we can do
+ \OCP\Util::writeLog('OC\Files\Cache\Scanner', "!!! Path '$path' is not readable !!!", \OCP\Util::DEBUG);
+ return null;
+ }
$data = array();
- if (!$this->storage->isReadable($path)) return null; //cant read, nothing we can do
$data['mimetype'] = $this->storage->getMimeType($path);
$data['mtime'] = $this->storage->filemtime($path);
if ($data['mimetype'] == 'httpd/unix-directory') {
@@ -96,22 +108,59 @@ class Scanner extends BasicEmitter {
}
}
$newData = $data;
- if ($reuseExisting and $cacheData = $this->cache->get($file)) {
- // only reuse data if the file hasn't explicitly changed
- if (isset($data['mtime']) && isset($cacheData['mtime']) && $data['mtime'] === $cacheData['mtime']) {
- if (($reuseExisting & self::REUSE_SIZE) && ($data['size'] === -1)) {
- $data['size'] = $cacheData['size'];
+ $cacheData = $this->cache->get($file);
+ if ($cacheData) {
+ if (isset($cacheData['fileid'])) {
+ $this->permissionsCache->remove($cacheData['fileid']);
+ }
+ if ($reuseExisting) {
+ // prevent empty etag
+ $etag = $cacheData['etag'];
+ $propagateETagChange = false;
+ if (empty($etag)) {
+ $etag = $data['etag'];
+ $propagateETagChange = true;
}
- if ($reuseExisting & self::REUSE_ETAG) {
- $data['etag'] = $cacheData['etag'];
+ // only reuse data if the file hasn't explicitly changed
+ if (isset($data['mtime']) && isset($cacheData['mtime']) && $data['mtime'] === $cacheData['mtime']) {
+ if (($reuseExisting & self::REUSE_SIZE) && ($data['size'] === -1)) {
+ $data['size'] = $cacheData['size'];
+ }
+ if ($reuseExisting & self::REUSE_ETAG) {
+ $data['etag'] = $etag;
+ if ($propagateETagChange) {
+ $parent = $file;
+ while ($parent !== '') {
+ $parent = dirname($parent);
+ if ($parent === '.') {
+ $parent = '';
+ }
+ $parentCacheData = $this->cache->get($parent);
+ $this->cache->update($parentCacheData['fileid'], array(
+ 'etag' => $this->storage->getETag($parent),
+ ));
+ }
+ }
+ }
+ }
+ // Only update metadata that has changed
+ $newData = array_diff_assoc($data, $cacheData);
+ if (isset($newData['etag'])) {
+ $cacheDataString = print_r($cacheData, true);
+ $dataString = print_r($data, true);
+ \OCP\Util::writeLog('OC\Files\Cache\Scanner',
+ "!!! No reuse of etag for '$file' !!! \ncache: $cacheDataString \ndata: $dataString",
+ \OCP\Util::DEBUG);
}
}
- // Only update metadata that has changed
- $newData = array_diff($data, $cacheData);
}
if (!empty($newData)) {
$this->cache->put($file, $newData);
+ $this->emit('\OC\Files\Cache\Scanner', 'postScanFile', array($file, $this->storageId));
+ \OC_Hook::emit('\OC\Files\Cache\Scanner', 'post_scan_file', array('path' => $file, 'storage' => $this->storageId));
}
+ } else {
+ $this->cache->remove($file);
}
return $data;
}
@@ -158,21 +207,33 @@ class Scanner extends BasicEmitter {
}
$newChildren = array();
if ($this->storage->is_dir($path) && ($dh = $this->storage->opendir($path))) {
+ $exceptionOccurred = false;
\OC_DB::beginTransaction();
- while ($file = readdir($dh)) {
- $child = ($path) ? $path . '/' . $file : $file;
- if (!Filesystem::isIgnoredDir($file)) {
- $newChildren[] = $file;
- $data = $this->scanFile($child, $reuse, true);
- if ($data) {
- if ($data['size'] === -1) {
- if ($recursive === self::SCAN_RECURSIVE) {
- $childQueue[] = $child;
- } else {
- $size = -1;
+ if (is_resource($dh)) {
+ while (($file = readdir($dh)) !== false) {
+ $child = ($path) ? $path . '/' . $file : $file;
+ if (!Filesystem::isIgnoredDir($file)) {
+ $newChildren[] = $file;
+ try {
+ $data = $this->scanFile($child, $reuse, true);
+ if ($data) {
+ if ($data['size'] === -1) {
+ if ($recursive === self::SCAN_RECURSIVE) {
+ $childQueue[] = $child;
+ } else {
+ $size = -1;
+ }
+ } else if ($size !== -1) {
+ $size += $data['size'];
+ }
}
- } else if ($size !== -1) {
- $size += $data['size'];
+ }
+ catch (\Doctrine\DBAL\DBALException $ex){
+ // might happen if inserting duplicate while a scanning
+ // process is running in parallel
+ // log and ignore
+ \OC_Log::write('core', 'Exception while scanning file "' . $child . '": ' . $ex->getMessage(), \OC_Log::DEBUG);
+ $exceptionOccurred = true;
}
}
}
@@ -183,8 +244,16 @@ class Scanner extends BasicEmitter {
$this->cache->remove($child);
}
\OC_DB::commit();
+ if ($exceptionOccurred){
+ // It might happen that the parallel scan process has already
+ // inserted mimetypes but those weren't available yet inside the transaction
+ // To make sure to have the updated mime types in such cases,
+ // we reload them here
+ $this->cache->loadMimetypes();
+ }
+
foreach ($childQueue as $child) {
- $childSize = $this->scanChildren($child, self::SCAN_RECURSIVE);
+ $childSize = $this->scanChildren($child, self::SCAN_RECURSIVE, $reuse);
if ($childSize === -1) {
$size = -1;
} else {
@@ -193,6 +262,7 @@ class Scanner extends BasicEmitter {
}
$this->cache->put($path, array('size' => $size));
}
+ $this->emit('\OC\Files\Cache\Scanner', 'postScanFolder', array($path, $this->storageId));
return $size;
}
@@ -216,7 +286,7 @@ class Scanner extends BasicEmitter {
public function backgroundScan() {
$lastPath = null;
while (($path = $this->cache->getIncomplete()) !== false && $path !== $lastPath) {
- $this->scan($path);
+ $this->scan($path, self::SCAN_RECURSIVE, self::REUSE_ETAG);
$this->cache->correctFolderSize($path);
$lastPath = $path;
}
diff --git a/lib/files/cache/storage.php b/lib/private/files/cache/storage.php
index 8a9e47ca36d..5657cf06e12 100644
--- a/lib/files/cache/storage.php
+++ b/lib/private/files/cache/storage.php
@@ -48,7 +48,7 @@ class Storage {
}
public static function getStorageId($numericId) {
-
+
$sql = 'SELECT `id` FROM `*PREFIX*storages` WHERE `numeric_id` = ?';
$result = \OC_DB::executeAudited($sql, array($numericId));
if ($row = $result->fetchRow()) {
@@ -57,4 +57,17 @@ class Storage {
return null;
}
}
+
+ public static function exists($storageId) {
+ if (strlen($storageId) > 64) {
+ $storageId = md5($storageId);
+ }
+ $sql = 'SELECT `numeric_id` FROM `*PREFIX*storages` WHERE `id` = ?';
+ $result = \OC_DB::executeAudited($sql, array($storageId));
+ if ($row = $result->fetchRow()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
}
diff --git a/lib/files/cache/updater.php b/lib/private/files/cache/updater.php
index 1f30173a8f8..73bc30e538f 100644
--- a/lib/files/cache/updater.php
+++ b/lib/private/files/cache/updater.php
@@ -7,6 +7,7 @@
*/
namespace OC\Files\Cache;
+
use OCP\Util;
/**
@@ -42,6 +43,7 @@ class Updater {
$scanner->scan($internalPath, Scanner::SCAN_SHALLOW);
$cache->correctFolderSize($internalPath);
self::correctFolder($path, $storage->filemtime($internalPath));
+ self::correctParentStorageMtime($storage, $internalPath);
}
}
@@ -57,10 +59,15 @@ class Updater {
*/
list($storage, $internalPath) = self::resolvePath($path);
if ($storage) {
+ $parent = dirname($internalPath);
+ if ($parent === '.') {
+ $parent = '';
+ }
$cache = $storage->getCache($internalPath);
$cache->remove($internalPath);
- $cache->correctFolderSize($internalPath);
+ $cache->correctFolderSize($parent);
self::correctFolder($path, time());
+ self::correctParentStorageMtime($storage, $internalPath);
}
}
@@ -83,10 +90,18 @@ class Updater {
if ($storageFrom === $storageTo) {
$cache = $storageFrom->getCache($internalFrom);
$cache->move($internalFrom, $internalTo);
+ if (pathinfo($internalFrom, PATHINFO_EXTENSION) !== pathinfo($internalTo, PATHINFO_EXTENSION)) {
+ // redetect mime type change
+ $mimeType = $storageTo->getMimeType($internalTo);
+ $fileId = $storageTo->getCache()->getId($internalTo);
+ $storageTo->getCache()->update($fileId, array('mimetype' => $mimeType));
+ }
$cache->correctFolderSize($internalFrom);
$cache->correctFolderSize($internalTo);
self::correctFolder($from, time());
self::correctFolder($to, time());
+ self::correctParentStorageMtime($storageFrom, $internalFrom);
+ self::correctParentStorageMtime($storageTo, $internalTo);
} else {
self::deleteUpdate($from);
self::writeUpdate($to);
@@ -95,6 +110,24 @@ class Updater {
}
/**
+ * @brief get file owner and path
+ * @param string $filename
+ * @return array with the oweners uid and the owners path
+ */
+ private static function getUidAndFilename($filename) {
+
+ $uid = \OC\Files\Filesystem::getOwner($filename);
+ \OC\Files\Filesystem::initMountPoints($uid);
+
+ if ($uid != \OCP\User::getUser()) {
+ $info = \OC\Files\Filesystem::getFileInfo($filename);
+ $ownerView = new \OC\Files\View('/' . $uid . '/files');
+ $filename = $ownerView->getPath($info['fileid']);
+ }
+ return array($uid, '/files/' . $filename);
+ }
+
+ /**
* Update the mtime and ETag of all parent folders
*
* @param string $path
@@ -102,29 +135,53 @@ class Updater {
*/
static public function correctFolder($path, $time) {
if ($path !== '' && $path !== '/') {
- $parent = dirname($path);
- if ($parent === '.' || $parent === '\\') {
- $parent = '';
- }
+
+ list($owner, $realPath) = self::getUidAndFilename(dirname($path));
+
/**
* @var \OC\Files\Storage\Storage $storage
* @var string $internalPath
*/
- list($storage, $internalPath) = self::resolvePath($parent);
- if ($storage) {
- $cache = $storage->getCache();
- $id = $cache->getId($internalPath);
- if ($id !== -1) {
- $cache->update($id, array('mtime' => $time, 'etag' => $storage->getETag($internalPath)));
- self::correctFolder($parent, $time);
+ $view = new \OC\Files\View('/' . $owner);
+
+ list($storage, $internalPath) = $view->resolvePath($realPath);
+ $cache = $storage->getCache();
+ $id = $cache->getId($internalPath);
+
+ while ($id !== -1) {
+ $cache->update($id, array('mtime' => $time, 'etag' => $storage->getETag($internalPath)));
+ if ($realPath !== '') {
+ $realPath = dirname($realPath);
+ if($realPath === DIRECTORY_SEPARATOR ) {
+ $realPath = "";
+ }
+ // check storage for parent in case we change the storage in this step
+ list($storage, $internalPath) = $view->resolvePath($realPath);
+ $cache = $storage->getCache();
+ $id = $cache->getId($internalPath);
} else {
- Util::writeLog('core', 'Path not in cache: '.$internalPath, Util::ERROR);
+ $id = -1;
}
}
}
}
/**
+ * update the storage_mtime of the parent
+ *
+ * @param \OC\Files\Storage\Storage $storage
+ * @param string $internalPath
+ */
+ static private function correctParentStorageMtime($storage, $internalPath) {
+ $cache = $storage->getCache();
+ $parentId = $cache->getParentId($internalPath);
+ $parent = dirname($internalPath);
+ if ($parentId != -1) {
+ $cache->update($parentId, array('storage_mtime' => $storage->filemtime($parent)));
+ }
+ }
+
+ /**
* @param array $params
*/
static public function writeHook($params) {
diff --git a/lib/files/cache/upgrade.php b/lib/private/files/cache/upgrade.php
index cfb9a117311..e3a46896cbf 100644
--- a/lib/files/cache/upgrade.php
+++ b/lib/private/files/cache/upgrade.php
@@ -192,7 +192,15 @@ class Upgrade {
*/
static function needUpgrade($user) {
$cacheVersion = (int)\OCP\Config::getUserValue($user, 'files', 'cache_version', 4);
- return $cacheVersion < 5;
+ if ($cacheVersion < 5) {
+ $legacy = new \OC\Files\Cache\Legacy($user);
+ if ($legacy->hasItems()) {
+ return true;
+ }
+ self::upgradeDone($user);
+ }
+
+ return false;
}
/**
diff --git a/lib/files/cache/watcher.php b/lib/private/files/cache/watcher.php
index 8bfd4602f3a..58f624c8990 100644
--- a/lib/files/cache/watcher.php
+++ b/lib/private/files/cache/watcher.php
@@ -15,17 +15,17 @@ class Watcher {
/**
* @var \OC\Files\Storage\Storage $storage
*/
- private $storage;
+ protected $storage;
/**
* @var Cache $cache
*/
- private $cache;
+ protected $cache;
/**
* @var Scanner $scanner;
*/
- private $scanner;
+ protected $scanner;
/**
* @param \OC\Files\Storage\Storage $storage
@@ -40,6 +40,7 @@ class Watcher {
* check $path for updates
*
* @param string $path
+ * @return boolean true if path was updated, false otherwise
*/
public function checkUpdate($path) {
$cachedEntry = $this->cache->get($path);
@@ -53,7 +54,9 @@ class Watcher {
$this->cleanFolder($path);
}
$this->cache->correctFolderSize($path);
+ return true;
}
+ return false;
}
/**
diff --git a/lib/files/filesystem.php b/lib/private/files/filesystem.php
index d6ebe7d629a..a83e9aa86d2 100644
--- a/lib/files/filesystem.php
+++ b/lib/private/files/filesystem.php
@@ -31,8 +31,9 @@
namespace OC\Files;
use OC\Files\Storage\Loader;
-const FREE_SPACE_UNKNOWN = -2;
-const FREE_SPACE_UNLIMITED = -3;
+const SPACE_NOT_COMPUTED = -1;
+const SPACE_UNKNOWN = -2;
+const SPACE_UNLIMITED = -3;
class Filesystem {
/**
@@ -148,6 +149,18 @@ class Filesystem {
*/
private static $loader;
+ /**
+ * @param callable $wrapper
+ */
+ public static function addStorageWrapper($wrapper) {
+ self::getLoader()->addStorageWrapper($wrapper);
+
+ $mounts = self::getMountManager()->getAll();
+ foreach ($mounts as $mount) {
+ $mount->wrapStorage($wrapper);
+ }
+ }
+
public static function getLoader() {
if (!self::$loader) {
self::$loader = new Loader();
@@ -292,7 +305,21 @@ class Filesystem {
$parser = new \OC\ArrayParser();
$root = \OC_User::getHome($user);
- self::mount('\OC\Files\Storage\Local', array('datadir' => $root), $user);
+
+ $userObject = \OC_User::getManager()->get($user);
+
+ if (!is_null($userObject)) {
+ // check for legacy home id (<= 5.0.12)
+ if (\OC\Files\Cache\Storage::exists('local::' . $root . '/')) {
+ self::mount('\OC\Files\Storage\Home', array('user' => $userObject, 'legacy' => true), $user);
+ }
+ else {
+ self::mount('\OC\Files\Storage\Home', array('user' => $userObject), $user);
+ }
+ }
+ else {
+ self::mount('\OC\Files\Storage\Local', array('datadir' => $root), $user);
+ }
$datadir = \OC_Config::getValue("datadirectory", \OC::$SERVERROOT . "/data");
//move config file to it's new position
@@ -662,18 +689,32 @@ class Filesystem {
}
//no windows style slashes
$path = str_replace('\\', '/', $path);
+
//add leading slash
if ($path[0] !== '/') {
$path = '/' . $path;
}
- //remove duplicate slashes
- while (strpos($path, '//') !== false) {
- $path = str_replace('//', '/', $path);
+
+ // remove '/./'
+ // ugly, but str_replace() can't replace them all in one go
+ // as the replacement itself is part of the search string
+ // which will only be found during the next iteration
+ while (strpos($path, '/./') !== false) {
+ $path = str_replace('/./', '/', $path);
}
+ // remove sequences of slashes
+ $path = preg_replace('#/{2,}#', '/', $path);
+
//remove trailing slash
if ($stripTrailingSlash and strlen($path) > 1 and substr($path, -1, 1) === '/') {
$path = substr($path, 0, -1);
}
+
+ // remove trailing '/.'
+ if (substr($path, -2) == '/.') {
+ $path = substr($path, 0, -2);
+ }
+
//normalize unicode if possible
$path = \OC_Util::normalizeUnicode($path);
@@ -684,6 +725,8 @@ class Filesystem {
* get the filesystem info
*
* @param string $path
+ * @param boolean $includeMountPoints whether to add mountpoint sizes,
+ * defaults to true
* @return array
*
* returns an associative array with the following keys:
@@ -693,8 +736,8 @@ class Filesystem {
* - encrypted
* - versioned
*/
- public static function getFileInfo($path) {
- return self::$defaultInstance->getFileInfo($path);
+ public static function getFileInfo($path, $includeMountPoints = true) {
+ return self::$defaultInstance->getFileInfo($path, $includeMountPoints);
}
/**
diff --git a/lib/files/mapper.php b/lib/private/files/mapper.php
index 47abd4e52fe..47abd4e52fe 100644
--- a/lib/files/mapper.php
+++ b/lib/private/files/mapper.php
diff --git a/lib/files/mount/manager.php b/lib/private/files/mount/manager.php
index 25a5fe241cc..4c432dcf724 100644
--- a/lib/files/mount/manager.php
+++ b/lib/private/files/mount/manager.php
@@ -96,6 +96,13 @@ class Manager {
}
/**
+ * @return Mount[]
+ */
+ public function getAll() {
+ return $this->mounts;
+ }
+
+ /**
* Find mounts by numeric storage id
*
* @param string $id
diff --git a/lib/files/mount/mount.php b/lib/private/files/mount/mount.php
index 17b0055ee84..0ce2f5975c7 100644
--- a/lib/files/mount/mount.php
+++ b/lib/private/files/mount/mount.php
@@ -138,4 +138,11 @@ class Mount {
}
return $path;
}
+
+ /**
+ * @param callable $wrapper
+ */
+ public function wrapStorage($wrapper) {
+ $this->storage = $wrapper($this->mountPoint, $this->storage);
+ }
}
diff --git a/lib/private/files/node/file.php b/lib/private/files/node/file.php
new file mode 100644
index 00000000000..75d5e0166b6
--- /dev/null
+++ b/lib/private/files/node/file.php
@@ -0,0 +1,155 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Files\Node;
+
+use OCP\Files\NotPermittedException;
+
+class File extends Node implements \OCP\Files\File {
+ /**
+ * @return string
+ * @throws \OCP\Files\NotPermittedException
+ */
+ public function getContent() {
+ if ($this->checkPermissions(\OCP\PERMISSION_READ)) {
+ /**
+ * @var \OC\Files\Storage\Storage $storage;
+ */
+ return $this->view->file_get_contents($this->path);
+ } else {
+ throw new NotPermittedException();
+ }
+ }
+
+ /**
+ * @param string $data
+ * @throws \OCP\Files\NotPermittedException
+ */
+ public function putContent($data) {
+ if ($this->checkPermissions(\OCP\PERMISSION_UPDATE)) {
+ $this->sendHooks(array('preWrite'));
+ $this->view->file_put_contents($this->path, $data);
+ $this->sendHooks(array('postWrite'));
+ } else {
+ throw new NotPermittedException();
+ }
+ }
+
+ /**
+ * @return string
+ */
+ public function getMimeType() {
+ return $this->view->getMimeType($this->path);
+ }
+
+ /**
+ * @param string $mode
+ * @return resource
+ * @throws \OCP\Files\NotPermittedException
+ */
+ public function fopen($mode) {
+ $preHooks = array();
+ $postHooks = array();
+ $requiredPermissions = \OCP\PERMISSION_READ;
+ switch ($mode) {
+ case 'r+':
+ case 'rb+':
+ case 'w+':
+ case 'wb+':
+ case 'x+':
+ case 'xb+':
+ case 'a+':
+ case 'ab+':
+ case 'w':
+ case 'wb':
+ case 'x':
+ case 'xb':
+ case 'a':
+ case 'ab':
+ $preHooks[] = 'preWrite';
+ $postHooks[] = 'postWrite';
+ $requiredPermissions |= \OCP\PERMISSION_UPDATE;
+ break;
+ }
+
+ if ($this->checkPermissions($requiredPermissions)) {
+ $this->sendHooks($preHooks);
+ $result = $this->view->fopen($this->path, $mode);
+ $this->sendHooks($postHooks);
+ return $result;
+ } else {
+ throw new NotPermittedException();
+ }
+ }
+
+ public function delete() {
+ if ($this->checkPermissions(\OCP\PERMISSION_DELETE)) {
+ $this->sendHooks(array('preDelete'));
+ $this->view->unlink($this->path);
+ $nonExisting = new NonExistingFile($this->root, $this->view, $this->path);
+ $this->root->emit('\OC\Files', 'postDelete', array($nonExisting));
+ $this->exists = false;
+ } else {
+ throw new NotPermittedException();
+ }
+ }
+
+ /**
+ * @param string $targetPath
+ * @throws \OCP\Files\NotPermittedException
+ * @return \OC\Files\Node\Node
+ */
+ public function copy($targetPath) {
+ $targetPath = $this->normalizePath($targetPath);
+ $parent = $this->root->get(dirname($targetPath));
+ if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) {
+ $nonExisting = new NonExistingFile($this->root, $this->view, $targetPath);
+ $this->root->emit('\OC\Files', 'preCopy', array($this, $nonExisting));
+ $this->root->emit('\OC\Files', 'preWrite', array($nonExisting));
+ $this->view->copy($this->path, $targetPath);
+ $targetNode = $this->root->get($targetPath);
+ $this->root->emit('\OC\Files', 'postCopy', array($this, $targetNode));
+ $this->root->emit('\OC\Files', 'postWrite', array($targetNode));
+ return $targetNode;
+ } else {
+ throw new NotPermittedException();
+ }
+ }
+
+ /**
+ * @param string $targetPath
+ * @throws \OCP\Files\NotPermittedException
+ * @return \OC\Files\Node\Node
+ */
+ public function move($targetPath) {
+ $targetPath = $this->normalizePath($targetPath);
+ $parent = $this->root->get(dirname($targetPath));
+ if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) {
+ $nonExisting = new NonExistingFile($this->root, $this->view, $targetPath);
+ $this->root->emit('\OC\Files', 'preRename', array($this, $nonExisting));
+ $this->root->emit('\OC\Files', 'preWrite', array($nonExisting));
+ $this->view->rename($this->path, $targetPath);
+ $targetNode = $this->root->get($targetPath);
+ $this->root->emit('\OC\Files', 'postRename', array($this, $targetNode));
+ $this->root->emit('\OC\Files', 'postWrite', array($targetNode));
+ $this->path = $targetPath;
+ return $targetNode;
+ } else {
+ throw new NotPermittedException();
+ }
+ }
+
+ /**
+ * @param string $type
+ * @param bool $raw
+ * @return string
+ */
+ public function hash($type, $raw = false) {
+ return $this->view->hash($type, $this->path, $raw);
+ }
+}
diff --git a/lib/private/files/node/folder.php b/lib/private/files/node/folder.php
new file mode 100644
index 00000000000..923f53821b2
--- /dev/null
+++ b/lib/private/files/node/folder.php
@@ -0,0 +1,382 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Files\Node;
+
+use OC\Files\Cache\Cache;
+use OC\Files\Cache\Scanner;
+use OCP\Files\NotFoundException;
+use OCP\Files\NotPermittedException;
+
+class Folder extends Node implements \OCP\Files\Folder {
+ /**
+ * @param string $path path relative to the folder
+ * @return string
+ * @throws \OCP\Files\NotPermittedException
+ */
+ public function getFullPath($path) {
+ if (!$this->isValidPath($path)) {
+ throw new NotPermittedException();
+ }
+ return $this->path . $this->normalizePath($path);
+ }
+
+ /**
+ * @param string $path
+ * @throws \OCP\Files\NotFoundException
+ * @return string
+ */
+ public function getRelativePath($path) {
+ if ($this->path === '' or $this->path === '/') {
+ return $this->normalizePath($path);
+ }
+ if (strpos($path, $this->path) !== 0) {
+ throw new NotFoundException();
+ } else {
+ $path = substr($path, strlen($this->path));
+ if (strlen($path) === 0) {
+ return '/';
+ } else {
+ return $this->normalizePath($path);
+ }
+ }
+ }
+
+ /**
+ * check if a node is a (grand-)child of the folder
+ *
+ * @param \OC\Files\Node\Node $node
+ * @return bool
+ */
+ public function isSubNode($node) {
+ return strpos($node->getPath(), $this->path . '/') === 0;
+ }
+
+ /**
+ * get the content of this directory
+ *
+ * @throws \OCP\Files\NotFoundException
+ * @return Node[]
+ */
+ public function getDirectoryListing() {
+ $result = array();
+
+ /**
+ * @var \OC\Files\Storage\Storage $storage
+ */
+ list($storage, $internalPath) = $this->view->resolvePath($this->path);
+ if ($storage) {
+ $cache = $storage->getCache($internalPath);
+ $permissionsCache = $storage->getPermissionsCache($internalPath);
+
+ //trigger cache update check
+ $this->view->getFileInfo($this->path);
+
+ $files = $cache->getFolderContents($internalPath);
+ $permissions = $permissionsCache->getDirectoryPermissions($this->getId(), $this->root->getUser()->getUID());
+ } else {
+ $files = array();
+ }
+
+ //add a folder for any mountpoint in this directory and add the sizes of other mountpoints to the folders
+ $mounts = $this->root->getMountsIn($this->path);
+ $dirLength = strlen($this->path);
+ foreach ($mounts as $mount) {
+ $subStorage = $mount->getStorage();
+ if ($subStorage) {
+ $subCache = $subStorage->getCache('');
+
+ if ($subCache->getStatus('') === Cache::NOT_FOUND) {
+ $subScanner = $subStorage->getScanner('');
+ $subScanner->scanFile('');
+ }
+
+ $rootEntry = $subCache->get('');
+ if ($rootEntry) {
+ $relativePath = trim(substr($mount->getMountPoint(), $dirLength), '/');
+ if ($pos = strpos($relativePath, '/')) {
+ //mountpoint inside subfolder add size to the correct folder
+ $entryName = substr($relativePath, 0, $pos);
+ foreach ($files as &$entry) {
+ if ($entry['name'] === $entryName) {
+ if ($rootEntry['size'] >= 0) {
+ $entry['size'] += $rootEntry['size'];
+ } else {
+ $entry['size'] = -1;
+ }
+ }
+ }
+ } else { //mountpoint in this folder, add an entry for it
+ $rootEntry['name'] = $relativePath;
+ $rootEntry['storageObject'] = $subStorage;
+
+ //remove any existing entry with the same name
+ foreach ($files as $i => $file) {
+ if ($file['name'] === $rootEntry['name']) {
+ $files[$i] = null;
+ break;
+ }
+ }
+ $files[] = $rootEntry;
+ }
+ }
+ }
+ }
+
+ foreach ($files as $file) {
+ if ($file) {
+ if (isset($permissions[$file['fileid']])) {
+ $file['permissions'] = $permissions[$file['fileid']];
+ }
+ $node = $this->createNode($this->path . '/' . $file['name'], $file);
+ $result[] = $node;
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * @param string $path
+ * @param array $info
+ * @return File|Folder
+ */
+ protected function createNode($path, $info = array()) {
+ if (!isset($info['mimetype'])) {
+ $isDir = $this->view->is_dir($path);
+ } else {
+ $isDir = $info['mimetype'] === 'httpd/unix-directory';
+ }
+ if ($isDir) {
+ return new Folder($this->root, $this->view, $path);
+ } else {
+ return new File($this->root, $this->view, $path);
+ }
+ }
+
+ /**
+ * Get the node at $path
+ *
+ * @param string $path
+ * @return \OC\Files\Node\Node
+ * @throws \OCP\Files\NotFoundException
+ */
+ public function get($path) {
+ return $this->root->get($this->getFullPath($path));
+ }
+
+ /**
+ * @param string $path
+ * @return bool
+ */
+ public function nodeExists($path) {
+ try {
+ $this->get($path);
+ return true;
+ } catch (NotFoundException $e) {
+ return false;
+ }
+ }
+
+ /**
+ * @param string $path
+ * @return \OC\Files\Node\Folder
+ * @throws \OCP\Files\NotPermittedException
+ */
+ public function newFolder($path) {
+ if ($this->checkPermissions(\OCP\PERMISSION_CREATE)) {
+ $fullPath = $this->getFullPath($path);
+ $nonExisting = new NonExistingFolder($this->root, $this->view, $fullPath);
+ $this->root->emit('\OC\Files', 'preWrite', array($nonExisting));
+ $this->root->emit('\OC\Files', 'preCreate', array($nonExisting));
+ $this->view->mkdir($fullPath);
+ $node = new Folder($this->root, $this->view, $fullPath);
+ $this->root->emit('\OC\Files', 'postWrite', array($node));
+ $this->root->emit('\OC\Files', 'postCreate', array($node));
+ return $node;
+ } else {
+ throw new NotPermittedException();
+ }
+ }
+
+ /**
+ * @param string $path
+ * @return \OC\Files\Node\File
+ * @throws \OCP\Files\NotPermittedException
+ */
+ public function newFile($path) {
+ if ($this->checkPermissions(\OCP\PERMISSION_CREATE)) {
+ $fullPath = $this->getFullPath($path);
+ $nonExisting = new NonExistingFile($this->root, $this->view, $fullPath);
+ $this->root->emit('\OC\Files', 'preWrite', array($nonExisting));
+ $this->root->emit('\OC\Files', 'preCreate', array($nonExisting));
+ $this->view->touch($fullPath);
+ $node = new File($this->root, $this->view, $fullPath);
+ $this->root->emit('\OC\Files', 'postWrite', array($node));
+ $this->root->emit('\OC\Files', 'postCreate', array($node));
+ return $node;
+ } else {
+ throw new NotPermittedException();
+ }
+ }
+
+ /**
+ * search for files with the name matching $query
+ *
+ * @param string $query
+ * @return \OC\Files\Node\Node[]
+ */
+ public function search($query) {
+ return $this->searchCommon('%' . $query . '%', 'search');
+ }
+
+ /**
+ * search for files by mimetype
+ *
+ * @param string $mimetype
+ * @return Node[]
+ */
+ public function searchByMime($mimetype) {
+ return $this->searchCommon($mimetype, 'searchByMime');
+ }
+
+ /**
+ * @param string $query
+ * @param string $method
+ * @return \OC\Files\Node\Node[]
+ */
+ private function searchCommon($query, $method) {
+ $files = array();
+ $rootLength = strlen($this->path);
+ /**
+ * @var \OC\Files\Storage\Storage $storage
+ */
+ list($storage, $internalPath) = $this->view->resolvePath($this->path);
+ $internalRootLength = strlen($internalPath);
+
+ $cache = $storage->getCache('');
+
+ $results = $cache->$method($query);
+ foreach ($results as $result) {
+ if ($internalRootLength === 0 or substr($result['path'], 0, $internalRootLength) === $internalPath) {
+ $result['internalPath'] = $result['path'];
+ $result['path'] = substr($result['path'], $internalRootLength);
+ $result['storage'] = $storage;
+ $files[] = $result;
+ }
+ }
+
+ $mounts = $this->root->getMountsIn($this->path);
+ foreach ($mounts as $mount) {
+ $storage = $mount->getStorage();
+ if ($storage) {
+ $cache = $storage->getCache('');
+
+ $relativeMountPoint = substr($mount->getMountPoint(), $rootLength);
+ $results = $cache->$method($query);
+ foreach ($results as $result) {
+ $result['internalPath'] = $result['path'];
+ $result['path'] = $relativeMountPoint . $result['path'];
+ $result['storage'] = $storage;
+ $files[] = $result;
+ }
+ }
+ }
+
+ $result = array();
+ foreach ($files as $file) {
+ $result[] = $this->createNode($this->normalizePath($this->path . '/' . $file['path']), $file);
+ }
+
+ return $result;
+ }
+
+ /**
+ * @param $id
+ * @return \OC\Files\Node\Node[]
+ */
+ public function getById($id) {
+ $nodes = $this->root->getById($id);
+ $result = array();
+ foreach ($nodes as $node) {
+ $pathPart = substr($node->getPath(), 0, strlen($this->getPath()) + 1);
+ if ($this->path === '/' or $pathPart === $this->getPath() . '/') {
+ $result[] = $node;
+ }
+ }
+ return $result;
+ }
+
+ public function getFreeSpace() {
+ return $this->view->free_space($this->path);
+ }
+
+ /**
+ * @return bool
+ */
+ public function isCreatable() {
+ return $this->checkPermissions(\OCP\PERMISSION_CREATE);
+ }
+
+ public function delete() {
+ if ($this->checkPermissions(\OCP\PERMISSION_DELETE)) {
+ $this->sendHooks(array('preDelete'));
+ $this->view->rmdir($this->path);
+ $nonExisting = new NonExistingFolder($this->root, $this->view, $this->path);
+ $this->root->emit('\OC\Files', 'postDelete', array($nonExisting));
+ $this->exists = false;
+ } else {
+ throw new NotPermittedException();
+ }
+ }
+
+ /**
+ * @param string $targetPath
+ * @throws \OCP\Files\NotPermittedException
+ * @return \OC\Files\Node\Node
+ */
+ public function copy($targetPath) {
+ $targetPath = $this->normalizePath($targetPath);
+ $parent = $this->root->get(dirname($targetPath));
+ if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) {
+ $nonExisting = new NonExistingFolder($this->root, $this->view, $targetPath);
+ $this->root->emit('\OC\Files', 'preCopy', array($this, $nonExisting));
+ $this->root->emit('\OC\Files', 'preWrite', array($nonExisting));
+ $this->view->copy($this->path, $targetPath);
+ $targetNode = $this->root->get($targetPath);
+ $this->root->emit('\OC\Files', 'postCopy', array($this, $targetNode));
+ $this->root->emit('\OC\Files', 'postWrite', array($targetNode));
+ return $targetNode;
+ } else {
+ throw new NotPermittedException();
+ }
+ }
+
+ /**
+ * @param string $targetPath
+ * @throws \OCP\Files\NotPermittedException
+ * @return \OC\Files\Node\Node
+ */
+ public function move($targetPath) {
+ $targetPath = $this->normalizePath($targetPath);
+ $parent = $this->root->get(dirname($targetPath));
+ if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) {
+ $nonExisting = new NonExistingFolder($this->root, $this->view, $targetPath);
+ $this->root->emit('\OC\Files', 'preRename', array($this, $nonExisting));
+ $this->root->emit('\OC\Files', 'preWrite', array($nonExisting));
+ $this->view->rename($this->path, $targetPath);
+ $targetNode = $this->root->get($targetPath);
+ $this->root->emit('\OC\Files', 'postRename', array($this, $targetNode));
+ $this->root->emit('\OC\Files', 'postWrite', array($targetNode));
+ $this->path = $targetPath;
+ return $targetNode;
+ } else {
+ throw new NotPermittedException();
+ }
+ }
+}
diff --git a/lib/private/files/node/node.php b/lib/private/files/node/node.php
new file mode 100644
index 00000000000..063e2424a64
--- /dev/null
+++ b/lib/private/files/node/node.php
@@ -0,0 +1,245 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Files\Node;
+
+use OC\Files\Cache\Cache;
+use OC\Files\Cache\Scanner;
+use OCP\Files\NotFoundException;
+use OCP\Files\NotPermittedException;
+
+class Node implements \OCP\Files\Node {
+ /**
+ * @var \OC\Files\View $view
+ */
+ protected $view;
+
+ /**
+ * @var \OC\Files\Node\Root $root
+ */
+ protected $root;
+
+ /**
+ * @var string $path
+ */
+ protected $path;
+
+ /**
+ * @param \OC\Files\View $view
+ * @param \OC\Files\Node\Root Root $root
+ * @param string $path
+ */
+ public function __construct($root, $view, $path) {
+ $this->view = $view;
+ $this->root = $root;
+ $this->path = $path;
+ }
+
+ /**
+ * @param string[] $hooks
+ */
+ protected function sendHooks($hooks) {
+ foreach ($hooks as $hook) {
+ $this->root->emit('\OC\Files', $hook, array($this));
+ }
+ }
+
+ /**
+ * @param int $permissions
+ * @return bool
+ */
+ protected function checkPermissions($permissions) {
+ return ($this->getPermissions() & $permissions) === $permissions;
+ }
+
+ /**
+ * @param string $targetPath
+ * @throws \OCP\Files\NotPermittedException
+ * @return \OC\Files\Node\Node
+ */
+ public function move($targetPath) {
+ return;
+ }
+
+ public function delete() {
+ return;
+ }
+
+ /**
+ * @param string $targetPath
+ * @return \OC\Files\Node\Node
+ */
+ public function copy($targetPath) {
+ return;
+ }
+
+ /**
+ * @param int $mtime
+ * @throws \OCP\Files\NotPermittedException
+ */
+ public function touch($mtime = null) {
+ if ($this->checkPermissions(\OCP\PERMISSION_UPDATE)) {
+ $this->sendHooks(array('preTouch'));
+ $this->view->touch($this->path, $mtime);
+ $this->sendHooks(array('postTouch'));
+ } else {
+ throw new NotPermittedException();
+ }
+ }
+
+ /**
+ * @return \OC\Files\Storage\Storage
+ * @throws \OCP\Files\NotFoundException
+ */
+ public function getStorage() {
+ list($storage,) = $this->view->resolvePath($this->path);
+ return $storage;
+ }
+
+ /**
+ * @return string
+ */
+ public function getPath() {
+ return $this->path;
+ }
+
+ /**
+ * @return string
+ */
+ public function getInternalPath() {
+ list(, $internalPath) = $this->view->resolvePath($this->path);
+ return $internalPath;
+ }
+
+ /**
+ * @return int
+ */
+ public function getId() {
+ $info = $this->view->getFileInfo($this->path);
+ return $info['fileid'];
+ }
+
+ /**
+ * @return array
+ */
+ public function stat() {
+ return $this->view->stat($this->path);
+ }
+
+ /**
+ * @return int
+ */
+ public function getMTime() {
+ return $this->view->filemtime($this->path);
+ }
+
+ /**
+ * @return int
+ */
+ public function getSize() {
+ return $this->view->filesize($this->path);
+ }
+
+ /**
+ * @return string
+ */
+ public function getEtag() {
+ $info = $this->view->getFileInfo($this->path);
+ return $info['etag'];
+ }
+
+ /**
+ * @return int
+ */
+ public function getPermissions() {
+ $info = $this->view->getFileInfo($this->path);
+ return $info['permissions'];
+ }
+
+ /**
+ * @return bool
+ */
+ public function isReadable() {
+ return $this->checkPermissions(\OCP\PERMISSION_READ);
+ }
+
+ /**
+ * @return bool
+ */
+ public function isUpdateable() {
+ return $this->checkPermissions(\OCP\PERMISSION_UPDATE);
+ }
+
+ /**
+ * @return bool
+ */
+ public function isDeletable() {
+ return $this->checkPermissions(\OCP\PERMISSION_DELETE);
+ }
+
+ /**
+ * @return bool
+ */
+ public function isShareable() {
+ return $this->checkPermissions(\OCP\PERMISSION_SHARE);
+ }
+
+ /**
+ * @return Node
+ */
+ public function getParent() {
+ return $this->root->get(dirname($this->path));
+ }
+
+ /**
+ * @return string
+ */
+ public function getName() {
+ return basename($this->path);
+ }
+
+ /**
+ * @param string $path
+ * @return string
+ */
+ protected function normalizePath($path) {
+ if ($path === '' or $path === '/') {
+ return '/';
+ }
+ //no windows style slashes
+ $path = str_replace('\\', '/', $path);
+ //add leading slash
+ if ($path[0] !== '/') {
+ $path = '/' . $path;
+ }
+ //remove duplicate slashes
+ while (strpos($path, '//') !== false) {
+ $path = str_replace('//', '/', $path);
+ }
+ //remove trailing slash
+ $path = rtrim($path, '/');
+
+ return $path;
+ }
+
+ /**
+ * check if the requested path is valid
+ *
+ * @param string $path
+ * @return bool
+ */
+ public function isValidPath($path) {
+ if (!$path || $path[0] !== '/') {
+ $path = '/' . $path;
+ }
+ if (strstr($path, '/../') || strrchr($path, '/') === '/..') {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/lib/private/files/node/nonexistingfile.php b/lib/private/files/node/nonexistingfile.php
new file mode 100644
index 00000000000..d45076f7fee
--- /dev/null
+++ b/lib/private/files/node/nonexistingfile.php
@@ -0,0 +1,89 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Files\Node;
+
+use OCP\Files\NotFoundException;
+
+class NonExistingFile extends File {
+ /**
+ * @param string $newPath
+ * @throws \OCP\Files\NotFoundException
+ */
+ public function rename($newPath) {
+ throw new NotFoundException();
+ }
+
+ public function delete() {
+ throw new NotFoundException();
+ }
+
+ public function copy($newPath) {
+ throw new NotFoundException();
+ }
+
+ public function touch($mtime = null) {
+ throw new NotFoundException();
+ }
+
+ public function getId() {
+ throw new NotFoundException();
+ }
+
+ public function stat() {
+ throw new NotFoundException();
+ }
+
+ public function getMTime() {
+ throw new NotFoundException();
+ }
+
+ public function getSize() {
+ throw new NotFoundException();
+ }
+
+ public function getEtag() {
+ throw new NotFoundException();
+ }
+
+ public function getPermissions() {
+ throw new NotFoundException();
+ }
+
+ public function isReadable() {
+ throw new NotFoundException();
+ }
+
+ public function isUpdateable() {
+ throw new NotFoundException();
+ }
+
+ public function isDeletable() {
+ throw new NotFoundException();
+ }
+
+ public function isShareable() {
+ throw new NotFoundException();
+ }
+
+ public function getContent() {
+ throw new NotFoundException();
+ }
+
+ public function putContent($data) {
+ throw new NotFoundException();
+ }
+
+ public function getMimeType() {
+ throw new NotFoundException();
+ }
+
+ public function fopen($mode) {
+ throw new NotFoundException();
+ }
+}
diff --git a/lib/private/files/node/nonexistingfolder.php b/lib/private/files/node/nonexistingfolder.php
new file mode 100644
index 00000000000..0346cbf1e21
--- /dev/null
+++ b/lib/private/files/node/nonexistingfolder.php
@@ -0,0 +1,113 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Files\Node;
+
+use OCP\Files\NotFoundException;
+
+class NonExistingFolder extends Folder {
+ /**
+ * @param string $newPath
+ * @throws \OCP\Files\NotFoundException
+ */
+ public function rename($newPath) {
+ throw new NotFoundException();
+ }
+
+ public function delete() {
+ throw new NotFoundException();
+ }
+
+ public function copy($newPath) {
+ throw new NotFoundException();
+ }
+
+ public function touch($mtime = null) {
+ throw new NotFoundException();
+ }
+
+ public function getId() {
+ throw new NotFoundException();
+ }
+
+ public function stat() {
+ throw new NotFoundException();
+ }
+
+ public function getMTime() {
+ throw new NotFoundException();
+ }
+
+ public function getSize() {
+ throw new NotFoundException();
+ }
+
+ public function getEtag() {
+ throw new NotFoundException();
+ }
+
+ public function getPermissions() {
+ throw new NotFoundException();
+ }
+
+ public function isReadable() {
+ throw new NotFoundException();
+ }
+
+ public function isUpdateable() {
+ throw new NotFoundException();
+ }
+
+ public function isDeletable() {
+ throw new NotFoundException();
+ }
+
+ public function isShareable() {
+ throw new NotFoundException();
+ }
+
+ public function get($path) {
+ throw new NotFoundException();
+ }
+
+ public function getDirectoryListing() {
+ throw new NotFoundException();
+ }
+
+ public function nodeExists($path) {
+ return false;
+ }
+
+ public function newFolder($path) {
+ throw new NotFoundException();
+ }
+
+ public function newFile($path) {
+ throw new NotFoundException();
+ }
+
+ public function search($pattern) {
+ throw new NotFoundException();
+ }
+
+ public function searchByMime($mime) {
+ throw new NotFoundException();
+ }
+
+ public function getById($id) {
+ throw new NotFoundException();
+ }
+
+ public function getFreeSpace() {
+ throw new NotFoundException();
+ }
+
+ public function isCreatable() {
+ throw new NotFoundException();
+ }
+}
diff --git a/lib/private/files/node/root.php b/lib/private/files/node/root.php
new file mode 100644
index 00000000000..e3d58476e9c
--- /dev/null
+++ b/lib/private/files/node/root.php
@@ -0,0 +1,337 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Files\Node;
+
+use OC\Files\Cache\Cache;
+use OC\Files\Cache\Scanner;
+use OC\Files\Mount\Manager;
+use OC\Files\Mount\Mount;
+use OCP\Files\NotFoundException;
+use OCP\Files\NotPermittedException;
+use OC\Hooks\Emitter;
+use OC\Hooks\PublicEmitter;
+
+/**
+ * Class Root
+ *
+ * Hooks available in scope \OC\Files
+ * - preWrite(\OCP\Files\Node $node)
+ * - postWrite(\OCP\Files\Node $node)
+ * - preCreate(\OCP\Files\Node $node)
+ * - postCreate(\OCP\Files\Node $node)
+ * - preDelete(\OCP\Files\Node $node)
+ * - postDelete(\OCP\Files\Node $node)
+ * - preTouch(\OC\FilesP\Node $node, int $mtime)
+ * - postTouch(\OCP\Files\Node $node)
+ * - preCopy(\OCP\Files\Node $source, \OCP\Files\Node $target)
+ * - postCopy(\OCP\Files\Node $source, \OCP\Files\Node $target)
+ * - preRename(\OCP\Files\Node $source, \OCP\Files\Node $target)
+ * - postRename(\OCP\Files\Node $source, \OCP\Files\Node $target)
+ *
+ * @package OC\Files\Node
+ */
+class Root extends Folder implements Emitter {
+
+ /**
+ * @var \OC\Files\Mount\Manager $mountManager
+ */
+ private $mountManager;
+
+ /**
+ * @var \OC\Hooks\PublicEmitter
+ */
+ private $emitter;
+
+ /**
+ * @var \OC\User\User $user
+ */
+ private $user;
+
+ /**
+ * @param \OC\Files\Mount\Manager $manager
+ * @param \OC\Files\View $view
+ * @param \OC\User\User $user
+ */
+ public function __construct($manager, $view, $user) {
+ parent::__construct($this, $view, '');
+ $this->mountManager = $manager;
+ $this->user = $user;
+ $this->emitter = new PublicEmitter();
+ }
+
+ /**
+ * Get the user for which the filesystem is setup
+ *
+ * @return \OC\User\User
+ */
+ public function getUser() {
+ return $this->user;
+ }
+
+ /**
+ * @param string $scope
+ * @param string $method
+ * @param callable $callback
+ */
+ public function listen($scope, $method, $callback) {
+ $this->emitter->listen($scope, $method, $callback);
+ }
+
+ /**
+ * @param string $scope optional
+ * @param string $method optional
+ * @param callable $callback optional
+ */
+ public function removeListener($scope = null, $method = null, $callback = null) {
+ $this->emitter->removeListener($scope, $method, $callback);
+ }
+
+ /**
+ * @param string $scope
+ * @param string $method
+ * @param array $arguments
+ */
+ public function emit($scope, $method, $arguments = array()) {
+ $this->emitter->emit($scope, $method, $arguments);
+ }
+
+ /**
+ * @param \OC\Files\Storage\Storage $storage
+ * @param string $mountPoint
+ * @param array $arguments
+ */
+ public function mount($storage, $mountPoint, $arguments = array()) {
+ $mount = new Mount($storage, $mountPoint, $arguments);
+ $this->mountManager->addMount($mount);
+ }
+
+ /**
+ * @param string $mountPoint
+ * @return \OC\Files\Mount\Mount
+ */
+ public function getMount($mountPoint) {
+ return $this->mountManager->find($mountPoint);
+ }
+
+ /**
+ * @param string $mountPoint
+ * @return \OC\Files\Mount\Mount[]
+ */
+ public function getMountsIn($mountPoint) {
+ return $this->mountManager->findIn($mountPoint);
+ }
+
+ /**
+ * @param string $storageId
+ * @return \OC\Files\Mount\Mount[]
+ */
+ public function getMountByStorageId($storageId) {
+ return $this->mountManager->findByStorageId($storageId);
+ }
+
+ /**
+ * @param int $numericId
+ * @return Mount[]
+ */
+ public function getMountByNumericStorageId($numericId) {
+ return $this->mountManager->findByNumericId($numericId);
+ }
+
+ /**
+ * @param \OC\Files\Mount\Mount $mount
+ */
+ public function unMount($mount) {
+ $this->mountManager->remove($mount);
+ }
+
+ /**
+ * @param string $path
+ * @throws \OCP\Files\NotFoundException
+ * @throws \OCP\Files\NotPermittedException
+ * @return Node
+ */
+ public function get($path) {
+ $path = $this->normalizePath($path);
+ if ($this->isValidPath($path)) {
+ $fullPath = $this->getFullPath($path);
+ if ($this->view->file_exists($fullPath)) {
+ return $this->createNode($fullPath);
+ } else {
+ throw new NotFoundException();
+ }
+ } else {
+ throw new NotPermittedException();
+ }
+ }
+
+ /**
+ * search file by id
+ *
+ * An array is returned because in the case where a single storage is mounted in different places the same file
+ * can exist in different places
+ *
+ * @param int $id
+ * @throws \OCP\Files\NotFoundException
+ * @return Node[]
+ */
+ public function getById($id) {
+ $result = Cache::getById($id);
+ if (is_null($result)) {
+ throw new NotFoundException();
+ } else {
+ list($storageId, $internalPath) = $result;
+ $nodes = array();
+ $mounts = $this->mountManager->findByStorageId($storageId);
+ foreach ($mounts as $mount) {
+ $nodes[] = $this->get($mount->getMountPoint() . $internalPath);
+ }
+ return $nodes;
+ }
+
+ }
+
+ //most operations cant be done on the root
+
+ /**
+ * @param string $targetPath
+ * @throws \OCP\Files\NotPermittedException
+ * @return \OC\Files\Node\Node
+ */
+ public function rename($targetPath) {
+ throw new NotPermittedException();
+ }
+
+ public function delete() {
+ throw new NotPermittedException();
+ }
+
+ /**
+ * @param string $targetPath
+ * @throws \OCP\Files\NotPermittedException
+ * @return \OC\Files\Node\Node
+ */
+ public function copy($targetPath) {
+ throw new NotPermittedException();
+ }
+
+ /**
+ * @param int $mtime
+ * @throws \OCP\Files\NotPermittedException
+ */
+ public function touch($mtime = null) {
+ throw new NotPermittedException();
+ }
+
+ /**
+ * @return \OC\Files\Storage\Storage
+ * @throws \OCP\Files\NotFoundException
+ */
+ public function getStorage() {
+ throw new NotFoundException();
+ }
+
+ /**
+ * @return string
+ */
+ public function getPath() {
+ return '/';
+ }
+
+ /**
+ * @return string
+ */
+ public function getInternalPath() {
+ return '';
+ }
+
+ /**
+ * @return int
+ */
+ public function getId() {
+ return null;
+ }
+
+ /**
+ * @return array
+ */
+ public function stat() {
+ return null;
+ }
+
+ /**
+ * @return int
+ */
+ public function getMTime() {
+ return null;
+ }
+
+ /**
+ * @return int
+ */
+ public function getSize() {
+ return null;
+ }
+
+ /**
+ * @return string
+ */
+ public function getEtag() {
+ return null;
+ }
+
+ /**
+ * @return int
+ */
+ public function getPermissions() {
+ return \OCP\PERMISSION_CREATE;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isReadable() {
+ return false;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isUpdateable() {
+ return false;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isDeletable() {
+ return false;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isShareable() {
+ return false;
+ }
+
+ /**
+ * @return Node
+ * @throws \OCP\Files\NotFoundException
+ */
+ public function getParent() {
+ throw new NotFoundException();
+ }
+
+ /**
+ * @return string
+ */
+ public function getName() {
+ return '';
+ }
+}
diff --git a/lib/files/storage/common.php b/lib/private/files/storage/common.php
index 3da13ac4df0..678bf419023 100644
--- a/lib/files/storage/common.php
+++ b/lib/private/files/storage/common.php
@@ -21,11 +21,11 @@ namespace OC\Files\Storage;
*/
abstract class Common implements \OC\Files\Storage\Storage {
- private $cache;
- private $scanner;
- private $permissioncache;
- private $watcher;
- private $storageCache;
+ protected $cache;
+ protected $scanner;
+ protected $permissioncache;
+ protected $watcher;
+ protected $storageCache;
public function __construct($parameters) {
}
@@ -51,6 +51,19 @@ abstract class Common implements \OC\Files\Storage\Storage {
}
}
+ public function isReadable($path) {
+ // at least check whether it exists
+ // subclasses might want to implement this more thoroughly
+ return $this->file_exists($path);
+ }
+
+ public function isUpdatable($path) {
+ // at least check whether it exists
+ // subclasses might want to implement this more thoroughly
+ // a non-existing file/folder isn't updatable
+ return $this->file_exists($path);
+ }
+
public function isCreatable($path) {
if ($this->is_dir($path) && $this->isUpdatable($path)) {
return true;
@@ -142,13 +155,15 @@ abstract class Common implements \OC\Files\Storage\Storage {
return false;
} else {
$directoryHandle = $this->opendir($directory);
- while ($contents = readdir($directoryHandle)) {
- if (!\OC\Files\Filesystem::isIgnoredDir($contents)) {
- $path = $directory . '/' . $contents;
- if ($this->is_dir($path)) {
- $this->deleteAll($path);
- } else {
- $this->unlink($path);
+ if (is_resource($directoryHandle)) {
+ while (($contents = readdir($directoryHandle)) !== false) {
+ if (!\OC\Files\Filesystem::isIgnoredDir($contents)) {
+ $path = $directory . '/' . $contents;
+ if ($this->is_dir($path)) {
+ $this->deleteAll($path);
+ } else {
+ $this->unlink($path);
+ }
}
}
}
@@ -163,27 +178,13 @@ abstract class Common implements \OC\Files\Storage\Storage {
}
public function getMimeType($path) {
- if (!$this->file_exists($path)) {
- return false;
- }
if ($this->is_dir($path)) {
return 'httpd/unix-directory';
- }
- $source = $this->fopen($path, 'r');
- if (!$source) {
- return false;
- }
- $head = fread($source, 8192); //8kb should suffice to determine a mimetype
- if ($pos = strrpos($path, '.')) {
- $extension = substr($path, $pos);
+ } elseif ($this->file_exists($path)) {
+ return \OC_Helper::getFileNameMimeType($path);
} else {
- $extension = '';
+ return false;
}
- $tmpFile = \OC_Helper::tmpFile($extension);
- file_put_contents($tmpFile, $head);
- $mime = \OC_Helper::getMimeType($tmpFile);
- unlink($tmpFile);
- return $mime;
}
public function hash($type, $path, $raw = false) {
@@ -224,8 +225,9 @@ abstract class Common implements \OC\Files\Storage\Storage {
}
private function addLocalFolder($path, $target) {
- if ($dh = $this->opendir($path)) {
- while ($file = readdir($dh)) {
+ $dh = $this->opendir($path);
+ if (is_resource($dh)) {
+ while (($file = readdir($dh)) !== false) {
if ($file !== '.' and $file !== '..') {
if ($this->is_dir($path . '/' . $file)) {
mkdir($target . '/' . $file);
@@ -242,8 +244,8 @@ abstract class Common implements \OC\Files\Storage\Storage {
protected function searchInDir($query, $dir = '') {
$files = array();
$dh = $this->opendir($dir);
- if ($dh) {
- while ($item = readdir($dh)) {
+ if (is_resource($dh)) {
+ while (($item = readdir($dh)) !== false) {
if ($item == '.' || $item == '..') continue;
if (strstr(strtolower($item), strtolower($query)) !== false) {
$files[] = $dir . '/' . $item;
@@ -295,7 +297,7 @@ abstract class Common implements \OC\Files\Storage\Storage {
return $this->watcher;
}
- public function getStorageCache(){
+ public function getStorageCache() {
if (!isset($this->storageCache)) {
$this->storageCache = new \OC\Files\Cache\Storage($this);
}
@@ -366,6 +368,6 @@ abstract class Common implements \OC\Files\Storage\Storage {
* @return int
*/
public function free_space($path) {
- return \OC\Files\FREE_SPACE_UNKNOWN;
+ return \OC\Files\SPACE_UNKNOWN;
}
}
diff --git a/lib/files/storage/commontest.php b/lib/private/files/storage/commontest.php
index fbdb7fbf110..2394b14a82f 100644
--- a/lib/files/storage/commontest.php
+++ b/lib/private/files/storage/commontest.php
@@ -54,7 +54,7 @@ class CommonTest extends \OC\Files\Storage\Common{
return $this->storage->stat($path);
}
public function filetype($path) {
- return $this->storage->filetype($path);
+ return @$this->storage->filetype($path);
}
public function isReadable($path) {
return $this->storage->isReadable($path);
@@ -77,4 +77,4 @@ class CommonTest extends \OC\Files\Storage\Common{
public function touch($path, $mtime=null) {
return $this->storage->touch($path, $mtime);
}
-} \ No newline at end of file
+}
diff --git a/lib/private/files/storage/home.php b/lib/private/files/storage/home.php
new file mode 100644
index 00000000000..1c2a682f197
--- /dev/null
+++ b/lib/private/files/storage/home.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Files\Storage;
+
+/**
+ * Specialized version of Local storage for home directory usage
+ */
+class Home extends Local {
+ /**
+ * @var string
+ */
+ protected $id;
+
+ /**
+ * @var \OC\User\User $user
+ */
+ protected $user;
+
+ /**
+ * @brief Construct a Home storage instance
+ * @param array $arguments array with "user" containing the
+ * storage owner and "legacy" containing "true" if the storage is
+ * a legacy storage with "local::" URL instead of the new "home::" one.
+ */
+ public function __construct($arguments) {
+ $this->user = $arguments['user'];
+ $datadir = $this->user->getHome();
+ if (isset($arguments['legacy']) && $arguments['legacy']) {
+ // legacy home id (<= 5.0.12)
+ $this->id = 'local::' . $datadir . '/';
+ }
+ else {
+ $this->id = 'home::' . $this->user->getUID();
+ }
+
+ parent::__construct(array('datadir' => $datadir));
+ }
+
+ public function getId() {
+ return $this->id;
+ }
+
+ /**
+ * @return \OC\Files\Cache\HomeCache
+ */
+ public function getCache($path = '') {
+ if (!isset($this->cache)) {
+ $this->cache = new \OC\Files\Cache\HomeCache($this);
+ }
+ return $this->cache;
+ }
+
+ /**
+ * @brief Returns the owner of this home storage
+ * @return \OC\User\User owner of this home storage
+ */
+ public function getUser() {
+ return $this->user;
+ }
+}
diff --git a/lib/files/storage/loader.php b/lib/private/files/storage/loader.php
index 2572ef443bc..2572ef443bc 100644
--- a/lib/files/storage/loader.php
+++ b/lib/private/files/storage/loader.php
diff --git a/lib/files/storage/local.php b/lib/private/files/storage/local.php
index b08fd73ce19..02e8df4af4e 100644
--- a/lib/files/storage/local.php
+++ b/lib/private/files/storage/local.php
@@ -203,14 +203,6 @@ if (\OC_Util::runningOnWindows()) {
return $return;
}
- public function getMimeType($path) {
- if ($this->isReadable($path)) {
- return \OC_Helper::getMimeType($this->datadir . $path);
- } else {
- return false;
- }
- }
-
private function delTree($dir) {
$dirRelative = $dir;
$dir = $this->datadir . $dir;
@@ -265,7 +257,7 @@ if (\OC_Util::runningOnWindows()) {
public function free_space($path) {
$space = @disk_free_space($this->datadir . $path);
if ($space === false) {
- return \OC\Files\FREE_SPACE_UNKNOWN;
+ return \OC\Files\SPACE_UNKNOWN;
}
return $space;
}
diff --git a/lib/files/storage/mappedlocal.php b/lib/private/files/storage/mappedlocal.php
index cf5d9b3ef4f..6c37d445867 100644
--- a/lib/files/storage/mappedlocal.php
+++ b/lib/private/files/storage/mappedlocal.php
@@ -65,16 +65,18 @@ class MappedLocal extends \OC\Files\Storage\Common{
$logicalPath = $this->mapper->physicalToLogic($physicalPath);
$dh = opendir($physicalPath);
- while ($file = readdir($dh)) {
- if ($file === '.' or $file === '..') {
- continue;
- }
+ if(is_resource($dh)) {
+ while (($file = readdir($dh)) !== false) {
+ if ($file === '.' or $file === '..') {
+ continue;
+ }
- $logicalFilePath = $this->mapper->physicalToLogic($physicalPath.'/'.$file);
+ $logicalFilePath = $this->mapper->physicalToLogic($physicalPath.'/'.$file);
- $file= $this->mapper->stripRootFolder($logicalFilePath, $logicalPath);
- $file = $this->stripLeading($file);
- $files[]= $file;
+ $file= $this->mapper->stripRootFolder($logicalFilePath, $logicalPath);
+ $file = $this->stripLeading($file);
+ $files[]= $file;
+ }
}
\OC\Files\Stream\Dir::register('local-win32'.$path, $files);
@@ -208,14 +210,6 @@ class MappedLocal extends \OC\Files\Storage\Common{
return $return;
}
- public function getMimeType($path) {
- if($this->isReadable($path)) {
- return \OC_Helper::getMimeType($this->buildPath($path));
- }else{
- return false;
- }
- }
-
private function delTree($dir, $isLogicPath=true) {
$dirRelative=$dir;
if ($isLogicPath) {
diff --git a/lib/private/files/storage/storage.php b/lib/private/files/storage/storage.php
new file mode 100644
index 00000000000..5be90f24756
--- /dev/null
+++ b/lib/private/files/storage/storage.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Files\Storage;
+
+/**
+ * Provide a common interface to all different storage options
+ *
+ * All paths passed to the storage are relative to the storage and should NOT have a leading slash.
+ */
+interface Storage extends \OCP\Files\Storage {
+
+ /**
+ * get a cache instance for the storage
+ *
+ * @param string $path
+ * @return \OC\Files\Cache\Cache
+ */
+ public function getCache($path = '');
+
+ /**
+ * get a scanner instance for the storage
+ *
+ * @param string $path
+ * @return \OC\Files\Cache\Scanner
+ */
+ public function getScanner($path = '');
+
+
+ /**
+ * get the user id of the owner of a file or folder
+ *
+ * @param string $path
+ * @return string
+ */
+ public function getOwner($path);
+
+ /**
+ * get a permissions cache instance for the cache
+ *
+ * @param string $path
+ * @return \OC\Files\Cache\Permissions
+ */
+ public function getPermissionsCache($path = '');
+
+ /**
+ * get a watcher instance for the cache
+ *
+ * @param string $path
+ * @return \OC\Files\Cache\Watcher
+ */
+ public function getWatcher($path = '');
+
+ /**
+ * @return \OC\Files\Cache\Storage
+ */
+ public function getStorageCache();
+
+}
diff --git a/lib/files/storage/temporary.php b/lib/private/files/storage/temporary.php
index d84dbda2e39..d84dbda2e39 100644
--- a/lib/files/storage/temporary.php
+++ b/lib/private/files/storage/temporary.php
diff --git a/lib/private/files/storage/wrapper/quota.php b/lib/private/files/storage/wrapper/quota.php
new file mode 100644
index 00000000000..43016e0892f
--- /dev/null
+++ b/lib/private/files/storage/wrapper/quota.php
@@ -0,0 +1,104 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Files\Storage\Wrapper;
+
+class Quota extends Wrapper {
+
+ /**
+ * @var int $quota
+ */
+ protected $quota;
+
+ /**
+ * @param array $parameters
+ */
+ public function __construct($parameters) {
+ $this->storage = $parameters['storage'];
+ $this->quota = $parameters['quota'];
+ }
+
+ protected function getSize($path) {
+ $cache = $this->getCache();
+ $data = $cache->get($path);
+ if (is_array($data) and isset($data['size'])) {
+ return $data['size'];
+ } else {
+ return \OC\Files\SPACE_NOT_COMPUTED;
+ }
+ }
+
+ /**
+ * Get free space as limited by the quota
+ *
+ * @param string $path
+ * @return int
+ */
+ public function free_space($path) {
+ if ($this->quota < 0) {
+ return $this->storage->free_space($path);
+ } else {
+ $used = $this->getSize('');
+ if ($used < 0) {
+ return \OC\Files\SPACE_NOT_COMPUTED;
+ } else {
+ $free = $this->storage->free_space($path);
+ return min($free, (max($this->quota - $used, 0)));
+ }
+ }
+ }
+
+ /**
+ * see http://php.net/manual/en/function.file_put_contents.php
+ *
+ * @param string $path
+ * @param string $data
+ * @return bool
+ */
+ public function file_put_contents($path, $data) {
+ $free = $this->free_space('');
+ if ($free < 0 or strlen($data) < $free) {
+ return $this->storage->file_put_contents($path, $data);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * see http://php.net/manual/en/function.copy.php
+ *
+ * @param string $source
+ * @param string $target
+ * @return bool
+ */
+ public function copy($source, $target) {
+ $free = $this->free_space('');
+ if ($free < 0 or $this->getSize($source) < $free) {
+ return $this->storage->copy($source, $target);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * see http://php.net/manual/en/function.fopen.php
+ *
+ * @param string $path
+ * @param string $mode
+ * @return resource
+ */
+ public function fopen($path, $mode) {
+ $source = $this->storage->fopen($path, $mode);
+ $free = $this->free_space('');
+ if ($free >= 0 && $mode !== 'r') {
+ return \OC\Files\Stream\Quota::wrap($source, $free);
+ } else {
+ return $source;
+ }
+ }
+}
diff --git a/lib/files/storage/wrapper/wrapper.php b/lib/private/files/storage/wrapper/wrapper.php
index 4feb0520f12..f9adda80314 100644
--- a/lib/files/storage/wrapper/wrapper.php
+++ b/lib/private/files/storage/wrapper/wrapper.php
@@ -395,7 +395,7 @@ class Wrapper implements \OC\Files\Storage\Storage {
* @return \OC\Files\Cache\Permissions
*/
public function getPermissionsCache($path = '') {
- return $this->storage->getPermissions($path);
+ return $this->storage->getPermissionsCache($path);
}
/**
@@ -424,4 +424,12 @@ class Wrapper implements \OC\Files\Storage\Storage {
public function getETag($path) {
return $this->storage->getETag($path);
}
+
+ /**
+ * Returns true
+ * @return true
+ */
+ public function test() {
+ return $this->storage->test();
+ }
}
diff --git a/lib/files/stream/close.php b/lib/private/files/stream/close.php
index 80de3497c36..80de3497c36 100644
--- a/lib/files/stream/close.php
+++ b/lib/private/files/stream/close.php
diff --git a/lib/files/stream/dir.php b/lib/private/files/stream/dir.php
index 6ca884fc994..6ca884fc994 100644
--- a/lib/files/stream/dir.php
+++ b/lib/private/files/stream/dir.php
diff --git a/lib/files/stream/oc.php b/lib/private/files/stream/oc.php
index 88e7e062df9..88e7e062df9 100644
--- a/lib/files/stream/oc.php
+++ b/lib/private/files/stream/oc.php
diff --git a/lib/private/files/stream/quota.php b/lib/private/files/stream/quota.php
new file mode 100644
index 00000000000..60e60da8e67
--- /dev/null
+++ b/lib/private/files/stream/quota.php
@@ -0,0 +1,140 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Files\Stream;
+
+/**
+ * stream wrapper limits the amount of data that can be written to a stream
+ *
+ * usage: void \OC\Files\Stream\Quota::register($id, $stream, $limit)
+ * or: resource \OC\Files\Stream\Quota::wrap($stream, $limit)
+ */
+class Quota {
+ private static $streams = array();
+
+ /**
+ * @var resource $source
+ */
+ private $source;
+
+ /**
+ * @var int $limit
+ */
+ private $limit;
+
+ /**
+ * @param string $id
+ * @param resource $stream
+ * @param int $limit
+ */
+ public static function register($id, $stream, $limit) {
+ self::$streams[$id] = array($stream, $limit);
+ }
+
+ /**
+ * remove all registered streams
+ */
+ public static function clear() {
+ self::$streams = array();
+ }
+
+ /**
+ * @param resource $stream
+ * @param int $limit
+ * @return resource
+ */
+ static public function wrap($stream, $limit) {
+ $id = uniqid();
+ self::register($id, $stream, $limit);
+ $meta = stream_get_meta_data($stream);
+ return fopen('quota://' . $id, $meta['mode']);
+ }
+
+ public function stream_open($path, $mode, $options, &$opened_path) {
+ $id = substr($path, strlen('quota://'));
+ if (isset(self::$streams[$id])) {
+ list($this->source, $this->limit) = self::$streams[$id];
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public function stream_seek($offset, $whence = SEEK_SET) {
+ if ($whence === SEEK_END){
+ // go to the end to find out last position's offset
+ $oldOffset = $this->stream_tell();
+ if (fseek($this->source, 0, $whence) !== 0){
+ return false;
+ }
+ $whence = SEEK_SET;
+ $offset = $this->stream_tell() + $offset;
+ $this->limit += $oldOffset - $offset;
+ }
+ else if ($whence === SEEK_SET) {
+ $this->limit += $this->stream_tell() - $offset;
+ } else {
+ $this->limit -= $offset;
+ }
+ // this wrapper needs to return "true" for success.
+ // the fseek call itself returns 0 on succeess
+ return !fseek($this->source, $offset, $whence);
+ }
+
+ public function stream_tell() {
+ return ftell($this->source);
+ }
+
+ public function stream_read($count) {
+ $this->limit -= $count;
+ return fread($this->source, $count);
+ }
+
+ public function stream_write($data) {
+ $size = strlen($data);
+ if ($size > $this->limit) {
+ $data = substr($data, 0, $this->limit);
+ $size = $this->limit;
+ }
+ $this->limit -= $size;
+ return fwrite($this->source, $data);
+ }
+
+ public function stream_set_option($option, $arg1, $arg2) {
+ switch ($option) {
+ case STREAM_OPTION_BLOCKING:
+ stream_set_blocking($this->source, $arg1);
+ break;
+ case STREAM_OPTION_READ_TIMEOUT:
+ stream_set_timeout($this->source, $arg1, $arg2);
+ break;
+ case STREAM_OPTION_WRITE_BUFFER:
+ stream_set_write_buffer($this->source, $arg1, $arg2);
+ }
+ }
+
+ public function stream_stat() {
+ return fstat($this->source);
+ }
+
+ public function stream_lock($mode) {
+ flock($this->source, $mode);
+ }
+
+ public function stream_flush() {
+ return fflush($this->source);
+ }
+
+ public function stream_eof() {
+ return feof($this->source);
+ }
+
+ public function stream_close() {
+ fclose($this->source);
+ }
+}
diff --git a/lib/files/stream/staticstream.php b/lib/private/files/stream/staticstream.php
index 45b1a7a81f8..45b1a7a81f8 100644
--- a/lib/files/stream/staticstream.php
+++ b/lib/private/files/stream/staticstream.php
diff --git a/lib/private/files/type/detection.php b/lib/private/files/type/detection.php
new file mode 100644
index 00000000000..d7cc9ebbf4e
--- /dev/null
+++ b/lib/private/files/type/detection.php
@@ -0,0 +1,125 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Files\Type;
+
+/**
+ * Class Detection
+ *
+ * Mimetype detection
+ *
+ * @package OC\Files\Type
+ */
+class Detection {
+ protected $mimetypes = array();
+
+ /**
+ * add an extension -> mimetype mapping
+ *
+ * @param string $extension
+ * @param string $mimetype
+ */
+ public function registerType($extension, $mimetype) {
+ $this->mimetypes[$extension] = $mimetype;
+ }
+
+ /**
+ * add an array of extension -> mimetype mappings
+ *
+ * @param array $types
+ */
+ public function registerTypeArray($types) {
+ $this->mimetypes = array_merge($this->mimetypes, $types);
+ }
+
+ /**
+ * detect mimetype only based on filename, content of file is not used
+ *
+ * @param string $path
+ * @return string
+ */
+ public function detectPath($path) {
+ if (strpos($path, '.')) {
+ //try to guess the type by the file extension
+ $extension = strtolower(strrchr(basename($path), "."));
+ $extension = substr($extension, 1); //remove leading .
+ return (isset($this->mimetypes[$extension])) ? $this->mimetypes[$extension] : 'application/octet-stream';
+ } else {
+ return 'application/octet-stream';
+ }
+ }
+
+ /**
+ * detect mimetype based on both filename and content
+ *
+ * @param string $path
+ * @return string
+ */
+ public function detect($path) {
+ if (@is_dir($path)) {
+ // directories are easy
+ return "httpd/unix-directory";
+ }
+
+ $mimeType = $this->detectPath($path);
+
+ if ($mimeType === 'application/octet-stream' and function_exists('finfo_open')
+ and function_exists('finfo_file') and $finfo = finfo_open(FILEINFO_MIME)
+ ) {
+ $info = @strtolower(finfo_file($finfo, $path));
+ if ($info) {
+ $mimeType = substr($info, 0, strpos($info, ';'));
+ return empty($mimeType) ? 'application/octet-stream' : $mimeType;
+ }
+ finfo_close($finfo);
+ }
+ $isWrapped = (strpos($path, '://') !== false) and (substr($path, 0, 7) === 'file://');
+ if (!$isWrapped and $mimeType === 'application/octet-stream' && function_exists("mime_content_type")) {
+ // use mime magic extension if available
+ $mimeType = mime_content_type($path);
+ }
+ if (!$isWrapped and $mimeType === 'application/octet-stream' && \OC_Helper::canExecute("file")) {
+ // it looks like we have a 'file' command,
+ // lets see if it does have mime support
+ $path = escapeshellarg($path);
+ $fp = popen("file -b --mime-type $path 2>/dev/null", "r");
+ $reply = fgets($fp);
+ pclose($fp);
+
+ //trim the newline
+ $mimeType = trim($reply);
+
+ if (empty($mimeType)) {
+ $mimeType = 'application/octet-stream';
+ }
+
+ }
+ return $mimeType;
+ }
+
+ /**
+ * detect mimetype based on the content of a string
+ *
+ * @param string $data
+ * @return string
+ */
+ public function detectString($data) {
+ if (function_exists('finfo_open') and function_exists('finfo_file')) {
+ $finfo = finfo_open(FILEINFO_MIME);
+ return finfo_buffer($finfo, $data);
+ } else {
+ $tmpFile = \OC_Helper::tmpFile();
+ $fh = fopen($tmpFile, 'wb');
+ fwrite($fh, $data, 8024);
+ fclose($fh);
+ $mime = $this->detect($tmpFile);
+ unset($tmpFile);
+ return $mime;
+ }
+ }
+}
diff --git a/lib/private/files/type/templatemanager.php b/lib/private/files/type/templatemanager.php
new file mode 100644
index 00000000000..cd1536d2732
--- /dev/null
+++ b/lib/private/files/type/templatemanager.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Files\Type;
+
+class TemplateManager {
+ protected $templates = array();
+
+ public function registerTemplate($mimetype, $path) {
+ $this->templates[$mimetype] = $path;
+ }
+
+ /**
+ * get the path of the template for a mimetype
+ *
+ * @param string $mimetype
+ * @return string | null
+ */
+ public function getTemplatePath($mimetype) {
+ if (isset($this->templates[$mimetype])) {
+ return $this->templates[$mimetype];
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * get the template content for a mimetype
+ *
+ * @param string $mimetype
+ * @return string
+ */
+ public function getTemplate($mimetype) {
+ $path = $this->getTemplatePath($mimetype);
+ if ($path) {
+ return file_get_contents($path);
+ } else {
+ return '';
+ }
+ }
+}
diff --git a/lib/files/utils/scanner.php b/lib/private/files/utils/scanner.php
index f0dc41ffad3..2cad7dd77bd 100644
--- a/lib/files/utils/scanner.php
+++ b/lib/private/files/utils/scanner.php
@@ -72,6 +72,9 @@ class Scanner extends PublicEmitter {
public function backgroundScan($dir) {
$mounts = $this->getMounts($dir);
foreach ($mounts as $mount) {
+ if (is_null($mount->getStorage())) {
+ continue;
+ }
$scanner = $mount->getStorage()->getScanner();
$this->attachListener($mount);
$scanner->backgroundScan();
@@ -81,6 +84,9 @@ class Scanner extends PublicEmitter {
public function scan($dir) {
$mounts = $this->getMounts($dir);
foreach ($mounts as $mount) {
+ if (is_null($mount->getStorage())) {
+ continue;
+ }
$scanner = $mount->getStorage()->getScanner();
$this->attachListener($mount);
$scanner->scan('', \OC\Files\Cache\Scanner::SCAN_RECURSIVE, \OC\Files\Cache\Scanner::REUSE_ETAG);
diff --git a/lib/files/view.php b/lib/private/files/view.php
index c9727fe4984..ac45a881331 100644
--- a/lib/files/view.php
+++ b/lib/private/files/view.php
@@ -30,7 +30,7 @@ class View {
private $internal_path_cache = array();
private $storage_cache = array();
- public function __construct($root) {
+ public function __construct($root = '') {
$this->fakeRoot = $root;
}
@@ -110,7 +110,9 @@ class View {
* @return array consisting of the storage and the internal path
*/
public function resolvePath($path) {
- return Filesystem::resolvePath($this->getAbsolutePath($path));
+ $a = $this->getAbsolutePath($path);
+ $p = Filesystem::normalizePath($a);
+ return Filesystem::resolvePath($p);
}
/**
@@ -157,7 +159,11 @@ class View {
}
public function rmdir($path) {
- return $this->basicOperation('rmdir', $path, array('delete'));
+ if ($this->is_dir($path)) {
+ return $this->basicOperation('rmdir', $path, array('delete'));
+ } else {
+ return false;
+ }
}
public function opendir($path) {
@@ -249,6 +255,7 @@ class View {
$hooks = array('touch');
if (!$this->file_exists($path)) {
+ $hooks[] = 'create';
$hooks[] = 'write';
}
$result = $this->basicOperation('touch', $path, $hooks, $mtime);
@@ -267,18 +274,18 @@ class View {
$absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
if (\OC_FileProxy::runPreProxies('file_put_contents', $absolutePath, $data)
and Filesystem::isValidPath($path)
- and !Filesystem::isFileBlacklisted($path)
+ and !Filesystem::isFileBlacklisted($path)
) {
$path = $this->getRelativePath($absolutePath);
$exists = $this->file_exists($path);
$run = true;
- if ($this->fakeRoot == Filesystem::getRoot() && !Cache\Scanner::isPartialFile($path)) {
+ if ($this->shouldEmitHooks($path)) {
if (!$exists) {
\OC_Hook::emit(
Filesystem::CLASSNAME,
Filesystem::signal_create,
array(
- Filesystem::signal_param_path => $path,
+ Filesystem::signal_param_path => $this->getHookPath($path),
Filesystem::signal_param_run => &$run
)
);
@@ -287,7 +294,7 @@ class View {
Filesystem::CLASSNAME,
Filesystem::signal_write,
array(
- Filesystem::signal_param_path => $path,
+ Filesystem::signal_param_path => $this->getHookPath($path),
Filesystem::signal_param_run => &$run
)
);
@@ -300,18 +307,18 @@ class View {
list ($count, $result) = \OC_Helper::streamCopy($data, $target);
fclose($target);
fclose($data);
- if ($this->fakeRoot == Filesystem::getRoot() && !Cache\Scanner::isPartialFile($path) && $result !== false) {
+ if ($this->shouldEmitHooks($path) && $result !== false) {
if (!$exists) {
\OC_Hook::emit(
Filesystem::CLASSNAME,
Filesystem::signal_post_create,
- array(Filesystem::signal_param_path => $path)
+ array(Filesystem::signal_param_path => $this->getHookPath($path))
);
}
\OC_Hook::emit(
Filesystem::CLASSNAME,
Filesystem::signal_post_write,
- array(Filesystem::signal_param_path => $path)
+ array(Filesystem::signal_param_path => $this->getHookPath($path))
);
}
\OC_FileProxy::runPostProxies('file_put_contents', $absolutePath, $count);
@@ -323,7 +330,8 @@ class View {
return false;
}
} else {
- return $this->basicOperation('file_put_contents', $path, array('create', 'write'), $data);
+ $hooks = ($this->file_exists($path)) ? array('write') : array('create', 'write');
+ return $this->basicOperation('file_put_contents', $path, $hooks, $data);
}
}
@@ -332,7 +340,7 @@ class View {
}
public function deleteAll($directory, $empty = false) {
- return $this->basicOperation('deleteAll', $directory, array('delete'), $empty);
+ return $this->rmdir($directory);
}
public function rename($path1, $path2) {
@@ -353,21 +361,21 @@ class View {
return false;
}
$run = true;
- if ($this->fakeRoot == Filesystem::getRoot() && (Cache\Scanner::isPartialFile($path1) && !Cache\Scanner::isPartialFile($path2))) {
+ if ($this->shouldEmitHooks() && (Cache\Scanner::isPartialFile($path1) && !Cache\Scanner::isPartialFile($path2))) {
// if it was a rename from a part file to a regular file it was a write and not a rename operation
\OC_Hook::emit(
Filesystem::CLASSNAME, Filesystem::signal_write,
array(
- Filesystem::signal_param_path => $path2,
+ Filesystem::signal_param_path => $this->getHookPath($path2),
Filesystem::signal_param_run => &$run
)
);
- } elseif ($this->fakeRoot == Filesystem::getRoot()) {
+ } elseif ($this->shouldEmitHooks()) {
\OC_Hook::emit(
Filesystem::CLASSNAME, Filesystem::signal_rename,
array(
- Filesystem::signal_param_oldpath => $path1,
- Filesystem::signal_param_newpath => $path2,
+ Filesystem::signal_param_oldpath => $this->getHookPath($path1),
+ Filesystem::signal_param_newpath => $this->getHookPath($path2),
Filesystem::signal_param_run => &$run
)
);
@@ -407,22 +415,22 @@ class View {
}
}
}
- if ($this->fakeRoot == Filesystem::getRoot() && (Cache\Scanner::isPartialFile($path1) && !Cache\Scanner::isPartialFile($path2)) && $result !== false) {
+ if ($this->shouldEmitHooks() && (Cache\Scanner::isPartialFile($path1) && !Cache\Scanner::isPartialFile($path2)) && $result !== false) {
// if it was a rename from a part file to a regular file it was a write and not a rename operation
\OC_Hook::emit(
Filesystem::CLASSNAME,
Filesystem::signal_post_write,
array(
- Filesystem::signal_param_path => $path2,
+ Filesystem::signal_param_path => $this->getHookPath($path2),
)
);
- } elseif ($this->fakeRoot == Filesystem::getRoot() && $result !== false) {
+ } elseif ($this->shouldEmitHooks() && $result !== false) {
\OC_Hook::emit(
Filesystem::CLASSNAME,
Filesystem::signal_post_rename,
array(
- Filesystem::signal_param_oldpath => $path1,
- Filesystem::signal_param_newpath => $path2
+ Filesystem::signal_param_oldpath => $this->getHookPath($path1),
+ Filesystem::signal_param_newpath => $this->getHookPath($path2)
)
);
}
@@ -454,13 +462,13 @@ class View {
}
$run = true;
$exists = $this->file_exists($path2);
- if ($this->fakeRoot == Filesystem::getRoot()) {
+ if ($this->shouldEmitHooks()) {
\OC_Hook::emit(
Filesystem::CLASSNAME,
Filesystem::signal_copy,
array(
- Filesystem::signal_param_oldpath => $path1,
- Filesystem::signal_param_newpath => $path2,
+ Filesystem::signal_param_oldpath => $this->getHookPath($path1),
+ Filesystem::signal_param_newpath => $this->getHookPath($path2),
Filesystem::signal_param_run => &$run
)
);
@@ -469,7 +477,7 @@ class View {
Filesystem::CLASSNAME,
Filesystem::signal_create,
array(
- Filesystem::signal_param_path => $path2,
+ Filesystem::signal_param_path => $this->getHookPath($path2),
Filesystem::signal_param_run => &$run
)
);
@@ -479,7 +487,7 @@ class View {
Filesystem::CLASSNAME,
Filesystem::signal_write,
array(
- Filesystem::signal_param_path => $path2,
+ Filesystem::signal_param_path => $this->getHookPath($path2),
Filesystem::signal_param_run => &$run
)
);
@@ -499,9 +507,11 @@ class View {
} else {
if ($this->is_dir($path1) && ($dh = $this->opendir($path1))) {
$result = $this->mkdir($path2);
- while ($file = readdir($dh)) {
- if (!Filesystem::isIgnoredDir($file)) {
- $result = $this->copy($path1 . '/' . $file, $path2 . '/' . $file);
+ if (is_resource($dh)) {
+ while (($file = readdir($dh)) !== false) {
+ if (!Filesystem::isIgnoredDir($file)) {
+ $result = $this->copy($path1 . '/' . $file, $path2 . '/' . $file);
+ }
}
}
} else {
@@ -510,26 +520,26 @@ class View {
list($count, $result) = \OC_Helper::streamCopy($source, $target);
}
}
- if ($this->fakeRoot == Filesystem::getRoot() && $result !== false) {
+ if ($this->shouldEmitHooks() && $result !== false) {
\OC_Hook::emit(
Filesystem::CLASSNAME,
Filesystem::signal_post_copy,
array(
- Filesystem::signal_param_oldpath => $path1,
- Filesystem::signal_param_newpath => $path2
+ Filesystem::signal_param_oldpath => $this->getHookPath($path1),
+ Filesystem::signal_param_newpath => $this->getHookPath($path2)
)
);
if (!$exists) {
\OC_Hook::emit(
Filesystem::CLASSNAME,
Filesystem::signal_post_create,
- array(Filesystem::signal_param_path => $path2)
+ array(Filesystem::signal_param_path => $this->getHookPath($path2))
);
}
\OC_Hook::emit(
Filesystem::CLASSNAME,
Filesystem::signal_post_write,
- array(Filesystem::signal_param_path => $path2)
+ array(Filesystem::signal_param_path => $this->getHookPath($path2))
);
}
return $result;
@@ -620,11 +630,11 @@ class View {
if ($path == null) {
return false;
}
- if (Filesystem::$loaded && $this->fakeRoot == Filesystem::getRoot()) {
+ if ($this->shouldEmitHooks($path)) {
\OC_Hook::emit(
Filesystem::CLASSNAME,
Filesystem::signal_read,
- array(Filesystem::signal_param_path => $path)
+ array(Filesystem::signal_param_path => $this->getHookPath($path))
);
}
list($storage, $internalPath) = Filesystem::resolvePath($absolutePath . $postFix);
@@ -658,7 +668,7 @@ class View {
$absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
if (\OC_FileProxy::runPreProxies($operation, $absolutePath, $extraParam)
and Filesystem::isValidPath($path)
- and !Filesystem::isFileBlacklisted($path)
+ and !Filesystem::isFileBlacklisted($path)
) {
$path = $this->getRelativePath($absolutePath);
if ($path == null) {
@@ -674,7 +684,7 @@ class View {
$result = $storage->$operation($internalPath);
}
$result = \OC_FileProxy::runPostProxies($operation, $this->getAbsolutePath($path), $result);
- if (Filesystem::$loaded and $this->fakeRoot == Filesystem::getRoot() && $result !== false) {
+ if ($this->shouldEmitHooks($path) && $result !== false) {
if ($operation != 'fopen') { //no post hooks for fopen, the file stream is still open
$this->runHooks($hooks, $path, true);
}
@@ -685,10 +695,38 @@ class View {
return null;
}
+ /**
+ * get the path relative to the default root for hook usage
+ *
+ * @param string $path
+ * @return string
+ */
+ private function getHookPath($path) {
+ if (!Filesystem::getView()) {
+ return $path;
+ }
+ return Filesystem::getView()->getRelativePath($this->getAbsolutePath($path));
+ }
+
+ private function shouldEmitHooks($path = '') {
+ if ($path && Cache\Scanner::isPartialFile($path)) {
+ return false;
+ }
+ if (!Filesystem::$loaded) {
+ return false;
+ }
+ $defaultRoot = Filesystem::getRoot();
+ if ($this->fakeRoot === $defaultRoot) {
+ return true;
+ }
+ return (strlen($this->fakeRoot) > strlen($defaultRoot)) && (substr($this->fakeRoot, 0, strlen($defaultRoot) + 1) === $defaultRoot . '/');
+ }
+
private function runHooks($hooks, $path, $post = false) {
+ $path = $this->getHookPath($path);
$prefix = ($post) ? 'post_' : '';
$run = true;
- if (Filesystem::$loaded and $this->fakeRoot == Filesystem::getRoot() && !Cache\Scanner::isPartialFile($path)) {
+ if ($this->shouldEmitHooks($path)) {
foreach ($hooks as $hook) {
if ($hook != 'read') {
\OC_Hook::emit(
@@ -728,6 +766,8 @@ class View {
* get the filesystem info
*
* @param string $path
+ * @param boolean $includeMountPoints whether to add mountpoint sizes,
+ * defaults to true
* @return array
*
* returns an associative array with the following keys:
@@ -737,7 +777,7 @@ class View {
* - encrypted
* - versioned
*/
- public function getFileInfo($path) {
+ public function getFileInfo($path, $includeMountPoints = true) {
$data = array();
if (!Filesystem::isValidPath($path)) {
return $data;
@@ -764,7 +804,7 @@ class View {
$data = $cache->get($internalPath);
if ($data and $data['fileid']) {
- if ($data['mimetype'] === 'httpd/unix-directory') {
+ if ($includeMountPoints and $data['mimetype'] === 'httpd/unix-directory') {
//add the sizes of other mountpoints to the folder
$mountPoints = Filesystem::getMountPoints($path);
foreach ($mountPoints as $mountPoint) {
@@ -870,7 +910,8 @@ class View {
$permissions = $subStorage->getPermissions($rootEntry['path']);
$subPermissionsCache->set($rootEntry['fileid'], $user, $permissions);
}
- $rootEntry['permissions'] = $permissions;
+ // do not allow renaming/deleting the mount point
+ $rootEntry['permissions'] = $permissions & (\OCP\PERMISSION_ALL - (\OCP\PERMISSION_UPDATE | \OCP\PERMISSION_DELETE));
//remove any existing entry with the same name
foreach ($files as $i => $file) {
@@ -947,7 +988,7 @@ class View {
/**
* search for files by mimetype
*
- * @param string $query
+ * @param string $mimetype
* @return array
*/
public function searchByMime($mimetype) {
@@ -970,7 +1011,7 @@ class View {
$results = $cache->$method($query);
foreach ($results as $result) {
- if (substr($mountPoint . $result['path'], 0, $rootLength) === $this->fakeRoot) {
+ if (substr($mountPoint . $result['path'], 0, $rootLength + 1) === $this->fakeRoot . '/') {
$result['path'] = substr($mountPoint . $result['path'], $rootLength);
$files[] = $result;
}
@@ -984,9 +1025,11 @@ class View {
$relativeMountPoint = substr($mountPoint, $rootLength);
$results = $cache->$method($query);
- foreach ($results as $result) {
- $result['path'] = $relativeMountPoint . $result['path'];
- $files[] = $result;
+ if ($results) {
+ foreach ($results as $result) {
+ $result['path'] = $relativeMountPoint . $result['path'];
+ $files[] = $result;
+ }
}
}
}
diff --git a/lib/geo.php b/lib/private/geo.php
index 4eb785da355..ed01ad0b616 100644
--- a/lib/geo.php
+++ b/lib/private/geo.php
@@ -28,4 +28,4 @@ class OC_Geo{
reset($variances);
return current($variances);
}
-} \ No newline at end of file
+}
diff --git a/lib/group.php b/lib/private/group.php
index ba93dc129a1..444788c97f1 100644
--- a/lib/group.php
+++ b/lib/private/group.php
@@ -265,10 +265,10 @@ class OC_Group {
public static function displayNamesInGroup($gid, $search = '', $limit = -1, $offset = 0) {
$group = self::getManager()->get($gid);
if ($group) {
- $users = $group->searchDisplayName($search . $limit, $offset);
+ $users = $group->searchDisplayName($search, $limit, $offset);
$displayNames = array();
foreach ($users as $user) {
- $displayNames[] = $user->getDisplayName();
+ $displayNames[$user->getUID()] = $user->getDisplayName();
}
return $displayNames;
} else {
diff --git a/lib/group/backend.php b/lib/private/group/backend.php
index 2e17b5d0b7f..2e17b5d0b7f 100644
--- a/lib/group/backend.php
+++ b/lib/private/group/backend.php
diff --git a/lib/group/database.php b/lib/private/group/database.php
index d0974685ff6..d0974685ff6 100644
--- a/lib/group/database.php
+++ b/lib/private/group/database.php
diff --git a/lib/group/dummy.php b/lib/private/group/dummy.php
index 9516fd52ff8..9516fd52ff8 100644
--- a/lib/group/dummy.php
+++ b/lib/private/group/dummy.php
diff --git a/lib/group/example.php b/lib/private/group/example.php
index 3519b9ed92f..3519b9ed92f 100644
--- a/lib/group/example.php
+++ b/lib/private/group/example.php
diff --git a/lib/group/group.php b/lib/private/group/group.php
index a752c4311c1..bcd2419b309 100644
--- a/lib/group/group.php
+++ b/lib/private/group/group.php
@@ -62,7 +62,6 @@ class Group {
return $this->users;
}
- $users = array();
$userIds = array();
foreach ($this->backends as $backend) {
$diff = array_diff(
@@ -74,11 +73,8 @@ class Group {
}
}
- foreach ($userIds as $userId) {
- $users[] = $this->userManager->get($userId);
- }
- $this->users = $users;
- return $users;
+ $this->users = $this->getVerifiedUsers($userIds);
+ return $this->users;
}
/**
@@ -113,7 +109,7 @@ class Group {
if ($backend->implementsActions(OC_GROUP_BACKEND_ADD_TO_GROUP)) {
$backend->addToGroup($user->getUID(), $this->gid);
if ($this->users) {
- $this->users[] = $user;
+ $this->users[$user->getUID()] = $user;
}
if ($this->emitter) {
$this->emitter->emit('\OC\Group', 'postAddUser', array($this, $user));
@@ -172,9 +168,7 @@ class Group {
if (!is_null($offset)) {
$offset -= count($userIds);
}
- foreach ($userIds as $userId) {
- $users[$userId] = $this->userManager->get($userId);
- }
+ $users += $this->getVerifiedUsers($userIds);
if (!is_null($limit) and $limit <= 0) {
return array_values($users);
}
@@ -191,7 +185,6 @@ class Group {
* @return \OC\User\User[]
*/
public function searchDisplayName($search, $limit = null, $offset = null) {
- $users = array();
foreach ($this->backends as $backend) {
if ($backend->implementsActions(OC_GROUP_BACKEND_GET_DISPLAYNAME)) {
$userIds = array_keys($backend->displayNamesInGroup($this->gid, $search, $limit, $offset));
@@ -204,9 +197,7 @@ class Group {
if (!is_null($offset)) {
$offset -= count($userIds);
}
- foreach ($userIds as $userId) {
- $users[$userId] = $this->userManager->get($userId);
- }
+ $users = $this->getVerifiedUsers($userIds);
if (!is_null($limit) and $limit <= 0) {
return array_values($users);
}
@@ -235,4 +226,23 @@ class Group {
}
return $result;
}
+
+ /**
+ * @brief returns all the Users from an array that really exists
+ * @param $userIds an array containing user IDs
+ * @return an Array with the userId as Key and \OC\User\User as value
+ */
+ private function getVerifiedUsers($userIds) {
+ if(!is_array($userIds)) {
+ return array();
+ }
+ $users = array();
+ foreach ($userIds as $userId) {
+ $user = $this->userManager->get($userId);
+ if(!is_null($user)) {
+ $users[$userId] = $user;
+ }
+ }
+ return $users;
+ }
}
diff --git a/lib/group/interface.php b/lib/private/group/interface.php
index 4ef3663837f..4ef3663837f 100644
--- a/lib/group/interface.php
+++ b/lib/private/group/interface.php
diff --git a/lib/group/manager.php b/lib/private/group/manager.php
index bf469d51d12..bf469d51d12 100644
--- a/lib/group/manager.php
+++ b/lib/private/group/manager.php
diff --git a/lib/helper.php b/lib/private/helper.php
index ca508e1d933..c82d3bd4ef4 100644
--- a/lib/helper.php
+++ b/lib/private/helper.php
@@ -25,9 +25,10 @@
* Collection of useful functions
*/
class OC_Helper {
- private static $mimetypes=array();
- private static $tmpFiles=array();
+ private static $tmpFiles = array();
private static $mimetypeIcons = array();
+ private static $mimetypeDetector;
+ private static $templateManager;
/**
* @brief Creates an url using a defined route
@@ -39,9 +40,8 @@ class OC_Helper {
*
* Returns a url to the given app and file.
*/
- public static function linkToRoute( $route, $parameters = array() ) {
- $urlLinkTo = OC::getRouter()->generate($route, $parameters);
- return $urlLinkTo;
+ public static function linkToRoute($route, $parameters = array()) {
+ return OC::$server->getURLGenerator()->linkToRoute($route, $parameters);
}
/**
@@ -49,41 +49,22 @@ class OC_Helper {
* @param string $app app
* @param string $file file
* @param array $args array with param=>value, will be appended to the returned url
- * The value of $args will be urlencoded
+ * The value of $args will be urlencoded
* @return string the url
*
* Returns a url to the given app and file.
*/
public static function linkTo( $app, $file, $args = array() ) {
- if( $app != '' ) {
- $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') {
- $urlLinkTo = OC::$WEBROOT . '/index.php/apps/' . $app;
- $urlLinkTo .= ($file!='index.php') ? '/' . $file : '';
- }else{
- $urlLinkTo = OC_App::getAppWebPath($app) . '/' . $file;
- }
- }
- else{
- $urlLinkTo = OC::$WEBROOT . '/' . $app . '/' . $file;
- }
- }
- else{
- if( file_exists( OC::$SERVERROOT . '/core/'. $file )) {
- $urlLinkTo = OC::$WEBROOT . '/core/'.$file;
- }
- else{
- $urlLinkTo = OC::$WEBROOT . '/'.$file;
- }
- }
-
- if ($args && $query = http_build_query($args, '', '&')) {
- $urlLinkTo .= '?'.$query;
- }
+ return OC::$server->getURLGenerator()->linkTo($app, $file, $args);
+ }
- return $urlLinkTo;
+ /**
+ * @param $key
+ * @return string url to the online documentation
+ */
+ public static function linkToDocs($key) {
+ $theme = new OC_Defaults();
+ return $theme->getDocBaseUrl() . '/server/6.0/go.php?to=' . $key;
}
/**
@@ -91,13 +72,13 @@ class OC_Helper {
* @param string $app app
* @param string $file file
* @param array $args array with param=>value, will be appended to the returned url
- * The value of $args will be urlencoded
+ * The value of $args will be urlencoded
* @return string the url
*
* Returns a absolute url to the given app and file.
*/
- public static function linkToAbsolute( $app, $file, $args = array() ) {
- $urlLinkTo = self::linkTo( $app, $file, $args );
+ public static function linkToAbsolute($app, $file, $args = array()) {
+ $urlLinkTo = self::linkTo($app, $file, $args);
return self::makeURLAbsolute($urlLinkTo);
}
@@ -108,9 +89,8 @@ class OC_Helper {
*
* Returns a absolute url to the given app and file.
*/
- public static function makeURLAbsolute( $url )
- {
- return OC_Request::serverProtocol(). '://' . OC_Request::serverHost() . $url;
+ public static function makeURLAbsolute($url) {
+ return OC::$server->getURLGenerator()->getAbsoluteURL($url);
}
/**
@@ -120,8 +100,8 @@ class OC_Helper {
*
* Returns a url to the given service.
*/
- public static function linkToRemoteBase( $service ) {
- return self::linkTo( '', 'remote.php') . '/' . $service;
+ public static function linkToRemoteBase($service) {
+ return self::linkTo('', 'remote.php') . '/' . $service;
}
/**
@@ -132,9 +112,9 @@ class OC_Helper {
*
* Returns a absolute url to the given service.
*/
- public static function linkToRemote( $service, $add_slash = true ) {
+ public static function linkToRemote($service, $add_slash = true) {
return self::makeURLAbsolute(self::linkToRemoteBase($service))
- . (($add_slash && $service[strlen($service)-1]!='/')?'/':'');
+ . (($add_slash && $service[strlen($service) - 1] != '/') ? '/' : '');
}
/**
@@ -146,8 +126,8 @@ class OC_Helper {
* Returns a absolute url to the given service.
*/
public static function linkToPublic($service, $add_slash = false) {
- return self::linkToAbsolute( '', 'public.php') . '?service=' . $service
- . (($add_slash && $service[strlen($service)-1]!='/')?'/':'');
+ return self::linkToAbsolute('', 'public.php') . '?service=' . $service
+ . (($add_slash && $service[strlen($service) - 1] != '/') ? '/' : '');
}
/**
@@ -158,26 +138,8 @@ class OC_Helper {
*
* Returns the path to the image.
*/
- public static function imagePath( $app, $image ) {
- // Read the selected theme from the config file
- $theme = OC_Util::getTheme();
-
- // Check if the app is in the app folder
- if( file_exists( OC::$SERVERROOT."/themes/$theme/apps/$app/img/$image" )) {
- return OC::$WEBROOT."/themes/$theme/apps/$app/img/$image";
- }elseif( file_exists(OC_App::getAppPath($app)."/img/$image" )) {
- return OC_App::getAppWebPath($app)."/img/$image";
- }elseif( !empty( $app ) and file_exists( OC::$SERVERROOT."/themes/$theme/$app/img/$image" )) {
- return OC::$WEBROOT."/themes/$theme/$app/img/$image";
- }elseif( !empty( $app ) and file_exists( OC::$SERVERROOT."/$app/img/$image" )) {
- return OC::$WEBROOT."/$app/img/$image";
- }elseif( file_exists( OC::$SERVERROOT."/themes/$theme/core/img/$image" )) {
- return OC::$WEBROOT."/themes/$theme/core/img/$image";
- }elseif( file_exists( OC::$SERVERROOT."/core/img/$image" )) {
- return OC::$WEBROOT."/core/img/$image";
- }else{
- throw new RuntimeException('image not found: image:'.$image.' webroot:'.OC::$WEBROOT.' serverroot:'.OC::$SERVERROOT);
- }
+ public static function imagePath($app, $image) {
+ return OC::$server->getURLGenerator()->imagePath($app, $image);
}
/**
@@ -188,7 +150,38 @@ class OC_Helper {
* Returns the path to the image of this file type.
*/
public static function mimetypeIcon($mimetype) {
- $alias = array('application/xml' => 'code/xml');
+ $alias = array(
+ 'application/xml' => 'code/xml',
+ 'application/msword' => 'x-office/document',
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'x-office/document',
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => 'x-office/document',
+ 'application/vnd.ms-word.document.macroEnabled.12' => 'x-office/document',
+ 'application/vnd.ms-word.template.macroEnabled.12' => 'x-office/document',
+ 'application/vnd.oasis.opendocument.text' => 'x-office/document',
+ 'application/vnd.oasis.opendocument.text-template' => 'x-office/document',
+ 'application/vnd.oasis.opendocument.text-web' => 'x-office/document',
+ 'application/vnd.oasis.opendocument.text-master' => 'x-office/document',
+ 'application/vnd.ms-powerpoint' => 'x-office/presentation',
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'x-office/presentation',
+ 'application/vnd.openxmlformats-officedocument.presentationml.template' => 'x-office/presentation',
+ 'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => 'x-office/presentation',
+ 'application/vnd.ms-powerpoint.addin.macroEnabled.12' => 'x-office/presentation',
+ 'application/vnd.ms-powerpoint.presentation.macroEnabled.12' => 'x-office/presentation',
+ 'application/vnd.ms-powerpoint.template.macroEnabled.12' => 'x-office/presentation',
+ 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12' => 'x-office/presentation',
+ 'application/vnd.oasis.opendocument.presentation' => 'x-office/presentation',
+ 'application/vnd.oasis.opendocument.presentation-template' => 'x-office/presentation',
+ 'application/vnd.ms-excel' => 'x-office/spreadsheet',
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'x-office/spreadsheet',
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => 'x-office/spreadsheet',
+ 'application/vnd.ms-excel.sheet.macroEnabled.12' => 'x-office/spreadsheet',
+ 'application/vnd.ms-excel.template.macroEnabled.12' => 'x-office/spreadsheet',
+ 'application/vnd.ms-excel.addin.macroEnabled.12' => 'x-office/spreadsheet',
+ 'application/vnd.ms-excel.sheet.binary.macroEnabled.12' => 'x-office/spreadsheet',
+ 'application/vnd.oasis.opendocument.spreadsheet' => 'x-office/spreadsheet',
+ 'application/vnd.oasis.opendocument.spreadsheet-template' => 'x-office/spreadsheet',
+ );
+
if (isset($alias[$mimetype])) {
$mimetype = $alias[$mimetype];
}
@@ -197,58 +190,87 @@ class OC_Helper {
}
// Replace slash and backslash with a minus
$icon = str_replace('/', '-', $mimetype);
- $icon = str_replace( '\\', '-', $icon);
+ $icon = str_replace('\\', '-', $icon);
// Is it a dir?
if ($mimetype === 'dir') {
- self::$mimetypeIcons[$mimetype] = OC::$WEBROOT.'/core/img/filetypes/folder.png';
- return OC::$WEBROOT.'/core/img/filetypes/folder.png';
+ self::$mimetypeIcons[$mimetype] = OC::$WEBROOT . '/core/img/filetypes/folder.png';
+ return OC::$WEBROOT . '/core/img/filetypes/folder.png';
+ }
+ if ($mimetype === 'dir-shared') {
+ self::$mimetypeIcons[$mimetype] = OC::$WEBROOT . '/core/img/filetypes/folder-shared.png';
+ return OC::$WEBROOT . '/core/img/filetypes/folder-shared.png';
+ }
+ if ($mimetype === 'dir-external') {
+ self::$mimetypeIcons[$mimetype] = OC::$WEBROOT . '/core/img/filetypes/folder-external.png';
+ return OC::$WEBROOT . '/core/img/filetypes/folder-external.png';
}
// Icon exists?
- if (file_exists(OC::$SERVERROOT.'/core/img/filetypes/'.$icon.'.png')) {
- self::$mimetypeIcons[$mimetype] = OC::$WEBROOT.'/core/img/filetypes/'.$icon.'.png';
- return OC::$WEBROOT.'/core/img/filetypes/'.$icon.'.png';
+ if (file_exists(OC::$SERVERROOT . '/core/img/filetypes/' . $icon . '.png')) {
+ self::$mimetypeIcons[$mimetype] = OC::$WEBROOT . '/core/img/filetypes/' . $icon . '.png';
+ return OC::$WEBROOT . '/core/img/filetypes/' . $icon . '.png';
}
// Try only the first part of the filetype
$mimePart = substr($icon, 0, strpos($icon, '-'));
- if (file_exists(OC::$SERVERROOT.'/core/img/filetypes/'.$mimePart.'.png')) {
- self::$mimetypeIcons[$mimetype] = OC::$WEBROOT.'/core/img/filetypes/'.$mimePart.'.png';
- return OC::$WEBROOT.'/core/img/filetypes/'.$mimePart.'.png';
+ if (file_exists(OC::$SERVERROOT . '/core/img/filetypes/' . $mimePart . '.png')) {
+ self::$mimetypeIcons[$mimetype] = OC::$WEBROOT . '/core/img/filetypes/' . $mimePart . '.png';
+ return OC::$WEBROOT . '/core/img/filetypes/' . $mimePart . '.png';
} else {
- self::$mimetypeIcons[$mimetype] = OC::$WEBROOT.'/core/img/filetypes/file.png';
- return OC::$WEBROOT.'/core/img/filetypes/file.png';
+ self::$mimetypeIcons[$mimetype] = OC::$WEBROOT . '/core/img/filetypes/file.png';
+ return OC::$WEBROOT . '/core/img/filetypes/file.png';
}
}
/**
+ * @brief get path to preview of file
+ * @param string $path path
+ * @return string the url
+ *
+ * Returns the path to the preview of the file.
+ */
+ public static function previewIcon($path) {
+ return self::linkToRoute( 'core_ajax_preview', array('x' => 36, 'y' => 36, 'file' => $path ));
+ }
+
+ public static function publicPreviewIcon( $path, $token ) {
+ return self::linkToRoute( 'core_ajax_public_preview', array('x' => 36, 'y' => 36, 'file' => $path, 't' => $token));
+ }
+
+ /**
* @brief Make a human file size
* @param int $bytes file size in bytes
* @return string a human readable file size
*
* Makes 2048 to 2 kB.
*/
- public static function humanFileSize( $bytes ) {
- if( $bytes < 0 ) {
- $l = OC_L10N::get('lib');
- return $l->t("couldn't be determined");
+ public static function humanFileSize($bytes) {
+ if ($bytes < 0) {
+ return "?";
}
- if( $bytes < 1024 ) {
+ if ($bytes < 1024) {
return "$bytes B";
}
- $bytes = round( $bytes / 1024, 1 );
- if( $bytes < 1024 ) {
+ $bytes = round($bytes / 1024, 1);
+ if ($bytes < 1024) {
return "$bytes kB";
}
- $bytes = round( $bytes / 1024, 1 );
- if( $bytes < 1024 ) {
+ $bytes = round($bytes / 1024, 1);
+ if ($bytes < 1024) {
return "$bytes MB";
}
+ $bytes = round($bytes / 1024, 1);
+ if ($bytes < 1024) {
+ return "$bytes GB";
+ }
+ $bytes = round($bytes / 1024, 1);
+ if ($bytes < 1024) {
+ return "$bytes TB";
+ }
- // Wow, heavy duty for owncloud
- $bytes = round( $bytes / 1024, 1 );
- return "$bytes GB";
+ $bytes = round($bytes / 1024, 1);
+ return "$bytes PB";
}
/**
@@ -260,21 +282,21 @@ class OC_Helper {
*
* Inspired by: http://www.php.net/manual/en/function.filesize.php#92418
*/
- public static function computerFileSize( $str ) {
- $str=strtolower($str);
+ public static function computerFileSize($str) {
+ $str = strtolower($str);
$bytes_array = array(
'b' => 1,
'k' => 1024,
'kb' => 1024,
'mb' => 1024 * 1024,
- 'm' => 1024 * 1024,
+ 'm' => 1024 * 1024,
'gb' => 1024 * 1024 * 1024,
- 'g' => 1024 * 1024 * 1024,
+ 'g' => 1024 * 1024 * 1024,
'tb' => 1024 * 1024 * 1024 * 1024,
- 't' => 1024 * 1024 * 1024 * 1024,
+ 't' => 1024 * 1024 * 1024 * 1024,
'pb' => 1024 * 1024 * 1024 * 1024 * 1024,
- 'p' => 1024 * 1024 * 1024 * 1024 * 1024,
+ 'p' => 1024 * 1024 * 1024 * 1024 * 1024,
);
$bytes = floatval($str);
@@ -298,19 +320,20 @@ class OC_Helper {
if (!is_dir($path))
return chmod($path, $filemode);
$dh = opendir($path);
- while (($file = readdir($dh)) !== false) {
- if($file != '.' && $file != '..') {
- $fullpath = $path.'/'.$file;
- if(is_link($fullpath))
- return false;
- elseif(!is_dir($fullpath) && !@chmod($fullpath, $filemode))
+ if(is_resource($dh)) {
+ while (($file = readdir($dh)) !== false) {
+ if ($file != '.' && $file != '..') {
+ $fullpath = $path . '/' . $file;
+ if (is_link($fullpath))
+ return false;
+ elseif (!is_dir($fullpath) && !@chmod($fullpath, $filemode))
+ return false; elseif (!self::chmodr($fullpath, $filemode))
return false;
- elseif(!self::chmodr($fullpath, $filemode))
- return false;
+ }
}
+ closedir($dh);
}
- closedir($dh);
- if(@chmod($path, $filemode))
+ if (@chmod($path, $filemode))
return true;
else
return false;
@@ -323,8 +346,8 @@ class OC_Helper {
*
*/
static function copyr($src, $dest) {
- if(is_dir($src)) {
- if(!is_dir($dest)) {
+ if (is_dir($src)) {
+ if (!is_dir($dest)) {
mkdir($dest);
}
$files = scandir($src);
@@ -333,7 +356,7 @@ class OC_Helper {
self::copyr("$src/$file", "$dest/$file");
}
}
- }elseif(file_exists($src) && !\OC\Files\Filesystem::isFileBlacklisted($src)) {
+ } elseif (file_exists($src) && !\OC\Files\Filesystem::isFileBlacklisted($src)) {
copy($src, $dest);
}
}
@@ -344,105 +367,74 @@ class OC_Helper {
* @return bool
*/
static function rmdirr($dir) {
- if(is_dir($dir)) {
- $files=scandir($dir);
- foreach($files as $file) {
+ if (is_dir($dir)) {
+ $files = scandir($dir);
+ foreach ($files as $file) {
if ($file != "." && $file != "..") {
self::rmdirr("$dir/$file");
}
}
rmdir($dir);
- }elseif(file_exists($dir)) {
+ } elseif (file_exists($dir)) {
unlink($dir);
}
- if(file_exists($dir)) {
+ if (file_exists($dir)) {
return false;
- }else{
+ } else {
return true;
}
}
/**
+ * @return \OC\Files\Type\Detection
+ */
+ static public function getMimetypeDetector() {
+ if (!self::$mimetypeDetector) {
+ self::$mimetypeDetector = new \OC\Files\Type\Detection();
+ self::$mimetypeDetector->registerTypeArray(include 'mimetypes.list.php');
+ }
+ return self::$mimetypeDetector;
+ }
+
+ /**
+ * @return \OC\Files\Type\TemplateManager
+ */
+ static public function getFileTemplateManager() {
+ if (!self::$templateManager) {
+ self::$templateManager = new \OC\Files\Type\TemplateManager();
+ }
+ return self::$templateManager;
+ }
+
+ /**
* Try to guess the mimetype based on filename
*
* @param string $path
* @return string
*/
- static public function getFileNameMimeType($path){
- if(strpos($path, '.')) {
- //try to guess the type by the file extension
- if(!self::$mimetypes || self::$mimetypes != include 'mimetypes.list.php') {
- self::$mimetypes=include 'mimetypes.list.php';
- }
- $extension=strtolower(strrchr(basename($path), "."));
- $extension=substr($extension, 1);//remove leading .
- return (isset(self::$mimetypes[$extension]))?self::$mimetypes[$extension]:'application/octet-stream';
- }else{
- return 'application/octet-stream';
- }
+ static public function getFileNameMimeType($path) {
+ return self::getMimetypeDetector()->detectPath($path);
}
/**
* get the mimetype form a local file
+ *
* @param string $path
* @return string
* does NOT work for ownClouds filesystem, use OC_FileSystem::getMimeType instead
*/
static function getMimeType($path) {
- $isWrapped=(strpos($path, '://')!==false) and (substr($path, 0, 7)=='file://');
-
- if (@is_dir($path)) {
- // directories are easy
- return "httpd/unix-directory";
- }
-
- $mimeType = self::getFileNameMimeType($path);
-
- if($mimeType=='application/octet-stream' and function_exists('finfo_open')
- and function_exists('finfo_file') and $finfo=finfo_open(FILEINFO_MIME)) {
- $info = @strtolower(finfo_file($finfo, $path));
- if($info) {
- $mimeType=substr($info, 0, strpos($info, ';'));
- }
- finfo_close($finfo);
- }
- if (!$isWrapped and $mimeType=='application/octet-stream' && function_exists("mime_content_type")) {
- // use mime magic extension if available
- $mimeType = mime_content_type($path);
- }
- if (!$isWrapped and $mimeType=='application/octet-stream' && OC_Helper::canExecute("file")) {
- // it looks like we have a 'file' command,
- // lets see if it does have mime support
- $path=escapeshellarg($path);
- $fp = popen("file -b --mime-type $path 2>/dev/null", "r");
- $reply = fgets($fp);
- pclose($fp);
-
- //trim the newline
- $mimeType = trim($reply);
-
- }
- return $mimeType;
+ return self::getMimetypeDetector()->detect($path);
}
/**
* get the mimetype form a data string
+ *
* @param string $data
* @return string
*/
static function getStringMimeType($data) {
- if(function_exists('finfo_open') and function_exists('finfo_file')) {
- $finfo=finfo_open(FILEINFO_MIME);
- return finfo_buffer($finfo, $data);
- }else{
- $tmpFile=OC_Helper::tmpFile();
- $fh=fopen($tmpFile, 'wb');
- fwrite($fh, $data, 8024);
- fclose($fh);
- $mime=self::getMimeType($tmpFile);
- unset($tmpFile);
- return $mime;
- }
+ return self::getMimetypeDetector()->detectString($data);
}
/**
@@ -454,9 +446,9 @@ class OC_Helper {
*/
//FIXME: should also check for value validation (i.e. the email is an email).
- public static function init_var($s, $d="") {
+ public static function init_var($s, $d = "") {
$r = $d;
- if(isset($_REQUEST[$s]) && !empty($_REQUEST[$s])) {
+ if (isset($_REQUEST[$s]) && !empty($_REQUEST[$s])) {
$r = OC_Util::sanitizeHTML($_REQUEST[$s]);
}
@@ -466,12 +458,13 @@ class OC_Helper {
/**
* returns "checked"-attribute if request contains selected radio element
* OR if radio element is the default one -- maybe?
+ *
* @param string $s Name of radio-button element name
* @param string $v Value of current radio-button element
* @param string $d Value of default radio-button element
*/
public static function init_radio($s, $v, $d) {
- if((isset($_REQUEST[$s]) && $_REQUEST[$s]==$v) || (!isset($_REQUEST[$s]) && $v == $d))
+ if ((isset($_REQUEST[$s]) && $_REQUEST[$s] == $v) || (!isset($_REQUEST[$s]) && $v == $d))
print "checked=\"checked\" ";
}
@@ -503,17 +496,17 @@ class OC_Helper {
$dirs = explode(PATH_SEPARATOR, $path);
// WARNING : We have to check if open_basedir is enabled :
$obd = ini_get('open_basedir');
- if($obd != "none") {
+ if ($obd != "none") {
$obd_values = explode(PATH_SEPARATOR, $obd);
- if(count($obd_values) > 0 and $obd_values[0]) {
+ if (count($obd_values) > 0 and $obd_values[0]) {
// open_basedir is in effect !
// We need to check if the program is in one of these dirs :
$dirs = $obd_values;
}
}
- foreach($dirs as $dir) {
- foreach($exts as $ext) {
- if($check_fn("$dir/$name".$ext))
+ foreach ($dirs as $dir) {
+ foreach ($exts as $ext) {
+ if ($check_fn("$dir/$name" . $ext))
return true;
}
}
@@ -522,18 +515,19 @@ class OC_Helper {
/**
* copy the contents of one stream to another
+ *
* @param resource $source
* @param resource $target
- * @return int the number of bytes copied
+ * @return array the number of bytes copied and result
*/
public static function streamCopy($source, $target) {
- if(!$source or !$target) {
- return false;
+ if (!$source or !$target) {
+ return array(0, false);
}
$result = true;
$count = 0;
- while(!feof($source)) {
- if ( ( $c = fwrite($target, fread($source, 8192)) ) === false) {
+ while (!feof($source)) {
+ if (($c = fwrite($target, fread($source, 8192))) === false) {
$result = false;
} else {
$count += $c;
@@ -544,37 +538,39 @@ class OC_Helper {
/**
* create a temporary file with an unique filename
+ *
* @param string $postfix
* @return string
*
* temporary files are automatically cleaned up after the script is finished
*/
- public static function tmpFile($postfix='') {
- $file=get_temp_dir().'/'.md5(time().rand()).$postfix;
- $fh=fopen($file, 'w');
+ public static function tmpFile($postfix = '') {
+ $file = get_temp_dir() . '/' . md5(time() . rand()) . $postfix;
+ $fh = fopen($file, 'w');
fclose($fh);
- self::$tmpFiles[]=$file;
+ self::$tmpFiles[] = $file;
return $file;
}
/**
* move a file to oc-noclean temp dir
+ *
* @param string $filename
* @return mixed
*
*/
- public static function moveToNoClean($filename='') {
+ public static function moveToNoClean($filename = '') {
if ($filename == '') {
return false;
}
- $tmpDirNoClean=get_temp_dir().'/oc-noclean/';
+ $tmpDirNoClean = get_temp_dir() . '/oc-noclean/';
if (!file_exists($tmpDirNoClean) || !is_dir($tmpDirNoClean)) {
if (file_exists($tmpDirNoClean)) {
unlink($tmpDirNoClean);
}
mkdir($tmpDirNoClean);
}
- $newname=$tmpDirNoClean.basename($filename);
+ $newname = $tmpDirNoClean . basename($filename);
if (rename($filename, $newname)) {
return $newname;
} else {
@@ -584,34 +580,35 @@ class OC_Helper {
/**
* create a temporary folder with an unique filename
+ *
* @return string
*
* temporary files are automatically cleaned up after the script is finished
*/
public static function tmpFolder() {
- $path=get_temp_dir().'/'.md5(time().rand());
+ $path = get_temp_dir() . '/' . md5(time() . rand());
mkdir($path);
- self::$tmpFiles[]=$path;
- return $path.'/';
+ self::$tmpFiles[] = $path;
+ return $path . '/';
}
/**
* remove all files created by self::tmpFile
*/
public static function cleanTmp() {
- $leftoversFile=get_temp_dir().'/oc-not-deleted';
- if(file_exists($leftoversFile)) {
- $leftovers=file($leftoversFile);
- foreach($leftovers as $file) {
+ $leftoversFile = get_temp_dir() . '/oc-not-deleted';
+ if (file_exists($leftoversFile)) {
+ $leftovers = file($leftoversFile);
+ foreach ($leftovers as $file) {
self::rmdirr($file);
}
unlink($leftoversFile);
}
- foreach(self::$tmpFiles as $file) {
- if(file_exists($file)) {
- if(!self::rmdirr($file)) {
- file_put_contents($leftoversFile, $file."\n", FILE_APPEND);
+ foreach (self::$tmpFiles as $file) {
+ if (file_exists($file)) {
+ if (!self::rmdirr($file)) {
+ file_put_contents($leftoversFile, $file . "\n", FILE_APPEND);
}
}
}
@@ -621,34 +618,53 @@ class OC_Helper {
* remove all files in PHP /oc-noclean temp dir
*/
public static function cleanTmpNoClean() {
- $tmpDirNoCleanFile=get_temp_dir().'/oc-noclean/';
- if(file_exists($tmpDirNoCleanFile)) {
- self::rmdirr($tmpDirNoCleanFile);
+ $tmpDirNoCleanName=get_temp_dir() . '/oc-noclean/';
+ if(file_exists($tmpDirNoCleanName) && is_dir($tmpDirNoCleanName)) {
+ $files=scandir($tmpDirNoCleanName);
+ foreach($files as $file) {
+ $fileName = $tmpDirNoCleanName . $file;
+ if (!\OC\Files\Filesystem::isIgnoredDir($file) && filemtime($fileName) + 600 < time()) {
+ unlink($fileName);
+ }
+ }
+ // if oc-noclean is empty delete it
+ $isTmpDirNoCleanEmpty = true;
+ $tmpDirNoClean = opendir($tmpDirNoCleanName);
+ if(is_resource($tmpDirNoClean)) {
+ while (false !== ($file = readdir($tmpDirNoClean))) {
+ if (!\OC\Files\Filesystem::isIgnoredDir($file)) {
+ $isTmpDirNoCleanEmpty = false;
+ }
+ }
+ }
+ if ($isTmpDirNoCleanEmpty) {
+ rmdir($tmpDirNoCleanName);
+ }
}
}
/**
- * Adds a suffix to the name in case the file exists
- *
- * @param $path
- * @param $filename
- * @return string
- */
+ * Adds a suffix to the name in case the file exists
+ *
+ * @param $path
+ * @param $filename
+ * @return string
+ */
public static function buildNotExistingFileName($path, $filename) {
$view = \OC\Files\Filesystem::getView();
return self::buildNotExistingFileNameForView($path, $filename, $view);
}
/**
- * Adds a suffix to the name in case the file exists
- *
- * @param $path
- * @param $filename
- * @return string
- */
+ * Adds a suffix to the name in case the file exists
+ *
+ * @param $path
+ * @param $filename
+ * @return string
+ */
public static function buildNotExistingFileNameForView($path, $filename, \OC\Files\View $view) {
- if($path==='/') {
- $path='';
+ if ($path === '/') {
+ $path = '';
}
if ($pos = strrpos($filename, '.')) {
$name = substr($filename, 0, $pos);
@@ -660,10 +676,10 @@ class OC_Helper {
$newpath = $path . '/' . $filename;
if ($view->file_exists($newpath)) {
- if(preg_match_all('/\((\d+)\)/', $name, $matches, PREG_OFFSET_CAPTURE)) {
- //Replace the last "(number)" with "(number+1)"
- $last_match = count($matches[0])-1;
- $counter = $matches[1][$last_match][0]+1;
+ if (preg_match_all('/\((\d+)\)/', $name, $matches, PREG_OFFSET_CAPTURE)) {
+ //Replace the last "(number)" with "(number+1)"
+ $last_match = count($matches[0]) - 1;
+ $counter = $matches[1][$last_match][0] + 1;
$offset = $matches[0][$last_match][1];
$match_length = strlen($matches[0][$last_match][0]);
} else {
@@ -671,9 +687,9 @@ class OC_Helper {
$offset = false;
}
do {
- if($offset) {
- //Replace the last "(number)" with "(number+1)"
- $newname = substr_replace($name, '('.$counter.')', $offset, $match_length);
+ if ($offset) {
+ //Replace the last "(number)" with "(number+1)"
+ $newname = substr_replace($name, '(' . $counter . ')', $offset, $match_length);
} else {
$newname = $name . ' (' . $counter . ')';
}
@@ -700,17 +716,17 @@ class OC_Helper {
}
/**
- * @brief Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is.
- *
- * @param array $input The array to work on
- * @param int $case Either MB_CASE_UPPER or MB_CASE_LOWER (default)
- * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
- * @return array
- *
- * Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is.
- * based on http://www.php.net/manual/en/function.array-change-key-case.php#107715
- *
- */
+ * @brief Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is.
+ *
+ * @param array $input The array to work on
+ * @param int $case Either MB_CASE_UPPER or MB_CASE_LOWER (default)
+ * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
+ * @return array
+ *
+ * Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is.
+ * based on http://www.php.net/manual/en/function.array-change-key-case.php#107715
+ *
+ */
public static function mb_array_change_key_case($input, $case = MB_CASE_LOWER, $encoding = 'UTF-8') {
$case = ($case != MB_CASE_UPPER) ? MB_CASE_LOWER : MB_CASE_UPPER;
$ret = array();
@@ -736,26 +752,26 @@ class OC_Helper {
$length = intval($length);
$string = mb_substr($string, 0, $start, $encoding) .
$replacement .
- mb_substr($string, $start+$length, mb_strlen($string, 'UTF-8')-$start, $encoding);
+ mb_substr($string, $start + $length, mb_strlen($string, 'UTF-8') - $start, $encoding);
return $string;
}
/**
- * @brief Replace all occurrences of the search string with the replacement string
- *
- * @param string $search The value being searched for, otherwise known as the needle.
- * @param string $replace The replacement
- * @param string $subject The string or array being searched and replaced on, otherwise known as the haystack.
- * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
- * @param int $count If passed, this will be set to the number of replacements performed.
- * @return string
- *
- */
+ * @brief Replace all occurrences of the search string with the replacement string
+ *
+ * @param string $search The value being searched for, otherwise known as the needle.
+ * @param string $replace The replacement
+ * @param string $subject The string or array being searched and replaced on, otherwise known as the haystack.
+ * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
+ * @param int $count If passed, this will be set to the number of replacements performed.
+ * @return string
+ *
+ */
public static function mb_str_replace($search, $replace, $subject, $encoding = 'UTF-8', &$count = null) {
$offset = -1;
$length = mb_strlen($search, $encoding);
- while(($i = mb_strrpos($subject, $search, $offset, $encoding)) !== false ) {
+ while (($i = mb_strrpos($subject, $search, $offset, $encoding)) !== false) {
$subject = OC_Helper::mb_substr_replace($subject, $replace, $i, $length);
$offset = $i - mb_strlen($subject, $encoding);
$count++;
@@ -764,21 +780,21 @@ class OC_Helper {
}
/**
- * @brief performs a search in a nested array
- * @param array $haystack the array to be searched
- * @param string $needle the search string
- * @param string $index optional, only search this key name
- * @return mixed the key of the matching field, otherwise false
- *
- * performs a search in a nested array
- *
- * taken from http://www.php.net/manual/en/function.array-search.php#97645
- */
+ * @brief performs a search in a nested array
+ * @param array $haystack the array to be searched
+ * @param string $needle the search string
+ * @param string $index optional, only search this key name
+ * @return mixed the key of the matching field, otherwise false
+ *
+ * performs a search in a nested array
+ *
+ * taken from http://www.php.net/manual/en/function.array-search.php#97645
+ */
public static function recursiveArraySearch($haystack, $needle, $index = null) {
$aIt = new RecursiveArrayIterator($haystack);
$it = new RecursiveIteratorIterator($aIt);
- while($it->valid()) {
+ while ($it->valid()) {
if (((isset($index) AND ($it->key() == $index)) OR (!isset($index))) AND ($it->current() == $needle)) {
return $aIt->key();
}
@@ -792,6 +808,7 @@ class OC_Helper {
/**
* Shortens str to maxlen by replacing characters in the middle with '...', eg.
* ellipsis('a very long string with lots of useless info to make a better example', 14) becomes 'a very ...example'
+ *
* @param string $str the string
* @param string $maxlen the maximum length of the result
* @return string with at most maxlen characters
@@ -815,14 +832,14 @@ class OC_Helper {
$post_max_size = OCP\Util::computerFileSize(ini_get('post_max_size'));
$freeSpace = \OC\Files\Filesystem::free_space($dir);
if ((int)$upload_max_filesize === 0 and (int)$post_max_size === 0) {
- $maxUploadFilesize = \OC\Files\FREE_SPACE_UNLIMITED;
+ $maxUploadFilesize = \OC\Files\SPACE_UNLIMITED;
} elseif ((int)$upload_max_filesize === 0 or (int)$post_max_size === 0) {
$maxUploadFilesize = max($upload_max_filesize, $post_max_size); //only the non 0 value counts
} else {
$maxUploadFilesize = min($upload_max_filesize, $post_max_size);
}
- if($freeSpace !== \OC\Files\FREE_SPACE_UNKNOWN){
+ if ($freeSpace !== \OC\Files\SPACE_UNKNOWN) {
$freeSpace = max($freeSpace, 0);
return min($maxUploadFilesize, $freeSpace);
@@ -833,6 +850,7 @@ class OC_Helper {
/**
* Checks if a function is available
+ *
* @param string $function_name
* @return bool
*/
@@ -852,24 +870,26 @@ class OC_Helper {
}
/**
- * Calculate the disc space
+ * Calculate the disc space for the given path
+ *
+ * @param string $path
+ * @return array
*/
- public static function getStorageInfo() {
- $rootInfo = \OC\Files\Filesystem::getFileInfo('/');
+ public static function getStorageInfo($path) {
+ // return storage info without adding mount points
+ $rootInfo = \OC\Files\Filesystem::getFileInfo($path, false);
$used = $rootInfo['size'];
if ($used < 0) {
$used = 0;
}
- $free = \OC\Files\Filesystem::free_space();
- if ($free >= 0){
+ $free = \OC\Files\Filesystem::free_space($path);
+ if ($free >= 0) {
$total = $free + $used;
} else {
$total = $free; //either unknown or unlimited
}
- if ($total == 0) {
- $total = 1; // prevent division by zero
- }
- if ($total >= 0){
+ if ($total > 0) {
+ // prevent division by zero or error codes (negative values)
$relative = round(($used / $total) * 10000) / 100;
} else {
$relative = 0;
diff --git a/lib/hintexception.php b/lib/private/hintexception.php
index 3934ae2a4c2..3934ae2a4c2 100644
--- a/lib/hintexception.php
+++ b/lib/private/hintexception.php
diff --git a/lib/hook.php b/lib/private/hook.php
index 8516cf0dcff..8516cf0dcff 100644
--- a/lib/hook.php
+++ b/lib/private/hook.php
diff --git a/lib/hooks/basicemitter.php b/lib/private/hooks/basicemitter.php
index 9ffe1af2314..9ffe1af2314 100644
--- a/lib/hooks/basicemitter.php
+++ b/lib/private/hooks/basicemitter.php
diff --git a/lib/hooks/emitter.php b/lib/private/hooks/emitter.php
index 8e9074bad67..8e9074bad67 100644
--- a/lib/hooks/emitter.php
+++ b/lib/private/hooks/emitter.php
diff --git a/lib/hooks/forwardingemitter.php b/lib/private/hooks/forwardingemitter.php
index 1aacc4012e0..1aacc4012e0 100644
--- a/lib/hooks/forwardingemitter.php
+++ b/lib/private/hooks/forwardingemitter.php
diff --git a/lib/hooks/legacyemitter.php b/lib/private/hooks/legacyemitter.php
index a2d16ace9a7..a2d16ace9a7 100644
--- a/lib/hooks/legacyemitter.php
+++ b/lib/private/hooks/legacyemitter.php
diff --git a/lib/hooks/publicemitter.php b/lib/private/hooks/publicemitter.php
index e2371713ac3..e2371713ac3 100644
--- a/lib/hooks/publicemitter.php
+++ b/lib/private/hooks/publicemitter.php
diff --git a/lib/image.php b/lib/private/image.php
index 4bc38e20e56..7761a3c7737 100644
--- a/lib/image.php
+++ b/lib/private/image.php
@@ -25,24 +25,27 @@
*/
class OC_Image {
protected $resource = false; // tmp resource.
- protected $imagetype = IMAGETYPE_PNG; // Default to png if file type isn't evident.
- protected $bit_depth = 24;
- protected $filepath = null;
+ protected $imageType = IMAGETYPE_PNG; // Default to png if file type isn't evident.
+ protected $mimeType = "image/png"; // Default to png
+ protected $bitDepth = 24;
+ protected $filePath = null;
+
+ private $fileInfo;
/**
* @brief Get mime type for an image file.
* @param $filepath The path to a local image file.
* @returns string The mime type if the it could be determined, otherwise an empty string.
*/
- static public function getMimeTypeForFile($filepath) {
+ static public function getMimeTypeForFile($filePath) {
// exif_imagetype throws "read error!" if file is less than 12 byte
- if (filesize($filepath) > 11) {
- $imagetype = exif_imagetype($filepath);
+ if (filesize($filePath) > 11) {
+ $imageType = exif_imagetype($filePath);
}
else {
- $imagetype = false;
+ $imageType = false;
}
- return $imagetype ? image_type_to_mime_type($imagetype) : '';
+ return $imageType ? image_type_to_mime_type($imageType) : '';
}
/**
@@ -50,14 +53,19 @@ class OC_Image {
* @param $imageref The path to a local file, a base64 encoded string or a resource created by an imagecreate* function.
* @returns bool False on error
*/
- public function __construct($imageref = null) {
+ public function __construct($imageRef = null) {
//OC_Log::write('core',__METHOD__.'(): start', OC_Log::DEBUG);
if(!extension_loaded('gd') || !function_exists('gd_info')) {
OC_Log::write('core', __METHOD__.'(): GD module not installed', OC_Log::ERROR);
return false;
}
- if(!is_null($imageref)) {
- $this->load($imageref);
+
+ if (\OC_Util::fileInfoLoaded()) {
+ $this->fileInfo = new finfo(FILEINFO_MIME_TYPE);
+ }
+
+ if(!is_null($imageRef)) {
+ $this->load($imageRef);
}
}
@@ -74,7 +82,7 @@ class OC_Image {
* @returns int
*/
public function mimeType() {
- return $this->valid() ? image_type_to_mime_type($this->imagetype) : '';
+ return $this->valid() ? $this->mimeType : '';
}
/**
@@ -157,30 +165,30 @@ class OC_Image {
* @returns bool
*/
- public function save($filepath=null) {
- if($filepath === null && $this->filepath === null) {
+ public function save($filePath=null) {
+ if($filePath === null && $this->filePath === null) {
OC_Log::write('core', __METHOD__.'(): called with no path.', OC_Log::ERROR);
return false;
- } elseif($filepath === null && $this->filepath !== null) {
- $filepath = $this->filepath;
+ } elseif($filePath === null && $this->filePath !== null) {
+ $filePath = $this->filePath;
}
- return $this->_output($filepath);
+ return $this->_output($filePath);
}
/**
* @brief Outputs/saves the image.
*/
- private function _output($filepath=null) {
- if($filepath) {
- if (!file_exists(dirname($filepath)))
- mkdir(dirname($filepath), 0777, true);
- if(!is_writable(dirname($filepath))) {
+ private function _output($filePath=null) {
+ if($filePath) {
+ if (!file_exists(dirname($filePath)))
+ mkdir(dirname($filePath), 0777, true);
+ if(!is_writable(dirname($filePath))) {
OC_Log::write('core',
- __METHOD__.'(): Directory \''.dirname($filepath).'\' is not writable.',
+ __METHOD__.'(): Directory \''.dirname($filePath).'\' is not writable.',
OC_Log::ERROR);
return false;
- } elseif(is_writable(dirname($filepath)) && file_exists($filepath) && !is_writable($filepath)) {
- OC_Log::write('core', __METHOD__.'(): File \''.$filepath.'\' is not writable.', OC_Log::ERROR);
+ } elseif(is_writable(dirname($filePath)) && file_exists($filePath) && !is_writable($filePath)) {
+ OC_Log::write('core', __METHOD__.'(): File \''.$filePath.'\' is not writable.', OC_Log::ERROR);
return false;
}
}
@@ -188,30 +196,30 @@ class OC_Image {
return false;
}
- $retval = false;
- switch($this->imagetype) {
+ $retVal = false;
+ switch($this->imageType) {
case IMAGETYPE_GIF:
- $retval = imagegif($this->resource, $filepath);
+ $retVal = imagegif($this->resource, $filePath);
break;
case IMAGETYPE_JPEG:
- $retval = imagejpeg($this->resource, $filepath);
+ $retVal = imagejpeg($this->resource, $filePath);
break;
case IMAGETYPE_PNG:
- $retval = imagepng($this->resource, $filepath);
+ $retVal = imagepng($this->resource, $filePath);
break;
case IMAGETYPE_XBM:
- $retval = imagexbm($this->resource, $filepath);
+ $retVal = imagexbm($this->resource, $filePath);
break;
case IMAGETYPE_WBMP:
- $retval = imagewbmp($this->resource, $filepath);
+ $retVal = imagewbmp($this->resource, $filePath);
break;
case IMAGETYPE_BMP:
- $retval = imagebmp($this->resource, $filepath, $this->bit_depth);
+ $retVal = imagebmp($this->resource, $filePath, $this->bitDepth);
break;
default:
- $retval = imagepng($this->resource, $filepath);
+ $retVal = imagepng($this->resource, $filePath);
}
- return $retval;
+ return $retVal;
}
/**
@@ -233,7 +241,21 @@ class OC_Image {
*/
function data() {
ob_start();
- $res = imagepng($this->resource);
+ switch ($this->mimeType) {
+ case "image/png":
+ $res = imagepng($this->resource);
+ break;
+ case "image/jpeg":
+ $res = imagejpeg($this->resource);
+ break;
+ case "image/gif":
+ $res = imagegif($this->resource);
+ break;
+ default:
+ $res = imagepng($this->resource);
+ OC_Log::write('core', 'OC_Image->data. Couldn\'t guess mimetype, defaulting to png', OC_Log::INFO);
+ break;
+ }
if (!$res) {
OC_Log::write('core', 'OC_Image->data. Error getting image data.', OC_Log::ERROR);
}
@@ -261,11 +283,11 @@ class OC_Image {
OC_Log::write('core', 'OC_Image->fixOrientation() No image loaded.', OC_Log::DEBUG);
return -1;
}
- if(is_null($this->filepath) || !is_readable($this->filepath)) {
+ if(is_null($this->filePath) || !is_readable($this->filePath)) {
OC_Log::write('core', 'OC_Image->fixOrientation() No readable file path set.', OC_Log::DEBUG);
return -1;
}
- $exif = @exif_read_data($this->filepath, 'IFD0');
+ $exif = @exif_read_data($this->filePath, 'IFD0');
if(!$exif) {
return -1;
}
@@ -351,19 +373,19 @@ class OC_Image {
* @param $imageref The path to a local file, a base64 encoded string or a resource created by an imagecreate* function or a file resource (file handle ).
* @returns An image resource or false on error
*/
- public function load($imageref) {
- if(is_resource($imageref)) {
- if(get_resource_type($imageref) == 'gd') {
- $this->resource = $imageref;
+ public function load($imageRef) {
+ if(is_resource($imageRef)) {
+ if(get_resource_type($imageRef) == 'gd') {
+ $this->resource = $imageRef;
return $this->resource;
- } elseif(in_array(get_resource_type($imageref), array('file', 'stream'))) {
- return $this->loadFromFileHandle($imageref);
+ } elseif(in_array(get_resource_type($imageRef), array('file', 'stream'))) {
+ return $this->loadFromFileHandle($imageRef);
}
- } elseif($this->loadFromFile($imageref) !== false) {
+ } elseif($this->loadFromFile($imageRef) !== false) {
return $this->resource;
- } elseif($this->loadFromBase64($imageref) !== false) {
+ } elseif($this->loadFromBase64($imageRef) !== false) {
return $this->resource;
- } elseif($this->loadFromData($imageref) !== false) {
+ } elseif($this->loadFromData($imageRef) !== false) {
return $this->resource;
} else {
OC_Log::write('core', __METHOD__.'(): couldn\'t load anything. Giving up!', OC_Log::DEBUG);
@@ -390,62 +412,62 @@ class OC_Image {
* @param $imageref The path to a local file.
* @returns An image resource or false on error
*/
- public function loadFromFile($imagepath=false) {
+ public function loadFromFile($imagePath=false) {
// exif_imagetype throws "read error!" if file is less than 12 byte
- if(!@is_file($imagepath) || !file_exists($imagepath) || filesize($imagepath) < 12 || !is_readable($imagepath)) {
+ if(!@is_file($imagePath) || !file_exists($imagePath) || filesize($imagePath) < 12 || !is_readable($imagePath)) {
// Debug output disabled because this method is tried before loadFromBase64?
- OC_Log::write('core', 'OC_Image->loadFromFile, couldn\'t load: '.$imagepath, OC_Log::DEBUG);
+ OC_Log::write('core', 'OC_Image->loadFromFile, couldn\'t load: '.$imagePath, OC_Log::DEBUG);
return false;
}
- $itype = exif_imagetype($imagepath);
- switch($itype) {
+ $iType = exif_imagetype($imagePath);
+ switch ($iType) {
case IMAGETYPE_GIF:
if (imagetypes() & IMG_GIF) {
- $this->resource = imagecreatefromgif($imagepath);
+ $this->resource = imagecreatefromgif($imagePath);
} else {
OC_Log::write('core',
- 'OC_Image->loadFromFile, GIF images not supported: '.$imagepath,
+ 'OC_Image->loadFromFile, GIF images not supported: '.$imagePath,
OC_Log::DEBUG);
}
break;
case IMAGETYPE_JPEG:
if (imagetypes() & IMG_JPG) {
- $this->resource = imagecreatefromjpeg($imagepath);
+ $this->resource = imagecreatefromjpeg($imagePath);
} else {
OC_Log::write('core',
- 'OC_Image->loadFromFile, JPG images not supported: '.$imagepath,
+ 'OC_Image->loadFromFile, JPG images not supported: '.$imagePath,
OC_Log::DEBUG);
}
break;
case IMAGETYPE_PNG:
if (imagetypes() & IMG_PNG) {
- $this->resource = imagecreatefrompng($imagepath);
+ $this->resource = imagecreatefrompng($imagePath);
} else {
OC_Log::write('core',
- 'OC_Image->loadFromFile, PNG images not supported: '.$imagepath,
+ 'OC_Image->loadFromFile, PNG images not supported: '.$imagePath,
OC_Log::DEBUG);
}
break;
case IMAGETYPE_XBM:
if (imagetypes() & IMG_XPM) {
- $this->resource = imagecreatefromxbm($imagepath);
+ $this->resource = imagecreatefromxbm($imagePath);
} else {
OC_Log::write('core',
- 'OC_Image->loadFromFile, XBM/XPM images not supported: '.$imagepath,
+ 'OC_Image->loadFromFile, XBM/XPM images not supported: '.$imagePath,
OC_Log::DEBUG);
}
break;
case IMAGETYPE_WBMP:
if (imagetypes() & IMG_WBMP) {
- $this->resource = imagecreatefromwbmp($imagepath);
+ $this->resource = imagecreatefromwbmp($imagePath);
} else {
OC_Log::write('core',
- 'OC_Image->loadFromFile, WBMP images not supported: '.$imagepath,
+ 'OC_Image->loadFromFile, WBMP images not supported: '.$imagePath,
OC_Log::DEBUG);
}
break;
case IMAGETYPE_BMP:
- $this->resource = $this->imagecreatefrombmp($imagepath);
+ $this->resource = $this->imagecreatefrombmp($imagePath);
break;
/*
case IMAGETYPE_TIFF_II: // (intel byte order)
@@ -474,14 +496,15 @@ class OC_Image {
default:
// this is mostly file created from encrypted file
- $this->resource = imagecreatefromstring(\OC\Files\Filesystem::file_get_contents(\OC\Files\Filesystem::getLocalPath($imagepath)));
- $itype = IMAGETYPE_PNG;
+ $this->resource = imagecreatefromstring(\OC\Files\Filesystem::file_get_contents(\OC\Files\Filesystem::getLocalPath($imagePath)));
+ $iType = IMAGETYPE_PNG;
OC_Log::write('core', 'OC_Image->loadFromFile, Default', OC_Log::DEBUG);
break;
}
if($this->valid()) {
- $this->imagetype = $itype;
- $this->filepath = $imagepath;
+ $this->imageType = $iType;
+ $this->mimeType = image_type_to_mime_type($iType);
+ $this->filePath = $imagePath;
}
return $this->resource;
}
@@ -496,6 +519,14 @@ class OC_Image {
return false;
}
$this->resource = @imagecreatefromstring($str);
+ if ($this->fileInfo) {
+ $this->mimeType = $this->fileInfo->buffer($str);
+ }
+ if(is_resource($this->resource)) {
+ imagealphablending($this->resource, false);
+ imagesavealpha($this->resource, true);
+ }
+
if(!$this->resource) {
OC_Log::write('core', 'OC_Image->loadFromData, couldn\'t load', OC_Log::DEBUG);
return false;
@@ -515,6 +546,9 @@ class OC_Image {
$data = base64_decode($str);
if($data) { // try to load from string data
$this->resource = @imagecreatefromstring($data);
+ if ($this->fileInfo) {
+ $this->mimeType = $this->fileInfo->buffer($data);
+ }
if(!$this->resource) {
OC_Log::write('core', 'OC_Image->loadFromBase64, couldn\'t load', OC_Log::DEBUG);
return false;
@@ -534,16 +568,16 @@ class OC_Image {
* </p>
* @return resource an image resource identifier on success, <b>FALSE</b> on errors.
*/
- private function imagecreatefrombmp($filename) {
- if (!($fh = fopen($filename, 'rb'))) {
- trigger_error('imagecreatefrombmp: Can not open ' . $filename, E_USER_WARNING);
+ private function imagecreatefrombmp($fileName) {
+ if (!($fh = fopen($fileName, 'rb'))) {
+ trigger_error('imagecreatefrombmp: Can not open ' . $fileName, E_USER_WARNING);
return false;
}
// read file header
$meta = unpack('vtype/Vfilesize/Vreserved/Voffset', fread($fh, 14));
// check for bitmap
if ($meta['type'] != 19778) {
- trigger_error('imagecreatefrombmp: ' . $filename . ' is not a bitmap!', E_USER_WARNING);
+ trigger_error('imagecreatefrombmp: ' . $fileName . ' is not a bitmap!', E_USER_WARNING);
return false;
}
// read image header
@@ -554,7 +588,7 @@ class OC_Image {
}
// set bytes and padding
$meta['bytes'] = $meta['bits'] / 8;
- $this->bit_depth = $meta['bits']; //remember the bit depth for the imagebmp call
+ $this->bitDepth = $meta['bits']; //remember the bit depth for the imagebmp call
$meta['decal'] = 4 - (4 * (($meta['width'] * $meta['bytes'] / 4)- floor($meta['width'] * $meta['bytes'] / 4)));
if ($meta['decal'] == 4) {
$meta['decal'] = 0;
@@ -590,7 +624,7 @@ class OC_Image {
$p = 0;
$vide = chr(0);
$y = $meta['height'] - 1;
- $error = 'imagecreatefrombmp: ' . $filename . ' has not enough data!';
+ $error = 'imagecreatefrombmp: ' . $fileName . ' has not enough data!';
// loop through the image data beginning with the lower left corner
while ($y >= 0) {
$x = 0;
@@ -653,7 +687,7 @@ class OC_Image {
break;
default:
trigger_error('imagecreatefrombmp: '
- . $filename . ' has ' . $meta['bits'] . ' bits and this is not supported!',
+ . $fileName . ' has ' . $meta['bits'] . ' bits and this is not supported!',
E_USER_WARNING);
return false;
}
@@ -673,24 +707,24 @@ class OC_Image {
* @param $maxsize The maximum size of either the width or height.
* @returns bool
*/
- public function resize($maxsize) {
+ public function resize($maxSize) {
if(!$this->valid()) {
OC_Log::write('core', __METHOD__.'(): No image loaded', OC_Log::ERROR);
return false;
}
- $width_orig=imageSX($this->resource);
- $height_orig=imageSY($this->resource);
- $ratio_orig = $width_orig/$height_orig;
+ $widthOrig=imageSX($this->resource);
+ $heightOrig=imageSY($this->resource);
+ $ratioOrig = $widthOrig/$heightOrig;
- if ($ratio_orig > 1) {
- $new_height = round($maxsize/$ratio_orig);
- $new_width = $maxsize;
+ if ($ratioOrig > 1) {
+ $newHeight = round($maxSize/$ratioOrig);
+ $newWidth = $maxSize;
} else {
- $new_width = round($maxsize*$ratio_orig);
- $new_height = $maxsize;
+ $newWidth = round($maxSize*$ratioOrig);
+ $newHeight = $maxSize;
}
- $this->preciseResize(round($new_width), round($new_height));
+ $this->preciseResize(round($newWidth), round($newHeight));
return true;
}
@@ -699,8 +733,8 @@ class OC_Image {
OC_Log::write('core', __METHOD__.'(): No image loaded', OC_Log::ERROR);
return false;
}
- $width_orig=imageSX($this->resource);
- $height_orig=imageSY($this->resource);
+ $widthOrig=imageSX($this->resource);
+ $heightOrig=imageSY($this->resource);
$process = imagecreatetruecolor($width, $height);
if ($process == false) {
@@ -710,13 +744,13 @@ class OC_Image {
}
// preserve transparency
- if($this->imagetype == IMAGETYPE_GIF or $this->imagetype == IMAGETYPE_PNG) {
+ if($this->imageType == IMAGETYPE_GIF or $this->imageType == IMAGETYPE_PNG) {
imagecolortransparent($process, imagecolorallocatealpha($process, 0, 0, 0, 127));
imagealphablending($process, false);
imagesavealpha($process, true);
}
- imagecopyresampled($process, $this->resource, 0, 0, 0, 0, $width, $height, $width_orig, $height_orig);
+ imagecopyresampled($process, $this->resource, 0, 0, 0, 0, $width, $height, $widthOrig, $heightOrig);
if ($process == false) {
OC_Log::write('core', __METHOD__.'(): Error resampling process image '.$width.'x'.$height, OC_Log::ERROR);
imagedestroy($process);
@@ -737,19 +771,19 @@ class OC_Image {
OC_Log::write('core', 'OC_Image->centerCrop, No image loaded', OC_Log::ERROR);
return false;
}
- $width_orig=imageSX($this->resource);
- $height_orig=imageSY($this->resource);
- if($width_orig === $height_orig and $size==0) {
+ $widthOrig=imageSX($this->resource);
+ $heightOrig=imageSY($this->resource);
+ if($widthOrig === $heightOrig and $size==0) {
return true;
}
- $ratio_orig = $width_orig/$height_orig;
- $width = $height = min($width_orig, $height_orig);
+ $ratioOrig = $widthOrig/$heightOrig;
+ $width = $height = min($widthOrig, $heightOrig);
- if ($ratio_orig > 1) {
- $x = ($width_orig/2) - ($width/2);
+ if ($ratioOrig > 1) {
+ $x = ($widthOrig/2) - ($width/2);
$y = 0;
} else {
- $y = ($height_orig/2) - ($height/2);
+ $y = ($heightOrig/2) - ($height/2);
$x = 0;
}
if($size>0) {
@@ -767,7 +801,7 @@ class OC_Image {
}
// preserve transparency
- if($this->imagetype == IMAGETYPE_GIF or $this->imagetype == IMAGETYPE_PNG) {
+ if($this->imageType == IMAGETYPE_GIF or $this->imageType == IMAGETYPE_PNG) {
imagecolortransparent($process, imagecolorallocatealpha($process, 0, 0, 0, 127));
imagealphablending($process, false);
imagesavealpha($process, true);
@@ -827,9 +861,9 @@ class OC_Image {
OC_Log::write('core', __METHOD__.'(): No image loaded', OC_Log::ERROR);
return false;
}
- $width_orig=imageSX($this->resource);
- $height_orig=imageSY($this->resource);
- $ratio = $width_orig/$height_orig;
+ $widthOrig=imageSX($this->resource);
+ $heightOrig=imageSY($this->resource);
+ $ratio = $widthOrig/$heightOrig;
$newWidth = min($maxWidth, $ratio*$maxHeight);
$newHeight = min($maxHeight, $maxWidth/$ratio);
@@ -863,7 +897,7 @@ if ( ! function_exists( 'imagebmp') ) {
* @param int $compression [optional]
* @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure.
*/
- function imagebmp($im, $filename='', $bit=24, $compression=0) {
+ function imagebmp($im, $fileName='', $bit=24, $compression=0) {
if (!in_array($bit, array(1, 4, 8, 16, 24, 32))) {
$bit = 24;
}
@@ -874,14 +908,14 @@ if ( ! function_exists( 'imagebmp') ) {
imagetruecolortopalette($im, true, $bits);
$width = imagesx($im);
$height = imagesy($im);
- $colors_num = imagecolorstotal($im);
- $rgb_quad = '';
+ $colorsNum = imagecolorstotal($im);
+ $rgbQuad = '';
if ($bit <= 8) {
- for ($i = 0; $i < $colors_num; $i++) {
+ for ($i = 0; $i < $colorsNum; $i++) {
$colors = imagecolorsforindex($im, $i);
- $rgb_quad .= chr($colors['blue']) . chr($colors['green']) . chr($colors['red']) . "\0";
+ $rgbQuad .= chr($colors['blue']) . chr($colors['green']) . chr($colors['red']) . "\0";
}
- $bmp_data = '';
+ $bmpData = '';
if ($compression == 0 || $bit < 8) {
$compression = 0;
$extra = '';
@@ -899,35 +933,35 @@ if ( ! function_exists( 'imagebmp') ) {
$bin |= $index << $k;
$i++;
}
- $bmp_data .= chr($bin);
+ $bmpData .= chr($bin);
}
- $bmp_data .= $extra;
+ $bmpData .= $extra;
}
}
// RLE8
else if ($compression == 1 && $bit == 8) {
for ($j = $height - 1; $j >= 0; $j--) {
- $last_index = "\0";
- $same_num = 0;
+ $lastIndex = "\0";
+ $sameNum = 0;
for ($i = 0; $i <= $width; $i++) {
$index = imagecolorat($im, $i, $j);
- if ($index !== $last_index || $same_num > 255) {
- if ($same_num != 0) {
- $bmp_data .= chr($same_num) . chr($last_index);
+ if ($index !== $lastIndex || $sameNum > 255) {
+ if ($sameNum != 0) {
+ $bmpData .= chr($same_num) . chr($lastIndex);
}
- $last_index = $index;
- $same_num = 1;
+ $lastIndex = $index;
+ $sameNum = 1;
}
else {
- $same_num++;
+ $sameNum++;
}
}
- $bmp_data .= "\0\0";
+ $bmpData .= "\0\0";
}
- $bmp_data .= "\0\1";
+ $bmpData .= "\0\1";
}
- $size_quad = strlen($rgb_quad);
- $size_data = strlen($bmp_data);
+ $sizeQuad = strlen($rgbQuad);
+ $sizeData = strlen($bmpData);
}
else {
$extra = '';
@@ -935,7 +969,7 @@ if ( ! function_exists( 'imagebmp') ) {
if ($padding % 4 != 0) {
$extra = str_repeat("\0", $padding);
}
- $bmp_data = '';
+ $bmpData = '';
for ($j = $height - 1; $j >= 0; $j--) {
for ($i = 0; $i < $width; $i++) {
$index = imagecolorat($im, $i, $j);
@@ -945,27 +979,27 @@ if ( ! function_exists( 'imagebmp') ) {
$bin |= ($colors['red'] >> 3) << 10;
$bin |= ($colors['green'] >> 3) << 5;
$bin |= $colors['blue'] >> 3;
- $bmp_data .= pack("v", $bin);
+ $bmpData .= pack("v", $bin);
}
else {
- $bmp_data .= pack("c*", $colors['blue'], $colors['green'], $colors['red']);
+ $bmpData .= pack("c*", $colors['blue'], $colors['green'], $colors['red']);
}
}
- $bmp_data .= $extra;
+ $bmpData .= $extra;
}
- $size_quad = 0;
- $size_data = strlen($bmp_data);
- $colors_num = 0;
- }
- $file_header = 'BM' . pack('V3', 54 + $size_quad + $size_data, 0, 54 + $size_quad);
- $info_header = pack('V3v2V*', 0x28, $width, $height, 1, $bit, $compression, $size_data, 0, 0, $colors_num, 0);
- if ($filename != '') {
- $fp = fopen($filename, 'wb');
- fwrite($fp, $file_header . $info_header . $rgb_quad . $bmp_data);
+ $sizeQuad = 0;
+ $sizeData = strlen($bmpData);
+ $colorsNum = 0;
+ }
+ $fileHeader = 'BM' . pack('V3', 54 + $sizeQuad + $sizeData, 0, 54 + $sizeQuad);
+ $infoHeader = pack('V3v2V*', 0x28, $width, $height, 1, $bit, $compression, $sizeData, 0, 0, $colorsNum, 0);
+ if ($fileName != '') {
+ $fp = fopen($fileName, 'wb');
+ fwrite($fp, $fileHeader . $infoHeader . $rgbQuad . $bmpData);
fclose($fp);
return true;
}
- echo $file_header . $info_header. $rgb_quad . $bmp_data;
+ echo $fileHeader . $infoHeader. $rgbQuad . $bmpData;
return true;
}
}
@@ -977,8 +1011,8 @@ if ( ! function_exists( 'exif_imagetype' ) ) {
* @param string $filename
* @return string|boolean
*/
- function exif_imagetype ( $filename ) {
- if ( ( $info = getimagesize( $filename ) ) !== false ) {
+ function exif_imagetype ( $fileName ) {
+ if ( ( $info = getimagesize( $fileName ) ) !== false ) {
return $info[2];
}
return false;
diff --git a/lib/installer.php b/lib/private/installer.php
index dcd29f9e1ad..8375b231e9b 100644
--- a/lib/installer.php
+++ b/lib/private/installer.php
@@ -27,6 +27,7 @@ class OC_Installer{
/**
* @brief Installs an app
* @param $data array with all information
+ * @throws \Exception
* @returns integer
*
* This function installs an app. All information needed are passed in the
@@ -56,23 +57,22 @@ class OC_Installer{
* needed to get the app working.
*/
public static function installApp( $data = array()) {
+ $l = \OC_L10N::get('lib');
+
if(!isset($data['source'])) {
- OC_Log::write('core', 'No source specified when installing app', OC_Log::ERROR);
- return false;
+ throw new \Exception($l->t("No source specified when installing app"));
}
//download the file if necesary
if($data['source']=='http') {
$path=OC_Helper::tmpFile();
if(!isset($data['href'])) {
- OC_Log::write('core', 'No href specified when installing app from http', OC_Log::ERROR);
- return false;
+ throw new \Exception($l->t("No href specified when installing app from http"));
}
copy($data['href'], $path);
}else{
if(!isset($data['path'])) {
- OC_Log::write('core', 'No path specified when installing app from local file', OC_Log::ERROR);
- return false;
+ throw new \Exception($l->t("No path specified when installing app from local file"));
}
$path=$data['path'];
}
@@ -86,8 +86,7 @@ class OC_Installer{
rename($path, $path.'.tgz');
$path.='.tgz';
}else{
- OC_Log::write('core', 'Archives of type '.$mime.' are not supported', OC_Log::ERROR);
- return false;
+ throw new \Exception($l->t("Archives of type %s are not supported", array($mime)));
}
//extract the archive in a temporary folder
@@ -97,83 +96,77 @@ class OC_Installer{
if($archive=OC_Archive::open($path)) {
$archive->extract($extractDir);
} else {
- OC_Log::write('core', 'Failed to open archive when installing app', OC_Log::ERROR);
OC_Helper::rmdirr($extractDir);
if($data['source']=='http') {
unlink($path);
}
- return false;
+ throw new \Exception($l->t("Failed to open archive when installing app"));
}
//load the info.xml file of the app
if(!is_file($extractDir.'/appinfo/info.xml')) {
//try to find it in a subdir
$dh=opendir($extractDir);
- while($folder=readdir($dh)) {
- if($folder[0]!='.' and is_dir($extractDir.'/'.$folder)) {
- if(is_file($extractDir.'/'.$folder.'/appinfo/info.xml')) {
- $extractDir.='/'.$folder;
+ if(is_resource($dh)) {
+ while (($folder = readdir($dh)) !== false) {
+ if($folder[0]!='.' and is_dir($extractDir.'/'.$folder)) {
+ if(is_file($extractDir.'/'.$folder.'/appinfo/info.xml')) {
+ $extractDir.='/'.$folder;
+ }
}
}
}
}
if(!is_file($extractDir.'/appinfo/info.xml')) {
- OC_Log::write('core', 'App does not provide an info.xml file', OC_Log::ERROR);
OC_Helper::rmdirr($extractDir);
if($data['source']=='http') {
unlink($path);
}
- return false;
+ throw new \Exception($l->t("App does not provide an info.xml file"));
}
$info=OC_App::getAppInfo($extractDir.'/appinfo/info.xml', true);
// check the code for not allowed calls
if(!OC_Installer::checkCode($info['id'], $extractDir)) {
- OC_Log::write('core', 'App can\'t be installed because of not allowed code in the App', OC_Log::ERROR);
OC_Helper::rmdirr($extractDir);
- return false;
+ throw new \Exception($l->t("App can't be installed because of not allowed code in the App"));
}
// check if the app is compatible with this version of ownCloud
if(
- !isset($info['require'])
- or !OC_App::isAppVersionCompatible(OC_Util::getVersion(), $info['require'])
- ) {
- OC_Log::write('core',
- 'App can\'t be installed because it is not compatible with this version of ownCloud',
- OC_Log::ERROR);
+ !isset($info['require'])
+ or !OC_App::isAppVersionCompatible(OC_Util::getVersion(), $info['require'])
+ ) {
OC_Helper::rmdirr($extractDir);
- return false;
+ throw new \Exception($l->t("App can't be installed because it is not compatible with this version of ownCloud"));
}
// check if shipped tag is set which is only allowed for apps that are shipped with ownCloud
if(isset($info['shipped']) and ($info['shipped']=='true')) {
- OC_Log::write('core',
- 'App can\'t be installed because it contains the <shipped>true</shippe>'
- .' tag which is not allowed for non shipped apps',
- OC_Log::ERROR);
OC_Helper::rmdirr($extractDir);
- return false;
+ throw new \Exception($l->t("App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps"));
}
// check if the ocs version is the same as the version in info.xml/version
- if(!isset($info['version']) or ($info['version']<>$data['appdata']['version'])) {
- OC_Log::write('core',
- 'App can\'t be installed because the version in info.xml/version is not the same'
- .' as the version reported from the app store',
- OC_Log::ERROR);
+ $versionFile= $extractDir.'/appinfo/version';
+ if(is_file($versionFile)) {
+ $version = trim(file_get_contents($versionFile));
+ }else{
+ $version = trim($info['version']);
+ }
+
+ if($version<>trim($data['appdata']['version'])) {
OC_Helper::rmdirr($extractDir);
- return false;
+ throw new \Exception($l->t("App can't be installed because the version in info.xml/version is not the same as the version reported from the app store"));
}
$basedir=OC_App::getInstallPath().'/'.$info['id'];
//check if the destination directory already exists
if(is_dir($basedir)) {
- OC_Log::write('core', 'App directory already exists', OC_Log::WARN);
OC_Helper::rmdirr($extractDir);
if($data['source']=='http') {
unlink($path);
}
- return false;
+ throw new \Exception($l->t("App directory already exists"));
}
if(isset($data['pretent']) and $data['pretent']==true) {
@@ -182,12 +175,11 @@ class OC_Installer{
//copy the app to the correct place
if(@!mkdir($basedir)) {
- OC_Log::write('core', 'Can\'t create app folder. Please fix permissions. ('.$basedir.')', OC_Log::ERROR);
OC_Helper::rmdirr($extractDir);
if($data['source']=='http') {
unlink($path);
}
- return false;
+ throw new \Exception($l->t("Can't create app folder. Please fix permissions. %s", array($basedir)));
}
OC_Helper::copyr($extractDir, $basedir);
@@ -196,7 +188,11 @@ class OC_Installer{
//install the database
if(is_file($basedir.'/appinfo/database.xml')) {
- OC_DB::createDbFromStructure($basedir.'/appinfo/database.xml');
+ if (OC_Appconfig::getValue($info['id'], 'installed_version') === null) {
+ OC_DB::createDbFromStructure($basedir.'/appinfo/database.xml');
+ } else {
+ OC_DB::updateDbFromStructure($basedir.'/appinfo/database.xml');
+ }
}
//run appinfo/install.php
@@ -274,7 +270,7 @@ class OC_Installer{
/**
* @brief Check if an update for the app is available
* @param $name name of the application
- * @returns empty string is no update available or the version number of the update
+ * @return boolean false or the version number of the update
*
* The function will check if an update for a version is available
*/
@@ -290,11 +286,11 @@ class OC_Installer{
return($ocsversion);
}else{
- return('');
+ return false;
}
}else{
- return('');
+ return false;
}
}
@@ -443,6 +439,7 @@ class OC_Installer{
'OC_API::',
'OC_App::',
'OC_AppConfig::',
+ 'OC_Avatar',
'OC_BackgroundJob::',
'OC_Config::',
'OC_DB::',
@@ -463,8 +460,7 @@ class OC_Installer{
);
// is the code checker enabled?
- if(OC_Config::getValue('appcodechecker', false)) {
-
+ if(OC_Config::getValue('appcodechecker', true)) {
// check if grep is installed
$grep = exec('which grep');
if($grep=='') {
diff --git a/lib/json.php b/lib/private/json.php
index 6ba0b13806b..6ba0b13806b 100644
--- a/lib/json.php
+++ b/lib/private/json.php
diff --git a/lib/l10n.php b/lib/private/l10n.php
index d2da302b644..98665c84c55 100644
--- a/lib/l10n.php
+++ b/lib/private/l10n.php
@@ -25,12 +25,7 @@
/**
* This class is for i18n and l10n
*/
-class OC_L10N {
- /**
- * cached instances
- */
- protected static $instances=array();
-
+class OC_L10N implements \OCP\IL10N {
/**
* cache
*/
@@ -83,13 +78,10 @@ class OC_L10N {
* @return OC_L10N
*/
public static function get($app, $lang=null) {
- if(is_null($lang)) {
- if(!isset(self::$instances[$app])) {
- self::$instances[$app]=new OC_L10N($app);
- }
- return self::$instances[$app];
- }else{
- return new OC_L10N($app, $lang);
+ if (is_null($lang)) {
+ return OC::$server->getL10N($app);
+ } else {
+ return new \OC_L10N($app, $lang);
}
}
@@ -270,7 +262,7 @@ class OC_L10N {
*/
public function n($text_singular, $text_plural, $count, $parameters = array()) {
$this->init();
- $identifier = "_${text_singular}__${text_plural}_";
+ $identifier = "_${text_singular}_::_${text_plural}_";
if( array_key_exists($identifier, $this->translations)) {
return new OC_L10N_String( $this, $identifier, $parameters, $count );
}
@@ -386,8 +378,7 @@ class OC_L10N {
case 'time':
if($data instanceof DateTime) {
return $data->format($this->localizations[$type]);
- }
- elseif(is_string($data)) {
+ } elseif(is_string($data) && !is_numeric($data)) {
$data = strtotime($data);
}
$locales = array(self::findLanguage());
@@ -428,7 +419,7 @@ class OC_L10N {
/**
* @brief find the best language
* @param $app Array or string, details below
- * @returns language
+ * @returns string language
*
* If $app is an array, ownCloud assumes that these are the available
* languages. Otherwise ownCloud tries to find the files in the l10n
@@ -447,8 +438,7 @@ class OC_L10N {
if(is_array($app)) {
$available = $app;
$lang_exists = array_search($lang, $available) !== false;
- }
- else {
+ } else {
$lang_exists = self::languageExists($app, $lang);
}
if($lang_exists) {
@@ -456,35 +446,40 @@ class OC_L10N {
}
}
- $default_language = OC_Config::getValue('default_language', false);
+ $default_language = OC_Config::getValue('default_language', false);
- if($default_language !== false) {
- return $default_language;
- }
+ if($default_language !== false) {
+ return $default_language;
+ }
if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
- $accepted_languages = preg_split('/,\s*/', strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE']));
if(is_array($app)) {
$available = $app;
- }
- else{
+ } else {
$available = self::findAvailableLanguages($app);
}
- foreach($accepted_languages as $i) {
- $temp = explode(';', $i);
- $temp[0] = str_replace('-', '_', $temp[0]);
- if( ($key = array_search($temp[0], $available)) !== false) {
- if (is_null($app)) {
- self::$language = $available[$key];
+
+ // E.g. make sure that 'de' is before 'de_DE'.
+ sort($available);
+
+ $preferences = preg_split('/,\s*/', strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE']));
+ foreach($preferences as $preference) {
+ list($preferred_language) = explode(';', $preference);
+ $preferred_language = str_replace('-', '_', $preferred_language);
+ foreach($available as $available_language) {
+ if ($preferred_language === strtolower($available_language)) {
+ if (is_null($app)) {
+ self::$language = $available_language;
+ }
+ return $available_language;
}
- return $available[$key];
}
- foreach($available as $l) {
- if ( $temp[0] == substr($l, 0, 2) ) {
+ foreach($available as $available_language) {
+ if (substr($preferred_language, 0, 2) === $available_language) {
if (is_null($app)) {
- self::$language = $l;
+ self::$language = $available_language;
}
- return $l;
+ return $available_language;
}
}
}
diff --git a/lib/private/l10n/factory.php b/lib/private/l10n/factory.php
new file mode 100644
index 00000000000..8c65f368171
--- /dev/null
+++ b/lib/private/l10n/factory.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ *
+ */
+
+namespace OC\L10N;
+
+/**
+ * TODO: Description
+ */
+class Factory {
+ /**
+ * cached instances
+ */
+ protected $instances = array();
+
+ /**
+ * get an L10N instance
+ * @param $app string
+ * @param $lang string|null
+ * @return \OC_L10N
+ */
+ public function get($app) {
+ if (!isset($this->instances[$app])) {
+ $this->instances[$app] = new \OC_L10N($app);
+ }
+ return $this->instances[$app];
+ }
+
+}
diff --git a/lib/l10n/string.php b/lib/private/l10n/string.php
index 88c85b32e70..88c85b32e70 100644
--- a/lib/l10n/string.php
+++ b/lib/private/l10n/string.php
diff --git a/lib/private/legacy/cache.php b/lib/private/legacy/cache.php
new file mode 100644
index 00000000000..f915eb516b1
--- /dev/null
+++ b/lib/private/legacy/cache.php
@@ -0,0 +1,10 @@
+<?php
+/**
+ * Copyright (c) 2013 Thomas Tanghus (thomas@tanghus.net)
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+class OC_Cache extends \OC\Cache {
+} \ No newline at end of file
diff --git a/lib/private/legacy/cache/fileglobalgc.php b/lib/private/legacy/cache/fileglobalgc.php
new file mode 100644
index 00000000000..385f6406673
--- /dev/null
+++ b/lib/private/legacy/cache/fileglobalgc.php
@@ -0,0 +1,4 @@
+<?php
+
+class OC_Cache_FileGlobalGC extends OC\Cache\FileGlobalGC{
+}
diff --git a/lib/legacy/config.php b/lib/private/legacy/config.php
index 7e498013737..c457979113e 100644
--- a/lib/legacy/config.php
+++ b/lib/private/legacy/config.php
@@ -83,11 +83,7 @@ class OC_Config {
*
*/
public static function setValue($key, $value) {
- try {
- self::$object->setValue($key, $value);
- } catch (\OC\HintException $e) {
- \OC_Template::printErrorPage($e->getMessage(), $e->getHint());
- }
+ self::$object->setValue($key, $value);
}
/**
@@ -98,10 +94,6 @@ class OC_Config {
*
*/
public static function deleteKey($key) {
- try {
- self::$object->deleteKey($key);
- } catch (\OC\HintException $e) {
- \OC_Template::printErrorPage($e->getMessage(), $e->getHint());
- }
+ self::$object->deleteKey($key);
}
}
diff --git a/lib/legacy/filesystem.php b/lib/private/legacy/filesystem.php
index 34f92b357ca..34f92b357ca 100644
--- a/lib/legacy/filesystem.php
+++ b/lib/private/legacy/filesystem.php
diff --git a/lib/legacy/filesystemview.php b/lib/private/legacy/filesystemview.php
index d6bca62e06a..d6bca62e06a 100644
--- a/lib/legacy/filesystemview.php
+++ b/lib/private/legacy/filesystemview.php
diff --git a/lib/legacy/log.php b/lib/private/legacy/log.php
index 027cb89e97c..027cb89e97c 100644
--- a/lib/legacy/log.php
+++ b/lib/private/legacy/log.php
diff --git a/lib/private/legacy/preferences.php b/lib/private/legacy/preferences.php
new file mode 100644
index 00000000000..a663db7598b
--- /dev/null
+++ b/lib/private/legacy/preferences.php
@@ -0,0 +1,146 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Frank Karlitschek
+ * @author Jakob Sack
+ * @copyright 2012 Frank Karlitschek frank@owncloud.org
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * This class provides an easy way for storing user preferences.
+ */
+OC_Preferences::$object = new \OC\Preferences(OC_DB::getConnection());
+class OC_Preferences{
+ public static $object;
+ /**
+ * @brief Get all users using the preferences
+ * @return array with user ids
+ *
+ * This function returns a list of all users that have at least one entry
+ * in the preferences table.
+ */
+ public static function getUsers() {
+ return self::$object->getUsers();
+ }
+
+ /**
+ * @brief Get all apps of a user
+ * @param string $user user
+ * @return array with app ids
+ *
+ * This function returns a list of all apps of the user that have at least
+ * one entry in the preferences table.
+ */
+ public static function getApps( $user ) {
+ return self::$object->getApps( $user );
+ }
+
+ /**
+ * @brief Get the available keys for an app
+ * @param string $user user
+ * @param string $app the app we are looking for
+ * @return array with key names
+ *
+ * This function gets all keys of an app of an user. Please note that the
+ * values are not returned.
+ */
+ public static function getKeys( $user, $app ) {
+ return self::$object->getKeys( $user, $app );
+ }
+
+ /**
+ * @brief Gets the preference
+ * @param string $user user
+ * @param string $app app
+ * @param string $key key
+ * @param string $default = null, default value if the key does not exist
+ * @return string the value or $default
+ *
+ * This function gets a value from the preferences table. If the key does
+ * not exist the default value will be returned
+ */
+ public static function getValue( $user, $app, $key, $default = null ) {
+ return self::$object->getValue( $user, $app, $key, $default );
+ }
+
+ /**
+ * @brief sets a value in the preferences
+ * @param string $user user
+ * @param string $app app
+ * @param string $key key
+ * @param string $value value
+ * @return bool
+ *
+ * Adds a value to the preferences. If the key did not exist before, it
+ * will be added automagically.
+ */
+ public static function setValue( $user, $app, $key, $value ) {
+ self::$object->setValue( $user, $app, $key, $value );
+ return true;
+ }
+
+ /**
+ * @brief Deletes a key
+ * @param string $user user
+ * @param string $app app
+ * @param string $key key
+ *
+ * Deletes a key.
+ */
+ public static function deleteKey( $user, $app, $key ) {
+ self::$object->deleteKey( $user, $app, $key );
+ return true;
+ }
+
+ /**
+ * @brief Remove app of user from preferences
+ * @param string $user user
+ * @param string $app app
+ * @return bool
+ *
+ * Removes all keys in preferences belonging to the app and the user.
+ */
+ public static function deleteApp( $user, $app ) {
+ self::$object->deleteApp( $user, $app );
+ return true;
+ }
+
+ /**
+ * @brief Remove user from preferences
+ * @param string $user user
+ * @return bool
+ *
+ * Removes all keys in preferences belonging to the user.
+ */
+ public static function deleteUser( $user ) {
+ self::$object->deleteUser( $user );
+ return true;
+ }
+
+ /**
+ * @brief Remove app from all users
+ * @param string $app app
+ * @return bool
+ *
+ * Removes all keys in preferences belonging to the app.
+ */
+ public static function deleteAppFromAllUsers( $app ) {
+ self::$object->deleteAppFromAllUsers( $app );
+ return true;
+ }
+}
diff --git a/lib/legacy/updater.php b/lib/private/legacy/updater.php
index eea7bb129cf..eea7bb129cf 100644
--- a/lib/legacy/updater.php
+++ b/lib/private/legacy/updater.php
diff --git a/lib/log.php b/lib/private/log.php
index e0b9fe3c696..e0b9fe3c696 100644
--- a/lib/log.php
+++ b/lib/private/log.php
diff --git a/lib/log/errorhandler.php b/lib/private/log/errorhandler.php
index 69cb960de91..69cb960de91 100644
--- a/lib/log/errorhandler.php
+++ b/lib/private/log/errorhandler.php
diff --git a/lib/log/owncloud.php b/lib/private/log/owncloud.php
index d16b9537a16..4c86d0e45e0 100644
--- a/lib/log/owncloud.php
+++ b/lib/private/log/owncloud.php
@@ -35,7 +35,17 @@ class OC_Log_Owncloud {
public static function init() {
$defaultLogFile = OC_Config::getValue("datadirectory", OC::$SERVERROOT.'/data').'/owncloud.log';
self::$logFile = OC_Config::getValue("logfile", $defaultLogFile);
- if (!file_exists(self::$logFile)) {
+
+ /*
+ * Fall back to default log file if specified logfile does not exist
+ * and can not be created. Error suppression is required in order to
+ * not end up in the error handler which will try to log the error.
+ * A better solution (compared to error suppression) would be checking
+ * !is_writable(dirname(self::$logFile)) before touch(), but
+ * is_writable() on directories used to be pretty unreliable on Windows
+ * for at least some time.
+ */
+ if (!file_exists(self::$logFile) && !@touch(self::$logFile)) {
self::$logFile = $defaultLogFile;
}
}
@@ -51,12 +61,25 @@ class OC_Log_Owncloud {
if($level>=$minLevel) {
// default to ISO8601
$format = OC_Config::getValue('logdateformat', 'c');
- $time = date($format, time());
- $entry=array('app'=>$app, 'message'=>$message, 'level'=>$level, 'time'=> $time);
+ $logtimezone=OC_Config::getValue( "logtimezone", 'UTC' );
+ try {
+ $timezone = new DateTimeZone($logtimezone);
+ } catch (Exception $e) {
+ $timezone = new DateTimeZone('UTC');
+ }
+ $time = new DateTime(null, $timezone);
+ // remove username/passswords from URLs before writing the to the log file
+ $message = preg_replace('/\/\/(.*):(.*)@/', '//xxx:xxx@', $message);
+ $entry=array('app'=>$app, 'message'=>$message, 'level'=>$level, 'time'=> $time->format($format));
+ $entry = json_encode($entry);
$handle = @fopen(self::$logFile, 'a');
+ @chmod(self::$logFile, 0640);
if ($handle) {
- fwrite($handle, json_encode($entry)."\n");
+ fwrite($handle, $entry."\n");
fclose($handle);
+ } else {
+ // Fall back to error_log
+ error_log($entry);
}
}
}
diff --git a/lib/private/log/rotate.php b/lib/private/log/rotate.php
new file mode 100644
index 00000000000..bf23ad588b3
--- /dev/null
+++ b/lib/private/log/rotate.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Log;
+
+/**
+ * This rotates the current logfile to a new name, this way the total log usage
+ * will stay limited and older entries are available for a while longer.
+ * For more professional log management set the 'logfile' config to a different
+ * location and manage that with your own tools.
+ */
+class Rotate extends \OC\BackgroundJob\Job {
+ private $max_log_size;
+ public function run($logFile) {
+ $this->max_log_size = \OC_Config::getValue('log_rotate_size', false);
+ if ($this->max_log_size) {
+ $filesize = @filesize($logFile);
+ if ($filesize >= $this->max_log_size) {
+ $this->rotate($logFile);
+ }
+ }
+ }
+
+ protected function rotate($logfile) {
+ $rotatedLogfile = $logfile.'.1';
+ rename($logfile, $rotatedLogfile);
+ $msg = 'Log file "'.$logfile.'" was over '.$this->max_log_size.' bytes, moved to "'.$rotatedLogfile.'"';
+ \OC_Log::write('OC\Log\Rotate', $msg, \OC_Log::WARN);
+ }
+}
diff --git a/lib/log/syslog.php b/lib/private/log/syslog.php
index c98deab7109..c98deab7109 100644
--- a/lib/log/syslog.php
+++ b/lib/private/log/syslog.php
diff --git a/lib/mail.php b/lib/private/mail.php
index b339b33e962..b339b33e962 100644
--- a/lib/mail.php
+++ b/lib/private/mail.php
diff --git a/lib/memcache/apc.php b/lib/private/memcache/apc.php
index 575ee4427db..575ee4427db 100644
--- a/lib/memcache/apc.php
+++ b/lib/private/memcache/apc.php
diff --git a/lib/memcache/apcu.php b/lib/private/memcache/apcu.php
index ccc1aa6e562..ccc1aa6e562 100644
--- a/lib/memcache/apcu.php
+++ b/lib/private/memcache/apcu.php
diff --git a/lib/memcache/cache.php b/lib/private/memcache/cache.php
index 0ad1cc7ec03..0ad1cc7ec03 100644
--- a/lib/memcache/cache.php
+++ b/lib/private/memcache/cache.php
diff --git a/lib/memcache/factory.php b/lib/private/memcache/factory.php
index 4c1b1ab207f..fde7d947567 100644
--- a/lib/memcache/factory.php
+++ b/lib/private/memcache/factory.php
@@ -37,4 +37,33 @@ class Factory {
public function isAvailable() {
return XCache::isAvailable() || APCu::isAvailable() || APC::isAvailable() || Memcached::isAvailable();
}
+
+ /**
+ * get a in-server cache instance, will return null if no backend is available
+ *
+ * @param string $prefix
+ * @return \OC\Memcache\Cache
+ */
+ public static function createLowLatency($prefix = '') {
+ if (XCache::isAvailable()) {
+ return new XCache($prefix);
+ } elseif (APCu::isAvailable()) {
+ return new APCu($prefix);
+ } elseif (APC::isAvailable()) {
+ return new APC($prefix);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * check if there is a in-server backend available
+ *
+ * @return bool
+ */
+ public static function isAvailableLowLatency() {
+ return XCache::isAvailable() || APCu::isAvailable() || APC::isAvailable();
+ }
+
+
}
diff --git a/lib/memcache/memcached.php b/lib/private/memcache/memcached.php
index 978e6c2eff1..978e6c2eff1 100644
--- a/lib/memcache/memcached.php
+++ b/lib/private/memcache/memcached.php
diff --git a/lib/memcache/xcache.php b/lib/private/memcache/xcache.php
index 2dc4a3a6016..2dc4a3a6016 100644
--- a/lib/memcache/xcache.php
+++ b/lib/private/memcache/xcache.php
diff --git a/lib/migrate.php b/lib/private/migrate.php
index 0b319177400..0b319177400 100644
--- a/lib/migrate.php
+++ b/lib/private/migrate.php
diff --git a/lib/migration/content.php b/lib/private/migration/content.php
index 2d8268a1d74..4413d722731 100644
--- a/lib/migration/content.php
+++ b/lib/private/migration/content.php
@@ -191,7 +191,8 @@ class OC_Migration_Content{
if( !file_exists( $dir ) ) {
return false;
}
- if ($dirhandle = opendir($dir)) {
+ $dirhandle = opendir($dir);
+ if(is_resource($dirhandle)) {
while (false !== ( $file = readdir($dirhandle))) {
if (( $file != '.' ) && ( $file != '..' )) {
diff --git a/lib/migration/provider.php b/lib/private/migration/provider.php
index 234ab3351f3..234ab3351f3 100644
--- a/lib/migration/provider.php
+++ b/lib/private/migration/provider.php
diff --git a/lib/mimetypes.list.php b/lib/private/mimetypes.list.php
index 8ab8ac81bd8..8ab8ac81bd8 100644
--- a/lib/mimetypes.list.php
+++ b/lib/private/mimetypes.list.php
diff --git a/lib/minimizer.php b/lib/private/minimizer.php
index db522de74dc..db522de74dc 100644
--- a/lib/minimizer.php
+++ b/lib/private/minimizer.php
diff --git a/lib/minimizer/css.php b/lib/private/minimizer/css.php
index 8d130572e2b..8d130572e2b 100644
--- a/lib/minimizer/css.php
+++ b/lib/private/minimizer/css.php
diff --git a/lib/minimizer/js.php b/lib/private/minimizer/js.php
index bd2d836deb0..bd2d836deb0 100644
--- a/lib/minimizer/js.php
+++ b/lib/private/minimizer/js.php
diff --git a/lib/private/navigationmanager.php b/lib/private/navigationmanager.php
new file mode 100644
index 00000000000..1f657b9ad80
--- /dev/null
+++ b/lib/private/navigationmanager.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ *
+ */
+
+namespace OC;
+
+/**
+ * Manages the ownCloud navigation
+ */
+class NavigationManager implements \OCP\INavigationManager {
+ protected $entries = array();
+ protected $activeEntry;
+
+ /**
+ * Creates a new navigation entry
+ * @param array $entry containing: id, name, order, icon and href key
+ */
+ public function add(array $entry) {
+ $entry['active'] = false;
+ if(!isset($entry['icon'])) {
+ $entry['icon'] = '';
+ }
+ $this->entries[] = $entry;
+ }
+
+ /**
+ * @brief returns all the added Menu entries
+ * @return array of the added entries
+ */
+ public function getAll() {
+ return $this->entries;
+ }
+
+ /**
+ * @brief removes all the entries
+ */
+ public function clear() {
+ $this->entries = array();
+ }
+
+ /**
+ * Sets the current navigation entry of the currently running app
+ * @param string $id of the app entry to activate (from added $entry)
+ */
+ public function setActiveEntry($id) {
+ $this->activeEntry = $id;
+ }
+
+ /**
+ * @brief gets the active Menu entry
+ * @return string id or empty string
+ *
+ * This function returns the id of the active navigation entry (set by
+ * setActiveEntry
+ */
+ public function getActiveEntry() {
+ return $this->activeEntry;
+ }
+}
diff --git a/lib/private/notsquareexception.php b/lib/private/notsquareexception.php
new file mode 100644
index 00000000000..03dba8fb25f
--- /dev/null
+++ b/lib/private/notsquareexception.php
@@ -0,0 +1,12 @@
+<?php
+/**
+ * Copyright (c) 2013 Christopher Schäpers <christopher@schaepers.it>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC;
+
+class NotSquareException extends \Exception {
+}
diff --git a/lib/ocs.php b/lib/private/ocs.php
index 93e8931ce2e..e067196cf11 100644
--- a/lib/ocs.php
+++ b/lib/private/ocs.php
@@ -228,36 +228,4 @@ class OC_OCS {
}
}
}
-
- /**
- * get private data
- * @param string $user
- * @param string $app
- * @param string $key
- * @param bool $like use LIKE instead of = when comparing keys
- * @return array
- */
- public static function getData($user, $app="", $key="") {
- if($app) {
- $apps=array($app);
- }else{
- $apps=OC_Preferences::getApps($user);
- }
- if($key) {
- $keys=array($key);
- }else{
- foreach($apps as $app) {
- $keys=OC_Preferences::getKeys($user, $app);
- }
- }
- $result=array();
- foreach($apps as $app) {
- foreach($keys as $key) {
- $value=OC_Preferences::getValue($user, $app, $key);
- $result[]=array('app'=>$app, 'key'=>$key, 'value'=>$value);
- }
- }
- return $result;
- }
-
}
diff --git a/lib/ocs/cloud.php b/lib/private/ocs/cloud.php
index 132d923d960..cbbf3b626f5 100644
--- a/lib/ocs/cloud.php
+++ b/lib/private/ocs/cloud.php
@@ -35,13 +35,58 @@ class OC_OCS_Cloud {
'edition' => OC_Util::getEditionString(),
);
- $result['capabilities'] = array(
- 'core' => array(
- 'pollinterval' => OC_Config::getValue('pollinterval', 60),
- ),
- );
+ $result['capabilities'] = array(
+ 'core' => array(
+ 'pollinterval' => OC_Config::getValue('pollinterval', 60),
+ ),
+ );
+
return new OC_OCS_Result($result);
}
+
+ /**
+ * gets user info
+ *
+ * exposes the quota of an user:
+ * <data>
+ * <quota>
+ * <free>1234</free>
+ * <used>4321</used>
+ * <total>5555</total>
+ * <ralative>0.78</ralative>
+ * </quota>
+ * </data>
+ *
+ * @param $parameters object should contain parameter 'userid' which identifies
+ * the user from whom the information will be returned
+ */
+ public static function getUser($parameters) {
+ // Check if they are viewing information on themselves
+ if($parameters['userid'] === OC_User::getUser()) {
+ // Self lookup
+ $storage = OC_Helper::getStorageInfo('/');
+ $quota = array(
+ 'free' => $storage['free'],
+ 'used' => $storage['used'],
+ 'total' => $storage['total'],
+ 'relative' => $storage['relative'],
+ );
+ return new OC_OCS_Result(array('quota' => $quota));
+ } else {
+ // No permission to view this user data
+ return new OC_OCS_Result(null, 997);
+ }
+ }
+
+ public static function getCurrentUser() {
+ $email=OC_Preferences::getValue(OC_User::getUser(), 'settings', 'email', '');
+ $data = array(
+ 'id' => OC_User::getUser(),
+ 'display-name' => OC_User::getDisplayName(),
+ 'email' => $email,
+ );
+ return new OC_OCS_Result($data);
+ }
public static function getUserPublickey($parameters) {
diff --git a/lib/ocs/config.php b/lib/private/ocs/config.php
index f19121f4b2b..f19121f4b2b 100644
--- a/lib/ocs/config.php
+++ b/lib/private/ocs/config.php
diff --git a/lib/ocs/person.php b/lib/private/ocs/person.php
index 1c8210d0825..1c8210d0825 100644
--- a/lib/ocs/person.php
+++ b/lib/private/ocs/person.php
diff --git a/lib/private/ocs/privatedata.php b/lib/private/ocs/privatedata.php
new file mode 100644
index 00000000000..932413711b8
--- /dev/null
+++ b/lib/private/ocs/privatedata.php
@@ -0,0 +1,108 @@
+<?php
+/**
+* ownCloud
+*
+* @author Frank Karlitschek
+* @author Tom Needham
+* @copyright 2012 Frank Karlitschek frank@owncloud.org
+* @copyright 2012 Tom Needham tom@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/>.
+*
+*/
+
+
+class OC_OCS_Privatedata {
+
+ /**
+ * read keys
+ * test: curl http://login:passwd@oc/core/ocs/v1.php/privatedata/getattribute/testy/123
+ * test: curl http://login:passwd@oc/core/ocs/v1.php/privatedata/getattribute/testy
+ * @param array $parameters The OCS parameter
+ * @return \OC_OCS_Result
+ */
+ public static function get($parameters) {
+ $user = OC_User::getUser();
+ $app = addslashes(strip_tags($parameters['app']));
+ $key = isset($parameters['key']) ? addslashes(strip_tags($parameters['key'])) : null;
+
+ if(empty($key)) {
+ $query = \OCP\DB::prepare('SELECT `key`, `app`, `value` FROM `*PREFIX*privatedata` WHERE `user` = ? AND `app` = ? ');
+ $result = $query->execute(array($user, $app));
+ } else {
+ $query = \OCP\DB::prepare('SELECT `key`, `app`, `value` FROM `*PREFIX*privatedata` WHERE `user` = ? AND `app` = ? AND `key` = ? ');
+ $result = $query->execute(array($user, $app, $key));
+ }
+
+ $xml = array();
+ while ($row = $result->fetchRow()) {
+ $data=array();
+ $data['key']=$row['key'];
+ $data['app']=$row['app'];
+ $data['value']=$row['value'];
+ $xml[] = $data;
+ }
+
+ return new OC_OCS_Result($xml);
+ }
+
+ /**
+ * set a key
+ * test: curl http://login:passwd@oc/core/ocs/v1.php/privatedata/setattribute/testy/123 --data "value=foobar"
+ * @param array $parameters The OCS parameter
+ * @return \OC_OCS_Result
+ */
+ public static function set($parameters) {
+ $user = OC_User::getUser();
+ $app = addslashes(strip_tags($parameters['app']));
+ $key = addslashes(strip_tags($parameters['key']));
+ $value = OC_OCS::readData('post', 'value', 'text');
+
+ // update in DB
+ $query = \OCP\DB::prepare('UPDATE `*PREFIX*privatedata` SET `value` = ? WHERE `user` = ? AND `app` = ? AND `key` = ?');
+ $numRows = $query->execute(array($value, $user, $app, $key));
+
+ if ($numRows === false || $numRows === 0) {
+ // store in DB
+ $query = \OCP\DB::prepare('INSERT INTO `*PREFIX*privatedata` (`user`, `app`, `key`, `value`)' . ' VALUES(?, ?, ?, ?)');
+ $query->execute(array($user, $app, $key, $value));
+ }
+
+ return new OC_OCS_Result(null, 100);
+ }
+
+ /**
+ * delete a key
+ * test: curl http://login:passwd@oc/core/ocs/v1.php/privatedata/deleteattribute/testy/123 --data "post=1"
+ * @param array $parameters The OCS parameter
+ * @return \OC_OCS_Result
+ */
+ public static function delete($parameters) {
+ $user = OC_User::getUser();
+ if (!isset($parameters['app']) or !isset($parameters['key'])) {
+ //key and app are NOT optional here
+ return new OC_OCS_Result(null, 101);
+ }
+
+ $app = addslashes(strip_tags($parameters['app']));
+ $key = addslashes(strip_tags($parameters['key']));
+
+ // delete in DB
+ $query = \OCP\DB::prepare('DELETE FROM `*PREFIX*privatedata` WHERE `user` = ? AND `app` = ? AND `key` = ? ');
+ $query->execute(array($user, $app, $key ));
+
+ return new OC_OCS_Result(null, 100);
+ }
+}
+
diff --git a/lib/ocs/result.php b/lib/private/ocs/result.php
index 729c39056d9..84f06fa01c7 100644
--- a/lib/ocs/result.php
+++ b/lib/private/ocs/result.php
@@ -94,4 +94,4 @@ class OC_OCS_Result{
}
-} \ No newline at end of file
+}
diff --git a/lib/ocsclient.php b/lib/private/ocsclient.php
index bd0302a2a81..e35556d92b8 100644
--- a/lib/ocsclient.php
+++ b/lib/private/ocsclient.php
@@ -36,20 +36,15 @@ class OC_OCSClient{
* to set it in the config file or it will fallback to the default
*/
private static function getAppStoreURL() {
- $url = OC_Config::getValue('appstoreurl', 'http://api.apps.owncloud.com/v1');
+ if(OC_Util::getEditionString()===''){
+ $default='http://api.apps.owncloud.com/v1';
+ }else{
+ $default='';
+ }
+ $url = OC_Config::getValue('appstoreurl', $default);
return($url);
}
- /**
- * @brief Get the url of the OCS KB server.
- * @returns string of the KB server
- * This function returns the url of the OCS knowledge base server. It´s
- * possible to set it in the config file or it will fallback to the default
- */
- private static function getKBURL() {
- $url = OC_Config::getValue('knowledgebaseurl', 'http://api.apps.owncloud.com/v1');
- return($url);
- }
/**
* @brief Get the content of an OCS url call.
@@ -214,44 +209,5 @@ class OC_OCSClient{
}
- /**
- * @brief Get all the knowledgebase entries from the OCS server
- * @returns array with q and a data
- *
- * This function returns a list of all the knowledgebase entries from the OCS server
- */
- public static function getKnownledgebaseEntries($page, $pagesize, $search='') {
- $kbe = array('totalitems' => 0);
- if(OC_Config::getValue('knowledgebaseenabled', true)) {
- $p = (int) $page;
- $s = (int) $pagesize;
- $searchcmd = '';
- if ($search) {
- $searchcmd = '&search='.urlencode($search);
- }
- $url = OC_OCSClient::getKBURL().'/knowledgebase/data?type=150&page='. $p .'&pagesize='. $s . $searchcmd;
- $xml = OC_OCSClient::getOCSresponse($url);
- $data = @simplexml_load_string($xml);
- if($data===false) {
- OC_Log::write('core', 'Unable to parse knowledgebase content', OC_Log::FATAL);
- return null;
- }
- $tmp = $data->data->content;
- for($i = 0; $i < count($tmp); $i++) {
- $kbe[] = array(
- 'id' => $tmp[$i]->id,
- 'name' => $tmp[$i]->name,
- 'description' => $tmp[$i]->description,
- 'answer' => $tmp[$i]->answer,
- 'preview1' => $tmp[$i]->smallpreviewpic1,
- 'detailpage' => $tmp[$i]->detailpage
- );
- }
- $kbe['totalitems'] = $data->meta->totalitems;
- }
- return $kbe;
- }
-
-
}
diff --git a/lib/preferences.php b/lib/private/preferences.php
index 11ca760830e..359d9a83589 100644
--- a/lib/preferences.php
+++ b/lib/private/preferences.php
@@ -34,10 +34,21 @@
*
*/
+namespace OC;
+
+use \OC\DB\Connection;
+
+
/**
* This class provides an easy way for storing user preferences.
*/
-class OC_Preferences{
+class Preferences {
+ protected $conn;
+
+ public function __construct(Connection $conn) {
+ $this->conn = $conn;
+ }
+
/**
* @brief Get all users using the preferences
* @return array with user ids
@@ -45,14 +56,13 @@ class OC_Preferences{
* This function returns a list of all users that have at least one entry
* in the preferences table.
*/
- public static function getUsers() {
- // No need for more comments
- $query = OC_DB::prepare( 'SELECT DISTINCT( `userid` ) FROM `*PREFIX*preferences`' );
- $result = $query->execute();
+ public function getUsers() {
+ $query = 'SELECT DISTINCT `userid` FROM `*PREFIX*preferences`';
+ $result = $this->conn->executeQuery( $query );
$users = array();
- while( $row = $result->fetchRow()) {
- $users[] = $row["userid"];
+ while( $userid = $result->fetchColumn()) {
+ $users[] = $userid;
}
return $users;
@@ -66,14 +76,13 @@ class OC_Preferences{
* This function returns a list of all apps of the user that have at least
* one entry in the preferences table.
*/
- public static function getApps( $user ) {
- // No need for more comments
- $query = OC_DB::prepare( 'SELECT DISTINCT( `appid` ) FROM `*PREFIX*preferences` WHERE `userid` = ?' );
- $result = $query->execute( array( $user ));
+ public function getApps( $user ) {
+ $query = 'SELECT DISTINCT `appid` FROM `*PREFIX*preferences` WHERE `userid` = ?';
+ $result = $this->conn->executeQuery( $query, array( $user ) );
$apps = array();
- while( $row = $result->fetchRow()) {
- $apps[] = $row["appid"];
+ while( $appid = $result->fetchColumn()) {
+ $apps[] = $appid;
}
return $apps;
@@ -88,14 +97,13 @@ class OC_Preferences{
* This function gets all keys of an app of an user. Please note that the
* values are not returned.
*/
- public static function getKeys( $user, $app ) {
- // No need for more comments
- $query = OC_DB::prepare( 'SELECT `configkey` FROM `*PREFIX*preferences` WHERE `userid` = ? AND `appid` = ?' );
- $result = $query->execute( array( $user, $app ));
+ public function getKeys( $user, $app ) {
+ $query = 'SELECT `configkey` FROM `*PREFIX*preferences` WHERE `userid` = ? AND `appid` = ?';
+ $result = $this->conn->executeQuery( $query, array( $user, $app ));
$keys = array();
- while( $row = $result->fetchRow()) {
- $keys[] = $row["configkey"];
+ while( $key = $result->fetchColumn()) {
+ $keys[] = $key;
}
return $keys;
@@ -112,16 +120,14 @@ class OC_Preferences{
* This function gets a value from the preferences table. If the key does
* not exist the default value will be returned
*/
- public static function getValue( $user, $app, $key, $default = null ) {
+ public function getValue( $user, $app, $key, $default = null ) {
// Try to fetch the value, return default if not exists.
- $query = OC_DB::prepare( 'SELECT `configvalue` FROM `*PREFIX*preferences`'
- .' WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?' );
- $result = $query->execute( array( $user, $app, $key ));
-
- $row = $result->fetchRow();
+ $query = 'SELECT `configvalue` FROM `*PREFIX*preferences`'
+ .' WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?';
+ $row = $this->conn->fetchAssoc( $query, array( $user, $app, $key ));
if($row) {
return $row["configvalue"];
- }else{
+ } else {
return $default;
}
}
@@ -132,29 +138,36 @@ class OC_Preferences{
* @param string $app app
* @param string $key key
* @param string $value value
- * @return bool
*
* Adds a value to the preferences. If the key did not exist before, it
* will be added automagically.
*/
- public static function setValue( $user, $app, $key, $value ) {
+ public function setValue( $user, $app, $key, $value ) {
// Check if the key does exist
- $query = OC_DB::prepare( 'SELECT `configvalue` FROM `*PREFIX*preferences`'
- .' WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?' );
- $values=$query->execute(array($user, $app, $key))->fetchAll();
- $exists=(count($values)>0);
+ $query = 'SELECT COUNT(*) FROM `*PREFIX*preferences`'
+ .' WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?';
+ $count = $this->conn->fetchColumn( $query, array( $user, $app, $key ));
+ $exists = $count > 0;
if( !$exists ) {
- $query = OC_DB::prepare( 'INSERT INTO `*PREFIX*preferences`'
- .' ( `userid`, `appid`, `configkey`, `configvalue` ) VALUES( ?, ?, ?, ? )' );
- $query->execute( array( $user, $app, $key, $value ));
+ $data = array(
+ 'userid' => $user,
+ 'appid' => $app,
+ 'configkey' => $key,
+ 'configvalue' => $value,
+ );
+ $this->conn->insert('*PREFIX*preferences', $data);
+ } else {
+ $data = array(
+ 'configvalue' => $value,
+ );
+ $where = array(
+ 'userid' => $user,
+ 'appid' => $app,
+ 'configkey' => $key,
+ );
+ $this->conn->update('*PREFIX*preferences', $data, $where);
}
- else{
- $query = OC_DB::prepare( 'UPDATE `*PREFIX*preferences` SET `configvalue` = ?'
- .' WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?' );
- $query->execute( array( $value, $user, $app, $key ));
- }
- return true;
}
/**
@@ -162,62 +175,58 @@ class OC_Preferences{
* @param string $user user
* @param string $app app
* @param string $key key
- * @return bool
*
* Deletes a key.
*/
- public static function deleteKey( $user, $app, $key ) {
- // No need for more comments
- $query = OC_DB::prepare( 'DELETE FROM `*PREFIX*preferences`'
- .' WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?' );
- $query->execute( array( $user, $app, $key ));
-
- return true;
+ public function deleteKey( $user, $app, $key ) {
+ $where = array(
+ 'userid' => $user,
+ 'appid' => $app,
+ 'configkey' => $key,
+ );
+ $this->conn->delete('*PREFIX*preferences', $where);
}
/**
* @brief Remove app of user from preferences
* @param string $user user
* @param string $app app
- * @return bool
*
- * Removes all keys in appconfig belonging to the app and the user.
+ * Removes all keys in preferences belonging to the app and the user.
*/
- public static function deleteApp( $user, $app ) {
- // No need for more comments
- $query = OC_DB::prepare( 'DELETE FROM `*PREFIX*preferences` WHERE `userid` = ? AND `appid` = ?' );
- $query->execute( array( $user, $app ));
-
- return true;
+ public function deleteApp( $user, $app ) {
+ $where = array(
+ 'userid' => $user,
+ 'appid' => $app,
+ );
+ $this->conn->delete('*PREFIX*preferences', $where);
}
/**
* @brief Remove user from preferences
* @param string $user user
- * @return bool
*
- * Removes all keys in appconfig belonging to the user.
+ * Removes all keys in preferences belonging to the user.
*/
- public static function deleteUser( $user ) {
- // No need for more comments
- $query = OC_DB::prepare( 'DELETE FROM `*PREFIX*preferences` WHERE `userid` = ?' );
- $query->execute( array( $user ));
-
- return true;
+ public function deleteUser( $user ) {
+ $where = array(
+ 'userid' => $user,
+ );
+ $this->conn->delete('*PREFIX*preferences', $where);
}
/**
* @brief Remove app from all users
* @param string $app app
- * @return bool
*
* Removes all keys in preferences belonging to the app.
*/
- public static function deleteAppFromAllUsers( $app ) {
- // No need for more comments
- $query = OC_DB::prepare( 'DELETE FROM `*PREFIX*preferences` WHERE `appid` = ?' );
- $query->execute( array( $app ));
-
- return true;
+ public function deleteAppFromAllUsers( $app ) {
+ $where = array(
+ 'appid' => $app,
+ );
+ $this->conn->delete('*PREFIX*preferences', $where);
}
}
+
+require_once __DIR__.'/legacy/'.basename(__FILE__);
diff --git a/lib/private/preview.php b/lib/private/preview.php
new file mode 100755
index 00000000000..ff93f438f73
--- /dev/null
+++ b/lib/private/preview.php
@@ -0,0 +1,641 @@
+<?php
+/**
+ * Copyright (c) 2013 Frank Karlitschek frank@owncloud.org
+ * Copyright (c) 2013 Georg Ehrke georg@ownCloud.com
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ *
+ * Thumbnails:
+ * structure of filename:
+ * /data/user/thumbnails/pathhash/x-y.png
+ *
+ */
+namespace OC;
+
+require_once 'preview/image.php';
+require_once 'preview/movies.php';
+require_once 'preview/mp3.php';
+require_once 'preview/pdf.php';
+require_once 'preview/svg.php';
+require_once 'preview/txt.php';
+require_once 'preview/unknown.php';
+require_once 'preview/office.php';
+
+class Preview {
+ //the thumbnail folder
+ const THUMBNAILS_FOLDER = 'thumbnails';
+
+ //config
+ private $maxScaleFactor;
+ private $configMaxX;
+ private $configMaxY;
+
+ //fileview object
+ private $fileView = null;
+ private $userView = null;
+
+ //vars
+ private $file;
+ private $maxX;
+ private $maxY;
+ private $scalingup;
+ private $mimetype;
+
+ //preview images object
+ /**
+ * @var \OC_Image
+ */
+ private $preview;
+
+ //preview providers
+ static private $providers = array();
+ static private $registeredProviders = array();
+
+ /**
+ * @brief check if thumbnail or bigger version of thumbnail of file is cached
+ * @param string $user userid - if no user is given, OC_User::getUser will be used
+ * @param string $root path of root
+ * @param string $file The path to the file where you want a thumbnail from
+ * @param int $maxX The maximum X size of the thumbnail. It can be smaller depending on the shape of the image
+ * @param int $maxY The maximum Y size of the thumbnail. It can be smaller depending on the shape of the image
+ * @param bool $scalingUp Disable/Enable upscaling of previews
+ * @return mixed (bool / string)
+ * false if thumbnail does not exist
+ * path to thumbnail if thumbnail exists
+ */
+ public function __construct($user='', $root='/', $file='', $maxX=1, $maxY=1, $scalingUp=true) {
+ //init fileviews
+ if($user === ''){
+ $user = \OC_User::getUser();
+ }
+ $this->fileView = new \OC\Files\View('/' . $user . '/' . $root);
+ $this->userView = new \OC\Files\View('/' . $user);
+
+ //set config
+ $this->configMaxX = \OC_Config::getValue('preview_max_x', null);
+ $this->configMaxY = \OC_Config::getValue('preview_max_y', null);
+ $this->maxScaleFactor = \OC_Config::getValue('preview_max_scale_factor', 2);
+
+ //save parameters
+ $this->setFile($file);
+ $this->setMaxX($maxX);
+ $this->setMaxY($maxY);
+ $this->setScalingUp($scalingUp);
+
+ $this->preview = null;
+
+ //check if there are preview backends
+ if(empty(self::$providers)) {
+ self::initProviders();
+ }
+
+ if(empty(self::$providers)) {
+ \OC_Log::write('core', 'No preview providers exist', \OC_Log::ERROR);
+ throw new \Exception('No preview providers');
+ }
+ }
+
+ /**
+ * @brief returns the path of the file you want a thumbnail from
+ * @return string
+ */
+ public function getFile() {
+ return $this->file;
+ }
+
+ /**
+ * @brief returns the max width of the preview
+ * @return integer
+ */
+ public function getMaxX() {
+ return $this->maxX;
+ }
+
+ /**
+ * @brief returns the max height of the preview
+ * @return integer
+ */
+ public function getMaxY() {
+ return $this->maxY;
+ }
+
+ /**
+ * @brief returns whether or not scalingup is enabled
+ * @return bool
+ */
+ public function getScalingUp() {
+ return $this->scalingup;
+ }
+
+ /**
+ * @brief returns the name of the thumbnailfolder
+ * @return string
+ */
+ public function getThumbnailsFolder() {
+ return self::THUMBNAILS_FOLDER;
+ }
+
+ /**
+ * @brief returns the max scale factor
+ * @return integer
+ */
+ public function getMaxScaleFactor() {
+ return $this->maxScaleFactor;
+ }
+
+ /**
+ * @brief returns the max width set in ownCloud's config
+ * @return integer
+ */
+ public function getConfigMaxX() {
+ return $this->configMaxX;
+ }
+
+ /**
+ * @brief returns the max height set in ownCloud's config
+ * @return integer
+ */
+ public function getConfigMaxY() {
+ return $this->configMaxY;
+ }
+
+ /**
+ * @brief set the path of the file you want a thumbnail from
+ * @param string $file
+ * @return $this
+ */
+ public function setFile($file) {
+ $this->file = $file;
+ if ($file !== '') {
+ $this->mimetype = $this->fileView->getMimeType($this->file);
+ }
+ return $this;
+ }
+
+ /**
+ * @brief set mimetype explicitely
+ * @param string $mimetype
+ */
+ public function setMimetype($mimetype) {
+ $this->mimetype = $mimetype;
+ }
+
+ /**
+ * @brief set the the max width of the preview
+ * @param int $maxX
+ * @return $this
+ */
+ public function setMaxX($maxX=1) {
+ if($maxX <= 0) {
+ throw new \Exception('Cannot set width of 0 or smaller!');
+ }
+ $configMaxX = $this->getConfigMaxX();
+ if(!is_null($configMaxX)) {
+ if($maxX > $configMaxX) {
+ \OC_Log::write('core', 'maxX reduced from ' . $maxX . ' to ' . $configMaxX, \OC_Log::DEBUG);
+ $maxX = $configMaxX;
+ }
+ }
+ $this->maxX = $maxX;
+ return $this;
+ }
+
+ /**
+ * @brief set the the max height of the preview
+ * @param int $maxY
+ * @return $this
+ */
+ public function setMaxY($maxY=1) {
+ if($maxY <= 0) {
+ throw new \Exception('Cannot set height of 0 or smaller!');
+ }
+ $configMaxY = $this->getConfigMaxY();
+ if(!is_null($configMaxY)) {
+ if($maxY > $configMaxY) {
+ \OC_Log::write('core', 'maxX reduced from ' . $maxY . ' to ' . $configMaxY, \OC_Log::DEBUG);
+ $maxY = $configMaxY;
+ }
+ }
+ $this->maxY = $maxY;
+ return $this;
+ }
+
+ /**
+ * @brief set whether or not scalingup is enabled
+ * @param bool $scalingUp
+ * @return $this
+ */
+ public function setScalingup($scalingUp) {
+ if($this->getMaxScaleFactor() === 1) {
+ $scalingUp = false;
+ }
+ $this->scalingup = $scalingUp;
+ return $this;
+ }
+
+ /**
+ * @brief check if all parameters are valid
+ * @return bool
+ */
+ public function isFileValid() {
+ $file = $this->getFile();
+ if($file === '') {
+ \OC_Log::write('core', 'No filename passed', \OC_Log::DEBUG);
+ return false;
+ }
+
+ if(!$this->fileView->file_exists($file)) {
+ \OC_Log::write('core', 'File:"' . $file . '" not found', \OC_Log::DEBUG);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * @brief deletes previews of a file with specific x and y
+ * @return bool
+ */
+ public function deletePreview() {
+ $file = $this->getFile();
+
+ $fileInfo = $this->fileView->getFileInfo($file);
+ $fileId = $fileInfo['fileid'];
+
+ $previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/' . $this->getMaxX() . '-' . $this->getMaxY() . '.png';
+ $this->userView->unlink($previewPath);
+ return !$this->userView->file_exists($previewPath);
+ }
+
+ /**
+ * @brief deletes all previews of a file
+ * @return bool
+ */
+ public function deleteAllPreviews() {
+ $file = $this->getFile();
+
+ $fileInfo = $this->fileView->getFileInfo($file);
+ $fileId = $fileInfo['fileid'];
+
+ $previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/';
+ $this->userView->deleteAll($previewPath);
+ $this->userView->rmdir($previewPath);
+ return !$this->userView->is_dir($previewPath);
+ }
+
+ /**
+ * @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
+ */
+ private function isCached() {
+ $file = $this->getFile();
+ $maxX = $this->getMaxX();
+ $maxY = $this->getMaxY();
+ $scalingUp = $this->getScalingUp();
+ $maxScaleFactor = $this->getMaxScaleFactor();
+
+ $fileInfo = $this->fileView->getFileInfo($file);
+ $fileId = $fileInfo['fileid'];
+
+ if(is_null($fileId)) {
+ return false;
+ }
+
+ $previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/';
+ if(!$this->userView->is_dir($previewPath)) {
+ return false;
+ }
+
+ //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';
+ }
+
+ $wantedAspectRatio = (float) ($maxX / $maxY);
+
+ //array for usable cached thumbnails
+ $possibleThumbnails = array();
+
+ $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];
+
+ $aspectRatio = (float) ($x / $y);
+ if($aspectRatio !== $wantedAspectRatio) {
+ 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));
+ }
+
+ if(key(end($possibleThumbnails)) < $maxX) {
+ return current(end($possibleThumbnails));
+ }
+
+ foreach($possibleThumbnails as $width => $path) {
+ if($width < $maxX) {
+ continue;
+ }else{
+ return $path;
+ }
+ }
+ }
+
+ /**
+ * @brief return a preview of a file
+ * @return \OC_Image
+ */
+ public function getPreview() {
+ if(!is_null($this->preview) && $this->preview->valid()){
+ return $this->preview;
+ }
+
+ $this->preview = null;
+ $file = $this->getFile();
+ $maxX = $this->getMaxX();
+ $maxY = $this->getMaxY();
+ $scalingUp = $this->getScalingUp();
+
+ $fileInfo = $this->fileView->getFileInfo($file);
+ $fileId = $fileInfo['fileid'];
+
+ $cached = $this->isCached();
+
+ if($cached) {
+ $image = new \OC_Image($this->userView->file_get_contents($cached, 'r'));
+ $this->preview = $image->valid() ? $image : null;
+ $this->resizeAndCrop();
+ }
+
+ if(is_null($this->preview)) {
+ $preview = null;
+
+ 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);
+
+ $preview = $provider->getThumbnail($file, $maxX, $maxY, $scalingUp, $this->fileView);
+
+ if(!($preview instanceof \OC_Image)) {
+ continue;
+ }
+
+ $this->preview = $preview;
+ $this->resizeAndCrop();
+
+ $previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/';
+ $cachePath = $previewPath . $maxX . '-' . $maxY . '.png';
+
+ if($this->userView->is_dir($this->getThumbnailsFolder() . '/') === false) {
+ $this->userView->mkdir($this->getThumbnailsFolder() . '/');
+ }
+
+ if($this->userView->is_dir($previewPath) === false) {
+ $this->userView->mkdir($previewPath);
+ }
+
+ $this->userView->file_put_contents($cachePath, $preview->data());
+
+ break;
+ }
+ }
+
+ if(is_null($this->preview)) {
+ $this->preview = new \OC_Image();
+ }
+
+ return $this->preview;
+ }
+
+ /**
+ * @brief show preview
+ * @return void
+ */
+ public function showPreview() {
+ \OCP\Response::enableCaching(3600 * 24); // 24 hours
+ if(is_null($this->preview)) {
+ $this->getPreview();
+ }
+ $this->preview->show();
+ return;
+ }
+
+ /**
+ * @brief show preview
+ * @return void
+ */
+ public function show() {
+ $this->showPreview();
+ return;
+ }
+
+ /**
+ * @brief resize, crop and fix orientation
+ * @return void
+ */
+ private function resizeAndCrop() {
+ $image = $this->preview;
+ $x = $this->getMaxX();
+ $y = $this->getMaxY();
+ $scalingUp = $this->getScalingUp();
+ $maxscalefactor = $this->getMaxScaleFactor();
+
+ if(!($image instanceof \OC_Image)) {
+ \OC_Log::write('core', '$this->preview is not an instance of OC_Image', \OC_Log::DEBUG);
+ return;
+ }
+
+ $image->fixOrientation();
+
+ $realx = (int) $image->width();
+ $realy = (int) $image->height();
+
+ if($x === $realx && $y === $realy) {
+ $this->preview = $image;
+ return;
+ }
+
+ $factorX = $x / $realx;
+ $factorY = $y / $realy;
+
+ if($factorX >= $factorY) {
+ $factor = $factorX;
+ }else{
+ $factor = $factorY;
+ }
+
+ if($scalingUp === false) {
+ if($factor > 1) {
+ $factor = 1;
+ }
+ }
+
+ if(!is_null($maxscalefactor)) {
+ if($factor > $maxscalefactor) {
+ \OC_Log::write('core', 'scalefactor reduced from ' . $factor . ' to ' . $maxscalefactor, \OC_Log::DEBUG);
+ $factor = $maxscalefactor;
+ }
+ }
+
+ $newXsize = (int) ($realx * $factor);
+ $newYsize = (int) ($realy * $factor);
+
+ $image->preciseResize($newXsize, $newYsize);
+
+ if($newXsize === $x && $newYsize === $y) {
+ $this->preview = $image;
+ return;
+ }
+
+ 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;
+
+ $image->crop($cropX, $cropY, $x, $y);
+
+ $this->preview = $image;
+ return;
+ }
+
+ 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);
+ }
+
+ $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);
+
+ $image = $image->resource();
+
+ $mergeX = floor(abs($x - $newXsize) * 0.5);
+ $mergeY = floor(abs($y - $newYsize) * 0.5);
+
+ imagecopy($backgroundlayer, $image, $mergeX, $mergeY, 0, 0, $newXsize, $newYsize);
+
+ //$black = imagecolorallocate(0,0,0);
+ //imagecolortransparent($transparentlayer, $black);
+
+ $image = new \OC_Image($backgroundlayer);
+
+ $this->preview = $image;
+ return;
+ }
+ }
+
+ /**
+ * @brief register a new preview provider to be used
+ * @param string $provider class name of a Preview_Provider
+ * @param array $options
+ * @return void
+ */
+ public static function registerProvider($class, $options=array()) {
+ self::$registeredProviders[]=array('class'=>$class, 'options'=>$options);
+ }
+
+ /**
+ * @brief create instances of all the registered preview providers
+ * @return void
+ */
+ private static function initProviders() {
+ if(!\OC_Config::getValue('enable_previews', true)) {
+ $provider = new Preview\Unknown(array());
+ self::$providers = array($provider->getMimeType() => $provider);
+ return;
+ }
+
+ if(count(self::$providers)>0) {
+ return;
+ }
+
+ foreach(self::$registeredProviders as $provider) {
+ $class=$provider['class'];
+ $options=$provider['options'];
+
+ $object = new $class($options);
+
+ self::$providers[$object->getMimeType()] = $object;
+ }
+
+ $keys = array_map('strlen', array_keys(self::$providers));
+ array_multisort($keys, SORT_DESC, self::$providers);
+ }
+
+ public static function post_write($args) {
+ self::post_delete($args);
+ }
+
+ public static function post_delete($args) {
+ $path = $args['path'];
+ if(substr($path, 0, 1) === '/') {
+ $path = substr($path, 1);
+ }
+ $preview = new Preview(\OC_User::getUser(), 'files/', $path);
+ $preview->deleteAllPreviews();
+ }
+
+ public static function isMimeSupported($mimetype) {
+ if(!\OC_Config::getValue('enable_previews', true)) {
+ return false;
+ }
+
+ //check if there are preview backends
+ if(empty(self::$providers)) {
+ self::initProviders();
+ }
+
+ //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)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/lib/private/preview/image.php b/lib/private/preview/image.php
new file mode 100644
index 00000000000..84343df2608
--- /dev/null
+++ b/lib/private/preview/image.php
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Copyright (c) 2013 Frank Karlitschek frank@owncloud.org
+ * Copyright (c) 2013 Georg Ehrke georg@ownCloud.com
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+namespace OC\Preview;
+
+class Image extends Provider {
+
+ public function getMimeType() {
+ return '/image\/.*/';
+ }
+
+ public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview) {
+ //get fileinfo
+ $fileInfo = $fileview->getFileInfo($path);
+ if(!$fileInfo) {
+ return false;
+ }
+
+ $image = new \OC_Image();
+ //check if file is encrypted
+ if($fileInfo['encrypted'] === true) {
+ $image->loadFromData(stream_get_contents($fileview->fopen($path, 'r')));
+ }else{
+ $image->loadFromFile($fileview->getLocalFile($path));
+ }
+
+ return $image->valid() ? $image : false;
+ }
+}
+
+\OC\Preview::registerProvider('OC\Preview\Image'); \ No newline at end of file
diff --git a/lib/private/preview/movies.php b/lib/private/preview/movies.php
new file mode 100644
index 00000000000..ac771deb413
--- /dev/null
+++ b/lib/private/preview/movies.php
@@ -0,0 +1,90 @@
+<?php
+/**
+ * Copyright (c) 2013 Frank Karlitschek frank@owncloud.org
+ * Copyright (c) 2013 Georg Ehrke georg@ownCloud.com
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+namespace OC\Preview;
+
+function findBinaryPath($program) {
+ exec('which ' . escapeshellarg($program) . ' 2> /dev/null', $output, $returnCode);
+ if ($returnCode === 0 && count($output) > 0) {
+ return escapeshellcmd($output[0]);
+ }
+ return null;
+}
+
+// movie preview is currently not supported on Windows
+if (!\OC_Util::runningOnWindows()) {
+ $isExecEnabled = !in_array('exec', explode(', ', ini_get('disable_functions')));
+ $ffmpegBinary = null;
+ $avconvBinary = null;
+
+ if ($isExecEnabled) {
+ $avconvBinary = findBinaryPath('avconv');
+ if (!$avconvBinary) {
+ $ffmpegBinary = findBinaryPath('ffmpeg');
+ }
+ }
+
+ if($isExecEnabled && ( $avconvBinary || $ffmpegBinary )) {
+
+ class Movie extends Provider {
+ public static $avconvBinary;
+ public static $ffmpegBinary;
+
+ public function getMimeType() {
+ return '/video\/.*/';
+ }
+
+ public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview) {
+ // TODO: use proc_open() and stream the source file ?
+ $absPath = \OC_Helper::tmpFile();
+ $tmpPath = \OC_Helper::tmpFile();
+
+ $handle = $fileview->fopen($path, 'rb');
+
+ // we better use 5MB (1024 * 1024 * 5 = 5242880) instead of 1MB.
+ // in some cases 1MB was no enough to generate thumbnail
+ $firstmb = stream_get_contents($handle, 5242880);
+ file_put_contents($absPath, $firstmb);
+
+ if (self::$avconvBinary) {
+ $cmd = self::$avconvBinary . ' -an -y -ss 5'.
+ ' -i ' . escapeshellarg($absPath) .
+ ' -f mjpeg -vframes 1 -vsync 1 ' . escapeshellarg($tmpPath) .
+ ' > /dev/null 2>&1';
+ }
+ else {
+ $cmd = self::$ffmpegBinary . ' -y -ss 5' .
+ ' -i ' . escapeshellarg($absPath) .
+ ' -f mjpeg -vframes 1' .
+ ' -s ' . escapeshellarg($maxX) . 'x' . escapeshellarg($maxY) .
+ ' ' . escapeshellarg($tmpPath) .
+ ' > /dev/null 2>&1';
+ }
+
+ exec($cmd, $output, $returnCode);
+
+ unlink($absPath);
+
+ if ($returnCode === 0) {
+ $image = new \OC_Image();
+ $image->loadFromFile($tmpPath);
+ unlink($tmpPath);
+ return $image->valid() ? $image : false;
+ }
+ return false;
+ }
+ }
+
+ // a bit hacky but didn't want to use subclasses
+ Movie::$avconvBinary = $avconvBinary;
+ Movie::$ffmpegBinary = $ffmpegBinary;
+
+ \OC\Preview::registerProvider('OC\Preview\Movie');
+ }
+}
+
diff --git a/lib/private/preview/mp3.php b/lib/private/preview/mp3.php
new file mode 100644
index 00000000000..3fc0ab0490c
--- /dev/null
+++ b/lib/private/preview/mp3.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Copyright (c) 2013 Georg Ehrke georg@ownCloud.com
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+namespace OC\Preview;
+
+class MP3 extends Provider {
+
+ public function getMimeType() {
+ return '/audio\/mpeg/';
+ }
+
+ public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview) {
+ require_once('getid3/getid3.php');
+
+ $getID3 = new \getID3();
+
+ $tmpPath = $fileview->toTmpFile($path);
+
+ $tags = $getID3->analyze($tmpPath);
+ \getid3_lib::CopyTagsToComments($tags);
+ if(isset($tags['id3v2']['APIC'][0]['data'])) {
+ $picture = @$tags['id3v2']['APIC'][0]['data'];
+ unlink($tmpPath);
+ $image = new \OC_Image();
+ $image->loadFromData($picture);
+ return $image->valid() ? $image : $this->getNoCoverThumbnail();
+ }
+
+ return $this->getNoCoverThumbnail();
+ }
+
+ private function getNoCoverThumbnail() {
+ $icon = \OC::$SERVERROOT . '/core/img/filetypes/audio.png';
+
+ if(!file_exists($icon)) {
+ return false;
+ }
+
+ $image = new \OC_Image();
+ $image->loadFromFile($icon);
+ return $image->valid() ? $image : false;
+ }
+
+}
+
+\OC\Preview::registerProvider('OC\Preview\MP3'); \ No newline at end of file
diff --git a/lib/private/preview/office-cl.php b/lib/private/preview/office-cl.php
new file mode 100644
index 00000000000..b11fed13ba1
--- /dev/null
+++ b/lib/private/preview/office-cl.php
@@ -0,0 +1,139 @@
+<?php
+/**
+ * Copyright (c) 2013 Georg Ehrke georg@ownCloud.com
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+namespace OC\Preview;
+
+// office preview is currently not supported on Windows
+if (!\OC_Util::runningOnWindows()) {
+
+ //we need imagick to convert
+ class Office extends Provider {
+
+ private $cmd;
+
+ public function getMimeType() {
+ return null;
+ }
+
+ public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview) {
+ $this->initCmd();
+ if(is_null($this->cmd)) {
+ return false;
+ }
+
+ $absPath = $fileview->toTmpFile($path);
+
+ $tmpDir = get_temp_dir();
+
+ $defaultParameters = ' --headless --nologo --nofirststartwizard --invisible --norestore -convert-to pdf -outdir ';
+ $clParameters = \OCP\Config::getSystemValue('preview_office_cl_parameters', $defaultParameters);
+
+ $exec = $this->cmd . $clParameters . escapeshellarg($tmpDir) . ' ' . escapeshellarg($absPath);
+ $export = 'export HOME=/' . $tmpDir;
+
+ shell_exec($export . "\n" . $exec);
+
+ //create imagick object from pdf
+ try{
+ $pdf = new \imagick($absPath . '.pdf' . '[0]');
+ $pdf->setImageFormat('jpg');
+ } catch (\Exception $e) {
+ unlink($absPath);
+ unlink($absPath . '.pdf');
+ \OC_Log::write('core', $e->getmessage(), \OC_Log::ERROR);
+ return false;
+ }
+
+ $image = new \OC_Image();
+ $image->loadFromData($pdf);
+
+ unlink($absPath);
+ unlink($absPath . '.pdf');
+
+ return $image->valid() ? $image : false;
+ }
+
+ private function initCmd() {
+ $cmd = '';
+
+ if(is_string(\OC_Config::getValue('preview_libreoffice_path', null))) {
+ $cmd = \OC_Config::getValue('preview_libreoffice_path', null);
+ }
+
+ $whichLibreOffice = shell_exec('which libreoffice');
+ if($cmd === '' && !empty($whichLibreOffice)) {
+ $cmd = 'libreoffice';
+ }
+
+ $whichOpenOffice = shell_exec('which openoffice');
+ if($cmd === '' && !empty($whichOpenOffice)) {
+ $cmd = 'openoffice';
+ }
+
+ if($cmd === '') {
+ $cmd = null;
+ }
+
+ $this->cmd = $cmd;
+ }
+ }
+
+ //.doc, .dot
+ class MSOfficeDoc extends Office {
+
+ public function getMimeType() {
+ return '/application\/msword/';
+ }
+
+ }
+
+ \OC\Preview::registerProvider('OC\Preview\MSOfficeDoc');
+
+ //.docm, .dotm, .xls(m), .xlt(m), .xla(m), .ppt(m), .pot(m), .pps(m), .ppa(m)
+ class MSOffice2003 extends Office {
+
+ public function getMimeType() {
+ return '/application\/vnd.ms-.*/';
+ }
+
+ }
+
+ \OC\Preview::registerProvider('OC\Preview\MSOffice2003');
+
+ //.docx, .dotx, .xlsx, .xltx, .pptx, .potx, .ppsx
+ class MSOffice2007 extends Office {
+
+ public function getMimeType() {
+ return '/application\/vnd.openxmlformats-officedocument.*/';
+ }
+
+ }
+
+ \OC\Preview::registerProvider('OC\Preview\MSOffice2007');
+
+ //.odt, .ott, .oth, .odm, .odg, .otg, .odp, .otp, .ods, .ots, .odc, .odf, .odb, .odi, .oxt
+ class OpenDocument extends Office {
+
+ public function getMimeType() {
+ return '/application\/vnd.oasis.opendocument.*/';
+ }
+
+ }
+
+ \OC\Preview::registerProvider('OC\Preview\OpenDocument');
+
+ //.sxw, .stw, .sxc, .stc, .sxd, .std, .sxi, .sti, .sxg, .sxm
+ class StarOffice extends Office {
+
+ public function getMimeType() {
+ return '/application\/vnd.sun.xml.*/';
+ }
+
+ }
+
+ \OC\Preview::registerProvider('OC\Preview\StarOffice');
+}
diff --git a/lib/private/preview/office-fallback.php b/lib/private/preview/office-fallback.php
new file mode 100644
index 00000000000..f184b3149d5
--- /dev/null
+++ b/lib/private/preview/office-fallback.php
@@ -0,0 +1,143 @@
+<?php
+/**
+ * Copyright (c) 2013 Georg Ehrke georg@ownCloud.com
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+namespace OC\Preview;
+
+/* //There is no (good) php-only solution for converting 2003 word documents to pdfs / pngs ...
+class DOC extends Provider {
+
+ public function getMimeType() {
+ return '/application\/msword/';
+ }
+
+ public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview) {
+ require_once('');
+ }
+
+}
+
+\OC\Preview::registerProvider('OC\Preview\DOC');
+*/
+
+class DOCX extends Provider {
+
+ public function getMimeType() {
+ return '/application\/vnd.openxmlformats-officedocument.wordprocessingml.document/';
+ }
+
+ public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview) {
+ require_once('phpdocx/classes/TransformDoc.inc');
+
+ $tmpDoc = $fileview->toTmpFile($path);
+
+ $transformdoc = new \TransformDoc();
+ $transformdoc->setStrFile($tmpDoc);
+ $transformdoc->generatePDF($tmpDoc);
+
+ $pdf = new \imagick($tmpDoc . '[0]');
+ $pdf->setImageFormat('jpg');
+
+ unlink($tmpDoc);
+
+ $image = new \OC_Image($pdf);
+
+ return $image->valid() ? $image : false;
+ }
+
+}
+
+\OC\Preview::registerProvider('OC\Preview\DOCX');
+
+class MSOfficeExcel extends Provider {
+
+ public function getMimeType() {
+ return null;
+ }
+
+ public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview) {
+ require_once('PHPExcel/Classes/PHPExcel.php');
+ require_once('PHPExcel/Classes/PHPExcel/IOFactory.php');
+
+ $absPath = $fileview->toTmpFile($path);
+ $tmpPath = \OC_Helper::tmpFile();
+
+ $rendererName = \PHPExcel_Settings::PDF_RENDERER_DOMPDF;
+ $rendererLibraryPath = \OC::$THIRDPARTYROOT . '/3rdparty/dompdf';
+
+ \PHPExcel_Settings::setPdfRenderer($rendererName, $rendererLibraryPath);
+
+ $phpexcel = new \PHPExcel($absPath);
+ $excel = \PHPExcel_IOFactory::createWriter($phpexcel, 'PDF');
+ $excel->save($tmpPath);
+
+ $pdf = new \imagick($tmpPath . '[0]');
+ $pdf->setImageFormat('jpg');
+
+ unlink($absPath);
+ unlink($tmpPath);
+
+ $image = new \OC_Image();
+ $image->loadFromData($pdf);
+
+ return $image->valid() ? $image : false;
+ }
+
+}
+
+class XLS extends MSOfficeExcel {
+
+ public function getMimeType() {
+ return '/application\/vnd.ms-excel/';
+ }
+
+}
+
+\OC\Preview::registerProvider('OC\Preview\XLS');
+
+class XLSX extends MSOfficeExcel {
+
+ public function getMimeType() {
+ return '/application\/vnd.openxmlformats-officedocument.spreadsheetml.sheet/';
+ }
+
+}
+
+\OC\Preview::registerProvider('OC\Preview\XLSX');
+
+/* //There is no (good) php-only solution for converting powerpoint documents to pdfs / pngs ...
+class MSOfficePowerPoint extends Provider {
+
+ public function getMimeType() {
+ return null;
+ }
+
+ public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview) {
+ return false;
+ }
+
+}
+
+class PPT extends MSOfficePowerPoint {
+
+ public function getMimeType() {
+ return '/application\/vnd.ms-powerpoint/';
+ }
+
+}
+
+\OC\Preview::registerProvider('OC\Preview\PPT');
+
+class PPTX extends MSOfficePowerPoint {
+
+ public function getMimeType() {
+ return '/application\/vnd.openxmlformats-officedocument.presentationml.presentation/';
+ }
+
+}
+
+\OC\Preview::registerProvider('OC\Preview\PPTX');
+*/ \ No newline at end of file
diff --git a/lib/private/preview/office.php b/lib/private/preview/office.php
new file mode 100644
index 00000000000..318ab51f851
--- /dev/null
+++ b/lib/private/preview/office.php
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Copyright (c) 2013 Georg Ehrke georg@ownCloud.com
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+//both, libreoffice backend and php fallback, need imagick
+if (extension_loaded('imagick')) {
+ $isShellExecEnabled = !in_array('shell_exec', explode(', ', ini_get('disable_functions')));
+
+ // LibreOffice preview is currently not supported on Windows
+ if (!\OC_Util::runningOnWindows()) {
+ $whichLibreOffice = ($isShellExecEnabled ? shell_exec('which libreoffice') : '');
+ $isLibreOfficeAvailable = !empty($whichLibreOffice);
+ $whichOpenOffice = ($isShellExecEnabled ? shell_exec('which libreoffice') : '');
+ $isOpenOfficeAvailable = !empty($whichOpenOffice);
+ //let's see if there is libreoffice or openoffice on this machine
+ if($isShellExecEnabled && ($isLibreOfficeAvailable || $isOpenOfficeAvailable || is_string(\OC_Config::getValue('preview_libreoffice_path', null)))) {
+ require_once('office-cl.php');
+ }else{
+ //in case there isn't, use our fallback
+ require_once('office-fallback.php');
+ }
+ } else {
+ //in case there isn't, use our fallback
+ require_once('office-fallback.php');
+ }
+}
diff --git a/lib/private/preview/pdf.php b/lib/private/preview/pdf.php
new file mode 100644
index 00000000000..cc974b68818
--- /dev/null
+++ b/lib/private/preview/pdf.php
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Copyright (c) 2013 Georg Ehrke georg@ownCloud.com
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+namespace OC\Preview;
+
+if (extension_loaded('imagick')) {
+
+ class PDF extends Provider {
+
+ public function getMimeType() {
+ return '/application\/pdf/';
+ }
+
+ public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview) {
+ $tmpPath = $fileview->toTmpFile($path);
+
+ //create imagick object from pdf
+ try{
+ $pdf = new \imagick($tmpPath . '[0]');
+ $pdf->setImageFormat('jpg');
+ } catch (\Exception $e) {
+ \OC_Log::write('core', $e->getmessage(), \OC_Log::ERROR);
+ return false;
+ }
+
+ unlink($tmpPath);
+
+ //new image object
+ $image = new \OC_Image($pdf);
+ //check if image object is valid
+ return $image->valid() ? $image : false;
+ }
+ }
+
+ \OC\Preview::registerProvider('OC\Preview\PDF');
+}
diff --git a/lib/private/preview/provider.php b/lib/private/preview/provider.php
new file mode 100644
index 00000000000..65d09705f40
--- /dev/null
+++ b/lib/private/preview/provider.php
@@ -0,0 +1,25 @@
+<?php
+namespace OC\Preview;
+
+abstract class Provider {
+ private $options;
+
+ public function __construct($options) {
+ $this->options=$options;
+ }
+
+ abstract public function getMimeType();
+
+ /**
+ * get thumbnail for file at path $path
+ * @param string $path Path of file
+ * @param int $maxX The maximum X size of the thumbnail. It can be smaller depending on the shape of the image
+ * @param int $maxY The maximum Y size of the thumbnail. It can be smaller depending on the shape of the image
+ * @param bool $scalingUp Disable/Enable upscaling of previews
+ * @param object $fileview fileview object of user folder
+ * @return mixed
+ * false if no preview was generated
+ * OC_Image object of the preview
+ */
+ abstract public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview);
+}
diff --git a/lib/private/preview/svg.php b/lib/private/preview/svg.php
new file mode 100644
index 00000000000..b49e51720fa
--- /dev/null
+++ b/lib/private/preview/svg.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Copyright (c) 2013 Georg Ehrke georg@ownCloud.com
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+namespace OC\Preview;
+
+if (extension_loaded('imagick')) {
+
+ class SVG extends Provider {
+
+ public function getMimeType() {
+ return '/image\/svg\+xml/';
+ }
+
+ public function getThumbnail($path,$maxX,$maxY,$scalingup,$fileview) {
+ try{
+ $svg = new \Imagick();
+ $svg->setBackgroundColor(new \ImagickPixel('transparent'));
+
+ $content = stream_get_contents($fileview->fopen($path, 'r'));
+ if(substr($content, 0, 5) !== '<?xml') {
+ $content = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>' . $content;
+ }
+
+ $svg->readImageBlob($content);
+ $svg->setImageFormat('png32');
+ } catch (\Exception $e) {
+ \OC_Log::write('core', $e->getmessage(), \OC_Log::ERROR);
+ return false;
+ }
+
+
+ //new image object
+ $image = new \OC_Image();
+ $image->loadFromData($svg);
+ //check if image object is valid
+ return $image->valid() ? $image : false;
+ }
+ }
+
+ \OC\Preview::registerProvider('OC\Preview\SVG');
+
+} \ No newline at end of file
diff --git a/lib/private/preview/txt.php b/lib/private/preview/txt.php
new file mode 100644
index 00000000000..c9aa20968d8
--- /dev/null
+++ b/lib/private/preview/txt.php
@@ -0,0 +1,72 @@
+<?php
+/**
+ * Copyright (c) 2013 Georg Ehrke georg@ownCloud.com
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+namespace OC\Preview;
+
+class TXT extends Provider {
+
+ public function getMimeType() {
+ return '/text\/plain/';
+ }
+
+ /**
+ * @param string $path
+ * @param int $maxX
+ * @param int $maxY
+ * @param boolean $scalingup
+ * @param \OC\Files\View $fileview
+ * @return bool|\OC_Image
+ */
+ public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview) {
+
+ $content = $fileview->fopen($path, 'r');
+ $content = stream_get_contents($content);
+
+ //don't create previews of empty text files
+ if(trim($content) === '') {
+ return false;
+ }
+
+ $lines = preg_split("/\r\n|\n|\r/", $content);
+
+ $fontSize = 5; //5px
+ $lineSize = ceil($fontSize * 1.25);
+
+ $image = imagecreate($maxX, $maxY);
+ imagecolorallocate($image, 255, 255, 255);
+ $textColor = imagecolorallocate($image, 0, 0, 0);
+
+ foreach($lines as $index => $line) {
+ $index = $index + 1;
+
+ $x = (int) 1;
+ $y = (int) ($index * $lineSize) - $fontSize;
+
+ imagestring($image, 1, $x, $y, $line, $textColor);
+
+ if(($index * $lineSize) >= $maxY) {
+ break;
+ }
+ }
+
+ $image = new \OC_Image($image);
+
+ return $image->valid() ? $image : false;
+ }
+}
+
+\OC\Preview::registerProvider('OC\Preview\TXT');
+
+class MarkDown extends TXT {
+
+ public function getMimeType() {
+ return '/text\/(x-)?markdown/';
+ }
+
+}
+
+\OC\Preview::registerProvider('OC\Preview\MarkDown');
diff --git a/lib/private/preview/unknown.php b/lib/private/preview/unknown.php
new file mode 100644
index 00000000000..4747f9e25ed
--- /dev/null
+++ b/lib/private/preview/unknown.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * Copyright (c) 2013 Frank Karlitschek frank@owncloud.org
+ * Copyright (c) 2013 Georg Ehrke georg@ownCloud.com
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+namespace OC\Preview;
+
+class Unknown extends Provider {
+
+ public function getMimeType() {
+ return '/.*/';
+ }
+
+ public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview) {
+ $mimetype = $fileview->getMimeType($path);
+
+ $path = \OC_Helper::mimetypeIcon($mimetype);
+ $path = \OC::$SERVERROOT . substr($path, strlen(\OC::$WEBROOT));
+
+ $svgPath = substr_replace($path, 'svg', -3);
+
+ if (extension_loaded('imagick') && file_exists($svgPath)) {
+
+ // http://www.php.net/manual/de/imagick.setresolution.php#85284
+ $svg = new \Imagick();
+ $svg->readImage($svgPath);
+ $res = $svg->getImageResolution();
+ $x_ratio = $res['x'] / $svg->getImageWidth();
+ $y_ratio = $res['y'] / $svg->getImageHeight();
+ $svg->removeImage();
+ $svg->setResolution($maxX * $x_ratio, $maxY * $y_ratio);
+ $svg->setBackgroundColor(new \ImagickPixel('transparent'));
+ $svg->readImage($svgPath);
+ $svg->setImageFormat('png32');
+
+ $image = new \OC_Image();
+ $image->loadFromData($svg);
+ } else {
+ $image = new \OC_Image($path);
+ }
+
+ return $image;
+ }
+}
+
+\OC\Preview::registerProvider('OC\Preview\Unknown');
diff --git a/lib/private/previewmanager.php b/lib/private/previewmanager.php
new file mode 100755
index 00000000000..ac9a866a75b
--- /dev/null
+++ b/lib/private/previewmanager.php
@@ -0,0 +1,38 @@
+<?php
+/**
+ * Copyright (c) 2013 Thomas Müller thomas.mueller@tmit.eu
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ *
+ */
+namespace OC;
+
+use OCP\image;
+use OCP\IPreview;
+
+class PreviewManager implements IPreview {
+ /**
+ * @brief return a preview of a file
+ * @param string $file The path to the file where you want a thumbnail from
+ * @param int $maxX The maximum X size of the thumbnail. It can be smaller depending on the shape of the image
+ * @param int $maxY The maximum Y size of the thumbnail. It can be smaller depending on the shape of the image
+ * @param boolean $scaleUp Scale smaller images up to the thumbnail size or not. Might look ugly
+ * @return \OCP\Image
+ */
+ function createPreview($file, $maxX = 100, $maxY = 75, $scaleUp = false)
+ {
+ $preview = new \OC\Preview('', '/', $file, $maxX, $maxY, $scaleUp);
+ return $preview->getPreview();
+ }
+
+ /**
+ * @brief returns true if the passed mime type is supported
+ * @param string $mimeType
+ * @return boolean
+ */
+ function isMimeSupported($mimeType = '*')
+ {
+ return \OC\Preview::isMimeSupported($mimeType);
+ }
+}
diff --git a/lib/private/repair.php b/lib/private/repair.php
new file mode 100644
index 00000000000..e9de3baa7ce
--- /dev/null
+++ b/lib/private/repair.php
@@ -0,0 +1,21 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC;
+
+use OC\Hooks\BasicEmitter;
+
+class Repair extends BasicEmitter {
+ /**
+ * run a series of repair steps for common problems
+ * progress can be reported by emitting \OC\Repair::step events
+ */
+ public function run() {
+ $this->emit('\OC\Repair', 'step', array('No repair steps configured at the moment'));
+ }
+}
diff --git a/lib/request.php b/lib/private/request.php
index df33217f95d..b2afda35922 100755
--- a/lib/request.php
+++ b/lib/private/request.php
@@ -9,6 +9,7 @@
class OC_Request {
/**
* @brief Check overwrite condition
+ * @param string $type
* @returns bool
*/
private static function isOverwriteCondition($type = '') {
@@ -99,7 +100,7 @@ class OC_Request {
public static function scriptName() {
$name = $_SERVER['SCRIPT_NAME'];
if (OC_Config::getValue('overwritewebroot', '') !== '' and self::isOverwriteCondition()) {
- $serverroot = str_replace("\\", '/', substr(__DIR__, 0, -4));
+ $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;
}
@@ -135,12 +136,40 @@ class OC_Request {
* @returns string Path info or false when not found
*/
public static function getRawPathInfo() {
- $path_info = substr($_SERVER['REQUEST_URI'], strlen($_SERVER['SCRIPT_NAME']));
+ $requestUri = $_SERVER['REQUEST_URI'];
+ // remove too many leading slashes - can be caused by reverse proxy configuration
+ if (strpos($requestUri, '/') === 0) {
+ $requestUri = '/' . ltrim($requestUri, '/');
+ }
+
// Remove the query string from REQUEST_URI
- if ($pos = strpos($path_info, '?')) {
- $path_info = substr($path_info, 0, $pos);
+ if ($pos = strpos($requestUri, '?')) {
+ $requestUri = substr($requestUri, 0, $pos);
+ }
+
+ $scriptName = $_SERVER['SCRIPT_NAME'];
+ $path_info = $requestUri;
+
+ // strip off the script name's dir and file name
+ list($path, $name) = \Sabre_DAV_URLUtil::splitPath($scriptName);
+ if (!empty($path)) {
+ if( $path === $path_info || strpos($path_info, $path.'/') === 0) {
+ $path_info = substr($path_info, strlen($path));
+ } else {
+ throw new Exception("The requested uri($requestUri) cannot be processed by the script '$scriptName')");
+ }
+ }
+ if (strpos($path_info, '/'.$name) === 0) {
+ $path_info = substr($path_info, strlen($name) + 1);
+ }
+ if (strpos($path_info, $name) === 0) {
+ $path_info = substr($path_info, strlen($name));
+ }
+ if($path_info === '/'){
+ return '';
+ } else {
+ return $path_info;
}
- return $path_info;
}
/**
diff --git a/lib/response.php b/lib/private/response.php
index 674176d078b..674176d078b 100644
--- a/lib/response.php
+++ b/lib/private/response.php
diff --git a/lib/route.php b/lib/private/route.php
index 5901717c094..fb7da456b62 100644
--- a/lib/route.php
+++ b/lib/private/route.php
@@ -52,6 +52,14 @@ class OC_Route extends Route {
}
/**
+ * Specify PATCH as the method to use with this route
+ */
+ public function patch() {
+ $this->method('PATCH');
+ return $this;
+ }
+
+ /**
* Defaults to use for this route
*
* @param array $defaults The defaults
diff --git a/lib/router.php b/lib/private/router.php
index dbaca9e0d5d..dbaca9e0d5d 100644
--- a/lib/router.php
+++ b/lib/private/router.php
diff --git a/lib/search.php b/lib/private/search.php
index b9c75dfc333..b9c75dfc333 100644
--- a/lib/search.php
+++ b/lib/private/search.php
diff --git a/lib/search/provider.php b/lib/private/search/provider.php
index b617b9c5d94..b617b9c5d94 100644
--- a/lib/search/provider.php
+++ b/lib/private/search/provider.php
diff --git a/lib/search/provider/file.php b/lib/private/search/provider/file.php
index 4d88c2a87f1..9bd50931517 100644
--- a/lib/search/provider/file.php
+++ b/lib/private/search/provider/file.php
@@ -10,6 +10,7 @@ class OC_Search_Provider_File extends OC_Search_Provider{
$mime = $fileData['mimetype'];
$name = basename($path);
+ $container = dirname($path);
$text = '';
$skip = false;
if($mime=='httpd/unix-directory') {
@@ -37,7 +38,7 @@ class OC_Search_Provider_File extends OC_Search_Provider{
}
}
if(!$skip) {
- $results[] = new OC_Search_Result($name, $text, $link, $type);
+ $results[] = new OC_Search_Result($name, $text, $link, $type, $container);
}
}
return $results;
diff --git a/lib/search/result.php b/lib/private/search/result.php
index 08beaea151c..42275c2df11 100644
--- a/lib/search/result.php
+++ b/lib/private/search/result.php
@@ -7,6 +7,7 @@ class OC_Search_Result{
public $text;
public $link;
public $type;
+ public $container;
/**
* create a new search result
@@ -15,10 +16,11 @@ class OC_Search_Result{
* @param string $link link for the result
* @param string $type the type of result as human readable string ('File', 'Music', etc)
*/
- public function __construct($name, $text, $link, $type) {
+ public function __construct($name, $text, $link, $type, $container) {
$this->name=$name;
$this->text=$text;
$this->link=$link;
$this->type=$type;
+ $this->container=$container;
}
}
diff --git a/lib/private/server.php b/lib/private/server.php
new file mode 100644
index 00000000000..77c3732a9ca
--- /dev/null
+++ b/lib/private/server.php
@@ -0,0 +1,316 @@
+<?php
+
+namespace OC;
+
+use OC\AppFramework\Http\Request;
+use OC\AppFramework\Utility\SimpleContainer;
+use OC\Cache\UserCache;
+use OC\DB\ConnectionWrapper;
+use OC\Files\Node\Root;
+use OC\Files\View;
+use OCP\IServerContainer;
+
+/**
+ * Class Server
+ * @package OC
+ *
+ * TODO: hookup all manager classes
+ */
+class Server extends SimpleContainer implements IServerContainer {
+
+ function __construct() {
+ $this->registerService('ContactsManager', function($c) {
+ return new ContactsManager();
+ });
+ $this->registerService('Request', function($c) {
+ if (isset($c['urlParams'])) {
+ $urlParams = $c['urlParams'];
+ } else {
+ $urlParams = array();
+ }
+
+ if (\OC::$session->exists('requesttoken')) {
+ $requesttoken = \OC::$session->get('requesttoken');
+ } else {
+ $requesttoken = false;
+ }
+
+ return new Request(
+ array(
+ 'get' => $_GET,
+ 'post' => $_POST,
+ 'files' => $_FILES,
+ 'server' => $_SERVER,
+ 'env' => $_ENV,
+ 'cookies' => $_COOKIE,
+ 'method' => (isset($_SERVER) && isset($_SERVER['REQUEST_METHOD']))
+ ? $_SERVER['REQUEST_METHOD']
+ : null,
+ 'urlParams' => $urlParams,
+ 'requesttoken' => $requesttoken,
+ )
+ );
+ });
+ $this->registerService('PreviewManager', function($c) {
+ return new PreviewManager();
+ });
+ $this->registerService('TagManager', function($c) {
+ $user = \OC_User::getUser();
+ return new TagManager($user);
+ });
+ $this->registerService('RootFolder', function($c) {
+ // TODO: get user and user manager from container as well
+ $user = \OC_User::getUser();
+ /** @var $c SimpleContainer */
+ $userManager = $c->query('UserManager');
+ $user = $userManager->get($user);
+ $manager = \OC\Files\Filesystem::getMountManager();
+ $view = new View();
+ return new Root($manager, $view, $user);
+ });
+ $this->registerService('UserManager', function($c) {
+ return new \OC\User\Manager();
+ });
+ $this->registerService('UserSession', function($c) {
+ /** @var $c SimpleContainer */
+ $manager = $c->query('UserManager');
+ $userSession = new \OC\User\Session($manager, \OC::$session);
+ $userSession->listen('\OC\User', 'preCreateUser', function ($uid, $password) {
+ \OC_Hook::emit('OC_User', 'pre_createUser', array('run' => true, 'uid' => $uid, 'password' => $password));
+ });
+ $userSession->listen('\OC\User', 'postCreateUser', function ($user, $password) {
+ /** @var $user \OC\User\User */
+ \OC_Hook::emit('OC_User', 'post_createUser', array('uid' => $user->getUID(), 'password' => $password));
+ });
+ $userSession->listen('\OC\User', 'preDelete', function ($user) {
+ /** @var $user \OC\User\User */
+ \OC_Hook::emit('OC_User', 'pre_deleteUser', array('run' => true, 'uid' => $user->getUID()));
+ });
+ $userSession->listen('\OC\User', 'postDelete', function ($user) {
+ /** @var $user \OC\User\User */
+ \OC_Hook::emit('OC_User', 'post_deleteUser', array('uid' => $user->getUID()));
+ });
+ $userSession->listen('\OC\User', 'preSetPassword', function ($user, $password, $recoveryPassword) {
+ /** @var $user \OC\User\User */
+ \OC_Hook::emit('OC_User', 'pre_setPassword', array('run' => true, 'uid' => $user->getUID(), 'password' => $password, 'recoveryPassword' => $recoveryPassword));
+ });
+ $userSession->listen('\OC\User', 'postSetPassword', function ($user, $password, $recoveryPassword) {
+ /** @var $user \OC\User\User */
+ \OC_Hook::emit('OC_User', 'post_setPassword', array('run' => true, 'uid' => $user->getUID(), 'password' => $password, 'recoveryPassword' => $recoveryPassword));
+ });
+ $userSession->listen('\OC\User', 'preLogin', function ($uid, $password) {
+ \OC_Hook::emit('OC_User', 'pre_login', array('run' => true, 'uid' => $uid, 'password' => $password));
+ });
+ $userSession->listen('\OC\User', 'postLogin', function ($user, $password) {
+ /** @var $user \OC\User\User */
+ \OC_Hook::emit('OC_User', 'post_login', array('run' => true, 'uid' => $user->getUID(), 'password' => $password));
+ });
+ $userSession->listen('\OC\User', 'logout', function () {
+ \OC_Hook::emit('OC_User', 'logout', array());
+ });
+ return $userSession;
+ });
+ $this->registerService('NavigationManager', function($c) {
+ return new \OC\NavigationManager();
+ });
+ $this->registerService('AllConfig', function($c) {
+ return new \OC\AllConfig();
+ });
+ $this->registerService('L10NFactory', function($c) {
+ return new \OC\L10N\Factory();
+ });
+ $this->registerService('URLGenerator', function($c) {
+ return new \OC\URLGenerator();
+ });
+ $this->registerService('AppHelper', function($c) {
+ return new \OC\AppHelper();
+ });
+ $this->registerService('UserCache', function($c) {
+ return new UserCache();
+ });
+ $this->registerService('ActivityManager', function($c) {
+ return new ActivityManager();
+ });
+ $this->registerService('AvatarManager', function($c) {
+ return new AvatarManager();
+ });
+ }
+
+ /**
+ * @return \OCP\Contacts\IManager
+ */
+ function getContactsManager() {
+ return $this->query('ContactsManager');
+ }
+
+ /**
+ * The current request object holding all information about the request
+ * currently being processed is returned from this method.
+ * In case the current execution was not initiated by a web request null is returned
+ *
+ * @return \OCP\IRequest|null
+ */
+ function getRequest() {
+ return $this->query('Request');
+ }
+
+ /**
+ * Returns the preview manager which can create preview images for a given file
+ *
+ * @return \OCP\IPreview
+ */
+ function getPreviewManager() {
+ return $this->query('PreviewManager');
+ }
+
+ /**
+ * Returns the tag manager which can get and set tags for different object types
+ *
+ * @see \OCP\ITagManager::load()
+ * @return \OCP\ITagManager
+ */
+ function getTagManager() {
+ return $this->query('TagManager');
+ }
+
+ /**
+ * Returns the avatar manager, used for avatar functionality
+ *
+ * @return \OCP\IAvatarManager
+ */
+ function getAvatarManager() {
+ return $this->query('AvatarManager');
+ }
+
+ /**
+ * Returns the root folder of ownCloud's data directory
+ *
+ * @return \OCP\Files\Folder
+ */
+ function getRootFolder() {
+ return $this->query('RootFolder');
+ }
+
+ /**
+ * Returns a view to ownCloud's files folder
+ *
+ * @return \OCP\Files\Folder
+ */
+ function getUserFolder() {
+
+ $dir = '/files';
+ $root = $this->getRootFolder();
+ $folder = null;
+ if(!$root->nodeExists($dir)) {
+ $folder = $root->newFolder($dir);
+ } else {
+ $folder = $root->get($dir);
+ }
+ return $folder;
+ }
+
+ /**
+ * Returns an app-specific view in ownClouds data directory
+ *
+ * @return \OCP\Files\Folder
+ */
+ function getAppFolder() {
+
+ $dir = '/' . \OC_App::getCurrentApp();
+ $root = $this->getRootFolder();
+ $folder = null;
+ if(!$root->nodeExists($dir)) {
+ $folder = $root->newFolder($dir);
+ } else {
+ $folder = $root->get($dir);
+ }
+ return $folder;
+ }
+
+ /**
+ * @return \OC\User\Manager
+ */
+ function getUserManager() {
+ return $this->query('UserManager');
+ }
+
+ /**
+ * @return \OC\User\Session
+ */
+ function getUserSession() {
+ return $this->query('UserSession');
+ }
+
+ /**
+ * @return \OC\NavigationManager
+ */
+ function getNavigationManager() {
+ return $this->query('NavigationManager');
+ }
+
+ /**
+ * @return \OC\Config
+ */
+ function getConfig() {
+ return $this->query('AllConfig');
+ }
+
+ /**
+ * get an L10N instance
+ * @param $app string appid
+ * @return \OC_L10N
+ */
+ function getL10N($app) {
+ return $this->query('L10NFactory')->get($app);
+ }
+
+ /**
+ * @return \OC\URLGenerator
+ */
+ function getURLGenerator() {
+ return $this->query('URLGenerator');
+ }
+
+ /**
+ * @return \OC\Helper
+ */
+ function getHelper() {
+ return $this->query('AppHelper');
+ }
+
+ /**
+ * Returns an ICache instance
+ *
+ * @return \OCP\ICache
+ */
+ function getCache() {
+ return $this->query('UserCache');
+ }
+
+ /**
+ * Returns the current session
+ *
+ * @return \OCP\ISession
+ */
+ function getSession() {
+ return \OC::$session;
+ }
+
+ /**
+ * Returns the current session
+ *
+ * @return \OCP\IDBConnection
+ */
+ function getDatabaseConnection() {
+ return new ConnectionWrapper(\OC_DB::getConnection());
+ }
+
+ /**
+ * Returns the activity manager
+ *
+ * @return \OCP\Activity\IManager
+ */
+ function getActivityManager() {
+ return $this->query('ActivityManager');
+ }
+}
diff --git a/lib/session/internal.php b/lib/private/session/internal.php
index 60aecccc8aa..60aecccc8aa 100644
--- a/lib/session/internal.php
+++ b/lib/private/session/internal.php
diff --git a/lib/session/memory.php b/lib/private/session/memory.php
index c148ff4b9b9..c148ff4b9b9 100644
--- a/lib/session/memory.php
+++ b/lib/private/session/memory.php
diff --git a/lib/session/session.php b/lib/private/session/session.php
index 55515f57a87..fe160faa267 100644
--- a/lib/session/session.php
+++ b/lib/private/session/session.php
@@ -8,7 +8,10 @@
namespace OC\Session;
-abstract class Session implements \ArrayAccess {
+use OCP\ISession;
+
+abstract class Session implements \ArrayAccess, ISession {
+
/**
* $name serves as a namespace for the session keys
*
@@ -17,36 +20,6 @@ abstract class Session implements \ArrayAccess {
abstract public function __construct($name);
/**
- * @param string $key
- * @param mixed $value
- */
- abstract public function set($key, $value);
-
- /**
- * @param string $key
- * @return mixed should return null if $key does not exist
- */
- abstract public function get($key);
-
- /**
- * @param string $key
- * @return bool
- */
- abstract public function exists($key);
-
- /**
- * should not throw any errors if $key does not exist
- *
- * @param string $key
- */
- abstract public function remove($key);
-
- /**
- * removes all entries within the cache namespace
- */
- abstract public function clear();
-
- /**
* @param mixed $offset
* @return bool
*/
diff --git a/lib/setup.php b/lib/private/setup.php
index 05a49890976..b5c530a091f 100644
--- a/lib/setup.php
+++ b/lib/private/setup.php
@@ -61,7 +61,7 @@ class OC_Setup {
}
//generate a random salt that is used to salt the local user passwords
- $salt = OC_Util::generate_random_bytes(30);
+ $salt = OC_Util::generateRandomBytes(30);
OC_Config::setValue('passwordsalt', $salt);
//write the config file
@@ -165,8 +165,19 @@ class OC_Setup {
}
public static function protectDataDirectory() {
- $content = "deny from all\n";
- $content.= "IndexIgnore *";
+ //Require all denied
+ $now = date('Y-m-d H:i:s');
+ $content = "# Generated by ownCloud on $now\n";
+ $content.= "# line below if for Apache 2.4\n";
+ $content.= "<ifModule mod_authz_core>\n";
+ $content.= "Require all denied\n";
+ $content.= "</ifModule>\n\n";
+ $content.= "# line below if for Apache 2.2\n";
+ $content.= "<ifModule !mod_authz_core>\n";
+ $content.= "deny from all\n";
+ $content.= "</ifModule>\n\n";
+ $content.= "# section for Apache 2.2 and 2.4\n";
+ $content.= "IndexIgnore *\n";
file_put_contents(OC_Config::getValue('datadirectory', OC::$SERVERROOT.'/data').'/.htaccess', $content);
file_put_contents(OC_Config::getValue('datadirectory', OC::$SERVERROOT.'/data').'/index.html', '');
}
@@ -183,7 +194,7 @@ class OC_Setup {
$error = $l->t('Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken.');
$hint = $l->t('Please double check the <a href=\'%s\'>installation guides</a>.',
- 'http://doc.owncloud.org/server/5.0/admin_manual/installation.html');
+ \OC_Helper::linkToDocs('admin-install'));
OC_Template::printErrorPage($error, $hint);
exit();
diff --git a/lib/setup/abstractdatabase.php b/lib/private/setup/abstractdatabase.php
index 0beada7bd29..84625a217ee 100644
--- a/lib/setup/abstractdatabase.php
+++ b/lib/private/setup/abstractdatabase.php
@@ -3,6 +3,10 @@
namespace OC\Setup;
abstract class AbstractDatabase {
+
+ /**
+ * @var \OC_L10N
+ */
protected $trans;
protected $dbDefinitionFile;
protected $dbuser;
diff --git a/lib/setup/mssql.php b/lib/private/setup/mssql.php
index b8329f99079..b8329f99079 100644
--- a/lib/setup/mssql.php
+++ b/lib/private/setup/mssql.php
diff --git a/lib/setup/mysql.php b/lib/private/setup/mysql.php
index 0cf04fde5a1..d97b6d2602f 100644
--- a/lib/setup/mysql.php
+++ b/lib/private/setup/mysql.php
@@ -23,7 +23,7 @@ class MySQL extends AbstractDatabase {
$this->dbuser=substr('oc_'.$username, 0, 16);
if($this->dbuser!=$oldUser) {
//hash the password so we don't need to store the admin config in the config file
- $this->dbpassword=\OC_Util::generate_random_bytes(30);
+ $this->dbpassword=\OC_Util::generateRandomBytes(30);
$this->createDBUser($connection);
diff --git a/lib/setup/oci.php b/lib/private/setup/oci.php
index 86b53de45a4..24863b9e38a 100644
--- a/lib/setup/oci.php
+++ b/lib/private/setup/oci.php
@@ -29,10 +29,10 @@ class OCI extends AbstractDatabase {
\OC_Log::write('setup oracle', 'connect string: ' . $easy_connect_string, \OC_Log::DEBUG);
$connection = @oci_connect($this->dbuser, $this->dbpassword, $easy_connect_string);
if(!$connection) {
- $e = oci_error();
- if (is_array ($e) && isset ($e['message'])) {
+ $errorMessage = $this->getLastError();
+ if ($errorMessage) {
throw new \DatabaseSetupException($this->trans->t('Oracle connection could not be established'),
- $e['message'].' Check environment: ORACLE_HOME='.getenv('ORACLE_HOME')
+ $errorMessage.' Check environment: ORACLE_HOME='.getenv('ORACLE_HOME')
.' ORACLE_SID='.getenv('ORACLE_SID')
.' LD_LIBRARY_PATH='.getenv('LD_LIBRARY_PATH')
.' NLS_LANG='.getenv('NLS_LANG')
@@ -51,7 +51,7 @@ class OCI extends AbstractDatabase {
." WHERE user_role_privs.granted_role = role_sys_privs.role AND privilege = 'CREATE ROLE'";
$stmt = oci_parse($connection, $query);
if (!$stmt) {
- $entry = $this->trans->t('DB Error: "%s"', array(oci_last_error($connection))) . '<br />';
+ $entry = $this->trans->t('DB Error: "%s"', array($this->getLastError($connection))) . '<br />';
$entry .= $this->trans->t('Offending command was: "%s"', array($query)) . '<br />';
\OC_Log::write('setup.oci', $entry, \OC_Log::WARN);
}
@@ -65,28 +65,28 @@ class OCI extends AbstractDatabase {
//add prefix to the oracle user name to prevent collisions
$this->dbuser='oc_'.$username;
//create a new password so we don't need to store the admin config in the config file
- $this->dbpassword=\OC_Util::generate_random_bytes(30);
+ $this->dbpassword=\OC_Util::generateRandomBytes(30);
//oracle passwords are treated as identifiers:
- // must start with aphanumeric char
+ // must start with alphanumeric char
// needs to be shortened to 30 bytes, as the two " needed to escape the identifier count towards the identifier length.
$this->dbpassword=substr($this->dbpassword, 0, 30);
$this->createDBUser($connection);
- \OC_Config::setValue('dbuser', $this->dbusername);
- \OC_Config::setValue('dbname', $this->dbusername);
+ \OC_Config::setValue('dbuser', $this->dbuser);
+ \OC_Config::setValue('dbname', $this->dbuser);
\OC_Config::setValue('dbpassword', $this->dbpassword);
- //create the database not neccessary, oracle implies user = schema
- //$this->createDatabase($this->dbname, $this->dbusername, $connection);
+ //create the database not necessary, oracle implies user = schema
+ //$this->createDatabase($this->dbname, $this->dbuser, $connection);
} else {
\OC_Config::setValue('dbuser', $this->dbuser);
\OC_Config::setValue('dbname', $this->dbname);
\OC_Config::setValue('dbpassword', $this->dbpassword);
- //create the database not neccessary, oracle implies user = schema
+ //create the database not necessary, oracle implies user = schema
//$this->createDatabase($this->dbname, $this->dbuser, $connection);
}
@@ -115,10 +115,10 @@ class OCI extends AbstractDatabase {
}
$query = "SELECT count(*) FROM user_tables WHERE table_name = :un";
$stmt = oci_parse($connection, $query);
- $un = $this->dbtableprefix.'users';
+ $un = $this->tableprefix.'users';
oci_bind_by_name($stmt, ':un', $un);
if (!$stmt) {
- $entry = $this->trans->t('DB Error: "%s"', array(oci_error($connection))) . '<br />';
+ $entry = $this->trans->t('DB Error: "%s"', array($this->getLastError($connection))) . '<br />';
$entry .= $this->trans->t('Offending command was: "%s"', array($query)) . '<br />';
\OC_Log::write('setup.oci', $entry, \OC_Log::WARN);
}
@@ -133,25 +133,22 @@ class OCI extends AbstractDatabase {
}
/**
- *
- * @param String $name
- * @param String $password
* @param resource $connection
*/
private function createDBUser($connection) {
$name = $this->dbuser;
- $password = $this->password;
+ $password = $this->dbpassword;
$query = "SELECT * FROM all_users WHERE USERNAME = :un";
$stmt = oci_parse($connection, $query);
if (!$stmt) {
- $entry = $this->trans->t('DB Error: "%s"', array(oci_error($connection))) . '<br />';
+ $entry = $this->trans->t('DB Error: "%s"', array($this->getLastError($connection))) . '<br />';
$entry .= $this->trans->t('Offending command was: "%s"', array($query)) . '<br />';
\OC_Log::write('setup.oci', $entry, \OC_Log::WARN);
}
oci_bind_by_name($stmt, ':un', $name);
$result = oci_execute($stmt);
if(!$result) {
- $entry = $this->trans->t('DB Error: "%s"', array(oci_error($connection))) . '<br />';
+ $entry = $this->trans->t('DB Error: "%s"', array($this->getLastError($connection))) . '<br />';
$entry .= $this->trans->t('Offending command was: "%s"', array($query)) . '<br />';
\OC_Log::write('setup.oci', $entry, \OC_Log::WARN);
}
@@ -162,14 +159,14 @@ class OCI extends AbstractDatabase {
$query = 'CREATE USER '.$name.' IDENTIFIED BY "'.$password.'" DEFAULT TABLESPACE '.$this->dbtablespace;
$stmt = oci_parse($connection, $query);
if (!$stmt) {
- $entry = $this->trans->t('DB Error: "%s"', array(oci_error($connection))) . '<br />';
+ $entry = $this->trans->t('DB Error: "%s"', array($this->getLastError($connection))) . '<br />';
$entry .= $this->trans->t('Offending command was: "%s"', array($query)) . '<br />';
\OC_Log::write('setup.oci', $entry, \OC_Log::WARN);
}
//oci_bind_by_name($stmt, ':un', $name);
$result = oci_execute($stmt);
if(!$result) {
- $entry = $this->trans->t('DB Error: "%s"', array(oci_error($connection))) . '<br />';
+ $entry = $this->trans->t('DB Error: "%s"', array($this->getLastError($connection))) . '<br />';
$entry .= $this->trans->t('Offending command was: "%s", name: %s, password: %s',
array($query, $name, $password)) . '<br />';
\OC_Log::write('setup.oci', $entry, \OC_Log::WARN);
@@ -178,7 +175,7 @@ class OCI extends AbstractDatabase {
$query = "ALTER USER :un IDENTIFIED BY :pw";
$stmt = oci_parse($connection, $query);
if (!$stmt) {
- $entry = $this->trans->t('DB Error: "%s"', array(oci_error($connection))) . '<br />';
+ $entry = $this->trans->t('DB Error: "%s"', array($this->getLastError($connection))) . '<br />';
$entry .= $this->trans->t('Offending command was: "%s"', array($query)) . '<br />';
\OC_Log::write('setup.oci', $entry, \OC_Log::WARN);
}
@@ -186,7 +183,7 @@ class OCI extends AbstractDatabase {
oci_bind_by_name($stmt, ':pw', $password);
$result = oci_execute($stmt);
if(!$result) {
- $entry = $this->trans->t('DB Error: "%s"', array(oci_error($connection))) . '<br />';
+ $entry = $this->trans->t('DB Error: "%s"', array($this->getLastError($connection))) . '<br />';
$entry .= $this->trans->t('Offending command was: "%s"', array($query)) . '<br />';
\OC_Log::write('setup.oci', $entry, \OC_Log::WARN);
}
@@ -195,16 +192,34 @@ class OCI extends AbstractDatabase {
$query = 'GRANT CREATE SESSION, CREATE TABLE, CREATE SEQUENCE, CREATE TRIGGER, UNLIMITED TABLESPACE TO '.$name;
$stmt = oci_parse($connection, $query);
if (!$stmt) {
- $entry = $this->trans->t('DB Error: "%s"', array(oci_error($connection))) . '<br />';
+ $entry = $this->trans->t('DB Error: "%s"', array($this->getLastError($connection))) . '<br />';
$entry .= $this->trans->t('Offending command was: "%s"', array($query)) . '<br />';
\OC_Log::write('setup.oci', $entry, \OC_Log::WARN);
}
$result = oci_execute($stmt);
if(!$result) {
- $entry = $this->trans->t('DB Error: "%s"', array(oci_error($connection))) . '<br />';
+ $entry = $this->trans->t('DB Error: "%s"', array($this->getLastError($connection))) . '<br />';
$entry .= $this->trans->t('Offending command was: "%s", name: %s, password: %s',
array($query, $name, $password)) . '<br />';
\OC_Log::write('setup.oci', $entry, \OC_Log::WARN);
}
}
+
+ /**
+ * @param resource $connection
+ * @return string
+ */
+ protected function getLastError($connection = null) {
+ if ($connection) {
+ $error = oci_error($connection);
+ } else {
+ $error = oci_error();
+ }
+ foreach (array('message', 'code') as $key) {
+ if (isset($error[$key])) {
+ return $error[$key];
+ }
+ }
+ return '';
+ }
}
diff --git a/lib/setup/postgresql.php b/lib/private/setup/postgresql.php
index 49fcbf0326e..89d328ada19 100644
--- a/lib/setup/postgresql.php
+++ b/lib/private/setup/postgresql.php
@@ -33,7 +33,7 @@ class PostgreSQL extends AbstractDatabase {
//add prefix to the postgresql user name to prevent collisions
$this->dbuser='oc_'.$username;
//create a new password so we don't need to store the admin config in the config file
- $this->dbpassword=\OC_Util::generate_random_bytes(30);
+ $this->dbpassword=\OC_Util::generateRandomBytes(30);
$this->createDBUser($connection);
diff --git a/lib/setup/sqlite.php b/lib/private/setup/sqlite.php
index fd4df792d62..fd4df792d62 100644
--- a/lib/setup/sqlite.php
+++ b/lib/private/setup/sqlite.php
diff --git a/lib/subadmin.php b/lib/private/subadmin.php
index 8cda7240ac9..8cda7240ac9 100644
--- a/lib/subadmin.php
+++ b/lib/private/subadmin.php
diff --git a/lib/private/tagmanager.php b/lib/private/tagmanager.php
new file mode 100644
index 00000000000..9a371a11253
--- /dev/null
+++ b/lib/private/tagmanager.php
@@ -0,0 +1,68 @@
+<?php
+/**
+* ownCloud
+*
+* @author Thomas Tanghus
+* @copyright 2013 Thomas Tanghus <thomas@tanghus.net>
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+/**
+ * Factory class creating instances of \OCP\ITags
+ *
+ * A tag can be e.g. 'Family', 'Work', 'Chore', 'Special Occation' or
+ * anything else that is either parsed from a vobject or that the user chooses
+ * to add.
+ * Tag names are not case-sensitive, but will be saved with the case they
+ * are entered in. If a user already has a tag 'family' for a type, and
+ * tries to add a tag named 'Family' it will be silently ignored.
+ */
+
+namespace OC;
+
+class TagManager implements \OCP\ITagManager {
+
+ /**
+ * User
+ *
+ * @var string
+ */
+ private $user = null;
+
+ /**
+ * Constructor.
+ *
+ * @param string $user The user whos data the object will operate on.
+ */
+ public function __construct($user) {
+
+ $this->user = $user;
+
+ }
+
+ /**
+ * Create a new \OCP\ITags instance and load tags from db.
+ *
+ * @see \OCP\ITags
+ * @param string $type The type identifier e.g. 'contact' or 'event'.
+ * @param array $defaultTags An array of default tags to be used if none are stored.
+ * @return \OCP\ITags
+ */
+ public function load($type, $defaultTags=array()) {
+ return new Tags($this->user, $type, $defaultTags);
+ }
+
+} \ No newline at end of file
diff --git a/lib/private/tags.php b/lib/private/tags.php
new file mode 100644
index 00000000000..9fdb35a7d6e
--- /dev/null
+++ b/lib/private/tags.php
@@ -0,0 +1,642 @@
+<?php
+/**
+* ownCloud
+*
+* @author Thomas Tanghus
+* @copyright 2012-2013 Thomas Tanghus <thomas@tanghus.net>
+* @copyright 2012 Bart Visscher bartv@thisnet.nl
+*
+* 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/>.
+*
+*/
+
+/**
+ * Class for easily tagging objects by their id
+ *
+ * A tag can be e.g. 'Family', 'Work', 'Chore', 'Special Occation' or
+ * anything else that is either parsed from a vobject or that the user chooses
+ * to add.
+ * Tag names are not case-sensitive, but will be saved with the case they
+ * are entered in. If a user already has a tag 'family' for a type, and
+ * tries to add a tag named 'Family' it will be silently ignored.
+ */
+
+namespace OC;
+
+class Tags implements \OCP\ITags {
+
+ /**
+ * Tags
+ *
+ * @var array
+ */
+ private $tags = array();
+
+ /**
+ * Used for storing objectid/categoryname pairs while rescanning.
+ *
+ * @var array
+ */
+ private static $relations = array();
+
+ /**
+ * Type
+ *
+ * @var string
+ */
+ private $type = null;
+
+ /**
+ * User
+ *
+ * @var string
+ */
+ private $user = null;
+
+ const TAG_TABLE = '*PREFIX*vcategory';
+ const RELATION_TABLE = '*PREFIX*vcategory_to_object';
+
+ const TAG_FAVORITE = '_$!<Favorite>!$_';
+
+ /**
+ * Constructor.
+ *
+ * @param string $user The user whos data the object will operate on.
+ */
+ public function __construct($user, $type, $defaultTags = array()) {
+ $this->user = $user;
+ $this->type = $type;
+ $this->loadTags($defaultTags);
+ }
+
+ /**
+ * Load tags from db.
+ *
+ * @param string $type The type identifier e.g. 'contact' or 'event'.
+ * @param array $defaultTags An array of default tags to be used if none are stored.
+ */
+ protected function loadTags($defaultTags=array()) {
+ $this->tags = array();
+ $result = null;
+ $sql = 'SELECT `id`, `category` FROM `' . self::TAG_TABLE . '` '
+ . 'WHERE `uid` = ? AND `type` = ? ORDER BY `category`';
+ try {
+ $stmt = \OCP\DB::prepare($sql);
+ $result = $stmt->execute(array($this->user, $this->type));
+ if (\OCP\DB::isError($result)) {
+ \OCP\Util::writeLog('core', __METHOD__. ', DB error: ' . \OCP\DB::getErrorMessage($result), \OCP\Util::ERROR);
+ }
+ } catch(\Exception $e) {
+ \OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
+ \OCP\Util::ERROR);
+ }
+
+ if(!is_null($result)) {
+ while( $row = $result->fetchRow()) {
+ $this->tags[$row['id']] = $row['category'];
+ }
+ }
+
+ if(count($defaultTags) > 0 && count($this->tags) === 0) {
+ $this->addMultiple($defaultTags, true);
+ }
+ \OCP\Util::writeLog('core', __METHOD__.', tags: ' . print_r($this->tags, true),
+ \OCP\Util::DEBUG);
+
+ }
+
+ /**
+ * Check if any tags are saved for this type and user.
+ *
+ * @return boolean.
+ */
+ public function isEmpty() {
+ $sql = 'SELECT COUNT(*) FROM `' . self::TAG_TABLE . '` '
+ . 'WHERE `uid` = ? AND `type` = ?';
+ try {
+ $stmt = \OCP\DB::prepare($sql);
+ $result = $stmt->execute(array($this->user, $this->type));
+ if (\OCP\DB::isError($result)) {
+ \OCP\Util::writeLog('core', __METHOD__. ', DB error: ' . \OCP\DB::getErrorMessage($result), \OCP\Util::ERROR);
+ return false;
+ }
+ return ((int)$result->fetchOne() === 0);
+ } catch(\Exception $e) {
+ \OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
+ \OCP\Util::ERROR);
+ return false;
+ }
+ }
+
+ /**
+ * Get the tags for a specific user.
+ *
+ * This returns an array with id/name maps:
+ * [
+ * ['id' => 0, 'name' = 'First tag'],
+ * ['id' => 1, 'name' = 'Second tag'],
+ * ]
+ *
+ * @return array
+ */
+ public function getTags() {
+ if(!count($this->tags)) {
+ return array();
+ }
+
+ $tags = array_values($this->tags);
+ uasort($tags, 'strnatcasecmp');
+ $tagMap = array();
+
+ foreach($tags as $tag) {
+ if($tag !== self::TAG_FAVORITE) {
+ $tagMap[] = array(
+ 'id' => $this->array_searchi($tag, $this->tags),
+ 'name' => $tag
+ );
+ }
+ }
+ return $tagMap;
+
+ }
+
+ /**
+ * Get the a list if items tagged with $tag.
+ *
+ * Throws an exception if the tag could not be found.
+ *
+ * @param string|integer $tag Tag id or name.
+ * @return array An array of object ids or false on error.
+ */
+ public function getIdsForTag($tag) {
+ $result = null;
+ if(is_numeric($tag)) {
+ $tagId = $tag;
+ } elseif(is_string($tag)) {
+ $tag = trim($tag);
+ $tagId = $this->array_searchi($tag, $this->tags);
+ }
+
+ if($tagId === false) {
+ $l10n = \OC_L10N::get('core');
+ throw new \Exception(
+ $l10n->t('Could not find category "%s"', $tag)
+ );
+ }
+
+ $ids = array();
+ $sql = 'SELECT `objid` FROM `' . self::RELATION_TABLE
+ . '` WHERE `categoryid` = ?';
+
+ try {
+ $stmt = \OCP\DB::prepare($sql);
+ $result = $stmt->execute(array($tagId));
+ if (\OCP\DB::isError($result)) {
+ \OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OCP\DB::getErrorMessage($result), \OCP\Util::ERROR);
+ return false;
+ }
+ } catch(\Exception $e) {
+ \OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
+ \OCP\Util::ERROR);
+ return false;
+ }
+
+ if(!is_null($result)) {
+ while( $row = $result->fetchRow()) {
+ $ids[] = (int)$row['objid'];
+ }
+ }
+
+ return $ids;
+ }
+
+ /**
+ * Checks whether a tag is already saved.
+ *
+ * @param string $name The name to check for.
+ * @return bool
+ */
+ public function hasTag($name) {
+ return $this->in_arrayi($name, $this->tags);
+ }
+
+ /**
+ * Add a new tag.
+ *
+ * @param string $name A string with a name of the tag
+ * @return int the id of the added tag or false if it already exists.
+ */
+ public function add($name) {
+ $name = trim($name);
+
+ if($this->hasTag($name)) {
+ \OCP\Util::writeLog('core', __METHOD__.', name: ' . $name. ' exists already', \OCP\Util::DEBUG);
+ return false;
+ }
+ try {
+ $result = \OCP\DB::insertIfNotExist(
+ self::TAG_TABLE,
+ array(
+ 'uid' => $this->user,
+ 'type' => $this->type,
+ 'category' => $name,
+ )
+ );
+ if (\OCP\DB::isError($result)) {
+ \OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OCP\DB::getErrorMessage($result), \OCP\Util::ERROR);
+ return false;
+ } elseif((int)$result === 0) {
+ \OCP\Util::writeLog('core', __METHOD__.', Tag already exists: ' . $name, \OCP\Util::DEBUG);
+ return false;
+ }
+ } catch(\Exception $e) {
+ \OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
+ \OCP\Util::ERROR);
+ return false;
+ }
+ $id = \OCP\DB::insertid(self::TAG_TABLE);
+ \OCP\Util::writeLog('core', __METHOD__.', id: ' . $id, \OCP\Util::DEBUG);
+ $this->tags[$id] = $name;
+ return $id;
+ }
+
+ /**
+ * Rename tag.
+ *
+ * @param string $from The name of the existing tag
+ * @param string $to The new name of the tag.
+ * @return bool
+ */
+ public function rename($from, $to) {
+ $from = trim($from);
+ $to = trim($to);
+ $id = $this->array_searchi($from, $this->tags);
+ if($id === false) {
+ \OCP\Util::writeLog('core', __METHOD__.', tag: ' . $from. ' does not exist', \OCP\Util::DEBUG);
+ return false;
+ }
+
+ $sql = 'UPDATE `' . self::TAG_TABLE . '` SET `category` = ? '
+ . 'WHERE `uid` = ? AND `type` = ? AND `id` = ?';
+ try {
+ $stmt = \OCP\DB::prepare($sql);
+ $result = $stmt->execute(array($to, $this->user, $this->type, $id));
+ if (\OCP\DB::isError($result)) {
+ \OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OCP\DB::getErrorMessage($result), \OCP\Util::ERROR);
+ return false;
+ }
+ } catch(\Exception $e) {
+ \OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
+ \OCP\Util::ERROR);
+ return false;
+ }
+ $this->tags[$id] = $to;
+ return true;
+ }
+
+ /**
+ * Add a list of new tags.
+ *
+ * @param string[] $names A string with a name or an array of strings containing
+ * the name(s) of the to add.
+ * @param bool $sync When true, save the tags
+ * @param int|null $id int Optional object id to add to this|these tag(s)
+ * @return bool Returns false on error.
+ */
+ public function addMultiple($names, $sync=false, $id = null) {
+ if(!is_array($names)) {
+ $names = array($names);
+ }
+ $names = array_map('trim', $names);
+ $newones = array();
+ foreach($names as $name) {
+ if(($this->in_arrayi(
+ $name, $this->tags) == false) && $name !== '') {
+ $newones[] = $name;
+ }
+ if(!is_null($id) ) {
+ // Insert $objectid, $categoryid pairs if not exist.
+ self::$relations[] = array('objid' => $id, 'tag' => $name);
+ }
+ }
+ $this->tags = array_merge($this->tags, $newones);
+ if($sync === true) {
+ $this->save();
+ }
+
+ return true;
+ }
+
+ /**
+ * Save the list of tags and their object relations
+ */
+ protected function save() {
+ if(is_array($this->tags)) {
+ foreach($this->tags as $tag) {
+ try {
+ \OCP\DB::insertIfNotExist(self::TAG_TABLE,
+ array(
+ 'uid' => $this->user,
+ 'type' => $this->type,
+ 'category' => $tag,
+ ));
+ } catch(\Exception $e) {
+ \OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
+ \OCP\Util::ERROR);
+ }
+ }
+ // reload tags to get the proper ids.
+ $this->loadTags();
+ // Loop through temporarily cached objectid/tagname pairs
+ // and save relations.
+ $tags = $this->tags;
+ // For some reason this is needed or array_search(i) will return 0..?
+ ksort($tags);
+ foreach(self::$relations as $relation) {
+ $tagId = $this->array_searchi($relation['tag'], $tags);
+ \OCP\Util::writeLog('core', __METHOD__ . 'catid, ' . $relation['tag'] . ' ' . $tagId, \OCP\Util::DEBUG);
+ if($tagId) {
+ try {
+ \OCP\DB::insertIfNotExist(self::RELATION_TABLE,
+ array(
+ 'objid' => $relation['objid'],
+ 'categoryid' => $tagId,
+ 'type' => $this->type,
+ ));
+ } catch(\Exception $e) {
+ \OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
+ \OCP\Util::ERROR);
+ }
+ }
+ }
+ self::$relations = array(); // reset
+ } else {
+ \OCP\Util::writeLog('core', __METHOD__.', $this->tags is not an array! '
+ . print_r($this->tags, true), \OCP\Util::ERROR);
+ }
+ }
+
+ /**
+ * Delete tags and tag/object relations for a user.
+ *
+ * For hooking up on post_deleteUser
+ *
+ * @param array
+ */
+ public static function post_deleteUser($arguments) {
+ // Find all objectid/tagId pairs.
+ $result = null;
+ try {
+ $stmt = \OCP\DB::prepare('SELECT `id` FROM `' . self::TAG_TABLE . '` '
+ . 'WHERE `uid` = ?');
+ $result = $stmt->execute(array($arguments['uid']));
+ if (\OCP\DB::isError($result)) {
+ \OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OCP\DB::getErrorMessage($result), \OCP\Util::ERROR);
+ }
+ } catch(\Exception $e) {
+ \OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
+ \OCP\Util::ERROR);
+ }
+
+ if(!is_null($result)) {
+ try {
+ $stmt = \OCP\DB::prepare('DELETE FROM `' . self::RELATION_TABLE . '` '
+ . 'WHERE `categoryid` = ?');
+ while( $row = $result->fetchRow()) {
+ try {
+ $stmt->execute(array($row['id']));
+ } catch(\Exception $e) {
+ \OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
+ \OCP\Util::ERROR);
+ }
+ }
+ } catch(\Exception $e) {
+ \OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
+ \OCP\Util::ERROR);
+ }
+ }
+ try {
+ $stmt = \OCP\DB::prepare('DELETE FROM `' . self::TAG_TABLE . '` '
+ . 'WHERE `uid` = ?');
+ $result = $stmt->execute(array($arguments['uid']));
+ if (\OCP\DB::isError($result)) {
+ \OCP\Util::writeLog('core', __METHOD__. ', DB error: ' . \OCP\DB::getErrorMessage($result), \OCP\Util::ERROR);
+ }
+ } catch(\Exception $e) {
+ \OCP\Util::writeLog('core', __METHOD__ . ', exception: '
+ . $e->getMessage(), \OCP\Util::ERROR);
+ }
+ }
+
+ /**
+ * Delete tag/object relations from the db
+ *
+ * @param array $ids The ids of the objects
+ * @return boolean Returns false on error.
+ */
+ public function purgeObjects(array $ids) {
+ if(count($ids) === 0) {
+ // job done ;)
+ return true;
+ }
+ $updates = $ids;
+ try {
+ $query = 'DELETE FROM `' . self::RELATION_TABLE . '` ';
+ $query .= 'WHERE `objid` IN (' . str_repeat('?,', count($ids)-1) . '?) ';
+ $query .= 'AND `type`= ?';
+ $updates[] = $this->type;
+ $stmt = \OCP\DB::prepare($query);
+ $result = $stmt->execute($updates);
+ if (\OCP\DB::isError($result)) {
+ \OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OCP\DB::getErrorMessage($result), \OCP\Util::ERROR);
+ return false;
+ }
+ } catch(\Exception $e) {
+ \OCP\Util::writeLog('core', __METHOD__.', exception: ' . $e->getMessage(),
+ \OCP\Util::ERROR);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Get favorites for an object type
+ *
+ * @return array An array of object ids.
+ */
+ public function getFavorites() {
+ try {
+ return $this->getIdsForTag(self::TAG_FAVORITE);
+ } catch(\Exception $e) {
+ \OCP\Util::writeLog('core', __METHOD__.', exception: ' . $e->getMessage(),
+ \OCP\Util::ERROR);
+ return array();
+ }
+ }
+
+ /**
+ * Add an object to favorites
+ *
+ * @param int $objid The id of the object
+ * @return boolean
+ */
+ public function addToFavorites($objid) {
+ if(!$this->hasTag(self::TAG_FAVORITE)) {
+ $this->add(self::TAG_FAVORITE, true);
+ }
+ return $this->tagAs($objid, self::TAG_FAVORITE, $this->type);
+ }
+
+ /**
+ * Remove an object from favorites
+ *
+ * @param int $objid The id of the object
+ * @return boolean
+ */
+ public function removeFromFavorites($objid) {
+ return $this->unTag($objid, self::TAG_FAVORITE, $this->type);
+ }
+
+ /**
+ * Creates a tag/object relation.
+ *
+ * @param int $objid The id of the object
+ * @param int|string $tag The id or name of the tag
+ * @return boolean Returns false on database error.
+ */
+ public function tagAs($objid, $tag) {
+ if(is_string($tag) && !is_numeric($tag)) {
+ $tag = trim($tag);
+ if(!$this->hasTag($tag)) {
+ $this->add($tag, true);
+ }
+ $tagId = $this->array_searchi($tag, $this->tags);
+ } else {
+ $tagId = $tag;
+ }
+ try {
+ \OCP\DB::insertIfNotExist(self::RELATION_TABLE,
+ array(
+ 'objid' => $objid,
+ 'categoryid' => $tagId,
+ 'type' => $this->type,
+ ));
+ } catch(\Exception $e) {
+ \OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
+ \OCP\Util::ERROR);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Delete single tag/object relation from the db
+ *
+ * @param int $objid The id of the object
+ * @param int|string $tag The id or name of the tag
+ * @return boolean
+ */
+ public function unTag($objid, $tag) {
+ if(is_string($tag) && !is_numeric($tag)) {
+ $tag = trim($tag);
+ $tagId = $this->array_searchi($tag, $this->tags);
+ } else {
+ $tagId = $tag;
+ }
+
+ try {
+ $sql = 'DELETE FROM `' . self::RELATION_TABLE . '` '
+ . 'WHERE `objid` = ? AND `categoryid` = ? AND `type` = ?';
+ $stmt = \OCP\DB::prepare($sql);
+ $stmt->execute(array($objid, $tagId, $this->type));
+ } catch(\Exception $e) {
+ \OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
+ \OCP\Util::ERROR);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Delete tags from the
+ *
+ * @param string[] $names An array of tags to delete
+ * @return bool Returns false on error
+ */
+ public function delete($names) {
+ if(!is_array($names)) {
+ $names = array($names);
+ }
+
+ $names = array_map('trim', $names);
+
+ \OCP\Util::writeLog('core', __METHOD__ . ', before: '
+ . print_r($this->tags, true), \OCP\Util::DEBUG);
+ foreach($names as $name) {
+ $id = null;
+
+ if($this->hasTag($name)) {
+ $id = $this->array_searchi($name, $this->tags);
+ unset($this->tags[$id]);
+ }
+ try {
+ $stmt = \OCP\DB::prepare('DELETE FROM `' . self::TAG_TABLE . '` WHERE '
+ . '`uid` = ? AND `type` = ? AND `category` = ?');
+ $result = $stmt->execute(array($this->user, $this->type, $name));
+ if (\OCP\DB::isError($result)) {
+ \OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OCP\DB::getErrorMessage($result), \OCP\Util::ERROR);
+ }
+ } catch(\Exception $e) {
+ \OCP\Util::writeLog('core', __METHOD__ . ', exception: '
+ . $e->getMessage(), \OCP\Util::ERROR);
+ return false;
+ }
+ if(!is_null($id) && $id !== false) {
+ try {
+ $sql = 'DELETE FROM `' . self::RELATION_TABLE . '` '
+ . 'WHERE `categoryid` = ?';
+ $stmt = \OCP\DB::prepare($sql);
+ $result = $stmt->execute(array($id));
+ if (\OCP\DB::isError($result)) {
+ \OCP\Util::writeLog('core',
+ __METHOD__. 'DB error: ' . \OCP\DB::getErrorMessage($result),
+ \OCP\Util::ERROR);
+ return false;
+ }
+ } catch(\Exception $e) {
+ \OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
+ \OCP\Util::ERROR);
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ // case-insensitive in_array
+ private function in_arrayi($needle, $haystack) {
+ if(!is_array($haystack)) {
+ return false;
+ }
+ return in_array(strtolower($needle), array_map('strtolower', $haystack));
+ }
+
+ // case-insensitive array_search
+ private function array_searchi($needle, $haystack) {
+ if(!is_array($haystack)) {
+ return false;
+ }
+ return array_search(strtolower($needle), array_map('strtolower', $haystack));
+ }
+}
diff --git a/lib/template.php b/lib/private/template.php
index 9b2c1211e61..9b2c1211e61 100644
--- a/lib/template.php
+++ b/lib/private/template.php
diff --git a/lib/template/base.php b/lib/private/template/base.php
index 88941bc7132..88941bc7132 100644
--- a/lib/template/base.php
+++ b/lib/private/template/base.php
diff --git a/lib/template/cssresourcelocator.php b/lib/private/template/cssresourcelocator.php
index 8e7831ca549..8e7831ca549 100644
--- a/lib/template/cssresourcelocator.php
+++ b/lib/private/template/cssresourcelocator.php
diff --git a/lib/template/functions.php b/lib/private/template/functions.php
index 2d43cae1c0c..ce42633b364 100644
--- a/lib/template/functions.php
+++ b/lib/private/template/functions.php
@@ -36,6 +36,14 @@ function link_to( $app, $file, $args = array() ) {
}
/**
+ * @param $key
+ * @return string url to the online documentation
+ */
+function link_to_docs($key) {
+ return OC_Helper::linkToDocs($key);
+}
+
+/**
* @brief make OC_Helper::imagePath available as a simple function
* @param string $app app
* @param string $image image
@@ -59,6 +67,22 @@ function mimetype_icon( $mimetype ) {
}
/**
+ * @brief make preview_icon available as a simple function
+ * Returns the path to the preview of the image.
+ * @param $path path of file
+ * @returns link to the preview
+ *
+ * For further information have a look at OC_Helper::previewIcon
+ */
+function preview_icon( $path ) {
+ return OC_Helper::previewIcon( $path );
+}
+
+function publicPreview_icon ( $path, $token ) {
+ return OC_Helper::publicPreviewIcon( $path, $token );
+}
+
+/**
* @brief make OC_Helper::humanFileSize available as a simple function
* @param int $bytes size in bytes
* @return string size as string
@@ -69,24 +93,51 @@ function human_file_size( $bytes ) {
return OC_Helper::humanFileSize( $bytes );
}
-function relative_modified_date($timestamp) {
+/**
+ * @brief Strips the timestamp of its time value
+ * @param int $timestamp UNIX timestamp to strip
+ * @return $timestamp without time value
+ */
+function strip_time($timestamp){
+ $date = new \DateTime("@{$timestamp}");
+ $date->setTime(0, 0, 0);
+ return intval($date->format('U'));
+}
+
+/**
+ * @brief Formats timestamp relatively to the current time using
+ * a human-friendly format like "x minutes ago" or "yesterday"
+ * @param int $timestamp timestamp to format
+ * @param int $fromTime timestamp to compare from, defaults to current time
+ * @param bool $dateOnly whether to strip time information
+ * @return formatted timestamp
+ */
+function relative_modified_date($timestamp, $fromTime = null, $dateOnly = false) {
$l=OC_L10N::get('lib');
- $timediff = time() - $timestamp;
+ if (!isset($fromTime) || $fromTime === null){
+ $fromTime = time();
+ }
+ if ($dateOnly){
+ $fromTime = strip_time($fromTime);
+ $timestamp = strip_time($timestamp);
+ }
+ $timediff = $fromTime - $timestamp;
$diffminutes = round($timediff/60);
$diffhours = round($diffminutes/60);
$diffdays = round($diffhours/24);
$diffmonths = round($diffdays/31);
- if($timediff < 60) { return $l->t('seconds ago'); }
- else if($timediff < 120) { return $l->t('1 minute ago'); }
- else if($timediff < 3600) { return $l->t('%d minutes ago', $diffminutes); }
- else if($timediff < 7200) { return $l->t('1 hour ago'); }
- else if($timediff < 86400) { return $l->t('%d hours ago', $diffhours); }
- else if((date('G')-$diffhours) > 0) { return $l->t('today'); }
- else if((date('G')-$diffhours) > -24) { return $l->t('yesterday'); }
- else if($timediff < 2678400) { return $l->t('%d days ago', $diffdays); }
+ if(!$dateOnly && $timediff < 60) { return $l->t('seconds ago'); }
+ else if(!$dateOnly && $timediff < 3600) { return $l->n('%n minute ago', '%n minutes ago', $diffminutes); }
+ else if(!$dateOnly && $timediff < 86400) { return $l->n('%n hour ago', '%n hours ago', $diffhours); }
+ else if((date('G', $fromTime)-$diffhours) >= 0) { return $l->t('today'); }
+ else if((date('G', $fromTime)-$diffhours) >= -24) { return $l->t('yesterday'); }
+ // 86400 * 31 days = 2678400
+ else if($timediff < 2678400) { return $l->n('%n day go', '%n days ago', $diffdays); }
+ // 86400 * 60 days = 518400
else if($timediff < 5184000) { return $l->t('last month'); }
- else if((date('n')-$diffmonths) > 0) { return $l->t('%d months ago', $diffmonths); }
+ else if((date('n', $fromTime)-$diffmonths) > 0) { return $l->n('%n month ago', '%n months ago', $diffmonths); }
+ // 86400 * 365.25 days * 2 = 63113852
else if($timediff < 63113852) { return $l->t('last year'); }
else { return $l->t('years ago'); }
}
diff --git a/lib/template/jsresourcelocator.php b/lib/private/template/jsresourcelocator.php
index f8fe3817ce6..f8fe3817ce6 100644
--- a/lib/template/jsresourcelocator.php
+++ b/lib/private/template/jsresourcelocator.php
diff --git a/lib/template/resourcelocator.php b/lib/private/template/resourcelocator.php
index 9f83673664d..9f83673664d 100644
--- a/lib/template/resourcelocator.php
+++ b/lib/private/template/resourcelocator.php
diff --git a/lib/template/templatefilelocator.php b/lib/private/template/templatefilelocator.php
index d5a484b1a14..d5a484b1a14 100644
--- a/lib/template/templatefilelocator.php
+++ b/lib/private/template/templatefilelocator.php
diff --git a/lib/templatelayout.php b/lib/private/templatelayout.php
index 0024c9d4960..625f3424a04 100644
--- a/lib/templatelayout.php
+++ b/lib/private/templatelayout.php
@@ -46,6 +46,7 @@ class OC_TemplateLayout extends OC_Template {
$user_displayname = OC_User::getDisplayName();
$this->assign( 'user_displayname', $user_displayname );
$this->assign( 'user_uid', OC_User::getUser() );
+ $this->assign('enableAvatars', \OC_Config::getValue('enable_avatars', true));
} else if ($renderas == 'guest' || $renderas == 'error') {
parent::__construct('core', 'layout.guest');
} else {
@@ -58,7 +59,7 @@ class OC_TemplateLayout extends OC_Template {
if (OC_Config::getValue('installed', false) && $renderas!='error') {
$this->append( 'jsfiles', OC_Helper::linkToRoute('js_config') . $versionParameter);
}
- if (!empty(OC_Util::$core_scripts)) {
+ if (!empty(OC_Util::$coreScripts)) {
$this->append( 'jsfiles', OC_Helper::linkToRemoteBase('core.js', false) . $versionParameter);
}
foreach($jsfiles as $info) {
@@ -71,7 +72,7 @@ class OC_TemplateLayout extends OC_Template {
// Add the css files
$cssfiles = self::findStylesheetFiles(OC_Util::$styles);
$this->assign('cssfiles', array());
- if (!empty(OC_Util::$core_styles)) {
+ if (!empty(OC_Util::$coreStyles)) {
$this->append( 'cssfiles', OC_Helper::linkToRemoteBase('core.css', false) . $versionParameter);
}
foreach($cssfiles as $info) {
diff --git a/lib/updater.php b/lib/private/updater.php
index df7332a96a9..764a0f14120 100644
--- a/lib/updater.php
+++ b/lib/private/updater.php
@@ -37,7 +37,7 @@ class Updater extends BasicEmitter {
/**
* Check if a new version is available
- * @param string $updateUrl the url to check, i.e. 'http://apps.owncloud.com/updater.php'
+ * @param string $updaterUrl the url to check, i.e. 'http://apps.owncloud.com/updater.php'
* @return array | bool
*/
public function check($updaterUrl) {
@@ -56,8 +56,9 @@ class Updater extends BasicEmitter {
$version = \OC_Util::getVersion();
$version['installed'] = \OC_Appconfig::getValue('core', 'installedat');
$version['updated'] = \OC_Appconfig::getValue('core', 'lastupdatedat');
- $version['updatechannel'] = 'stable';
+ $version['updatechannel'] = \OC_Util::getChannel();
$version['edition'] = \OC_Util::getEditionString();
+ $version['build'] = \OC_Util::getBuild();
$versionString = implode('x', $version);
//fetch xml data from updater
@@ -115,6 +116,10 @@ class Updater extends BasicEmitter {
\OC_App::checkAppsRequirements();
// load all apps to also upgrade enabled apps
\OC_App::loadApps();
+
+ $repair = new Repair();
+ $repair->run();
+
\OC_Config::setValue('maintenance', false);
$this->emit('\OC\Updater', 'maintenanceEnd');
}
diff --git a/lib/private/urlgenerator.php b/lib/private/urlgenerator.php
new file mode 100644
index 00000000000..7795011fd06
--- /dev/null
+++ b/lib/private/urlgenerator.php
@@ -0,0 +1,129 @@
+<?php
+/**
+ * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ *
+ */
+
+namespace OC;
+use OCP\IURLGenerator;
+use RuntimeException;
+
+/**
+ * Class to generate URLs
+ */
+class URLGenerator implements IURLGenerator {
+ /**
+ * @brief Creates an url using a defined route
+ * @param $route
+ * @param array $parameters
+ * @return
+ * @internal param array $args with param=>value, will be appended to the returned url
+ * @returns string the url
+ *
+ * Returns a url to the given app and file.
+ */
+ public function linkToRoute($route, $parameters = array()) {
+ $urlLinkTo = \OC::getRouter()->generate($route, $parameters);
+ return $urlLinkTo;
+ }
+
+ /**
+ * @brief Creates an url
+ * @param string $app app
+ * @param string $file file
+ * @param array $args array with param=>value, will be appended to the returned url
+ * The value of $args will be urlencoded
+ * @return string the url
+ *
+ * Returns a url to the given app and file.
+ */
+ public function linkTo( $app, $file, $args = array() ) {
+ if( $app != '' ) {
+ $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') {
+ $urlLinkTo = \OC::$WEBROOT . '/index.php/apps/' . $app;
+ $urlLinkTo .= ($file != 'index.php') ? '/' . $file : '';
+ } else {
+ $urlLinkTo = \OC_App::getAppWebPath($app) . '/' . $file;
+ }
+ } else {
+ $urlLinkTo = \OC::$WEBROOT . '/' . $app . '/' . $file;
+ }
+ } else {
+ if (file_exists(\OC::$SERVERROOT . '/core/' . $file)) {
+ $urlLinkTo = \OC::$WEBROOT . '/core/' . $file;
+ } else {
+ $urlLinkTo = \OC::$WEBROOT . '/' . $file;
+ }
+ }
+
+ if ($args && $query = http_build_query($args, '', '&')) {
+ $urlLinkTo .= '?' . $query;
+ }
+
+ return $urlLinkTo;
+ }
+
+ /**
+ * @brief Creates path to an image
+ * @param string $app app
+ * @param string $image image name
+ * @return string the url
+ *
+ * Returns the path to the image.
+ */
+ public function imagePath($app, $image) {
+ // Read the selected theme from the config file
+ $theme = \OC_Util::getTheme();
+
+ //if a theme has a png but not an svg always use the png
+ $basename = substr(basename($image),0,-4);
+
+ // Check if the app is in the app folder
+ if (file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$image")) {
+ return \OC::$WEBROOT . "/themes/$theme/apps/$app/img/$image";
+ } elseif (!file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$basename.svg")
+ && file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$basename.png")) {
+ return \OC::$WEBROOT . "/themes/$theme/apps/$app/img/$basename.png";
+ } elseif (file_exists(\OC_App::getAppPath($app) . "/img/$image")) {
+ return \OC_App::getAppWebPath($app) . "/img/$image";
+ } elseif (!file_exists(\OC_App::getAppPath($app) . "/img/$basename.svg")
+ && file_exists(\OC_App::getAppPath($app) . "/img/$basename.png")) {
+ return \OC_App::getAppPath($app) . "/img/$basename.png";
+ } elseif (!empty($app) and file_exists(\OC::$SERVERROOT . "/themes/$theme/$app/img/$image")) {
+ return \OC::$WEBROOT . "/themes/$theme/$app/img/$image";
+ } elseif (!empty($app) and (!file_exists(\OC::$SERVERROOT . "/themes/$theme/$app/img/$basename.svg")
+ && file_exists(\OC::$SERVERROOT . "/themes/$theme/$app/img/$basename.png"))) {
+ return \OC::$WEBROOT . "/themes/$theme/$app/img/$basename.png";
+ } elseif (!empty($app) and file_exists(\OC::$SERVERROOT . "/$app/img/$image")) {
+ return \OC::$WEBROOT . "/$app/img/$image";
+ } elseif (!empty($app) and (!file_exists(\OC::$SERVERROOT . "/$app/img/$basename.svg")
+ && file_exists(\OC::$SERVERROOT . "/$app/img/$basename.png"))) {
+ return \OC::$WEBROOT . "/$app/img/$basename.png";
+ } elseif (file_exists(\OC::$SERVERROOT . "/themes/$theme/core/img/$image")) {
+ return \OC::$WEBROOT . "/themes/$theme/core/img/$image";
+ } elseif (!file_exists(\OC::$SERVERROOT . "/themes/$theme/core/img/$basename.svg")
+ && file_exists(\OC::$SERVERROOT . "/themes/$theme/core/img/$basename.png")) {
+ return \OC::$WEBROOT . "/themes/$theme/core/img/$basename.png";
+ } elseif (file_exists(\OC::$SERVERROOT . "/core/img/$image")) {
+ return \OC::$WEBROOT . "/core/img/$image";
+ } else {
+ throw new RuntimeException('image not found: image:' . $image . ' webroot:' . \OC::$WEBROOT . ' serverroot:' . \OC::$SERVERROOT);
+ }
+ }
+
+
+ /**
+ * Makes an URL absolute
+ * @param string $url the url in the owncloud host
+ * @return string the absolute version of the url
+ */
+ public function getAbsoluteURL($url) {
+ return \OC_Request::serverProtocol() . '://' . \OC_Request::serverHost() . $url;
+ }
+}
diff --git a/lib/user.php b/lib/private/user.php
index 93c7c9d4cd5..e0d6b9f3f51 100644
--- a/lib/user.php
+++ b/lib/private/user.php
@@ -37,54 +37,15 @@
* logout()
*/
class OC_User {
- public static $userSession = null;
-
public static function getUserSession() {
- if (!self::$userSession) {
- $manager = new \OC\User\Manager();
- self::$userSession = new \OC\User\Session($manager, \OC::$session);
- self::$userSession->listen('\OC\User', 'preCreateUser', function ($uid, $password) {
- \OC_Hook::emit('OC_User', 'pre_createUser', array('run' => true, 'uid' => $uid, 'password' => $password));
- });
- self::$userSession->listen('\OC\User', 'postCreateUser', function ($user, $password) {
- /** @var $user \OC\User\User */
- \OC_Hook::emit('OC_User', 'post_createUser', array('uid' => $user->getUID(), 'password' => $password));
- });
- self::$userSession->listen('\OC\User', 'preDelete', function ($user) {
- /** @var $user \OC\User\User */
- \OC_Hook::emit('OC_User', 'pre_deleteUser', array('run' => true, 'uid' => $user->getUID()));
- });
- self::$userSession->listen('\OC\User', 'postDelete', function ($user) {
- /** @var $user \OC\User\User */
- \OC_Hook::emit('OC_User', 'post_deleteUser', array('uid' => $user->getUID()));
- });
- self::$userSession->listen('\OC\User', 'preSetPassword', function ($user, $password, $recoveryPassword) {
- /** @var $user \OC\User\User */
- OC_Hook::emit('OC_User', 'pre_setPassword', array('run' => true, 'uid' => $user->getUID(), 'password' => $password, 'recoveryPassword' => $recoveryPassword));
- });
- self::$userSession->listen('\OC\User', 'postSetPassword', function ($user, $password, $recoveryPassword) {
- /** @var $user \OC\User\User */
- OC_Hook::emit('OC_User', 'post_setPassword', array('run' => true, 'uid' => $user->getUID(), 'password' => $password, 'recoveryPassword' => $recoveryPassword));
- });
- self::$userSession->listen('\OC\User', 'preLogin', function ($uid, $password) {
- \OC_Hook::emit('OC_User', 'pre_login', array('run' => true, 'uid' => $uid, 'password' => $password));
- });
- self::$userSession->listen('\OC\User', 'postLogin', function ($user, $password) {
- /** @var $user \OC\User\User */
- \OC_Hook::emit('OC_User', 'post_login', array('run' => true, 'uid' => $user->getUID(), 'password' => $password));
- });
- self::$userSession->listen('\OC\User', 'logout', function () {
- \OC_Hook::emit('OC_User', 'logout', array());
- });
- }
- return self::$userSession;
+ return OC::$server->getUserSession();
}
/**
* @return \OC\User\Manager
*/
public static function getManager() {
- return self::getUserSession()->getManager();
+ return OC::$server->getUserManager();
}
private static $_backends = array();
@@ -93,6 +54,9 @@ class OC_User {
private static $_setupedBackends = array();
+ // bool, stores if a user want to access a resource anonymously, e.g if he opens a public link
+ private static $incognitoMode = false;
+
/**
* @brief registers backend
* @param string $backend name of the backend
@@ -177,6 +141,7 @@ class OC_User {
* setup the configured backends in config.php
*/
public static function setupBackends() {
+ OC_App::loadApps(array('prelogin'));
$backends = OC_Config::getValue('user_backends', array());
foreach ($backends as $i => $config) {
$class = $config['class'];
@@ -225,17 +190,28 @@ class OC_User {
public static function deleteUser($uid) {
$user = self::getManager()->get($uid);
if ($user) {
- $user->delete();
+ $result = $user->delete();
+
+ // if delete was successful we clean-up the rest
+ if ($result) {
+
+ // We have to delete the user from all groups
+ foreach (OC_Group::getUserGroups($uid) as $i) {
+ OC_Group::removeFromGroup($uid, $i);
+ }
+ // Delete the user's keys in preferences
+ OC_Preferences::deleteUser($uid);
+
+ // Delete user files in /data/
+ OC_Helper::rmdirr(\OC_User::getHome($uid));
- // We have to delete the user from all groups
- foreach (OC_Group::getUserGroups($uid) as $i) {
- OC_Group::removeFromGroup($uid, $i);
+ // Remove it from the Cache
+ self::getManager()->delete($uid);
}
- // Delete the user's keys in preferences
- OC_Preferences::deleteUser($uid);
- // Delete user files in /data/
- OC_Helper::rmdirr(OC_Config::getValue('datadirectory', OC::$SERVERROOT . '/data') . '/' . $uid . '/');
+ return true;
+ } else {
+ return false;
}
}
@@ -252,6 +228,55 @@ class OC_User {
}
/**
+ * @brief Try to login a user, assuming authentication
+ * has already happened (e.g. via Single Sign On).
+ *
+ * Log in a user and regenerate a new session.
+ *
+ * @param \OCP\Authentication\IApacheBackend $backend
+ * @return bool
+ */
+ public static function loginWithApache(\OCP\Authentication\IApacheBackend $backend) {
+
+ $uid = $backend->getCurrentUserId();
+ $run = true;
+ OC_Hook::emit( "OC_User", "pre_login", array( "run" => &$run, "uid" => $uid ));
+
+ if($uid) {
+ session_regenerate_id(true);
+ self::setUserId($uid);
+ self::setDisplayName($uid);
+ OC_Hook::emit( "OC_User", "post_login", array( "uid" => $uid, 'password'=>'' ));
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @brief Verify with Apache whether user is authenticated.
+ *
+ * @return boolean|null
+ * true: authenticated
+ * false: not authenticated
+ * null: not handled / no backend available
+ */
+ public static function handleApacheAuth() {
+ $backend = self::findFirstActiveUsedBackend();
+ if ($backend) {
+ OC_App::loadApps();
+
+ //setup extra user backends
+ self::setupBackends();
+ self::unsetMagicInCookie();
+
+ return self::loginWithApache($backend);
+ }
+
+ return null;
+ }
+
+
+ /**
* @brief Sets user id for session and triggers emit
*/
public static function setUserId($uid) {
@@ -289,7 +314,7 @@ class OC_User {
* Checks if the user is logged in
*/
public static function isLoggedIn() {
- if (\OC::$session->get('user_id')) {
+ if (\OC::$session->get('user_id') && self::$incognitoMode === false) {
OC_App::loadApps(array('authentication'));
self::setupBackends();
return self::userExists(\OC::$session->get('user_id'));
@@ -298,12 +323,37 @@ class OC_User {
}
/**
+ * @brief set incognito mode, e.g. if a user wants to open a public link
+ * @param bool $status
+ */
+ public static function setIncognitoMode($status) {
+ self::$incognitoMode = $status;
+
+ }
+
+ /**
+ * Supplies an attribute to the logout hyperlink. The default behaviour
+ * is to return an href with '?logout=true' appended. However, it can
+ * supply any attribute(s) which are valid for <a>.
+ *
+ * @return string with one or more HTML attributes.
+ */
+ public static function getLogoutAttribute() {
+ $backend = self::findFirstActiveUsedBackend();
+ if ($backend) {
+ return $backend->getLogoutAttribute();
+ }
+
+ return 'href="' . link_to('', 'index.php') . '?logout=true"';
+ }
+
+ /**
* @brief Check if the user is an admin user
* @param string $uid uid of the admin
* @return bool
*/
public static function isAdminUser($uid) {
- if (OC_Group::inGroup($uid, 'admin')) {
+ if (OC_Group::inGroup($uid, 'admin') && self::$incognitoMode === false) {
return true;
}
return false;
@@ -316,7 +366,7 @@ class OC_User {
*/
public static function getUser() {
$uid = OC::$session ? OC::$session->get('user_id') : null;
- if (!is_null($uid)) {
+ if (!is_null($uid) && self::$incognitoMode === false) {
return $uid;
} else {
return false;
@@ -353,7 +403,7 @@ class OC_User {
* generates a password
*/
public static function generatePassword() {
- return OC_Util::generate_random_bytes(30);
+ return OC_Util::generateRandomBytes(30);
}
/**
@@ -375,6 +425,22 @@ class OC_User {
}
/**
+ * @brief Check whether user can change his avatar
+ * @param string $uid The username
+ * @return bool
+ *
+ * Check whether a specified user can change his avatar
+ */
+ public static function canUserChangeAvatar($uid) {
+ $user = self::getManager()->get($uid);
+ if ($user) {
+ return $user->canChangeAvatar();
+ } else {
+ return false;
+ }
+ }
+
+ /**
* @brief Check whether user can change his password
* @param string $uid The username
* @return bool
@@ -410,22 +476,18 @@ class OC_User {
* @brief Check if the password is correct
* @param string $uid The username
* @param string $password The password
- * @return bool
+ * @return mixed user id a string on success, false otherwise
*
* Check if the password is correct without logging in the user
* returns the user id or false
*/
public static function checkPassword($uid, $password) {
- $user = self::getManager()->get($uid);
- if ($user) {
- if ($user->checkPassword($password)) {
- return $user->getUID();
- } else {
- return false;
- }
- } else {
- return false;
+ $manager = self::getManager();
+ $username = $manager->checkPassword($uid, $password);
+ if ($username !== false) {
+ return $username->getUID();
}
+ return false;
}
/**
@@ -539,4 +601,20 @@ class OC_User {
public static function unsetMagicInCookie() {
self::getUserSession()->unsetMagicInCookie();
}
+
+ /**
+ * @brief Returns the first active backend from self::$_usedBackends.
+ * @return null if no backend active, otherwise OCP\Authentication\IApacheBackend
+ */
+ private static function findFirstActiveUsedBackend() {
+ foreach (self::$_usedBackends as $backend) {
+ if ($backend instanceof OCP\Authentication\IApacheBackend) {
+ if ($backend->isSessionActive()) {
+ return $backend;
+ }
+ }
+ }
+
+ return null;
+ }
}
diff --git a/lib/user/backend.php b/lib/private/user/backend.php
index e9be08e429c..02c93d13bdf 100644
--- a/lib/user/backend.php
+++ b/lib/private/user/backend.php
@@ -31,13 +31,13 @@ define('OC_USER_BACKEND_NOT_IMPLEMENTED', -501);
/**
* actions that user backends can define
*/
-define('OC_USER_BACKEND_CREATE_USER', 0x000001);
-define('OC_USER_BACKEND_SET_PASSWORD', 0x000010);
-define('OC_USER_BACKEND_CHECK_PASSWORD', 0x000100);
-define('OC_USER_BACKEND_GET_HOME', 0x001000);
-define('OC_USER_BACKEND_GET_DISPLAYNAME', 0x010000);
-define('OC_USER_BACKEND_SET_DISPLAYNAME', 0x100000);
-
+define('OC_USER_BACKEND_CREATE_USER', 0x0000001);
+define('OC_USER_BACKEND_SET_PASSWORD', 0x0000010);
+define('OC_USER_BACKEND_CHECK_PASSWORD', 0x0000100);
+define('OC_USER_BACKEND_GET_HOME', 0x0001000);
+define('OC_USER_BACKEND_GET_DISPLAYNAME', 0x0010000);
+define('OC_USER_BACKEND_SET_DISPLAYNAME', 0x0100000);
+define('OC_USER_BACKEND_PROVIDE_AVATAR', 0x1000000);
/**
* Abstract base class for user management. Provides methods for querying backend
@@ -54,6 +54,7 @@ abstract class OC_User_Backend implements OC_User_Interface {
OC_USER_BACKEND_GET_HOME => 'getHome',
OC_USER_BACKEND_GET_DISPLAYNAME => 'getDisplayName',
OC_USER_BACKEND_SET_DISPLAYNAME => 'setDisplayName',
+ OC_USER_BACKEND_PROVIDE_AVATAR => 'canChangeAvatar',
);
/**
diff --git a/lib/user/database.php b/lib/private/user/database.php
index 9f00a022d9f..c99db3b27ca 100644
--- a/lib/user/database.php
+++ b/lib/private/user/database.php
@@ -42,13 +42,13 @@ class OC_User_Database extends OC_User_Backend {
/**
* @var PasswordHash
*/
- static private $hasher=null;
+ static private $hasher = null;
private function getHasher() {
- if(!self::$hasher) {
+ if (!self::$hasher) {
//we don't want to use DES based crypt(), since it doesn't return a hash with a recognisable prefix
- $forcePortable=(CRYPT_BLOWFISH!=1);
- self::$hasher=new PasswordHash(8, $forcePortable);
+ $forcePortable = (CRYPT_BLOWFISH != 1);
+ self::$hasher = new PasswordHash(8, $forcePortable);
}
return self::$hasher;
@@ -63,14 +63,14 @@ class OC_User_Database extends OC_User_Backend {
* Creates a new user. Basic checking of username is done in OC_User
* itself, not in its subclasses.
*/
- public function createUser( $uid, $password ) {
- if( $this->userExists($uid) ) {
+ public function createUser($uid, $password) {
+ if ($this->userExists($uid)) {
return false;
- }else{
- $hasher=$this->getHasher();
- $hash = $hasher->HashPassword($password.OC_Config::getValue('passwordsalt', ''));
- $query = OC_DB::prepare( 'INSERT INTO `*PREFIX*users` ( `uid`, `password` ) VALUES( ?, ? )' );
- $result = $query->execute( array( $uid, $hash));
+ } else {
+ $hasher = $this->getHasher();
+ $hash = $hasher->HashPassword($password . OC_Config::getValue('passwordsalt', ''));
+ $query = OC_DB::prepare('INSERT INTO `*PREFIX*users` ( `uid`, `password` ) VALUES( ?, ? )');
+ $result = $query->execute(array($uid, $hash));
return $result ? true : false;
}
@@ -83,10 +83,10 @@ class OC_User_Database extends OC_User_Backend {
*
* Deletes a user
*/
- public function deleteUser( $uid ) {
+ public function deleteUser($uid) {
// Delete user-group-relation
- $query = OC_DB::prepare( 'DELETE FROM `*PREFIX*users` WHERE `uid` = ?' );
- $query->execute( array( $uid ));
+ $query = OC_DB::prepare('DELETE FROM `*PREFIX*users` WHERE `uid` = ?');
+ $query->execute(array($uid));
return true;
}
@@ -98,15 +98,15 @@ class OC_User_Database extends OC_User_Backend {
*
* Change the password of a user
*/
- public function setPassword( $uid, $password ) {
- if( $this->userExists($uid) ) {
- $hasher=$this->getHasher();
- $hash = $hasher->HashPassword($password.OC_Config::getValue('passwordsalt', ''));
- $query = OC_DB::prepare( 'UPDATE `*PREFIX*users` SET `password` = ? WHERE `uid` = ?' );
- $query->execute( array( $hash, $uid ));
+ public function setPassword($uid, $password) {
+ if ($this->userExists($uid)) {
+ $hasher = $this->getHasher();
+ $hash = $hasher->HashPassword($password . OC_Config::getValue('passwordsalt', ''));
+ $query = OC_DB::prepare('UPDATE `*PREFIX*users` SET `password` = ? WHERE `uid` = ?');
+ $query->execute(array($hash, $uid));
return true;
- }else{
+ } else {
return false;
}
}
@@ -119,12 +119,12 @@ class OC_User_Database extends OC_User_Backend {
*
* Change the display name of a user
*/
- public function setDisplayName( $uid, $displayName ) {
- if( $this->userExists($uid) ) {
- $query = OC_DB::prepare( 'UPDATE `*PREFIX*users` SET `displayname` = ? WHERE `uid` = ?' );
- $query->execute( array( $displayName, $uid ));
+ public function setDisplayName($uid, $displayName) {
+ if ($this->userExists($uid)) {
+ $query = OC_DB::prepare('UPDATE `*PREFIX*users` SET `displayname` = ? WHERE LOWER(`uid`) = ?');
+ $query->execute(array($displayName, $uid));
return true;
- }else{
+ } else {
return false;
}
}
@@ -132,18 +132,16 @@ class OC_User_Database extends OC_User_Backend {
/**
* @brief get display name of the user
* @param $uid user ID of the user
- * @return display name
+ * @return string display name
*/
public function getDisplayName($uid) {
- if( $this->userExists($uid) ) {
- $query = OC_DB::prepare( 'SELECT `displayname` FROM `*PREFIX*users` WHERE `uid` = ?' );
- $result = $query->execute( array( $uid ))->fetchAll();
- $displayName = trim($result[0]['displayname'], ' ');
- if ( !empty($displayName) ) {
- return $displayName;
- } else {
- return $uid;
- }
+ $query = OC_DB::prepare('SELECT `displayname` FROM `*PREFIX*users` WHERE `uid` = ?');
+ $result = $query->execute(array($uid))->fetchAll();
+ $displayName = trim($result[0]['displayname'], ' ');
+ if (!empty($displayName)) {
+ return $displayName;
+ } else {
+ return $uid;
}
}
@@ -156,25 +154,14 @@ class OC_User_Database extends OC_User_Backend {
public function getDisplayNames($search = '', $limit = null, $offset = null) {
$displayNames = array();
$query = OC_DB::prepare('SELECT `uid`, `displayname` FROM `*PREFIX*users`'
- .' WHERE LOWER(`displayname`) LIKE LOWER(?)', $limit, $offset);
- $result = $query->execute(array($search.'%'));
+ . ' WHERE LOWER(`displayname`) LIKE LOWER(?) OR '
+ . 'LOWER(`uid`) LIKE LOWER(?)', $limit, $offset);
+ $result = $query->execute(array($search . '%', $search . '%'));
$users = array();
while ($row = $result->fetchRow()) {
$displayNames[$row['uid']] = $row['displayname'];
}
- // let's see if we can also find some users who don't have a display name yet
- $query = OC_DB::prepare('SELECT `uid`, `displayname` FROM `*PREFIX*users`'
- .' WHERE LOWER(`uid`) LIKE LOWER(?)', $limit, $offset);
- $result = $query->execute(array($search.'%'));
- while ($row = $result->fetchRow()) {
- $displayName = trim($row['displayname'], ' ');
- if ( empty($displayName) ) {
- $displayNames[$row['uid']] = $row['uid'];
- }
- }
-
-
return $displayNames;
}
@@ -187,30 +174,30 @@ class OC_User_Database extends OC_User_Backend {
* Check if the password is correct without logging in the user
* returns the user id or false
*/
- public function checkPassword( $uid, $password ) {
- $query = OC_DB::prepare( 'SELECT `uid`, `password` FROM `*PREFIX*users` WHERE LOWER(`uid`) = LOWER(?)' );
- $result = $query->execute( array( $uid));
+ public function checkPassword($uid, $password) {
+ $query = OC_DB::prepare('SELECT `uid`, `password` FROM `*PREFIX*users` WHERE LOWER(`uid`) = LOWER(?)');
+ $result = $query->execute(array($uid));
- $row=$result->fetchRow();
- if($row) {
- $storedHash=$row['password'];
- if ($storedHash[0]=='$') {//the new phpass based hashing
- $hasher=$this->getHasher();
- if($hasher->CheckPassword($password.OC_Config::getValue('passwordsalt', ''), $storedHash)) {
+ $row = $result->fetchRow();
+ if ($row) {
+ $storedHash = $row['password'];
+ if ($storedHash[0] == '$') { //the new phpass based hashing
+ $hasher = $this->getHasher();
+ if ($hasher->CheckPassword($password . OC_Config::getValue('passwordsalt', ''), $storedHash)) {
return $row['uid'];
- }else{
+ } else {
return false;
}
- }else{//old sha1 based hashing
- if(sha1($password)==$storedHash) {
+ } else { //old sha1 based hashing
+ if (sha1($password) == $storedHash) {
//upgrade to new hashing
$this->setPassword($row['uid'], $password);
return $row['uid'];
- }else{
+ } else {
return false;
}
}
- }else{
+ } else {
return false;
}
}
@@ -223,7 +210,7 @@ class OC_User_Database extends OC_User_Backend {
*/
public function getUsers($search = '', $limit = null, $offset = null) {
$query = OC_DB::prepare('SELECT `uid` FROM `*PREFIX*users` WHERE LOWER(`uid`) LIKE LOWER(?)', $limit, $offset);
- $result = $query->execute(array($search.'%'));
+ $result = $query->execute(array($search . '%'));
$users = array();
while ($row = $result->fetchRow()) {
$users[] = $row['uid'];
@@ -237,8 +224,8 @@ class OC_User_Database extends OC_User_Backend {
* @return boolean
*/
public function userExists($uid) {
- $query = OC_DB::prepare( 'SELECT COUNT(*) FROM `*PREFIX*users` WHERE LOWER(`uid`) = LOWER(?)' );
- $result = $query->execute( array( $uid ));
+ $query = OC_DB::prepare('SELECT COUNT(*) FROM `*PREFIX*users` WHERE LOWER(`uid`) = LOWER(?)');
+ $result = $query->execute(array($uid));
if (OC_DB::isError($result)) {
OC_Log::write('core', OC_DB::getErrorMessage($result), OC_Log::ERROR);
return false;
@@ -247,14 +234,14 @@ class OC_User_Database extends OC_User_Backend {
}
/**
- * @brief get the user's home directory
- * @param string $uid the username
- * @return boolean
- */
+ * @brief get the user's home directory
+ * @param string $uid the username
+ * @return boolean
+ */
public function getHome($uid) {
- if($this->userExists($uid)) {
- return OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" ) . '/' . $uid;
- }else{
+ if ($this->userExists($uid)) {
+ return OC_Config::getValue("datadirectory", OC::$SERVERROOT . "/data") . '/' . $uid;
+ } else {
return false;
}
}
diff --git a/lib/user/dummy.php b/lib/private/user/dummy.php
index b5b7a6c3c7a..52be7edfa75 100644
--- a/lib/user/dummy.php
+++ b/lib/private/user/dummy.php
@@ -88,8 +88,8 @@ class OC_User_Dummy extends OC_User_Backend {
* returns the user id or false
*/
public function checkPassword($uid, $password) {
- if (isset($this->users[$uid])) {
- return ($this->users[$uid] == $password);
+ if (isset($this->users[$uid]) && $this->users[$uid] === $password) {
+ return $uid;
} else {
return false;
}
diff --git a/lib/user/example.php b/lib/private/user/example.php
index b2d0dc25410..b2d0dc25410 100644
--- a/lib/user/example.php
+++ b/lib/private/user/example.php
diff --git a/lib/user/http.php b/lib/private/user/http.php
index 944ede73a0b..e99afe59ba7 100644
--- a/lib/user/http.php
+++ b/lib/private/user/http.php
@@ -79,7 +79,11 @@ class OC_User_HTTP extends OC_User_Backend {
curl_close($ch);
- return $status==200;
+ if($status === 200) {
+ return $uid;
+ }
+
+ return false;
}
/**
@@ -103,4 +107,4 @@ class OC_User_HTTP extends OC_User_Backend {
return false;
}
}
-} \ No newline at end of file
+}
diff --git a/lib/user/interface.php b/lib/private/user/interface.php
index b1e19aea7fb..c72bdfaf3fd 100644
--- a/lib/user/interface.php
+++ b/lib/private/user/interface.php
@@ -77,4 +77,4 @@ interface OC_User_Interface {
* @return boolean if users can be listed or not
*/
public function hasUserListings();
-} \ No newline at end of file
+}
diff --git a/lib/user/manager.php b/lib/private/user/manager.php
index 8dc9bfe2729..703c8cd7413 100644
--- a/lib/user/manager.php
+++ b/lib/private/user/manager.php
@@ -119,6 +119,39 @@ class Manager extends PublicEmitter {
}
/**
+ * remove deleted user from cache
+ *
+ * @param string $uid
+ * @return bool
+ */
+ public function delete($uid) {
+ if (isset($this->cachedUsers[$uid])) {
+ unset($this->cachedUsers[$uid]);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Check if the password is valid for the user
+ *
+ * @param $loginname
+ * @param $password
+ * @return mixed the User object on success, false otherwise
+ */
+ public function checkPassword($loginname, $password) {
+ foreach ($this->backends as $backend) {
+ if($backend->implementsActions(\OC_USER_BACKEND_CHECK_PASSWORD)) {
+ $uid = $backend->checkPassword($loginname, $password);
+ if ($uid !== false) {
+ return $this->getUserObject($uid, $backend);
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
* search by user id
*
* @param string $pattern
diff --git a/lib/user/session.php b/lib/private/user/session.php
index 9a6c669e935..c2885d00413 100644
--- a/lib/user/session.php
+++ b/lib/private/user/session.php
@@ -27,7 +27,7 @@ use OC\Hooks\Emitter;
*
* @package OC\User
*/
-class Session implements Emitter {
+class Session implements Emitter, \OCP\IUserSession {
/**
* @var \OC\User\Manager $manager
*/
@@ -113,6 +113,38 @@ class Session implements Emitter {
}
/**
+ * set the login name
+ *
+ * @param string login name for the logged in user
+ */
+ public function setLoginname($loginname) {
+ if (is_null($loginname)) {
+ $this->session->remove('loginname');
+ } else {
+ $this->session->set('loginname', $loginname);
+ }
+ }
+
+ /**
+ * get the login name of the current user
+ *
+ * @return string
+ */
+ public function getLoginname() {
+ if ($this->activeUser) {
+ return $this->session->get('loginname');
+ } else {
+ $uid = $this->session->get('user_id');
+ if ($uid) {
+ $this->activeUser = $this->manager->get($uid);
+ return $this->session->get('loginname');
+ } else {
+ return null;
+ }
+ }
+ }
+
+ /**
* try to login with the provided credentials
*
* @param string $uid
@@ -121,15 +153,17 @@ class Session implements Emitter {
*/
public function login($uid, $password) {
$this->manager->emit('\OC\User', 'preLogin', array($uid, $password));
- $user = $this->manager->get($uid);
- if ($user) {
- $result = $user->checkPassword($password);
- if ($result and $user->isEnabled()) {
- $this->setUser($user);
- $this->manager->emit('\OC\User', 'postLogin', array($user, $password));
- return true;
- } else {
- return false;
+ $user = $this->manager->checkPassword($uid, $password);
+ if($user !== false) {
+ if (!is_null($user)) {
+ if ($user->isEnabled()) {
+ $this->setUser($user);
+ $this->setLoginname($uid);
+ $this->manager->emit('\OC\User', 'postLogin', array($user, $password));
+ return true;
+ } else {
+ return false;
+ }
}
} else {
return false;
@@ -142,6 +176,7 @@ class Session implements Emitter {
public function logout() {
$this->manager->emit('\OC\User', 'logout');
$this->setUser(null);
+ $this->setLoginname(null);
$this->unsetMagicInCookie();
}
@@ -169,5 +204,10 @@ class Session implements Emitter {
setcookie('oc_username', '', time()-3600, \OC::$WEBROOT);
setcookie('oc_token', '', time()-3600, \OC::$WEBROOT);
setcookie('oc_remember_login', '', time()-3600, \OC::$WEBROOT);
+ // old cookies might be stored under /webroot/ instead of /webroot
+ // and Firefox doesn't like it!
+ setcookie('oc_username', '', time()-3600, \OC::$WEBROOT . '/');
+ setcookie('oc_token', '', time()-3600, \OC::$WEBROOT . '/');
+ setcookie('oc_remember_login', '', time()-3600, \OC::$WEBROOT . '/');
}
}
diff --git a/lib/user/user.php b/lib/private/user/user.php
index 8115c43198c..b4f33fa73cc 100644
--- a/lib/user/user.php
+++ b/lib/private/user/user.php
@@ -38,6 +38,11 @@ class User {
private $emitter;
/**
+ * @var string $home
+ */
+ private $home;
+
+ /**
* @param string $uid
* @param \OC_User_Backend $backend
* @param Emitter $emitter
@@ -106,24 +111,6 @@ class User {
}
/**
- * Check if the password is valid for the user
- *
- * @param $password
- * @return bool
- */
- public function checkPassword($password) {
- if ($this->backend->implementsActions(\OC_USER_BACKEND_CHECK_PASSWORD)) {
- $result = $this->backend->checkPassword($this->uid, $password);
- if ($result !== false) {
- $this->uid = $result;
- }
- return !($result === false);
- } else {
- return false;
- }
- }
-
- /**
* Set the password of the user
*
* @param string $password
@@ -151,10 +138,26 @@ class User {
* @return string
*/
public function getHome() {
- if ($this->backend->implementsActions(\OC_USER_BACKEND_GET_HOME) and $home = $this->backend->getHome($this->uid)) {
- return $home;
+ if (!$this->home) {
+ if ($this->backend->implementsActions(\OC_USER_BACKEND_GET_HOME) and $home = $this->backend->getHome($this->uid)) {
+ $this->home = $home;
+ } else {
+ $this->home = \OC_Config::getValue("datadirectory", \OC::$SERVERROOT . "/data") . '/' . $this->uid; //TODO switch to Config object once implemented
+ }
+ }
+ return $this->home;
+ }
+
+ /**
+ * check if the backend allows the user to change his avatar on Personal page
+ *
+ * @return bool
+ */
+ public function canChangeAvatar() {
+ if ($this->backend->implementsActions(\OC_USER_BACKEND_PROVIDE_AVATAR)) {
+ return $this->backend->canChangeAvatar($this->uid);
}
- return \OC_Config::getValue("datadirectory", \OC::$SERVERROOT . "/data") . '/' . $this->uid; //TODO switch to Config object once implemented
+ return true;
}
/**
diff --git a/lib/private/util.php b/lib/private/util.php
new file mode 100755
index 00000000000..c0e618cc863
--- /dev/null
+++ b/lib/private/util.php
@@ -0,0 +1,1139 @@
+<?php
+
+/**
+ * Class for utility functions
+ *
+ */
+
+class OC_Util {
+ public static $scripts=array();
+ public static $styles=array();
+ public static $headers=array();
+ private static $rootMounted=false;
+ private static $fsSetup=false;
+ public static $coreStyles=array();
+ public static $coreScripts=array();
+
+ /**
+ * @brief Can be set up
+ * @param string $user
+ * @return boolean
+ * @description configure the initial filesystem based on the configuration
+ */
+ public static function setupFS( $user = '' ) {
+ //setting up the filesystem twice can only lead to trouble
+ if(self::$fsSetup) {
+ return false;
+ }
+
+ // If we are not forced to load a specific user we load the one that is logged in
+ if( $user == "" && OC_User::isLoggedIn()) {
+ $user = OC_User::getUser();
+ }
+
+ // load all filesystem apps before, so no setup-hook gets lost
+ if(!isset($RUNTIME_NOAPPS) || !$RUNTIME_NOAPPS) {
+ 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
+ // OC_Filesystem
+ if ($user != '') {
+ self::$fsSetup=true;
+ }
+
+ $configDataDirectory = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" );
+ //first set up the local "root" storage
+ \OC\Files\Filesystem::initMounts();
+ if(!self::$rootMounted) {
+ \OC\Files\Filesystem::mount('\OC\Files\Storage\Local', array('datadir'=>$configDataDirectory), '/');
+ self::$rootMounted = true;
+ }
+
+ //if we aren't logged in, there is no use to set up the filesystem
+ if( $user != "" ) {
+ \OC\Files\Filesystem::addStorageWrapper(function($mountPoint, $storage){
+ // set up quota for home storages, even for other users
+ // which can happen when using sharing
+
+ if ($storage instanceof \OC\Files\Storage\Home) {
+ $user = $storage->getUser()->getUID();
+ $quota = OC_Util::getUserQuota($user);
+ if ($quota !== \OC\Files\SPACE_UNLIMITED) {
+ return new \OC\Files\Storage\Wrapper\Quota(array('storage' => $storage, 'quota' => $quota));
+ }
+ }
+
+ return $storage;
+ });
+
+ $userDir = '/'.$user.'/files';
+ $userRoot = OC_User::getHome($user);
+ $userDirectory = $userRoot . '/files';
+ if( !is_dir( $userDirectory )) {
+ mkdir( $userDirectory, 0755, true );
+ OC_Util::copySkeleton($userDirectory);
+ }
+ //jail the user into his "home" directory
+ \OC\Files\Filesystem::init($user, $userDir);
+
+ $fileOperationProxy = new OC_FileProxy_FileOperations();
+ OC_FileProxy::register($fileOperationProxy);
+
+ OC_Hook::emit('OC_Filesystem', 'setup', array('user' => $user, 'user_dir' => $userDir));
+ }
+ return true;
+ }
+
+ public static function getUserQuota($user){
+ $userQuota = OC_Preferences::getValue($user, 'files', 'quota', 'default');
+ if($userQuota === 'default') {
+ $userQuota = OC_AppConfig::getValue('files', 'default_quota', 'none');
+ }
+ if($userQuota === 'none') {
+ return \OC\Files\SPACE_UNLIMITED;
+ }else{
+ return OC_Helper::computerFileSize($userQuota);
+ }
+ }
+
+ /**
+ * @brief copies the user skeleton files into the fresh user home files
+ * @param string $userDirectory
+ */
+ public static function copySkeleton($userDirectory) {
+ OC_Util::copyr(\OC::$SERVERROOT.'/core/skeleton' , $userDirectory);
+ }
+
+ /**
+ * @brief copies a directory recursively
+ * @param string $source
+ * @param string $target
+ * @return void
+ */
+ public static function copyr($source,$target) {
+ $dir = opendir($source);
+ @mkdir($target);
+ while(false !== ( $file = readdir($dir)) ) {
+ if ( !\OC\Files\Filesystem::isIgnoredDir($file) ) {
+ if ( is_dir($source . '/' . $file) ) {
+ OC_Util::copyr($source . '/' . $file , $target . '/' . $file);
+ } else {
+ copy($source . '/' . $file,$target . '/' . $file);
+ }
+ }
+ }
+ closedir($dir);
+ }
+
+ /**
+ * @return void
+ */
+ public static function tearDownFS() {
+ \OC\Files\Filesystem::tearDown();
+ self::$fsSetup=false;
+ self::$rootMounted=false;
+ }
+
+ /**
+ * @brief get the current installed version of ownCloud
+ * @return array
+ */
+ public static function getVersion() {
+ OC_Util::loadVersion();
+ return \OC::$server->getSession()->get('OC_Version');
+ }
+
+ /**
+ * @brief get the current installed version string of ownCloud
+ * @return string
+ */
+ public static function getVersionString() {
+ OC_Util::loadVersion();
+ return \OC::$server->getSession()->get('OC_VersionString');
+ }
+
+ /**
+ * @description get the current installed edition of ownCloud. There is the community
+ * edition that just returns an empty string and the enterprise edition
+ * that returns "Enterprise".
+ * @return string
+ */
+ public static function getEditionString() {
+ OC_Util::loadVersion();
+ return \OC::$server->getSession()->get('OC_Edition');
+ }
+
+ /**
+ * @description get the update channel of the current installed of ownCloud.
+ * @return string
+ */
+ public static function getChannel() {
+ OC_Util::loadVersion();
+ return \OC::$server->getSession()->get('OC_Channel');
+ }
+
+ /**
+ * @description get the build number of the current installed of ownCloud.
+ * @return string
+ */
+ public static function getBuild() {
+ OC_Util::loadVersion();
+ return \OC::$server->getSession()->get('OC_Build');
+ }
+
+ /**
+ * @description load the version.php into the session as cache
+ */
+ private static function loadVersion() {
+ $timestamp = filemtime(OC::$SERVERROOT.'/version.php');
+ if(!\OC::$server->getSession()->exists('OC_Version') or OC::$server->getSession()->get('OC_Version_Timestamp') != $timestamp) {
+ require 'version.php';
+ $session = \OC::$server->getSession();
+ /** @var $timestamp int */
+ $session->set('OC_Version_Timestamp', $timestamp);
+ /** @var $OC_Version string */
+ $session->set('OC_Version', $OC_Version);
+ /** @var $OC_VersionString string */
+ $session->set('OC_VersionString', $OC_VersionString);
+ /** @var $OC_Edition string */
+ $session->set('OC_Edition', $OC_Edition);
+ /** @var $OC_Channel string */
+ $session->set('OC_Channel', $OC_Channel);
+ /** @var $OC_Build string */
+ $session->set('OC_Build', $OC_Build);
+ }
+ }
+
+ /**
+ * @brief add a javascript file
+ *
+ * @param string $application
+ * @param filename $file
+ * @return void
+ */
+ public static function addScript( $application, $file = null ) {
+ if ( is_null( $file )) {
+ $file = $application;
+ $application = "";
+ }
+ if ( !empty( $application )) {
+ self::$scripts[] = "$application/js/$file";
+ } else {
+ self::$scripts[] = "js/$file";
+ }
+ }
+
+ /**
+ * @brief add a css file
+ *
+ * @param string $application
+ * @param filename $file
+ * @return void
+ */
+ public static function addStyle( $application, $file = null ) {
+ if ( is_null( $file )) {
+ $file = $application;
+ $application = "";
+ }
+ if ( !empty( $application )) {
+ self::$styles[] = "$application/css/$file";
+ } else {
+ self::$styles[] = "css/$file";
+ }
+ }
+
+ /**
+ * @brief Add a custom element to the header
+ * @param string $tag tag name of the element
+ * @param array $attributes array of attributes for the element
+ * @param string $text the text content for the element
+ * @return void
+ */
+ public static function addHeader( $tag, $attributes, $text='') {
+ self::$headers[] = array(
+ 'tag'=>$tag,
+ 'attributes'=>$attributes,
+ 'text'=>$text
+ );
+ }
+
+ /**
+ * @brief formats a timestamp in the "right" way
+ *
+ * @param int $timestamp
+ * @param bool $dateOnly option to omit time from the result
+ * @return string timestamp
+ * @description adjust to clients timezone if we know it
+ */
+ public static function formatDate( $timestamp, $dateOnly=false) {
+ if(\OC::$session->exists('timezone')) {
+ $systemTimeZone = intval(date('O'));
+ $systemTimeZone = (round($systemTimeZone/100, 0)*60) + ($systemTimeZone%100);
+ $clientTimeZone = \OC::$session->get('timezone')*60;
+ $offset = $clientTimeZone - $systemTimeZone;
+ $timestamp = $timestamp + $offset*60;
+ }
+ $l = OC_L10N::get('lib');
+ return $l->l($dateOnly ? 'date' : 'datetime', $timestamp);
+ }
+
+ /**
+ * @brief check if the current server configuration is suitable for ownCloud
+ * @return array arrays with error messages and hints
+ */
+ public static function checkServer() {
+ // Assume that if checkServer() succeeded before in this session, then all is fine.
+ if(\OC::$session->exists('checkServer_suceeded') && \OC::$session->get('checkServer_suceeded')) {
+ return array();
+ }
+
+ $errors = array();
+
+ $defaults = new \OC_Defaults();
+
+ $webServerRestart = false;
+ //check for database drivers
+ if(!(is_callable('sqlite_open') or class_exists('SQLite3'))
+ and !is_callable('mysql_connect')
+ and !is_callable('pg_connect')
+ and !is_callable('oci_connect')) {
+ $errors[] = array(
+ 'error'=>'No database drivers (sqlite, mysql, or postgresql) installed.',
+ 'hint'=>'' //TODO: sane hint
+ );
+ $webServerRestart = true;
+ }
+
+ //common hint for all file permissions error messages
+ $permissionsHint = 'Permissions can usually be fixed by '
+ .'<a href="' . OC_Helper::linkToDocs('admin-dir_permissions')
+ .'" target="_blank">giving the webserver write access to the root directory</a>.';
+
+ // Check if config folder is writable.
+ if(!is_writable(OC::$SERVERROOT."/config/") or !is_readable(OC::$SERVERROOT."/config/")) {
+ $errors[] = array(
+ 'error' => "Can't write into config directory",
+ 'hint' => 'This can usually be fixed by '
+ .'<a href="' . OC_Helper::linkToDocs('admin-dir_permissions')
+ .'" target="_blank">giving the webserver write access to the config directory</a>.'
+ );
+ }
+
+ // Check if there is a writable install folder.
+ if(OC_Config::getValue('appstoreenabled', true)) {
+ if( OC_App::getInstallPath() === null
+ || !is_writable(OC_App::getInstallPath())
+ || !is_readable(OC_App::getInstallPath()) ) {
+ $errors[] = array(
+ 'error' => "Can't write into apps directory",
+ 'hint' => 'This can usually be fixed by '
+ .'<a href="' . OC_Helper::linkToDocs('admin-dir_permissions')
+ .'" target="_blank">giving the webserver write access to the apps directory</a> '
+ .'or disabling the appstore in the config file.'
+ );
+ }
+ }
+ $CONFIG_DATADIRECTORY = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" );
+ // Create root dir.
+ if(!is_dir($CONFIG_DATADIRECTORY)) {
+ $success=@mkdir($CONFIG_DATADIRECTORY);
+ if ($success) {
+ $errors = array_merge($errors, self::checkDataDirectoryPermissions($CONFIG_DATADIRECTORY));
+ } else {
+ $errors[] = array(
+ 'error' => "Can't create data directory (".$CONFIG_DATADIRECTORY.")",
+ 'hint' => 'This can usually be fixed by '
+ .'<a href="' . OC_Helper::linkToDocs('admin-dir_permissions')
+ .'" target="_blank">giving the webserver write access to the root directory</a>.'
+ );
+ }
+ } else if(!is_writable($CONFIG_DATADIRECTORY) or !is_readable($CONFIG_DATADIRECTORY)) {
+ $errors[] = array(
+ 'error'=>'Data directory ('.$CONFIG_DATADIRECTORY.') not writable by ownCloud',
+ 'hint'=>$permissionsHint
+ );
+ } else {
+ $errors = array_merge($errors, self::checkDataDirectoryPermissions($CONFIG_DATADIRECTORY));
+ }
+
+ if(!OC_Util::isSetLocaleWorking()) {
+ $errors[] = array(
+ 'error' => 'Setting locale to en_US.UTF-8/fr_FR.UTF-8/es_ES.UTF-8/de_DE.UTF-8/ru_RU.UTF-8/pt_BR.UTF-8/it_IT.UTF-8/ja_JP.UTF-8/zh_CN.UTF-8 failed',
+ 'hint' => 'Please install one of theses locales on your system and restart your webserver.'
+ );
+ }
+
+ $moduleHint = "Please ask your server administrator to install the module.";
+ // check if all required php modules are present
+ if(!class_exists('ZipArchive')) {
+ $errors[] = array(
+ 'error'=>'PHP module zip not installed.',
+ 'hint'=>$moduleHint
+ );
+ $webServerRestart = true;
+ }
+ if(!class_exists('DOMDocument')) {
+ $errors[] = array(
+ 'error' => 'PHP module dom not installed.',
+ 'hint' => $moduleHint
+ );
+ $webServerRestart =true;
+ }
+ if(!function_exists('xml_parser_create')) {
+ $errors[] = array(
+ 'error' => 'PHP module libxml not installed.',
+ 'hint' => $moduleHint
+ );
+ $webServerRestart = true;
+ }
+ if(!function_exists('mb_detect_encoding')) {
+ $errors[] = array(
+ 'error'=>'PHP module mb multibyte not installed.',
+ 'hint'=>$moduleHint
+ );
+ $webServerRestart = true;
+ }
+ if(!function_exists('ctype_digit')) {
+ $errors[] = array(
+ 'error'=>'PHP module ctype is not installed.',
+ 'hint'=>$moduleHint
+ );
+ $webServerRestart = true;
+ }
+ if(!function_exists('json_encode')) {
+ $errors[] = array(
+ 'error'=>'PHP module JSON is not installed.',
+ 'hint'=>$moduleHint
+ );
+ $webServerRestart = true;
+ }
+ if(!extension_loaded('gd') || !function_exists('gd_info')) {
+ $errors[] = array(
+ 'error'=>'PHP module GD is not installed.',
+ 'hint'=>$moduleHint
+ );
+ $webServerRestart = true;
+ }
+ if(!function_exists('gzencode')) {
+ $errors[] = array(
+ 'error'=>'PHP module zlib is not installed.',
+ 'hint'=>$moduleHint
+ );
+ $webServerRestart = true;
+ }
+ if(!function_exists('iconv')) {
+ $errors[] = array(
+ 'error'=>'PHP module iconv is not installed.',
+ 'hint'=>$moduleHint
+ );
+ $webServerRestart = true;
+ }
+ if(!function_exists('simplexml_load_string')) {
+ $errors[] = array(
+ 'error'=>'PHP module SimpleXML is not installed.',
+ 'hint'=>$moduleHint
+ );
+ $webServerRestart = true;
+ }
+ if(version_compare(phpversion(), '5.3.3', '<')) {
+ $errors[] = array(
+ 'error'=>'PHP 5.3.3 or higher is required.',
+ 'hint'=>'Please ask your server administrator to update PHP to the latest version.'
+ .' Your PHP version is no longer supported by ownCloud and the PHP community.'
+ );
+ $webServerRestart = true;
+ }
+ if(!defined('PDO::ATTR_DRIVER_NAME')) {
+ $errors[] = array(
+ 'error'=>'PHP PDO module is not installed.',
+ 'hint'=>$moduleHint
+ );
+ $webServerRestart = true;
+ }
+ if (((strtolower(@ini_get('safe_mode')) == 'on')
+ || (strtolower(@ini_get('safe_mode')) == 'yes')
+ || (strtolower(@ini_get('safe_mode')) == 'true')
+ || (ini_get("safe_mode") == 1 ))) {
+ $errors[] = array(
+ 'error'=>'PHP Safe Mode is enabled. ownCloud requires that it is disabled to work properly.',
+ 'hint'=>'PHP Safe Mode is a deprecated and mostly useless setting that should be disabled. '
+ .'Please ask your server administrator to disable it in php.ini or in your webserver config.'
+ );
+ $webServerRestart = true;
+ }
+ if (get_magic_quotes_gpc() == 1 ) {
+ $errors[] = array(
+ 'error'=>'Magic Quotes is enabled. ownCloud requires that it is disabled to work properly.',
+ 'hint'=>'Magic Quotes is a deprecated and mostly useless setting that should be disabled. '
+ .'Please ask your server administrator to disable it in php.ini or in your webserver config.'
+ );
+ $webServerRestart = true;
+ }
+
+ if($webServerRestart) {
+ $errors[] = array(
+ 'error'=>'PHP modules have been installed, but they are still listed as missing?',
+ 'hint'=>'Please ask your server administrator to restart the web server.'
+ );
+ }
+
+ // Cache the result of this function
+ \OC::$session->set('checkServer_suceeded', count($errors) == 0);
+
+ return $errors;
+ }
+
+ /**
+ * @brief check if there are still some encrypted files stored
+ * @return boolean
+ */
+ public static function encryptedFiles() {
+ //check if encryption was enabled in the past
+ $encryptedFiles = false;
+ if (OC_App::isEnabled('files_encryption') === false) {
+ $view = new OC\Files\View('/' . OCP\User::getUser());
+ $keyfilePath = '/files_encryption/keyfiles';
+ if ($view->is_dir($keyfilePath)) {
+ $dircontent = $view->getDirectoryContent($keyfilePath);
+ if (!empty($dircontent)) {
+ $encryptedFiles = true;
+ }
+ }
+ }
+
+ return $encryptedFiles;
+ }
+
+ /**
+ * @brief Check for correct file permissions of data directory
+ * @paran string $dataDirectory
+ * @return array arrays with error messages and hints
+ */
+ public static function checkDataDirectoryPermissions($dataDirectory) {
+ $errors = array();
+ if (self::runningOnWindows()) {
+ //TODO: permissions checks for windows hosts
+ } else {
+ $permissionsModHint = 'Please change the permissions to 0770 so that the directory'
+ .' cannot be listed by other users.';
+ $perms = substr(decoct(@fileperms($dataDirectory)), -3);
+ if (substr($perms, -1) != '0') {
+ OC_Helper::chmodr($dataDirectory, 0770);
+ clearstatcache();
+ $perms = substr(decoct(@fileperms($dataDirectory)), -3);
+ if (substr($perms, 2, 1) != '0') {
+ $errors[] = array(
+ 'error' => 'Data directory ('.$dataDirectory.') is readable for other users',
+ 'hint' => $permissionsModHint
+ );
+ }
+ }
+ }
+ return $errors;
+ }
+
+ /**
+ * @return void
+ */
+ public static function displayLoginPage($errors = array()) {
+ $parameters = array();
+ foreach( $errors as $key => $value ) {
+ $parameters[$value] = true;
+ }
+ if (!empty($_POST['user'])) {
+ $parameters["username"] = $_POST['user'];
+ $parameters['user_autofocus'] = false;
+ } else {
+ $parameters["username"] = '';
+ $parameters['user_autofocus'] = true;
+ }
+ if (isset($_REQUEST['redirect_url'])) {
+ $redirectUrl = $_REQUEST['redirect_url'];
+ $parameters['redirect_url'] = urlencode($redirectUrl);
+ }
+
+ $parameters['alt_login'] = OC_App::getAlternativeLogIns();
+ $parameters['rememberLoginAllowed'] = self::rememberLoginAllowed();
+ OC_Template::printGuestPage("", "login", $parameters);
+ }
+
+
+ /**
+ * @brief Check if the app is enabled, redirects to home if not
+ * @return void
+ */
+ public static function checkAppEnabled($app) {
+ if( !OC_App::isEnabled($app)) {
+ header( 'Location: '.OC_Helper::linkToAbsolute( '', 'index.php' ));
+ exit();
+ }
+ }
+
+ /**
+ * Check if the user is logged in, redirects to home if not. With
+ * redirect URL parameter to the request URI.
+ * @return void
+ */
+ public static function checkLoggedIn() {
+ // Check if we are a user
+ if( !OC_User::isLoggedIn()) {
+ header( 'Location: '.OC_Helper::linkToAbsolute( '', 'index.php',
+ array('redirectUrl' => OC_Request::requestUri())
+ ));
+ exit();
+ }
+ }
+
+ /**
+ * @brief Check if the user is a admin, redirects to home if not
+ * @return void
+ */
+ public static function checkAdminUser() {
+ OC_Util::checkLoggedIn();
+ if( !OC_User::isAdminUser(OC_User::getUser())) {
+ header( 'Location: '.OC_Helper::linkToAbsolute( '', 'index.php' ));
+ exit();
+ }
+ }
+
+ /**
+ * Check if it is allowed to remember login.
+ *
+ * @note Every app can set 'rememberlogin' to 'false' to disable the remember login feature
+ *
+ * @return bool
+ */
+ public static function rememberLoginAllowed() {
+
+ $apps = OC_App::getEnabledApps();
+
+ foreach ($apps as $app) {
+ $appInfo = OC_App::getAppInfo($app);
+ if (isset($appInfo['rememberlogin']) && $appInfo['rememberlogin'] === 'false') {
+ return false;
+ }
+
+ }
+ return true;
+ }
+
+ /**
+ * @brief Check if the user is a subadmin, redirects to home if not
+ * @return array $groups where the current user is subadmin
+ */
+ public static function checkSubAdminUser() {
+ OC_Util::checkLoggedIn();
+ if(!OC_SubAdmin::isSubAdmin(OC_User::getUser())) {
+ header( 'Location: '.OC_Helper::linkToAbsolute( '', 'index.php' ));
+ exit();
+ }
+ return true;
+ }
+
+ /**
+ * @brief Redirect to the user default page
+ * @return void
+ */
+ public static function redirectToDefaultPage() {
+ if(isset($_REQUEST['redirect_url'])) {
+ $location = OC_Helper::makeURLAbsolute(urldecode($_REQUEST['redirect_url']));
+ }
+ else if (isset(OC::$REQUESTEDAPP) && !empty(OC::$REQUESTEDAPP)) {
+ $location = OC_Helper::linkToAbsolute( OC::$REQUESTEDAPP, 'index.php' );
+ } else {
+ $defaultPage = OC_Appconfig::getValue('core', 'defaultpage');
+ if ($defaultPage) {
+ $location = OC_Helper::makeURLAbsolute(OC::$WEBROOT.'/'.$defaultPage);
+ } else {
+ $location = OC_Helper::linkToAbsolute( 'files', 'index.php' );
+ }
+ }
+ OC_Log::write('core', 'redirectToDefaultPage: '.$location, OC_Log::DEBUG);
+ header( 'Location: '.$location );
+ exit();
+ }
+
+ /**
+ * @brief get an id unique for this instance
+ * @return string
+ */
+ public static function getInstanceId() {
+ $id = OC_Config::getValue('instanceid', null);
+ if(is_null($id)) {
+ // We need to guarantee at least one letter in instanceid so it can be used as the session_name
+ $id = 'oc' . self::generateRandomBytes(10);
+ OC_Config::$object->setValue('instanceid', $id);
+ }
+ return $id;
+ }
+
+ /**
+ * @brief Static lifespan (in seconds) when a request token expires.
+ * @see OC_Util::callRegister()
+ * @see OC_Util::isCallRegistered()
+ * @description
+ * Also required for the client side to compute the point in time when to
+ * request a fresh token. The client will do so when nearly 97% of the
+ * time span coded here has expired.
+ */
+ public static $callLifespan = 3600; // 3600 secs = 1 hour
+
+ /**
+ * @brief Register an get/post call. Important to prevent CSRF attacks.
+ * @todo Write howto: CSRF protection guide
+ * @return $token Generated token.
+ * @description
+ * Creates a 'request token' (random) and stores it inside the session.
+ * Ever subsequent (ajax) request must use such a valid token to succeed,
+ * otherwise the request will be denied as a protection against CSRF.
+ * The tokens expire after a fixed lifespan.
+ * @see OC_Util::$callLifespan
+ * @see OC_Util::isCallRegistered()
+ */
+ public static function callRegister() {
+ // Check if a token exists
+ if(!\OC::$session->exists('requesttoken')) {
+ // No valid token found, generate a new one.
+ $requestToken = self::generateRandomBytes(20);
+ \OC::$session->set('requesttoken', $requestToken);
+ } else {
+ // Valid token already exists, send it
+ $requestToken = \OC::$session->get('requesttoken');
+ }
+ return($requestToken);
+ }
+
+ /**
+ * @brief Check an ajax get/post call if the request token is valid.
+ * @return boolean False if request token is not set or is invalid.
+ * @see OC_Util::$callLifespan
+ * @see OC_Util::callRegister()
+ */
+ public static function isCallRegistered() {
+ return \OC::$server->getRequest()->passesCSRFCheck();
+ }
+
+ /**
+ * @brief Check an ajax get/post call if the request token is valid. exit if not.
+ * @todo Write howto
+ * @return void
+ */
+ public static function callCheck() {
+ if(!OC_Util::isCallRegistered()) {
+ exit();
+ }
+ }
+
+ /**
+ * @brief Public function to sanitize HTML
+ *
+ * This function is used to sanitize HTML and should be applied on any
+ * string or array of strings before displaying it on a web page.
+ *
+ * @param string|array of strings
+ * @return array with sanitized strings or a single sanitized string, depends on the input parameter.
+ */
+ public static function sanitizeHTML( &$value ) {
+ if (is_array($value)) {
+ array_walk_recursive($value, 'OC_Util::sanitizeHTML');
+ } else {
+ //Specify encoding for PHP<5.4
+ $value = htmlentities((string)$value, ENT_QUOTES, 'UTF-8');
+ }
+ return $value;
+ }
+
+ /**
+ * @brief Public function to encode url parameters
+ *
+ * This function is used to encode path to file before output.
+ * Encoding is done according to RFC 3986 with one exception:
+ * Character '/' is preserved as is.
+ *
+ * @param string $component part of URI to encode
+ * @return string
+ */
+ public static function encodePath($component) {
+ $encoded = rawurlencode($component);
+ $encoded = str_replace('%2F', '/', $encoded);
+ return $encoded;
+ }
+
+ /**
+ * @brief Check if the htaccess file is working
+ * @return bool
+ * @description Check if the htaccess file is working by creating a test
+ * file in the data directory and trying to access via http
+ */
+ public static function isHtAccessWorking() {
+ if (!\OC_Config::getValue("check_for_working_htaccess", true)) {
+ return true;
+ }
+
+ // testdata
+ $fileName = '/htaccesstest.txt';
+ $testContent = 'testcontent';
+
+ // creating a test file
+ $testFile = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" ).'/'.$fileName;
+
+ if(file_exists($testFile)) {// already running this test, possible recursive call
+ return false;
+ }
+
+ $fp = @fopen($testFile, 'w');
+ @fwrite($fp, $testContent);
+ @fclose($fp);
+
+ // accessing the file via http
+ $url = OC_Helper::makeURLAbsolute(OC::$WEBROOT.'/data'.$fileName);
+ $fp = @fopen($url, 'r');
+ $content=@fread($fp, 2048);
+ @fclose($fp);
+
+ // cleanup
+ @unlink($testFile);
+
+ // does it work ?
+ if($content==$testContent) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * @brief test if webDAV is working properly
+ * @return bool
+ * @description
+ * The basic assumption is that if the server returns 401/Not Authenticated for an unauthenticated PROPFIND
+ * the web server it self is setup properly.
+ *
+ * Why not an authenticated PROPFIND and other verbs?
+ * - We don't have the password available
+ * - We have no idea about other auth methods implemented (e.g. OAuth with Bearer header)
+ *
+ */
+ public static function isWebDAVWorking() {
+ if (!function_exists('curl_init')) {
+ return true;
+ }
+ if (!\OC_Config::getValue("check_for_working_webdav", true)) {
+ return true;
+ }
+ $settings = array(
+ 'baseUri' => OC_Helper::linkToRemote('webdav'),
+ );
+
+ $client = new \OC_DAVClient($settings);
+
+ $client->setRequestTimeout(10);
+
+ // for this self test we don't care if the ssl certificate is self signed and the peer cannot be verified.
+ $client->setVerifyPeer(false);
+
+ $return = true;
+ try {
+ // test PROPFIND
+ $client->propfind('', array('{DAV:}resourcetype'));
+ } catch (\Sabre_DAV_Exception_NotAuthenticated $e) {
+ $return = true;
+ } catch (\Exception $e) {
+ OC_Log::write('core', 'isWebDAVWorking: NO - Reason: '.$e->getMessage(). ' ('.get_class($e).')', OC_Log::WARN);
+ $return = false;
+ }
+
+ return $return;
+ }
+
+ /**
+ * Check if the setlocal call does not work. This can happen if the right
+ * local packages are not available on the server.
+ * @return bool
+ */
+ public static function isSetLocaleWorking() {
+ // setlocale test is pointless on Windows
+ if (OC_Util::runningOnWindows() ) {
+ return true;
+ }
+
+ \Patchwork\Utf8\Bootup::initLocale();
+ if ('' === basename('§')) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @brief Check if the PHP module fileinfo is loaded.
+ * @return bool
+ */
+ public static function fileInfoLoaded() {
+ return function_exists('finfo_open');
+ }
+
+ /**
+ * @brief Check if a PHP version older then 5.3.8 is installed.
+ * @return bool
+ */
+ public static function isPHPoutdated() {
+ return version_compare(phpversion(), '5.3.8', '<');
+ }
+
+ /**
+ * @brief Check if the ownCloud server can connect to the internet
+ * @return bool
+ */
+ public static function isInternetConnectionWorking() {
+ // in case there is no internet connection on purpose return false
+ if (self::isInternetConnectionEnabled() === false) {
+ return false;
+ }
+
+ // try to connect to owncloud.org to see if http connections to the internet are possible.
+ $connected = @fsockopen("www.owncloud.org", 80);
+ if ($connected) {
+ fclose($connected);
+ return true;
+ } else {
+ // second try in case one server is down
+ $connected = @fsockopen("apps.owncloud.com", 80);
+ if ($connected) {
+ fclose($connected);
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ /**
+ * @brief Check if the connection to the internet is disabled on purpose
+ * @return bool
+ */
+ public static function isInternetConnectionEnabled(){
+ return \OC_Config::getValue("has_internet_connection", true);
+ }
+
+ /**
+ * @brief clear all levels of output buffering
+ * @return void
+ */
+ public static function obEnd(){
+ while (ob_get_level()) {
+ ob_end_clean();
+ }
+ }
+
+
+ /**
+ * @brief Generates a cryptographic secure pseudo-random string
+ * @param Int $length of the random string
+ * @return String
+ * Please also update secureRNGAvailable if you change something here
+ */
+ public static function generateRandomBytes($length = 30) {
+ // Try to use openssl_random_pseudo_bytes
+ if (function_exists('openssl_random_pseudo_bytes')) {
+ $pseudoByte = bin2hex(openssl_random_pseudo_bytes($length, $strong));
+ if($strong == true) {
+ return substr($pseudoByte, 0, $length); // Truncate it to match the length
+ }
+ }
+
+ // Try to use /dev/urandom
+ if (!self::runningOnWindows()) {
+ $fp = @file_get_contents('/dev/urandom', false, null, 0, $length);
+ if ($fp !== false) {
+ $string = substr(bin2hex($fp), 0, $length);
+ return $string;
+ }
+ }
+
+ // Fallback to mt_rand()
+ $characters = '0123456789';
+ $characters .= 'abcdefghijklmnopqrstuvwxyz';
+ $charactersLength = strlen($characters)-1;
+ $pseudoByte = "";
+
+ // Select some random characters
+ for ($i = 0; $i < $length; $i++) {
+ $pseudoByte .= $characters[mt_rand(0, $charactersLength)];
+ }
+ return $pseudoByte;
+ }
+
+ /**
+ * @brief Checks if a secure random number generator is available
+ * @return bool
+ */
+ public static function secureRNGAvailable() {
+ // Check openssl_random_pseudo_bytes
+ if(function_exists('openssl_random_pseudo_bytes')) {
+ openssl_random_pseudo_bytes(1, $strong);
+ if($strong == true) {
+ return true;
+ }
+ }
+
+ // Check /dev/urandom
+ if (!self::runningOnWindows()) {
+ $fp = @file_get_contents('/dev/urandom', false, null, 0, 1);
+ if ($fp !== false) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * @Brief Get file content via curl.
+ * @param string $url Url to get content
+ * @return string of the response or false on error
+ * This function get the content of a page via curl, if curl is enabled.
+ * If not, file_get_contents is used.
+ */
+ public static function getUrlContent($url) {
+ if (function_exists('curl_init')) {
+ $curl = curl_init();
+
+ 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', '') != '') {
+ curl_setopt($curl, CURLOPT_PROXY, OC_Config::getValue('proxy'));
+ }
+ if(OC_Config::getValue('proxyuserpwd', '') != '') {
+ curl_setopt($curl, CURLOPT_PROXYUSERPWD, OC_Config::getValue('proxyuserpwd'));
+ }
+ $data = curl_exec($curl);
+ curl_close($curl);
+
+ } else {
+ $contextArray = null;
+
+ if(OC_Config::getValue('proxy', '') != '') {
+ $contextArray = array(
+ 'http' => array(
+ 'timeout' => 10,
+ 'proxy' => OC_Config::getValue('proxy')
+ )
+ );
+ } else {
+ $contextArray = array(
+ 'http' => array(
+ 'timeout' => 10
+ )
+ );
+ }
+
+ $ctx = stream_context_create(
+ $contextArray
+ );
+ $data = @file_get_contents($url, 0, $ctx);
+
+ }
+ return $data;
+ }
+
+ /**
+ * @return bool - well are we running on windows or not
+ */
+ public static function runningOnWindows() {
+ return (substr(PHP_OS, 0, 3) === "WIN");
+ }
+
+ /**
+ * Handles the case that there may not be a theme, then check if a "default"
+ * theme exists and take that one
+ * @return string the theme
+ */
+ public static function getTheme() {
+ $theme = OC_Config::getValue("theme", '');
+
+ if($theme === '') {
+ if(is_dir(OC::$SERVERROOT . '/themes/default')) {
+ $theme = 'default';
+ }
+ }
+
+ return $theme;
+ }
+
+ /**
+ * @brief Clear the opcode cache if one exists
+ * This is necessary for writing to the config file
+ * in case the opcode cache does not re-validate files
+ * @return void
+ */
+ public static function clearOpcodeCache() {
+ // APC
+ if (function_exists('apc_clear_cache')) {
+ apc_clear_cache();
+ }
+ // Zend Opcache
+ if (function_exists('accelerator_reset')) {
+ accelerator_reset();
+ }
+ // XCache
+ if (function_exists('xcache_clear_cache')) {
+ if (ini_get('xcache.admin.enable_auth')) {
+ OC_Log::write('core', 'XCache opcode cache will not be cleared because "xcache.admin.enable_auth" is enabled.', \OC_Log::WARN);
+ } else {
+ xcache_clear_cache(XC_TYPE_PHP, 0);
+ }
+ }
+ // Opcache (PHP >= 5.5)
+ if (function_exists('opcache_reset')) {
+ opcache_reset();
+ }
+ }
+
+ /**
+ * Normalize a unicode string
+ * @param string $value a not normalized string
+ * @return bool|string
+ */
+ public static function normalizeUnicode($value) {
+ if(class_exists('Patchwork\PHP\Shim\Normalizer')) {
+ $normalizedValue = \Patchwork\PHP\Shim\Normalizer::normalize($value);
+ if($normalizedValue === false) {
+ \OC_Log::write( 'core', 'normalizing failed for "' . $value . '"', \OC_Log::WARN);
+ } else {
+ $value = $normalizedValue;
+ }
+ }
+
+ return $value;
+ }
+
+ /**
+ * @return string
+ */
+ public static function basename($file) {
+ $file = rtrim($file, '/');
+ $t = explode('/', $file);
+ return array_pop($t);
+ }
+
+ /**
+ * A human readable string is generated based on version, channel and build number
+ * @return string
+ */
+ public static function getHumanVersion() {
+ $version = OC_Util::getVersionString().' ('.OC_Util::getChannel().')';
+ $build = OC_Util::getBuild();
+ if(!empty($build) and OC_Util::getChannel() === 'daily') {
+ $version .= ' Build:' . $build;
+ }
+ return $version;
+ }
+}
diff --git a/lib/vobject.php b/lib/private/vobject.php
index 267176ebc07..267176ebc07 100644
--- a/lib/vobject.php
+++ b/lib/private/vobject.php
diff --git a/lib/vobject/compoundproperty.php b/lib/private/vobject/compoundproperty.php
index d702ab802e0..7fe42574bed 100644
--- a/lib/vobject/compoundproperty.php
+++ b/lib/private/vobject/compoundproperty.php
@@ -67,4 +67,4 @@ class CompoundProperty extends \Sabre\VObject\Property\Compound {
}
-} \ No newline at end of file
+}
diff --git a/lib/vobject/stringproperty.php b/lib/private/vobject/stringproperty.php
index b98a8f26c2b..a9d63a0a789 100644
--- a/lib/vobject/stringproperty.php
+++ b/lib/private/vobject/stringproperty.php
@@ -77,4 +77,4 @@ class StringProperty extends \Sabre\VObject\Property {
}
-} \ No newline at end of file
+}
diff --git a/lib/public/activity/iconsumer.php b/lib/public/activity/iconsumer.php
new file mode 100644
index 00000000000..9afacf4e745
--- /dev/null
+++ b/lib/public/activity/iconsumer.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Thomas Müller
+ * @copyright 2013 Thomas Müller deepdiver@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/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Activity/IConsumer interface
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP\Activity;
+
+interface IConsumer {
+ /**
+ * @param $app
+ * @param $subject
+ * @param $subjectParams
+ * @param $message
+ * @param $messageParams
+ * @param $file
+ * @param $link
+ * @param $affectedUser
+ * @param $type
+ * @param $priority
+ * @return mixed
+ */
+ function receive($app, $subject, $subjectParams, $message, $messageParams, $file, $link, $affectedUser, $type, $priority );
+}
+
diff --git a/lib/public/activity/imanager.php b/lib/public/activity/imanager.php
new file mode 100644
index 00000000000..086e430d677
--- /dev/null
+++ b/lib/public/activity/imanager.php
@@ -0,0 +1,59 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Thomas Müller
+ * @copyright 2013 Thomas Müller deepdiver@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/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Activity/IManager interface
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP\Activity;
+
+interface IManager {
+
+ /**
+ * @param $app
+ * @param $subject
+ * @param $subjectParams
+ * @param $message
+ * @param $messageParams
+ * @param $file
+ * @param $link
+ * @param $affectedUser
+ * @param $type
+ * @param $priority
+ * @return mixed
+ */
+ function publishActivity($app, $subject, $subjectParams, $message, $messageParams, $file, $link, $affectedUser, $type, $priority);
+
+ /**
+ * In order to improve lazy loading a closure can be registered which will be called in case
+ * activity consumers are actually requested
+ *
+ * $callable has to return an instance of OCA\Activity\IConsumer
+ *
+ * @param \Closure $callable
+ */
+ function registerConsumer(\Closure $callable);
+
+}
diff --git a/lib/public/api.php b/lib/public/api.php
index d94b68e908a..f53188d2721 100644
--- a/lib/public/api.php
+++ b/lib/public/api.php
@@ -1,25 +1,33 @@
<?php
/**
-* ownCloud
-*
-* @author Tom Needham
-* @copyright 2012 Tom Needham tom@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/>.
-*
-*/
+ * ownCloud
+ *
+ * @author Tom Needham
+ * @copyright 2012 Tom Needham tom@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/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * API Class
+ *
+ */
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
namespace OCP;
/**
diff --git a/lib/public/app.php b/lib/public/app.php
index a1ecf524cc8..e0b5682242b 100644
--- a/lib/public/app.php
+++ b/lib/public/app.php
@@ -1,28 +1,28 @@
<?php
/**
-* ownCloud
-*
-* @author Frank Karlitschek
-* @copyright 2012 Frank Karlitschek frank@owncloud.org
-*
-* 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/>.
-*
-*/
+ * ownCloud
+ *
+ * @author Frank Karlitschek
+ * @copyright 2012 Frank Karlitschek frank@owncloud.org
+ *
+ * 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/>.
+ *
+ */
/**
* Public interface of ownCloud for apps to use.
- * App Class.
+ * App Class
*
*/
@@ -35,14 +35,12 @@ namespace OCP;
*/
class App {
/**
- * @brief Makes owncloud aware of this app
- * @brief This call is deprecated and not necessary to use.
- * @param $data array with all information
- * @returns true/false
+ * Makes ownCloud aware of this app
+ * @param array with all information
+ * @return boolean
*
- * @deprecated this method is deprecated
- * Do not call it anymore
- * It'll remain in our public API for compatibility reasons
+ * @deprecated This method is deprecated. Do not call it anymore.
+ * It'll remain in our public API for compatibility reasons.
*
*/
public static function register( $data ) {
@@ -50,9 +48,9 @@ class App {
}
/**
- * @brief adds an entry to the navigation
- * @param $data array containing the data
- * @returns true/false
+ * Adds an entry to the navigation
+ * @param array containing the data
+ * @return boolean
*
* This function adds a new entry to the navigation visible to users. $data
* is an associative array.
@@ -71,9 +69,9 @@ class App {
}
/**
- * @brief marks a navigation entry as active
- * @param $id id of the entry
- * @returns true/false
+ * Marks a navigation entry as active
+ * @param string id of the entry
+ * @return boolean
*
* This function sets a navigation entry as active and removes the 'active'
* property from all other entries. The templates can use this for
@@ -84,7 +82,7 @@ class App {
}
/**
- * @brief Register a Configuration Screen that should appear in the personal settings section.
+ * Register a Configuration Screen that should appear in the personal settings section.
* @param $app string appid
* @param $page string page to be included
*/
@@ -93,7 +91,7 @@ class App {
}
/**
- * @brief Register a Configuration Screen that should appear in the Admin section.
+ * Register a Configuration Screen that should appear in the Admin section.
* @param $app string appid
* @param $page string page to be included
*/
@@ -102,19 +100,19 @@ class App {
}
/**
- * @brief Read app metadata from the info.xml file
+ * Read app metadata from the info.xml file
* @param string $app id of the app or the path of the info.xml file
- * @param boolean path (optional)
- * @returns array
+ * @param boolean $path (optional)
+ * @return array
*/
public static function getAppInfo( $app, $path=false ) {
return \OC_App::getAppInfo( $app, $path);
}
/**
- * @brief checks whether or not an app is enabled
- * @param $app app
- * @returns true/false
+ * checks whether or not an app is enabled
+ * @param string
+ * @return boolean
*
* This function checks whether or not an app is enabled.
*/
@@ -123,17 +121,17 @@ class App {
}
/**
- * @brief Check if the app is enabled, redirects to home if not
- * @param $app app
+ * Check if the app is enabled, redirects to home if not
+ * @param string
*/
public static function checkAppEnabled( $app ) {
\OC_Util::checkAppEnabled( $app );
}
/**
- * @brief Get the last version of the app, either from appinfo/version or from appinfo/info.xml
- * @param $app app
- * @returns true/false
+ * Get the last version of the app, either from appinfo/version or from appinfo/info.xml
+ * @param string
+ * @return boolean
*/
public static function getAppVersion( $app ) {
return \OC_App::getAppVersion( $app );
diff --git a/lib/public/appframework/app.php b/lib/public/appframework/app.php
new file mode 100644
index 00000000000..90150245c41
--- /dev/null
+++ b/lib/public/appframework/app.php
@@ -0,0 +1,111 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Thomas Müller
+ * @copyright 2013 Thomas Müller deepdiver@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/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * AppFramework/App class
+ */
+
+namespace OCP\AppFramework;
+use OC\AppFramework\routing\RouteConfig;
+
+
+/**
+ * Class App
+ * @package OCP\AppFramework
+ *
+ * Any application must inherit this call - all controller instances to be used are
+ * to be registered using IContainer::registerService
+ */
+class App {
+ /**
+ * @param array $urlParams an array with variables extracted from the routes
+ */
+ public function __construct($appName, $urlParams = array()) {
+ $this->container = new \OC\AppFramework\DependencyInjection\DIContainer($appName, $urlParams);
+ }
+
+ private $container;
+
+ /**
+ * @return IAppContainer
+ */
+ public function getContainer() {
+ return $this->container;
+ }
+
+ /**
+ * This function is to be called to create single routes and restful routes based on the given $routes array.
+ *
+ * Example code in routes.php of tasks app (it will register two restful resources):
+ * $routes = array(
+ * 'resources' => array(
+ * 'lists' => array('url' => '/tasklists'),
+ * 'tasks' => array('url' => '/tasklists/{listId}/tasks')
+ * )
+ * );
+ *
+ * $a = new TasksApp();
+ * $a->registerRoutes($this, $routes);
+ *
+ * @param \OC_Router $router
+ * @param array $routes
+ */
+ public function registerRoutes($router, $routes) {
+ $routeConfig = new RouteConfig($this->container, $router, $routes);
+ $routeConfig->register();
+ }
+
+ /**
+ * This function is called by the routing component to fire up the frameworks dispatch mechanism.
+ *
+ * Example code in routes.php of the task app:
+ * $this->create('tasks_index', '/')->get()->action(
+ * function($params){
+ * $app = new TaskApp($params);
+ * $app->dispatch('PageController', 'index');
+ * }
+ * );
+ *
+ *
+ * Example for for TaskApp implementation:
+ * class TaskApp extends \OCP\AppFramework\App {
+ *
+ * public function __construct($params){
+ * parent::__construct('tasks', $params);
+ *
+ * $this->getContainer()->registerService('PageController', function(IAppContainer $c){
+ * $a = $c->query('API');
+ * $r = $c->query('Request');
+ * return new PageController($a, $r);
+ * });
+ * }
+ * }
+ *
+ * @param string $controllerName the name of the controller under which it is
+ * stored in the DI container
+ * @param string $methodName the method that you want to call
+ */
+ public function dispatch($controllerName, $methodName) {
+ \OC\AppFramework\App::main($controllerName, $methodName, $this->container);
+ }
+}
diff --git a/lib/public/appframework/controller.php b/lib/public/appframework/controller.php
new file mode 100644
index 00000000000..dc8da967871
--- /dev/null
+++ b/lib/public/appframework/controller.php
@@ -0,0 +1,151 @@
+<?php
+/**
+ * ownCloud - App Framework
+ *
+ * @author Bernhard Posselt
+ * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * AppFramework\Controller class
+ */
+
+namespace OCP\AppFramework;
+
+use OCP\AppFramework\Http\TemplateResponse;
+use OCP\AppFramework\IAppContainer;
+use OCP\IRequest;
+
+
+/**
+ * Base class to inherit your controllers from
+ */
+abstract class Controller {
+
+ /**
+ * app container for dependency injection
+ * @var \OCP\AppFramework\IAppContainer
+ */
+ protected $app;
+
+ /**
+ * current request
+ * @var \OCP\IRequest
+ */
+ protected $request;
+
+ /**
+ * constructor of the controller
+ * @param IAppContainer $app interface to the app
+ * @param IRequest $request an instance of the request
+ */
+ public function __construct(IAppContainer $app, IRequest $request){
+ $this->app = $app;
+ $this->request = $request;
+ }
+
+
+ /**
+ * Lets you access post and get parameters by the index
+ * @param string $key the key which you want to access in the URL Parameter
+ * placeholder, $_POST or $_GET array.
+ * The priority how they're returned is the following:
+ * 1. URL parameters
+ * 2. POST parameters
+ * 3. GET parameters
+ * @param mixed $default If the key is not found, this value will be returned
+ * @return mixed the content of the array
+ */
+ public function params($key, $default=null){
+ return $this->request->getParam($key, $default);
+ }
+
+
+ /**
+ * Returns all params that were received, be it from the request
+ * (as GET or POST) or throuh the URL by the route
+ * @return array the array with all parameters
+ */
+ public function getParams() {
+ return $this->request->getParams();
+ }
+
+
+ /**
+ * Returns the method of the request
+ * @return string the method of the request (POST, GET, etc)
+ */
+ public function method() {
+ return $this->request->getMethod();
+ }
+
+
+ /**
+ * Shortcut for accessing an uploaded file through the $_FILES array
+ * @param string $key the key that will be taken from the $_FILES array
+ * @return array the file in the $_FILES element
+ */
+ public function getUploadedFile($key) {
+ return $this->request->getUploadedFile($key);
+ }
+
+
+ /**
+ * Shortcut for getting env variables
+ * @param string $key the key that will be taken from the $_ENV array
+ * @return array the value in the $_ENV element
+ */
+ public function env($key) {
+ return $this->request->getEnv($key);
+ }
+
+
+ /**
+ * Shortcut for getting cookie variables
+ * @param string $key the key that will be taken from the $_COOKIE array
+ * @return array the value in the $_COOKIE element
+ */
+ public function cookie($key) {
+ return $this->request->getCookie($key);
+ }
+
+
+ /**
+ * Shortcut for rendering a template
+ * @param string $templateName the name of the template
+ * @param array $params the template parameters in key => value structure
+ * @param string $renderAs user renders a full page, blank only your template
+ * admin an entry in the admin settings
+ * @param array $headers set additional headers in name/value pairs
+ * @return \OCP\AppFramework\Http\TemplateResponse containing the page
+ */
+ public function render($templateName, array $params=array(),
+ $renderAs='user', array $headers=array()){
+ $response = new TemplateResponse($this->app->getAppName(), $templateName);
+ $response->setParams($params);
+ $response->renderAs($renderAs);
+
+ foreach($headers as $name => $value){
+ $response->addHeader($name, $value);
+ }
+
+ return $response;
+ }
+
+
+}
diff --git a/lib/public/appframework/http.php b/lib/public/appframework/http.php
new file mode 100644
index 00000000000..60f314202cc
--- /dev/null
+++ b/lib/public/appframework/http.php
@@ -0,0 +1,94 @@
+<?php
+/**
+ * ownCloud - App Framework
+ *
+ * @author Bernhard Posselt, Thomas Tanghus, Bart Visscher
+ * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * AppFramework\HTTP class
+ */
+
+namespace OCP\AppFramework;
+
+/**
+ * Base class which contains constants for HTTP status codes
+ */
+class Http {
+
+ const STATUS_CONTINUE = 100;
+ const STATUS_SWITCHING_PROTOCOLS = 101;
+ const STATUS_PROCESSING = 102;
+ const STATUS_OK = 200;
+ const STATUS_CREATED = 201;
+ const STATUS_ACCEPTED = 202;
+ const STATUS_NON_AUTHORATIVE_INFORMATION = 203;
+ const STATUS_NO_CONTENT = 204;
+ const STATUS_RESET_CONTENT = 205;
+ const STATUS_PARTIAL_CONTENT = 206;
+ const STATUS_MULTI_STATUS = 207;
+ const STATUS_ALREADY_REPORTED = 208;
+ const STATUS_IM_USED = 226;
+ const STATUS_MULTIPLE_CHOICES = 300;
+ const STATUS_MOVED_PERMANENTLY = 301;
+ const STATUS_FOUND = 302;
+ const STATUS_SEE_OTHER = 303;
+ const STATUS_NOT_MODIFIED = 304;
+ const STATUS_USE_PROXY = 305;
+ const STATUS_RESERVED = 306;
+ const STATUS_TEMPORARY_REDIRECT = 307;
+ const STATUS_BAD_REQUEST = 400;
+ const STATUS_UNAUTHORIZED = 401;
+ const STATUS_PAYMENT_REQUIRED = 402;
+ const STATUS_FORBIDDEN = 403;
+ const STATUS_NOT_FOUND = 404;
+ const STATUS_METHOD_NOT_ALLOWED = 405;
+ const STATUS_NOT_ACCEPTABLE = 406;
+ const STATUS_PROXY_AUTHENTICATION_REQUIRED = 407;
+ const STATUS_REQUEST_TIMEOUT = 408;
+ const STATUS_CONFLICT = 409;
+ const STATUS_GONE = 410;
+ const STATUS_LENGTH_REQUIRED = 411;
+ const STATUS_PRECONDITION_FAILED = 412;
+ const STATUS_REQUEST_ENTITY_TOO_LARGE = 413;
+ const STATUS_REQUEST_URI_TOO_LONG = 414;
+ const STATUS_UNSUPPORTED_MEDIA_TYPE = 415;
+ const STATUS_REQUEST_RANGE_NOT_SATISFIABLE = 416;
+ const STATUS_EXPECTATION_FAILED = 417;
+ const STATUS_IM_A_TEAPOT = 418;
+ const STATUS_UNPROCESSABLE_ENTITY = 422;
+ const STATUS_LOCKED = 423;
+ const STATUS_FAILED_DEPENDENCY = 424;
+ const STATUS_UPGRADE_REQUIRED = 426;
+ const STATUS_PRECONDITION_REQUIRED = 428;
+ const STATUS_TOO_MANY_REQUESTS = 429;
+ const STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE = 431;
+ const STATUS_INTERNAL_SERVER_ERROR = 500;
+ const STATUS_NOT_IMPLEMENTED = 501;
+ const STATUS_BAD_GATEWAY = 502;
+ const STATUS_SERVICE_UNAVAILABLE = 503;
+ const STATUS_GATEWAY_TIMEOUT = 504;
+ const STATUS_HTTP_VERSION_NOT_SUPPORTED = 505;
+ const STATUS_VARIANT_ALSO_NEGOTIATES = 506;
+ const STATUS_INSUFFICIENT_STORAGE = 507;
+ const STATUS_LOOP_DETECTED = 508;
+ const STATUS_BANDWIDTH_LIMIT_EXCEEDED = 509;
+ const STATUS_NOT_EXTENDED = 510;
+ const STATUS_NETWORK_AUTHENTICATION_REQUIRED = 511;
+}
diff --git a/lib/public/appframework/http/jsonresponse.php b/lib/public/appframework/http/jsonresponse.php
new file mode 100644
index 00000000000..b54b23a34e6
--- /dev/null
+++ b/lib/public/appframework/http/jsonresponse.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * ownCloud - App Framework
+ *
+ * @author Bernhard Posselt
+ * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * AppFramework\HTTP\JSONResponse class
+ */
+
+namespace OCP\AppFramework\Http;
+
+use OCP\AppFramework\Http;
+
+/**
+ * A renderer for JSON calls
+ */
+class JSONResponse extends Response {
+
+ /**
+ * response data
+ * @var array|object
+ */
+ protected $data;
+
+
+ /**
+ * constructor of JSONResponse
+ * @param array|object $data the object or array that should be transformed
+ * @param int $statusCode the Http status code, defaults to 200
+ */
+ public function __construct($data=array(), $statusCode=Http::STATUS_OK) {
+ $this->data = $data;
+ $this->setStatus($statusCode);
+ $this->addHeader('X-Content-Type-Options', 'nosniff');
+ $this->addHeader('Content-type', 'application/json; charset=utf-8');
+ }
+
+
+ /**
+ * Returns the rendered json
+ * @return string the rendered json
+ */
+ public function render(){
+ return json_encode($this->data);
+ }
+
+ /**
+ * Sets values in the data json array
+ * @param array|object $data an array or object which will be transformed
+ * to JSON
+ */
+ public function setData($data){
+ $this->data = $data;
+ }
+
+
+ /**
+ * Used to get the set parameters
+ * @return array the data
+ */
+ public function getData(){
+ return $this->data;
+ }
+
+}
diff --git a/lib/public/appframework/http/response.php b/lib/public/appframework/http/response.php
new file mode 100644
index 00000000000..0f5a18ca4fe
--- /dev/null
+++ b/lib/public/appframework/http/response.php
@@ -0,0 +1,183 @@
+<?php
+/**
+ * ownCloud - App Framework
+ *
+ * @author Bernhard Posselt, Thomas Tanghus, Bart Visscher
+ * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * AppFramework\HTTP\Response class
+ */
+
+namespace OCP\AppFramework\Http;
+
+use OCP\AppFramework\Http;
+
+/**
+ * Base class for responses. Also used to just send headers.
+ *
+ * It handles headers, HTTP status code, last modified and ETag.
+ */
+class Response {
+
+ /**
+ * Headers - defaults to ['Cache-Control' => 'no-cache, must-revalidate']
+ * @var array
+ */
+ private $headers = array(
+ 'Cache-Control' => 'no-cache, must-revalidate'
+ );
+
+
+ /**
+ * HTTP status code - defaults to STATUS OK
+ * @var string
+ */
+ private $status = Http::STATUS_OK;
+
+
+ /**
+ * Last modified date
+ * @var \DateTime
+ */
+ private $lastModified;
+
+
+ /**
+ * ETag
+ * @var string
+ */
+ private $ETag;
+
+
+ /**
+ * Caches the response
+ * @param int $cacheSeconds the amount of seconds that should be cached
+ * if 0 then caching will be disabled
+ */
+ public function cacheFor($cacheSeconds) {
+
+ if($cacheSeconds > 0) {
+ $this->addHeader('Cache-Control', 'max-age=' . $cacheSeconds .
+ ', must-revalidate');
+ } else {
+ $this->addHeader('Cache-Control', 'no-cache, must-revalidate');
+ }
+
+ }
+
+
+ /**
+ * Adds a new header to the response that will be called before the render
+ * function
+ * @param string $name The name of the HTTP header
+ * @param string $value The value, null will delete it
+ */
+ public function addHeader($name, $value) {
+ if(is_null($value)) {
+ unset($this->headers[$name]);
+ } else {
+ $this->headers[$name] = $value;
+ }
+ }
+
+
+ /**
+ * Returns the set headers
+ * @return array the headers
+ */
+ public function getHeaders() {
+ $mergeWith = array();
+
+ if($this->lastModified) {
+ $mergeWith['Last-Modified'] =
+ $this->lastModified->format(\DateTime::RFC2822);
+ }
+
+ if($this->ETag) {
+ $mergeWith['ETag'] = '"' . $this->ETag . '"';
+ }
+
+ return array_merge($mergeWith, $this->headers);
+ }
+
+
+ /**
+ * By default renders no output
+ * @return null
+ */
+ public function render() {
+ return null;
+ }
+
+
+ /**
+ * Set response status
+ * @param int $status a HTTP status code, see also the STATUS constants
+ */
+ public function setStatus($status) {
+ $this->status = $status;
+ }
+
+
+ /**
+ * Get response status
+ */
+ public function getStatus() {
+ return $this->status;
+ }
+
+
+ /**
+ * Get the ETag
+ * @return string the etag
+ */
+ public function getETag() {
+ return $this->ETag;
+ }
+
+
+ /**
+ * Get "last modified" date
+ * @return string RFC2822 formatted last modified date
+ */
+ public function getLastModified() {
+ return $this->lastModified;
+ }
+
+
+ /**
+ * Set the ETag
+ * @param string $ETag
+ */
+ public function setETag($ETag) {
+ $this->ETag = $ETag;
+ }
+
+
+ /**
+ * Set "last modified" date
+ * @param \DateTime $lastModified
+ */
+ public function setLastModified($lastModified) {
+ $this->lastModified = $lastModified;
+ }
+
+
+}
diff --git a/lib/public/appframework/http/templateresponse.php b/lib/public/appframework/http/templateresponse.php
new file mode 100644
index 00000000000..2200a38beca
--- /dev/null
+++ b/lib/public/appframework/http/templateresponse.php
@@ -0,0 +1,137 @@
+<?php
+/**
+ * ownCloud - App Framework
+ *
+ * @author Bernhard Posselt
+ * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * AppFramework\HTTP\TemplateResponse class
+ */
+
+namespace OCP\AppFramework\Http;
+
+
+/**
+ * Response for a normal template
+ */
+class TemplateResponse extends Response {
+
+ /**
+ * name of the template
+ * @var string
+ */
+ protected $templateName;
+
+ /**
+ * parameters
+ * @var array
+ */
+ protected $params;
+
+ /**
+ * rendering type (admin, user, blank)
+ * @var string
+ */
+ protected $renderAs;
+
+ /**
+ * app name
+ * @var string
+ */
+ protected $appName;
+
+ /**
+ * constructor of TemplateResponse
+ * @param string $appName the name of the app to load the template from
+ * @param string $templateName the name of the template
+ */
+ public function __construct($appName, $templateName) {
+ $this->templateName = $templateName;
+ $this->appName = $appName;
+ $this->params = array();
+ $this->renderAs = 'user';
+ }
+
+
+ /**
+ * Sets template parameters
+ * @param array $params an array with key => value structure which sets template
+ * variables
+ */
+ public function setParams(array $params){
+ $this->params = $params;
+ }
+
+
+ /**
+ * Used for accessing the set parameters
+ * @return array the params
+ */
+ public function getParams(){
+ return $this->params;
+ }
+
+
+ /**
+ * Used for accessing the name of the set template
+ * @return string the name of the used template
+ */
+ public function getTemplateName(){
+ return $this->templateName;
+ }
+
+
+ /**
+ * Sets the template page
+ * @param string $renderAs admin, user or blank. Admin also prints the admin
+ * settings header and footer, user renders the normal
+ * normal page including footer and header and blank
+ * just renders the plain template
+ */
+ public function renderAs($renderAs){
+ $this->renderAs = $renderAs;
+ }
+
+
+ /**
+ * Returns the set renderAs
+ * @return string the renderAs value
+ */
+ public function getRenderAs(){
+ return $this->renderAs;
+ }
+
+
+ /**
+ * Returns the rendered html
+ * @return string the rendered html
+ */
+ public function render(){
+
+ $template = new \OCP\Template($this->appName, $this->templateName, $this->renderAs);
+
+ foreach($this->params as $key => $value){
+ $template->assign($key, $value);
+ }
+
+ return $template->fetchPage();
+ }
+
+}
diff --git a/lib/public/appframework/iapi.php b/lib/public/appframework/iapi.php
new file mode 100644
index 00000000000..963e870f79b
--- /dev/null
+++ b/lib/public/appframework/iapi.php
@@ -0,0 +1,81 @@
+<?php
+/**
+ * ownCloud - App Framework
+ *
+ * @author Bernhard Posselt
+ * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * AppFramework/IApi interface
+ */
+
+namespace OCP\AppFramework;
+
+
+/**
+ * A few very basic and frequently used API functions are combined in here
+ */
+interface IApi {
+
+
+ /**
+ * Gets the userid of the current user
+ * @return string the user id of the current user
+ */
+ function getUserId();
+
+
+ /**
+ * Adds a new javascript file
+ * @param string $scriptName the name of the javascript in js/ without the suffix
+ * @param string $appName the name of the app, defaults to the current one
+ */
+ function addScript($scriptName, $appName = null);
+
+
+ /**
+ * Adds a new css file
+ * @param string $styleName the name of the css file in css/without the suffix
+ * @param string $appName the name of the app, defaults to the current one
+ */
+ function addStyle($styleName, $appName = null);
+
+
+ /**
+ * shorthand for addScript for files in the 3rdparty directory
+ * @param string $name the name of the file without the suffix
+ */
+ function add3rdPartyScript($name);
+
+
+ /**
+ * shorthand for addStyle for files in the 3rdparty directory
+ * @param string $name the name of the file without the suffix
+ */
+ function add3rdPartyStyle($name);
+
+
+ /**
+ * Checks if an app is enabled
+ * @param string $appName the name of an app
+ * @return bool true if app is enabled
+ */
+ public function isAppEnabled($appName);
+
+}
diff --git a/lib/public/appframework/iappcontainer.php b/lib/public/appframework/iappcontainer.php
new file mode 100644
index 00000000000..7e6ec6016b7
--- /dev/null
+++ b/lib/public/appframework/iappcontainer.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Thomas Müller
+ * @copyright 2013 Thomas Müller deepdiver@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 OCP\AppFramework;
+
+use OCP\AppFramework\IApi;
+use OCP\IContainer;
+
+/**
+ * Class IAppContainer
+ * @package OCP\AppFramework
+ *
+ * This container interface provides short cuts for app developers to access predefined app service.
+ */
+interface IAppContainer extends IContainer{
+
+ /**
+ * used to return the appname of the set application
+ * @return string the name of your application
+ */
+ function getAppName();
+
+ /**
+ * @return IApi
+ */
+ function getCoreApi();
+
+ /**
+ * @return \OCP\IServerContainer
+ */
+ function getServer();
+
+ /**
+ * @param Middleware $middleWare
+ * @return boolean
+ */
+ function registerMiddleWare(Middleware $middleWare);
+
+ /**
+ * @return boolean
+ */
+ function isLoggedIn();
+
+ /**
+ * @return boolean
+ */
+ function isAdminUser();
+
+ /**
+ * @param $message
+ * @param $level
+ * @return mixed
+ */
+ function log($message, $level);
+
+}
diff --git a/lib/public/appframework/middleware.php b/lib/public/appframework/middleware.php
new file mode 100644
index 00000000000..24f31939935
--- /dev/null
+++ b/lib/public/appframework/middleware.php
@@ -0,0 +1,104 @@
+<?php
+/**
+ * ownCloud - App Framework
+ *
+ * @author Bernhard Posselt
+ * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * AppFramework\Middleware class
+ */
+
+namespace OCP\AppFramework;
+
+use OCP\AppFramework\Controller;
+use OCP\AppFramework\Http\Response;
+
+
+/**
+ * Middleware is used to provide hooks before or after controller methods and
+ * deal with possible exceptions raised in the controller methods.
+ * They're modeled after Django's middleware system:
+ * https://docs.djangoproject.com/en/dev/topics/http/middleware/
+ */
+abstract class Middleware {
+
+
+ /**
+ * This is being run in normal order before the controller is being
+ * called which allows several modifications and checks
+ *
+ * @param Controller $controller the controller that is being called
+ * @param string $methodName the name of the method that will be called on
+ * the controller
+ */
+ public function beforeController($controller, $methodName){
+
+ }
+
+
+ /**
+ * This is being run when either the beforeController method or the
+ * controller method itself is throwing an exception. The middleware is
+ * asked in reverse order to handle the exception and to return a response.
+ * If the response is null, it is assumed that the exception could not be
+ * handled and the error will be thrown again
+ *
+ * @param Controller $controller the controller that is being called
+ * @param string $methodName the name of the method that will be called on
+ * the controller
+ * @param \Exception $exception the thrown exception
+ * @throws \Exception the passed in exception if it cant handle it
+ * @return Response a Response object in case that the exception was handled
+ */
+ public function afterException($controller, $methodName, \Exception $exception){
+ throw $exception;
+ }
+
+
+ /**
+ * This is being run after a successful controllermethod call and allows
+ * the manipulation of a Response object. The middleware is run in reverse order
+ *
+ * @param Controller $controller the controller that is being called
+ * @param string $methodName the name of the method that will be called on
+ * the controller
+ * @param Response $response the generated response from the controller
+ * @return Response a Response object
+ */
+ public function afterController($controller, $methodName, Response $response){
+ return $response;
+ }
+
+
+ /**
+ * This is being run after the response object has been rendered and
+ * allows the manipulation of the output. The middleware is run in reverse order
+ *
+ * @param Controller $controller the controller that is being called
+ * @param string $methodName the name of the method that will be called on
+ * the controller
+ * @param string $output the generated output from a response
+ * @return string the output that should be printed
+ */
+ public function beforeOutput($controller, $methodName, $output){
+ return $output;
+ }
+
+}
diff --git a/lib/public/authentication/iapachebackend.php b/lib/public/authentication/iapachebackend.php
new file mode 100644
index 00000000000..3979a14302e
--- /dev/null
+++ b/lib/public/authentication/iapachebackend.php
@@ -0,0 +1,55 @@
+<?php
+/**
+ * ownCloud - Apache backend
+ *
+ * @author Karl Beecher
+ * @copyright 2013 Karl Beecher - karl@endocode.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/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Authentication/IApacheBackend interface
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP\Authentication;
+
+interface IApacheBackend {
+
+ /**
+ * In case the user has been authenticated by Apache true is returned.
+ *
+ * @return boolean whether Apache reports a user as currently logged in.
+ */
+ public function isSessionActive();
+
+ /**
+ * Creates an attribute which is added to the logout hyperlink. It can
+ * supply any attribute(s) which are valid for <a>.
+ *
+ * @return string with one or more HTML attributes.
+ */
+ public function getLogoutAttribute();
+
+ /**
+ * Return the id of the current user
+ * @return string
+ */
+ public function getCurrentUserId();
+
+}
diff --git a/lib/public/backgroundjob.php b/lib/public/backgroundjob.php
index cc076a3a845..a7f54491dfa 100644
--- a/lib/public/backgroundjob.php
+++ b/lib/public/backgroundjob.php
@@ -44,7 +44,8 @@ use \OC\BackgroundJob\JobList;
*/
class BackgroundJob {
/**
- * @brief get the execution type of background jobs
+ * get the execution type of background jobs
+ *
* @return string
*
* This method returns the type how background jobs are executed. If the user
@@ -55,7 +56,8 @@ class BackgroundJob {
}
/**
- * @brief sets the background jobs execution type
+ * sets the background jobs execution type
+ *
* @param string $type execution type
* @return boolean
*
@@ -77,19 +79,21 @@ class BackgroundJob {
/**
* @deprecated
- * @brief creates a regular task
+ * creates a regular task
* @param string $klass class name
* @param string $method method name
* @return true
*/
public static function addRegularTask($klass, $method) {
- self::registerJob('OC\BackgroundJob\Legacy\RegularJob', array($klass, $method));
- return true;
+ if (!\OC::needUpgrade()) {
+ self::registerJob('OC\BackgroundJob\Legacy\RegularJob', array($klass, $method));
+ return true;
+ }
}
/**
* @deprecated
- * @brief gets all regular tasks
+ * gets all regular tasks
* @return associative array
*
* key is string "$klass-$method", value is array( $klass, $method )
@@ -109,7 +113,7 @@ class BackgroundJob {
/**
* @deprecated
- * @brief Gets one queued task
+ * Gets one queued task
* @param int $id ID of the task
* @return associative array
*/
@@ -120,7 +124,7 @@ class BackgroundJob {
/**
* @deprecated
- * @brief Gets all queued tasks
+ * Gets all queued tasks
* @return array with associative arrays
*/
public static function allQueuedTasks() {
@@ -139,7 +143,7 @@ class BackgroundJob {
/**
* @deprecated
- * @brief Gets all queued tasks of a specific app
+ * Gets all queued tasks of a specific app
* @param string $app app name
* @return array with associative arrays
*/
@@ -161,7 +165,7 @@ class BackgroundJob {
/**
* @deprecated
- * @brief queues a task
+ * queues a task
* @param string $app app name
* @param string $class class name
* @param string $method method name
@@ -175,7 +179,7 @@ class BackgroundJob {
/**
* @deprecated
- * @brief deletes a queued task
+ * deletes a queued task
* @param int $id id of task
* @return bool
*
diff --git a/lib/public/config.php b/lib/public/config.php
index 73476d7551d..d9355a0605f 100644
--- a/lib/public/config.php
+++ b/lib/public/config.php
@@ -1,24 +1,24 @@
<?php
/**
-* ownCloud
-*
-* @author Frank Karlitschek
-* @copyright 2012 Frank Karlitschek frank@owncloud.org
-*
-* 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/>.
-*
-*/
+ * ownCloud
+ *
+ * @author Frank Karlitschek
+ * @copyright 2012 Frank Karlitschek frank@owncloud.org
+ *
+ * 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/>.
+ *
+ */
/**
* Public interface of ownCloud for apps to use.
@@ -27,7 +27,7 @@
*/
/**
- * @brief use OCP namespace for all classes that are considered public.
+ * Use OCP namespace for all classes that are considered public.
*
* Classes that use this namespace are for use by apps, and not for use by internal
* OC classes
@@ -40,7 +40,7 @@ namespace OCP;
*/
class Config {
/**
- * @brief Gets a value from config.php
+ * Gets a value from config.php
* @param string $key key
* @param string $default = null default value
* @return string the value or $default
@@ -53,7 +53,7 @@ class Config {
}
/**
- * @brief Sets a value
+ * Sets a value
* @param string $key key
* @param string $value value
* @return bool
@@ -71,7 +71,7 @@ class Config {
}
/**
- * @brief Gets the config value
+ * Gets the config value
* @param string $app app
* @param string $key key
* @param string $default = null, default value if the key does not exist
@@ -85,7 +85,7 @@ class Config {
}
/**
- * @brief sets a value in the appconfig
+ * Sets a value in the appconfig
* @param string $app app
* @param string $key key
* @param string $value value
@@ -103,7 +103,7 @@ class Config {
}
/**
- * @brief Gets the preference
+ * Gets the preference
* @param string $user user
* @param string $app app
* @param string $key key
@@ -118,12 +118,12 @@ class Config {
}
/**
- * @brief sets a value in the preferences
+ * Sets a value in the preferences
* @param string $user user
* @param string $app app
* @param string $key key
* @param string $value value
- * @returns bool
+ * @return bool
*
* Adds a value to the preferences. If the key did not exist before, it
* will be added automagically.
diff --git a/lib/public/contacts.php b/lib/public/contacts.php
index 88d812e735a..1b61d7aa4ff 100644
--- a/lib/public/contacts.php
+++ b/lib/public/contacts.php
@@ -90,13 +90,8 @@ namespace OCP {
* @return array of contacts which are arrays of key-value-pairs
*/
public static function search($pattern, $searchProperties = array(), $options = array()) {
- $result = array();
- foreach(self::$address_books as $address_book) {
- $r = $address_book->search($pattern, $searchProperties, $options);
- $result = array_merge($result, $r);
- }
-
- return $result;
+ $cm = \OC::$server->getContactsManager();
+ return $cm->search($pattern, $searchProperties, $options);
}
/**
@@ -107,14 +102,8 @@ namespace OCP {
* @return bool successful or not
*/
public static function delete($id, $address_book_key) {
- if (!array_key_exists($address_book_key, self::$address_books))
- return null;
-
- $address_book = self::$address_books[$address_book_key];
- if ($address_book->getPermissions() & \OCP\PERMISSION_DELETE)
- return null;
-
- return $address_book->delete($id);
+ $cm = \OC::$server->getContactsManager();
+ return $cm->delete($id, $address_book_key);
}
/**
@@ -126,15 +115,8 @@ namespace OCP {
* @return array representing the contact just created or updated
*/
public static function createOrUpdate($properties, $address_book_key) {
-
- if (!array_key_exists($address_book_key, self::$address_books))
- return null;
-
- $address_book = self::$address_books[$address_book_key];
- if ($address_book->getPermissions() & \OCP\PERMISSION_CREATE)
- return null;
-
- return $address_book->createOrUpdate($properties);
+ $cm = \OC::$server->getContactsManager();
+ return $cm->search($properties, $address_book_key);
}
/**
@@ -143,45 +125,40 @@ namespace OCP {
* @return bool true if enabled, false if not
*/
public static function isEnabled() {
- return !empty(self::$address_books);
+ $cm = \OC::$server->getContactsManager();
+ return $cm->isEnabled();
}
/**
* @param \OCP\IAddressBook $address_book
*/
public static function registerAddressBook(\OCP\IAddressBook $address_book) {
- self::$address_books[$address_book->getKey()] = $address_book;
+ $cm = \OC::$server->getContactsManager();
+ return $cm->registerAddressBook($address_book);
}
/**
* @param \OCP\IAddressBook $address_book
*/
public static function unregisterAddressBook(\OCP\IAddressBook $address_book) {
- unset(self::$address_books[$address_book->getKey()]);
+ $cm = \OC::$server->getContactsManager();
+ return $cm->unregisterAddressBook($address_book);
}
/**
* @return array
*/
public static function getAddressBooks() {
- $result = array();
- foreach(self::$address_books as $address_book) {
- $result[$address_book->getKey()] = $address_book->getDisplayName();
- }
-
- return $result;
+ $cm = \OC::$server->getContactsManager();
+ return $cm->getAddressBooks();
}
/**
* removes all registered address book instances
*/
public static function clear() {
- self::$address_books = array();
+ $cm = \OC::$server->getContactsManager();
+ $cm->clear();
}
-
- /**
- * @var \OCP\IAddressBook[] which holds all registered address books
- */
- private static $address_books = array();
}
}
diff --git a/lib/public/contacts/imanager.php b/lib/public/contacts/imanager.php
new file mode 100644
index 00000000000..973d48be5ec
--- /dev/null
+++ b/lib/public/contacts/imanager.php
@@ -0,0 +1,154 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Thomas Müller
+ * @copyright 2013 Thomas Müller thomas.mueller@tmit.eu
+ *
+ * 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/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Contacts Class
+ *
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP\Contacts {
+
+ /**
+ * This class provides access to the contacts app. Use this class exclusively if you want to access contacts.
+ *
+ * Contacts in general will be expressed as an array of key-value-pairs.
+ * The keys will match the property names defined in https://tools.ietf.org/html/rfc2426#section-1
+ *
+ * Proposed workflow for working with contacts:
+ * - search for the contacts
+ * - manipulate the results array
+ * - createOrUpdate will save the given contacts overwriting the existing data
+ *
+ * For updating it is mandatory to keep the id.
+ * Without an id a new contact will be created.
+ *
+ */
+ interface IManager {
+
+ /**
+ * This function is used to search and find contacts within the users address books.
+ * In case $pattern is empty all contacts will be returned.
+ *
+ * Example:
+ * Following function shows how to search for contacts for the name and the email address.
+ *
+ * public static function getMatchingRecipient($term) {
+ * $cm = \OC::$server->getContactsManager();
+ * // The API is not active -> nothing to do
+ * if (!$cm->isEnabled()) {
+ * return array();
+ * }
+ *
+ * $result = $cm->search($term, array('FN', 'EMAIL'));
+ * $receivers = array();
+ * foreach ($result as $r) {
+ * $id = $r['id'];
+ * $fn = $r['FN'];
+ * $email = $r['EMAIL'];
+ * if (!is_array($email)) {
+ * $email = array($email);
+ * }
+ *
+ * // loop through all email addresses of this contact
+ * foreach ($email as $e) {
+ * $displayName = $fn . " <$e>";
+ * $receivers[] = array(
+ * 'id' => $id,
+ * 'label' => $displayName,
+ * 'value' => $displayName);
+ * }
+ * }
+ *
+ * return $receivers;
+ * }
+ *
+ *
+ * @param string $pattern which should match within the $searchProperties
+ * @param array $searchProperties defines the properties within the query pattern should match
+ * @param array $options - for future use. One should always have options!
+ * @return array of contacts which are arrays of key-value-pairs
+ */
+ function search($pattern, $searchProperties = array(), $options = array());
+
+ /**
+ * 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
+ * @return bool successful or not
+ */
+ function delete($id, $address_book_key);
+
+ /**
+ * This function is used to create a new contact if 'id' is not given or not present.
+ * 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
+ * @return array representing the contact just created or updated
+ */
+ function createOrUpdate($properties, $address_book_key);
+
+ /**
+ * Check if contacts are available (e.g. contacts app enabled)
+ *
+ * @return bool true if enabled, false if not
+ */
+ function isEnabled();
+
+ /**
+ * Registers an address book
+ *
+ * @param \OCP\IAddressBook $address_book
+ */
+ function registerAddressBook(\OCP\IAddressBook $address_book);
+
+ /**
+ * Unregisters an address book
+ *
+ * @param \OCP\IAddressBook $address_book
+ */
+ function unregisterAddressBook(\OCP\IAddressBook $address_book);
+
+ /**
+ * In order to improve lazy loading a closure can be registered which will be called in case
+ * address books are actually requested
+ *
+ * @param string $key
+ * @param \Closure $callable
+ */
+ function register($key, \Closure $callable);
+
+ /**
+ * @return array
+ */
+ function getAddressBooks();
+
+ /**
+ * removes all registered address book instances
+ */
+ function clear();
+ }
+}
diff --git a/lib/public/db.php b/lib/public/db.php
index 932e79d9ef1..c9997c79c3c 100644
--- a/lib/public/db.php
+++ b/lib/public/db.php
@@ -1,24 +1,24 @@
<?php
/**
-* ownCloud
-*
-* @author Frank Karlitschek
-* @copyright 2012 Frank Karlitschek frank@owncloud.org
-*
-* 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/>.
-*
-*/
+ * ownCloud
+ *
+ * @author Frank Karlitschek
+ * @copyright 2012 Frank Karlitschek frank@owncloud.org
+ *
+ * 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/>.
+ *
+ */
/**
* Public interface of ownCloud for apps to use.
@@ -35,8 +35,10 @@ namespace OCP;
*/
class DB {
/**
- * @brief Prepare a SQL query
+ * Prepare a SQL query
* @param string $query Query string
+ * @param int $limit Limit of the SQL statement
+ * @param int $offset Offset of the SQL statement
* @return \MDB2_Statement_Common prepared SQL query
*
* SQL query via MDB2 prepare(), needs to be execute()'d!
@@ -46,7 +48,7 @@ class DB {
}
/**
- * @brief Insert a row if a matching row doesn't exists.
+ * Insert a row if a matching row doesn't exists.
* @param $table string The table name (will replace *PREFIX*) to perform the replace on.
* @param $input array
*
@@ -67,7 +69,7 @@ class DB {
}
/**
- * @brief gets last value of autoincrement
+ * Gets last value of autoincrement
* @param $table string The optional table name (will replace *PREFIX*) and add sequence suffix
* @return int
*
@@ -81,25 +83,36 @@ class DB {
}
/**
- * @brief Start a transaction
+ * Start a transaction
*/
public static function beginTransaction() {
return(\OC_DB::beginTransaction());
}
/**
- * @brief Commit the database changes done during a transaction that is in progress
+ * Commit the database changes done during a transaction that is in progress
*/
public static function commit() {
return(\OC_DB::commit());
}
/**
- * @brief check if a result is an error, works with MDB2 and PDOException
+ * Check if a result is an error, works with MDB2 and PDOException
* @param mixed $result
* @return bool
*/
public static function isError($result) {
return(\OC_DB::isError($result));
}
+
+ /**
+ * returns the error code and message as a string for logging
+ * works with DoctrineException
+ * @param mixed $error
+ * @return string
+ */
+ public static function getErrorMessage($error) {
+ return(\OC_DB::getErrorMessage($error));
+ }
+
}
diff --git a/lib/public/defaults.php b/lib/public/defaults.php
index 147f23e341f..34b68903ee8 100644
--- a/lib/public/defaults.php
+++ b/lib/public/defaults.php
@@ -1,41 +1,56 @@
<?php
/**
-* ownCloud
-*
-* @author Björn Schießle
-* @copyright 2013 Björn Schießle 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/>.
-*
-*/
+ * ownCloud
+ *
+ * @author Björn Schießle
+ * @copyright 2013 Björn Schießle 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/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Defaults Class
+ *
+ */
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
namespace OCP;
-/*
+/**
* public api to access default strings and urls for your templates
*/
-
class Defaults {
+ /**
+ * \OC_Defaults instance to retrieve the defaults
+ * @return string
+ */
private $defaults;
+ /**
+ * creates a \OC_Defaults instance which is used in all methods to retrieve the
+ * actual defaults
+ */
function __construct() {
$this->defaults = new \OC_Defaults();
}
/**
- * @breif get base URL for the organisation behind your ownCloud instance
+ * get base URL for the organisation behind your ownCloud instance
* @return string
*/
public function getBaseUrl() {
@@ -43,7 +58,7 @@ class Defaults {
}
/**
- * @breif link to the desktop sync client
+ * link to the desktop sync client
* @return string
*/
public function getSyncClientUrl() {
@@ -51,7 +66,7 @@ class Defaults {
}
/**
- * @breif base URL to the documentation of your ownCloud instance
+ * base URL to the documentation of your ownCloud instance
* @return string
*/
public function getDocBaseUrl() {
@@ -59,7 +74,7 @@ class Defaults {
}
/**
- * @breif name of your ownCloud instance
+ * name of your ownCloud instance
* @return string
*/
public function getName() {
@@ -67,7 +82,7 @@ class Defaults {
}
/**
- * @breif Entity behind your onwCloud instance
+ * Entity behind your onwCloud instance
* @return string
*/
public function getEntity() {
@@ -75,7 +90,7 @@ class Defaults {
}
/**
- * @breif ownCloud slogan
+ * ownCloud slogan
* @return string
*/
public function getSlogan() {
@@ -83,7 +98,7 @@ class Defaults {
}
/**
- * @breif logo claim
+ * logo claim
* @return string
*/
public function getLogoClaim() {
@@ -91,7 +106,7 @@ class Defaults {
}
/**
- * @breif footer, short version
+ * footer, short version
* @return string
*/
public function getShortFooter() {
@@ -99,7 +114,7 @@ class Defaults {
}
/**
- * @breif footer, long version
+ * footer, long version
* @return string
*/
public function getLongFooter() {
diff --git a/lib/public/files.php b/lib/public/files.php
index 852b041eefb..d36d74fdf77 100644
--- a/lib/public/files.php
+++ b/lib/public/files.php
@@ -1,24 +1,24 @@
<?php
/**
-* ownCloud
-*
-* @author Frank Karlitschek
-* @copyright 2012 Frank Karlitschek frank@owncloud.org
-*
-* 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/>.
-*
-*/
+ * ownCloud
+ *
+ * @author Frank Karlitschek
+ * @copyright 2012 Frank Karlitschek frank@owncloud.org
+ *
+ * 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/>.
+ *
+ */
/**
* Public interface of ownCloud for apps to use.
@@ -36,9 +36,8 @@ namespace OCP;
*/
class Files {
/**
- * @brief Recusive deletion of folders
- * @param string $dir path to the folder
- *
+ * Recusive deletion of folders
+ * @param string path to the folder
* @return bool
*/
static function rmdirr( $dir ) {
@@ -46,7 +45,7 @@ class Files {
}
/**
- * get the mimetype form a local file
+ * Get the mimetype form a local file
* @param string path
* @return string
* does NOT work for ownClouds filesystem, use OC_FileSystem::getMimeType instead
@@ -56,17 +55,16 @@ class Files {
}
/**
- * search for files by mimetype
- *
- * @param string $query
+ * Search for files by mimetype
+ * @param string mimetype
* @return array
*/
- static public function searchByMime($mimetype) {
+ static public function searchByMime( $mimetype ) {
return(\OC\Files\Filesystem::searchByMime( $mimetype ));
}
/**
- * copy the contents of one stream to another
+ * Copy the contents of one stream to another
* @param resource source
* @param resource target
* @return int the number of bytes copied
@@ -77,7 +75,7 @@ class Files {
}
/**
- * create a temporary file with an unique filename
+ * Create a temporary file with an unique filename
* @param string postfix
* @return string
*
@@ -88,7 +86,7 @@ class Files {
}
/**
- * create a temporary folder with an unique filename
+ * Create a temporary folder with an unique filename
* @return string
*
* temporary files are automatically cleaned up after the script is finished
@@ -99,9 +97,8 @@ class Files {
/**
* Adds a suffix to the name in case the file exists
- *
- * @param $path
- * @param $filename
+ * @param string path
+ * @param string filename
* @return string
*/
public static function buildNotExistingFileName( $path, $filename ) {
@@ -109,8 +106,9 @@ class Files {
}
/**
+ * Gets the Storage for an app - creates the needed folder if they are not
+ * existant
* @param string appid
- * @param $app app
* @return \OC\Files\View
*/
public static function getStorage( $app ) {
diff --git a/lib/public/files/alreadyexistsexception.php b/lib/public/files/alreadyexistsexception.php
new file mode 100644
index 00000000000..7bea947aef0
--- /dev/null
+++ b/lib/public/files/alreadyexistsexception.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Robin Appelman
+ * @copyright 2013 Robin Appelman icewind@owncloud.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Files/AlreadyExistsException class
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP\Files;
+
+/**
+ * Exception for already existing files/folders
+ */
+class AlreadyExistsException extends \Exception {}
diff --git a/lib/public/files/entitytoolargeexception.php b/lib/public/files/entitytoolargeexception.php
new file mode 100644
index 00000000000..eaa68a548b9
--- /dev/null
+++ b/lib/public/files/entitytoolargeexception.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Thomas Müller
+ * @copyright 2013 Thomas Müller deepdiver@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/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Files/EntityTooLargeException class
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP\Files;
+
+/**
+ * Exception for too large entity
+ */
+class EntityTooLargeException extends \Exception {}
diff --git a/lib/public/files/file.php b/lib/public/files/file.php
new file mode 100644
index 00000000000..c6cda59f9b0
--- /dev/null
+++ b/lib/public/files/file.php
@@ -0,0 +1,74 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Robin Appelman
+ * @copyright 2013 Robin Appelman icewind@owncloud.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Files/File interface
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP\Files;
+
+interface File extends Node {
+ /**
+ * Get the content of the file as string
+ *
+ * @return string
+ * @throws \OCP\Files\NotPermittedException
+ */
+ public function getContent();
+
+ /**
+ * Write to the file from string data
+ *
+ * @param string $data
+ * @throws \OCP\Files\NotPermittedException
+ */
+ public function putContent($data);
+
+ /**
+ * Get the mimetype of the file
+ *
+ * @return string
+ */
+ public function getMimeType();
+
+ /**
+ * Open the file as stream, resulting resource can be operated as stream like the result from php's own fopen
+ *
+ * @param string $mode
+ * @return resource
+ * @throws \OCP\Files\NotPermittedException
+ */
+ public function fopen($mode);
+
+ /**
+ * Compute the hash of the file
+ * Type of hash is set with $type and can be anything supported by php's hash_file
+ *
+ * @param string $type
+ * @param bool $raw
+ * @return string
+ */
+ public function hash($type, $raw = false);
+}
diff --git a/lib/public/files/folder.php b/lib/public/files/folder.php
new file mode 100644
index 00000000000..7fec1c529a5
--- /dev/null
+++ b/lib/public/files/folder.php
@@ -0,0 +1,140 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Robin Appelman
+ * @copyright 2013 Robin Appelman icewind@owncloud.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Files/Folder interface
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP\Files;
+
+interface Folder extends Node {
+ /**
+ * Get the full path of an item in the folder within owncloud's filesystem
+ *
+ * @param string $path relative path of an item in the folder
+ * @return string
+ * @throws \OCP\Files\NotPermittedException
+ */
+ public function getFullPath($path);
+
+ /**
+ * Get the path of an item in the folder relative to the folder
+ *
+ * @param string $path absolute path of an item in the folder
+ * @throws \OCP\Files\NotFoundException
+ * @return string
+ */
+ public function getRelativePath($path);
+
+ /**
+ * check if a node is a (grand-)child of the folder
+ *
+ * @param \OCP\Files\Node $node
+ * @return bool
+ */
+ public function isSubNode($node);
+
+ /**
+ * get the content of this directory
+ *
+ * @throws \OCP\Files\NotFoundException
+ * @return \OCP\Files\Node[]
+ */
+ public function getDirectoryListing();
+
+ /**
+ * Get the node at $path
+ *
+ * @param string $path relative path of the file or folder
+ * @return \OCP\Files\Node
+ * @throws \OCP\Files\NotFoundException
+ */
+ public function get($path);
+
+ /**
+ * Check if a file or folder exists in the folder
+ *
+ * @param string $path relative path of the file or folder
+ * @return bool
+ */
+ public function nodeExists($path);
+
+ /**
+ * Create a new folder
+ *
+ * @param string $path relative path of the new folder
+ * @return \OCP\Files\Folder
+ * @throws \OCP\Files\NotPermittedException
+ */
+ public function newFolder($path);
+
+ /**
+ * Create a new file
+ *
+ * @param string $path relative path of the new file
+ * @return \OCP\Files\File
+ * @throws \OCP\Files\NotPermittedException
+ */
+ public function newFile($path);
+
+ /**
+ * search for files with the name matching $query
+ *
+ * @param string $query
+ * @return \OCP\Files\Node[]
+ */
+ public function search($query);
+
+ /**
+ * search for files by mimetype
+ * $mimetype can either be a full mimetype (image/png) or a wildcard mimetype (image)
+ *
+ * @param string $mimetype
+ * @return \OCP\Files\Node[]
+ */
+ public function searchByMime($mimetype);
+
+ /**
+ * get a file or folder inside the folder by it's internal id
+ *
+ * @param int $id
+ * @return \OCP\Files\Node[]
+ */
+ public function getById($id);
+
+ /**
+ * Get the amount of free space inside the folder
+ *
+ * @return int
+ */
+ public function getFreeSpace();
+
+ /**
+ * Check if new files or folders can be created within the folder
+ *
+ * @return bool
+ */
+ public function isCreatable();
+}
diff --git a/lib/public/files/invalidcontentexception.php b/lib/public/files/invalidcontentexception.php
new file mode 100644
index 00000000000..3dfe7378c4d
--- /dev/null
+++ b/lib/public/files/invalidcontentexception.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Thomas Müller
+ * @copyright 2013 Thomas Müller deepdiver@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/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Files/InvalidContentException class
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP\Files;
+
+/**
+ * Exception for invalid content
+ */
+class InvalidContentException extends \Exception {}
diff --git a/lib/public/files/invalidpathexception.php b/lib/public/files/invalidpathexception.php
new file mode 100644
index 00000000000..8ecfa7d89ad
--- /dev/null
+++ b/lib/public/files/invalidpathexception.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Thomas Müller
+ * @copyright 2013 Thomas Müller deepdiver@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/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Files/InvalidPathException class
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP\Files;
+
+/**
+ * Exception for invalid path
+ */
+class InvalidPathException extends \Exception {}
diff --git a/lib/public/files/node.php b/lib/public/files/node.php
new file mode 100644
index 00000000000..972b1cfa492
--- /dev/null
+++ b/lib/public/files/node.php
@@ -0,0 +1,180 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Robin Appelman
+ * @copyright 2013 Robin Appelman icewind@owncloud.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Files/Node interface
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP\Files;
+
+interface Node {
+ /**
+ * Move the file or folder to a new location
+ *
+ * @param string $targetPath the absolute target path
+ * @throws \OCP\Files\NotPermittedException
+ * @return \OCP\Files\Node
+ */
+ public function move($targetPath);
+
+ /**
+ * Delete the file or folder
+ */
+ public function delete();
+
+ /**
+ * Cope the file or folder to a new location
+ *
+ * @param string $targetPath the absolute target path
+ * @return \OCP\Files\Node
+ */
+ public function copy($targetPath);
+
+ /**
+ * Change the modified date of the file or folder
+ * If $mtime is omitted the current time will be used
+ *
+ * @param int $mtime (optional) modified date as unix timestamp
+ * @throws \OCP\Files\NotPermittedException
+ */
+ public function touch($mtime = null);
+
+ /**
+ * Get the storage backend the file or folder is stored on
+ *
+ * @return \OCP\Files\Storage
+ * @throws \OCP\Files\NotFoundException
+ */
+ public function getStorage();
+
+ /**
+ * Get the full path of the file or folder
+ *
+ * @return string
+ */
+ public function getPath();
+
+ /**
+ * Get the path of the file or folder relative to the mountpoint of it's storage
+ *
+ * @return string
+ */
+ public function getInternalPath();
+
+ /**
+ * Get the internal file id for the file or folder
+ *
+ * @return int
+ */
+ public function getId();
+
+ /**
+ * Get metadata of the file or folder
+ * The returned array contains the following values:
+ * - mtime
+ * - size
+ *
+ * @return array
+ */
+ public function stat();
+
+ /**
+ * Get the modified date of the file or folder as unix timestamp
+ *
+ * @return int
+ */
+ public function getMTime();
+
+ /**
+ * Get the size of the file or folder in bytes
+ *
+ * @return int
+ */
+ public function getSize();
+
+ /**
+ * Get the Etag of the file or folder
+ * The Etag is an string id used to detect changes to a file or folder,
+ * every time the file or folder is changed the Etag will change to
+ *
+ * @return string
+ */
+ public function getEtag();
+
+
+ /**
+ * Get the permissions of the file or folder as a combination of one or more of the following constants:
+ * - \OCP\PERMISSION_READ
+ * - \OCP\PERMISSION_UPDATE
+ * - \OCP\PERMISSION_CREATE
+ * - \OCP\PERMISSION_DELETE
+ * - \OCP\PERMISSION_SHARE
+ *
+ * @return int
+ */
+ public function getPermissions();
+
+ /**
+ * Check if the file or folder is readable
+ *
+ * @return bool
+ */
+ public function isReadable();
+
+ /**
+ * Check if the file or folder is writable
+ *
+ * @return bool
+ */
+ public function isUpdateable();
+
+ /**
+ * Check if the file or folder is deletable
+ *
+ * @return bool
+ */
+ public function isDeletable();
+
+ /**
+ * Check if the file or folder is shareable
+ *
+ * @return bool
+ */
+ public function isShareable();
+
+ /**
+ * Get the parent folder of the file or folder
+ *
+ * @return Folder
+ */
+ public function getParent();
+
+ /**
+ * Get the filename of the file or folder
+ *
+ * @return string
+ */
+ public function getName();
+}
diff --git a/lib/public/files/notenoughspaceexception.php b/lib/public/files/notenoughspaceexception.php
new file mode 100644
index 00000000000..17f91b31bfc
--- /dev/null
+++ b/lib/public/files/notenoughspaceexception.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Robin Appelman
+ * @copyright 2013 Robin Appelman icewind@owncloud.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Files/NotEnoughSpaceException class
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP\Files;
+
+/**
+ * Exception for not enough space
+ */
+class NotEnoughSpaceException extends \Exception {}
diff --git a/lib/public/files/notfoundexception.php b/lib/public/files/notfoundexception.php
new file mode 100644
index 00000000000..cb35199220b
--- /dev/null
+++ b/lib/public/files/notfoundexception.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Robin Appelman
+ * @copyright 2013 Robin Appelman icewind@owncloud.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Files/NotFoundException class
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP\Files;
+
+/**
+ * Exception for not found entity
+ */
+class NotFoundException extends \Exception {}
diff --git a/lib/public/files/notpermittedexception.php b/lib/public/files/notpermittedexception.php
new file mode 100644
index 00000000000..e37bd6fad3c
--- /dev/null
+++ b/lib/public/files/notpermittedexception.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Robin Appelman
+ * @copyright 2013 Robin Appelman icewind@owncloud.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Files/NotPermittedException class
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP\Files;
+
+/**
+ * Exception for not permitted action
+ */
+class NotPermittedException extends \Exception {}
diff --git a/lib/files/storage/storage.php b/lib/public/files/storage.php
index c96caebf4af..194b42a6481 100644
--- a/lib/files/storage/storage.php
+++ b/lib/public/files/storage.php
@@ -1,12 +1,33 @@
<?php
/**
- * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
- * This file is licensed under the Affero General Public License version 3 or
- * later.
- * See the COPYING-README file.
+ * ownCloud
+ *
+ * @author Robin Appelman
+ * @copyright 2012 Robin Appelman icewind@owncloud.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
*/
-namespace OC\Files\Storage;
+/**
+ * Public interface of ownCloud for apps to use.
+ * Files/Storage interface
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP\Files;
/**
* Provide a common interface to all different storage options
@@ -223,7 +244,7 @@ interface Storage {
public function getMimeType($path);
/**
- * see http://php.net/manual/en/function.hash.php
+ * see http://php.net/manual/en/function.hash-file.php
*
* @param string $type
* @param string $path
@@ -288,52 +309,6 @@ interface Storage {
public function hasUpdated($path, $time);
/**
- * get a cache instance for the storage
- *
- * @param string $path
- * @return \OC\Files\Cache\Cache
- */
- public function getCache($path = '');
-
- /**
- * get a scanner instance for the storage
- *
- * @param string $path
- * @return \OC\Files\Cache\Scanner
- */
- public function getScanner($path = '');
-
-
- /**
- * get the user id of the owner of a file or folder
- *
- * @param string $path
- * @return string
- */
- public function getOwner($path);
-
- /**
- * get a permissions cache instance for the cache
- *
- * @param string $path
- * @return \OC\Files\Cache\Permissions
- */
- public function getPermissionsCache($path = '');
-
- /**
- * get a watcher instance for the cache
- *
- * @param string $path
- * @return \OC\Files\Cache\Watcher
- */
- public function getWatcher($path = '');
-
- /**
- * @return \OC\Files\Cache\Storage
- */
- public function getStorageCache();
-
- /**
* get the ETag for a file or folder
*
* @param string $path
diff --git a/lib/public/groupinterface.php b/lib/public/groupinterface.php
index 97833028118..625e0b12a87 100644
--- a/lib/public/groupinterface.php
+++ b/lib/public/groupinterface.php
@@ -1,24 +1,24 @@
<?php
/**
-* ownCloud
-*
-* @author Arthur Schiwon
-* @copyright 2012 Arthur Schiwon blizzz@owncloud.org
-*
-* 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/>.
-*
-*/
+ * ownCloud
+ *
+ * @author Arthur Schiwon
+ * @copyright 2012 Arthur Schiwon blizzz@owncloud.org
+ *
+ * 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/>.
+ *
+ */
/**
* Public interface of ownCloud for apps to use.
@@ -26,6 +26,8 @@
*
*/
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
namespace OCP;
-interface GroupInterface extends \OC_Group_Interface {} \ No newline at end of file
+interface GroupInterface extends \OC_Group_Interface {}
diff --git a/lib/public/iaddressbook.php b/lib/public/iaddressbook.php
index 77e8750d9da..dcfe08012e6 100644
--- a/lib/public/iaddressbook.php
+++ b/lib/public/iaddressbook.php
@@ -20,6 +20,11 @@
*
*/
+/**
+ * Public interface of ownCloud for apps to use.
+ * IAddressBook interface
+ */
+
// use OCP namespace for all classes that are considered public.
// This means that they should be used by apps instead of the internal ownCloud classes
namespace OCP {
diff --git a/lib/public/iavatar.php b/lib/public/iavatar.php
new file mode 100644
index 00000000000..2cbec0d45c3
--- /dev/null
+++ b/lib/public/iavatar.php
@@ -0,0 +1,38 @@
+<?php
+/**
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OCP;
+
+/**
+ * This class provides avatar functionality
+ */
+
+interface IAvatar {
+
+ /**
+ * @brief get the users avatar
+ * @param $size integer size in px of the avatar, avatars are square, defaults to 64
+ * @return boolean|\OC_Image containing the avatar or false if there's no image
+ */
+ function get($size = 64);
+
+ /**
+ * @brief sets the users avatar
+ * @param $data mixed imagedata or path to set a new avatar
+ * @throws Exception if the provided file is not a jpg or png image
+ * @throws Exception if the provided image is not valid
+ * @throws \OCP\NotSquareException if the image is not square
+ * @return void
+ */
+ function set($data);
+
+ /**
+ * @brief remove the users avatar
+ * @return void
+ */
+ function remove();
+}
diff --git a/lib/public/iavatarmanager.php b/lib/public/iavatarmanager.php
new file mode 100644
index 00000000000..9b185ae0467
--- /dev/null
+++ b/lib/public/iavatarmanager.php
@@ -0,0 +1,23 @@
+<?php
+/**
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OCP;
+
+/**
+ * This class provides avatar functionality
+ */
+
+interface IAvatarManager {
+
+ /**
+ * @brief return a user specific instance of \OCP\IAvatar
+ * @see \OCP\IAvatar
+ * @param $user string the ownCloud user id
+ * @return \OCP\IAvatar
+ */
+ function getAvatar($user);
+}
diff --git a/lib/public/icache.php b/lib/public/icache.php
new file mode 100644
index 00000000000..0da994eadb3
--- /dev/null
+++ b/lib/public/icache.php
@@ -0,0 +1,74 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Thomas Tanghus
+ * @copyright 2013 Thomas Tanghus thomas@tanghus.net
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Cache interface
+ *
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP;
+
+/**
+ * This interface defines method for accessing the file based user cache.
+ */
+interface ICache {
+
+ /**
+ * Get a value from the user cache
+ * @param string $key
+ * @return mixed
+ */
+ public function get($key);
+
+ /**
+ * Set a value in the user cache
+ * @param string $key
+ * @param mixed $value
+ * @param int $ttl Time To Live in seconds. Defaults to 60*60*24
+ * @return bool
+ */
+ public function set($key, $value, $ttl = 0);
+
+ /**
+ * Check if a value is set in the user cache
+ * @param string $key
+ * @return bool
+ */
+ public function hasKey($key);
+
+ /**
+ * Remove an item from the user cache
+ * @param string $key
+ * @return bool
+ */
+ public function remove($key);
+
+ /**
+ * Clear the user cache of all entries starting with a prefix
+ * @param string $prefix (optional)
+ * @return bool
+ */
+ public function clear($prefix = '');
+}
diff --git a/lib/public/iconfig.php b/lib/public/iconfig.php
new file mode 100644
index 00000000000..da6b6c54843
--- /dev/null
+++ b/lib/public/iconfig.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Bart Visscher
+ * @copyright 2013 Bart Visscher bartv@thisnet.nl
+ *
+ * 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/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Config interface
+ *
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP;
+
+/**
+ * Access to all the configuration options ownCloud offers
+ */
+interface IConfig {
+ /**
+ * Sets a new system wide value
+ * @param string $key the key of the value, under which will be saved
+ * @param string $value the value that should be stored
+ * @todo need a use case for this
+ */
+// public function setSystemValue($key, $value);
+
+ /**
+ * Looks up a system wide defined value
+ * @param string $key the key of the value, under which it was saved
+ * @return string the saved value
+ */
+ public function getSystemValue($key);
+
+
+ /**
+ * Writes a new app wide value
+ * @param string $appName the appName that we want to store the value under
+ * @param string $key the key of the value, under which will be saved
+ * @param string $value the value that should be stored
+ */
+ public function setAppValue($appName, $key, $value);
+
+ /**
+ * Looks up an app wide defined value
+ * @param string $appName the appName that we stored the value under
+ * @param string $key the key of the value, under which it was saved
+ * @return string the saved value
+ */
+ public function getAppValue($appName, $key);
+
+
+ /**
+ * Set a user defined value
+ * @param string $userId the userId of the user that we want to store the value under
+ * @param string $appName the appName that we want to store the value under
+ * @param string $key the key under which the value is being stored
+ * @param string $value the value that you want to store
+ */
+ public function setUserValue($userId, $appName, $key, $value);
+
+ /**
+ * Shortcut for getting a user defined value
+ * @param string $userId the userId of the user that we want to store the value under
+ * @param string $appName the appName that we stored the value under
+ * @param string $key the key under which the value is being stored
+ */
+ public function getUserValue($userId, $appName, $key);
+}
diff --git a/lib/public/icontainer.php b/lib/public/icontainer.php
new file mode 100644
index 00000000000..eaffa5d5a06
--- /dev/null
+++ b/lib/public/icontainer.php
@@ -0,0 +1,72 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Thomas Müller
+ * @copyright 2013 Thomas Müller deepdiver@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/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Container interface
+ *
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP;
+
+/**
+ * Class IContainer
+ *
+ * IContainer is the basic interface to be used for any internal dependency injection mechanism
+ *
+ * @package OCP
+ */
+interface IContainer {
+
+ /**
+ * Look up a service for a given name in the container.
+ *
+ * @param string $name
+ * @return mixed
+ */
+ function query($name);
+
+ /**
+ * A value is stored in the container with it's corresponding name
+ *
+ * @param string $name
+ * @param mixed $value
+ * @return void
+ */
+ function registerParameter($name, $value);
+
+ /**
+ * A service is registered in the container where a closure is passed in which will actually
+ * create the service on demand.
+ * In case the parameter $shared is set to true (the default usage) the once created service will remain in
+ * memory and be reused on subsequent calls.
+ * In case the parameter is false the service will be recreated on every call.
+ *
+ * @param string $name
+ * @param \Closure $closure
+ * @param bool $shared
+ * @return void
+ */
+ function registerService($name, \Closure $closure, $shared = true);
+}
diff --git a/lib/public/idbconnection.php b/lib/public/idbconnection.php
new file mode 100644
index 00000000000..656b5e7e5b2
--- /dev/null
+++ b/lib/public/idbconnection.php
@@ -0,0 +1,95 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Bart Visscher
+ * @copyright 2013 Bart Visscher bartv@thisnet.nl
+ *
+ * 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/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * DBConnection interface
+ *
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP;
+
+/**
+ * TODO: Description
+ */
+interface IDBConnection {
+ /**
+ * Used to abstract the owncloud database access away
+ * @param string $sql the sql query with ? placeholder for params
+ * @param int $limit the maximum number of rows
+ * @param int $offset from which row we want to start
+ * @return \Doctrine\DBAL\Driver\Statement The prepared statement.
+ */
+ public function prepare($sql, $limit=null, $offset=null);
+
+ /**
+ * Used to get the id of the just inserted element
+ * @param string $table the name of the table where we inserted the item
+ * @return int the id of the inserted element
+ */
+ public function lastInsertId($table = null);
+
+ /**
+ * Insert a row if a matching row doesn't exists.
+ * @param string The table name (will replace *PREFIX*) to perform the replace on.
+ * @param array
+ *
+ * The input array if in the form:
+ *
+ * array ( 'id' => array ( 'value' => 6,
+ * 'key' => true
+ * ),
+ * 'name' => array ('value' => 'Stoyan'),
+ * 'family' => array ('value' => 'Stefanov'),
+ * 'birth_date' => array ('value' => '1975-06-20')
+ * );
+ * @return bool
+ *
+ */
+ public function insertIfNotExist($table, $input);
+
+ /**
+ * Start a transaction
+ * @return bool TRUE on success or FALSE on failure
+ */
+ public function beginTransaction();
+
+ /**
+ * Commit the database changes done during a transaction that is in progress
+ * @return bool TRUE on success or FALSE on failure
+ */
+ public function commit();
+
+ /**
+ * Rollback the database changes done during a transaction that is in progress
+ * @return bool TRUE on success or FALSE on failure
+ */
+ public function rollBack();
+
+ /**
+ * Gets the error code and message as a string for logging
+ * @return string
+ */
+ public function getError();
+}
diff --git a/lib/public/ihelper.php b/lib/public/ihelper.php
new file mode 100644
index 00000000000..c0723b8edc7
--- /dev/null
+++ b/lib/public/ihelper.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Bart Visscher
+ * @copyright 2013 Bart Visscher bartv@thisnet.nl
+ *
+ * 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/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Helper interface
+ *
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP;
+
+/**
+ * Functions that don't have any specific interface to place
+ */
+interface IHelper {
+ /**
+ * Gets the content of an URL by using CURL or a fallback if it is not
+ * installed
+ * @param string $url the url that should be fetched
+ * @return string the content of the webpage
+ */
+ public function getUrlContent($url);
+}
diff --git a/lib/public/il10n.php b/lib/public/il10n.php
new file mode 100644
index 00000000000..817b299b0b7
--- /dev/null
+++ b/lib/public/il10n.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * L10n interface
+ *
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP;
+
+/**
+ * TODO: Description
+ */
+interface IL10N {
+ /**
+ * Translating
+ * @param $text String The text we need a translation for
+ * @param array $parameters default:array() Parameters for sprintf
+ * @return \OC_L10N_String|string Translation or the same text
+ *
+ * Returns the translation. If no translation is found, $text will be
+ * returned.
+ */
+ public function t($text, $parameters = array());
+
+ /**
+ * 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 array $parameters default:array() Parameters for sprintf
+ * @return \OC_L10N_String|string Translation or the same text
+ *
+ * Returns the translation. If no translation is found, $text will be
+ * returned. %n will be replaced with the number of objects.
+ *
+ * The correct plural is determined by the plural_forms-function
+ * provided by the po file.
+ *
+ */
+ public function n($text_singular, $text_plural, $count, $parameters = array());
+
+ /**
+ * Localization
+ * @param $type Type of localization
+ * @param $params parameters for this localization
+ * @return String or false
+ *
+ * Returns the localized data.
+ *
+ * Implemented types:
+ * - date
+ * - Creates a date
+ * - l10n-field: date
+ * - params: timestamp (int/string)
+ * - datetime
+ * - Creates date and time
+ * - l10n-field: datetime
+ * - params: timestamp (int/string)
+ * - time
+ * - Creates a time
+ * - l10n-field: time
+ * - params: timestamp (int/string)
+ */
+ public function l($type, $data);
+}
diff --git a/lib/public/image.php b/lib/public/image.php
index c6dd9a113ab..a9e2bfa724e 100644
--- a/lib/public/image.php
+++ b/lib/public/image.php
@@ -1,25 +1,33 @@
<?php
/**
-* ownCloud
-*
-* @author Bart Visscher
-* @copyright 2013 Bart Visscher <bartv@thisnet.nl>
-*
-* 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/>.
-*
-*/
+ * ownCloud
+ *
+ * @author Bart Visscher
+ * @copyright 2013 Bart Visscher <bartv@thisnet.nl>
+ *
+ * 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/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Image class
+ *
+ */
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
namespace OCP;
/**
diff --git a/lib/public/inavigationmanager.php b/lib/public/inavigationmanager.php
new file mode 100644
index 00000000000..73e85d03761
--- /dev/null
+++ b/lib/public/inavigationmanager.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Bart Visscher
+ * @copyright 2013 Bart Visscher bartv@thisnet.nl
+ *
+ * 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/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Navigation manager interface
+ *
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP;
+
+/**
+ * Manages the ownCloud navigation
+ */
+interface INavigationManager {
+ /**
+ * Creates a new navigation entry
+ * @param array $entry containing: id, name, order, icon and href key
+ */
+ public function add(array $entry);
+
+ /**
+ * Sets the current navigation entry of the currently running app
+ * @param string $appId id of the app entry to activate (from added $entry)
+ */
+ public function setActiveEntry($appId);
+}
diff --git a/lib/public/ipreview.php b/lib/public/ipreview.php
new file mode 100644
index 00000000000..f74472ad368
--- /dev/null
+++ b/lib/public/ipreview.php
@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * ownCloud
+ *
+ * @author Frank Karlitschek
+ * @author Georg Ehrke
+ * @copyright 2013 Frank Karlitschek frank@owncloud.org
+ * @copyright 2013 Georg Ehrke georg@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/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Preview interface
+ *
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP;
+
+/**
+ * This class provides functions to render and show thumbnails and previews of files
+ */
+interface IPreview
+{
+
+ /**
+ * Return a preview of a file
+ * @param string $file The path to the file where you want a thumbnail from
+ * @param int $maxX The maximum X size of the thumbnail. It can be smaller depending on the shape of the image
+ * @param int $maxY The maximum Y size of the thumbnail. It can be smaller depending on the shape of the image
+ * @param boolean $scaleUp Scale smaller images up to the thumbnail size or not. Might look ugly
+ * @return \OCP\Image
+ */
+ function createPreview($file, $maxX = 100, $maxY = 75, $scaleUp = false);
+
+
+ /**
+ * Returns true if the passed mime type is supported
+ * @param string $mimeType
+ * @return boolean
+ */
+ function isMimeSupported($mimeType = '*');
+
+}
diff --git a/lib/public/irequest.php b/lib/public/irequest.php
new file mode 100644
index 00000000000..ca23e12b7f5
--- /dev/null
+++ b/lib/public/irequest.php
@@ -0,0 +1,123 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Thomas Müller
+ * @copyright 2013 Thomas Müller deepdiver@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/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Request interface
+ *
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP;
+
+/**
+ * This interface provides an immutable object with with accessors to
+ * request variables and headers.
+ *
+ * Access request variables by method and name.
+ *
+ * Examples:
+ *
+ * $request->post['myvar']; // Only look for POST variables
+ * $request->myvar; or $request->{'myvar'}; or $request->{$myvar}
+ * Looks in the combined GET, POST and urlParams array.
+ *
+ * If you access e.g. ->post but the current HTTP request method
+ * is GET a \LogicException will be thrown.
+ *
+ * NOTE:
+ * - When accessing ->put a stream resource is returned and the accessor
+ * will return false on subsequent access to ->put or ->patch.
+ * - When accessing ->patch and the Content-Type is either application/json
+ * or application/x-www-form-urlencoded (most cases) it will act like ->get
+ * and ->post and return an array. Otherwise the raw data will be returned.
+ */
+
+interface IRequest {
+
+ function getHeader($name);
+
+ /**
+ * Lets you access post and get parameters by the index
+ * In case of json requests the encoded json body is accessed
+ *
+ * @param string $key the key which you want to access in the URL Parameter
+ * placeholder, $_POST or $_GET array.
+ * The priority how they're returned is the following:
+ * 1. URL parameters
+ * 2. POST parameters
+ * 3. GET parameters
+ * @param mixed $default If the key is not found, this value will be returned
+ * @return mixed the content of the array
+ */
+ public function getParam($key, $default = null);
+
+
+ /**
+ * Returns all params that were received, be it from the request
+ *
+ * (as GET or POST) or through the URL by the route
+ * @return array the array with all parameters
+ */
+ public function getParams();
+
+ /**
+ * Returns the method of the request
+ *
+ * @return string the method of the request (POST, GET, etc)
+ */
+ public function getMethod();
+
+ /**
+ * Shortcut for accessing an uploaded file through the $_FILES array
+ *
+ * @param string $key the key that will be taken from the $_FILES array
+ * @return array the file in the $_FILES element
+ */
+ public function getUploadedFile($key);
+
+
+ /**
+ * Shortcut for getting env variables
+ *
+ * @param string $key the key that will be taken from the $_ENV array
+ * @return array the value in the $_ENV element
+ */
+ public function getEnv($key);
+
+
+ /**
+ * Shortcut for getting cookie variables
+ *
+ * @param string $key the key that will be taken from the $_COOKIE array
+ * @return array the value in the $_COOKIE element
+ */
+ function getCookie($key);
+
+
+ /**
+ * Checks if the CSRF check was correct
+ * @return bool true if CSRF check passed
+ */
+ public function passesCSRFCheck();
+}
diff --git a/lib/public/iservercontainer.php b/lib/public/iservercontainer.php
new file mode 100644
index 00000000000..b958d2d03f4
--- /dev/null
+++ b/lib/public/iservercontainer.php
@@ -0,0 +1,172 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Thomas Müller
+ * @copyright 2013 Thomas Müller deepdiver@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/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Server container interface
+ *
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP;
+
+
+/**
+ * Class IServerContainer
+ * @package OCP
+ *
+ * This container holds all ownCloud services
+ */
+interface IServerContainer {
+
+ /**
+ * The contacts manager will act as a broker between consumers for contacts information and
+ * providers which actual deliver the contact information.
+ *
+ * @return \OCP\Contacts\IManager
+ */
+ function getContactsManager();
+
+ /**
+ * The current request object holding all information about the request currently being processed
+ * is returned from this method.
+ * In case the current execution was not initiated by a web request null is returned
+ *
+ * @return \OCP\IRequest|null
+ */
+ function getRequest();
+
+ /**
+ * Returns the preview manager which can create preview images for a given file
+ *
+ * @return \OCP\IPreview
+ */
+ function getPreviewManager();
+
+ /**
+ * Returns the tag manager which can get and set tags for different object types
+ *
+ * @see \OCP\ITagManager::load()
+ * @return \OCP\ITagManager
+ */
+ function getTagManager();
+
+ /**
+ * Returns the root folder of ownCloud's data directory
+ *
+ * @return \OCP\Files\Folder
+ */
+ function getRootFolder();
+
+ /**
+ * Returns a view to ownCloud's files folder
+ *
+ * @return \OCP\Files\Folder
+ */
+ function getUserFolder();
+
+ /**
+ * Returns an app-specific view in ownClouds data directory
+ *
+ * @return \OCP\Files\Folder
+ */
+ function getAppFolder();
+
+ /**
+ * Returns the user session
+ *
+ * @return \OCP\IUserSession
+ */
+ function getUserSession();
+
+ /**
+ * Returns the navigation manager
+ *
+ * @return \OCP\INavigationManager
+ */
+ function getNavigationManager();
+
+ /**
+ * Returns the config manager
+ *
+ * @return \OCP\IConfig
+ */
+ function getConfig();
+
+ /**
+ * get an L10N instance
+ * @param $app string appid
+ * @return \OCP\IL10N
+ */
+ function getL10N($app);
+
+ /**
+ * Returns the URL generator
+ *
+ * @return \OCP\IURLGenerator
+ */
+ function getURLGenerator();
+
+ /**
+ * Returns the Helper
+ *
+ * @return \OCP\IHelper
+ */
+ function getHelper();
+
+ /**
+ * Returns an ICache instance
+ *
+ * @return \OCP\ICache
+ */
+ function getCache();
+
+ /**
+ * Returns the current session
+ *
+ * @return \OCP\ISession
+ */
+ function getSession();
+
+ /**
+ * Returns the activity manager
+ *
+ * @return \OCP\Activity\IManager
+ */
+ function getActivityManager();
+
+ /**
+ * Returns the current session
+ *
+ * @return \OCP\IDBConnection
+ */
+ function getDatabaseConnection();
+
+ /**
+ * Returns an avatar manager, used for avatar functionality
+ *
+ * @return \OCP\IAvatarManager
+ */
+ function getAvatarManager();
+
+}
diff --git a/lib/public/isession.php b/lib/public/isession.php
new file mode 100644
index 00000000000..20da712cda3
--- /dev/null
+++ b/lib/public/isession.php
@@ -0,0 +1,78 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Thomas Tanghus
+ * @author Robin Appelman
+ * @copyright 2013 Thomas Tanghus thomas@tanghus.net
+ * @copyright 2013 Robin Appelman icewind@owncloud.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Session interface
+ *
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP;
+
+/**
+ * Interface ISession
+ *
+ * wrap PHP's internal session handling into the ISession interface
+ */
+interface ISession {
+
+ /**
+ * Set a value in the session
+ *
+ * @param string $key
+ * @param mixed $value
+ */
+ public function set($key, $value);
+
+ /**
+ * Get a value from the session
+ *
+ * @param string $key
+ * @return mixed should return null if $key does not exist
+ */
+ public function get($key);
+
+ /**
+ * Check if a named key exists in the session
+ *
+ * @param string $key
+ * @return bool
+ */
+ public function exists($key);
+
+ /**
+ * Remove a $key/$value pair from the session
+ *
+ * @param string $key
+ */
+ public function remove($key);
+
+ /**
+ * Reset and recreate the session
+ */
+ public function clear();
+
+}
diff --git a/lib/public/itagmanager.php b/lib/public/itagmanager.php
new file mode 100644
index 00000000000..40487de42b4
--- /dev/null
+++ b/lib/public/itagmanager.php
@@ -0,0 +1,55 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Thomas Tanghus
+ * @copyright 2013 Thomas Tanghus <thomas@tanghus.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Tag manager interface
+ *
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP;
+
+/**
+ * Factory class creating instances of \OCP\ITags
+ *
+ * A tag can be e.g. 'Family', 'Work', 'Chore', 'Special Occation' or
+ * anything else that is either parsed from a vobject or that the user chooses
+ * to add.
+ * Tag names are not case-sensitive, but will be saved with the case they
+ * are entered in. If a user already has a tag 'family' for a type, and
+ * tries to add a tag named 'Family' it will be silently ignored.
+ */
+interface ITagManager {
+
+ /**
+ * Create a new \OCP\ITags instance and load tags from db.
+ *
+ * @see \OCP\ITags
+ * @param string $type The type identifier e.g. 'contact' or 'event'.
+ * @param array $defaultTags An array of default tags to be used if none are stored.
+ * @return \OCP\ITags
+ */
+ public function load($type, $defaultTags=array());
+
+} \ No newline at end of file
diff --git a/lib/public/itags.php b/lib/public/itags.php
new file mode 100644
index 00000000000..ea62fb38ecb
--- /dev/null
+++ b/lib/public/itags.php
@@ -0,0 +1,172 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Thomas Tanghus
+ * @copyright 2013 Thomas Tanghus <thomas@tanghus.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Tags interface
+ *
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP;
+
+// FIXME: Where should I put this? Or should it be implemented as a Listener?
+\OC_Hook::connect('OC_User', 'post_deleteUser', 'OC\Tags', 'post_deleteUser');
+
+/**
+ * Class for easily tagging objects by their id
+ *
+ * A tag can be e.g. 'Family', 'Work', 'Chore', 'Special Occation' or
+ * anything else that is either parsed from a vobject or that the user chooses
+ * to add.
+ * Tag names are not case-sensitive, but will be saved with the case they
+ * are entered in. If a user already has a tag 'family' for a type, and
+ * tries to add a tag named 'Family' it will be silently ignored.
+ */
+
+interface ITags {
+
+ /**
+ * Check if any tags are saved for this type and user.
+ *
+ * @return boolean.
+ */
+ public function isEmpty();
+
+ /**
+ * Get the tags for a specific user.
+ *
+ * This returns an array with id/name maps:
+ * [
+ * ['id' => 0, 'name' = 'First tag'],
+ * ['id' => 1, 'name' = 'Second tag'],
+ * ]
+ *
+ * @returns array
+ */
+ public function getTags();
+
+ /**
+ * Get the a list if items tagged with $tag.
+ *
+ * Throws an exception if the tag could not be found.
+ *
+ * @param string|integer $tag Tag id or name.
+ * @return array An array of object ids or false on error.
+ */
+ public function getIdsForTag($tag);
+
+ /**
+ * Checks whether a tag is already saved.
+ *
+ * @param string $name The name to check for.
+ * @return bool
+ */
+ public function hasTag($name);
+
+ /**
+ * Add a new tag.
+ *
+ * @param string $name A string with a name of the tag
+ * @return int the id of the added tag or false if it already exists.
+ */
+ public function add($name);
+
+ /**
+ * Rename tag.
+ *
+ * @param string $from The name of the existing tag
+ * @param string $to The new name of the tag.
+ * @return bool
+ */
+ public function rename($from, $to);
+
+ /**
+ * Add a list of new tags.
+ *
+ * @param string[] $names A string with a name or an array of strings containing
+ * the name(s) of the to add.
+ * @param bool $sync When true, save the tags
+ * @param int|null $id int Optional object id to add to this|these tag(s)
+ * @return bool Returns false on error.
+ */
+ public function addMultiple($names, $sync=false, $id = null);
+
+ /**
+ * Delete tag/object relations from the db
+ *
+ * @param array $ids The ids of the objects
+ * @return boolean Returns false on error.
+ */
+ public function purgeObjects(array $ids);
+
+ /**
+ * Get favorites for an object type
+ *
+ * @return array An array of object ids.
+ */
+ public function getFavorites();
+
+ /**
+ * Add an object to favorites
+ *
+ * @param int $objid The id of the object
+ * @return boolean
+ */
+ public function addToFavorites($objid);
+
+ /**
+ * Remove an object from favorites
+ *
+ * @param int $objid The id of the object
+ * @return boolean
+ */
+ public function removeFromFavorites($objid);
+
+ /**
+ * Creates a tag/object relation.
+ *
+ * @param int $objid The id of the object
+ * @param int|string $tag The id or name of the tag
+ * @return boolean Returns false on database error.
+ */
+ public function tagAs($objid, $tag);
+
+ /**
+ * Delete single tag/object relation from the db
+ *
+ * @param int $objid The id of the object
+ * @param int|string $tag The id or name of the tag
+ * @return boolean
+ */
+ public function unTag($objid, $tag);
+
+ /**
+ * Delete tags from the
+ *
+ * @param string[] $names An array of tags to delete
+ * @return bool Returns false on error
+ */
+ public function delete($names);
+
+} \ No newline at end of file
diff --git a/lib/public/iurlgenerator.php b/lib/public/iurlgenerator.php
new file mode 100644
index 00000000000..afdf1b6f299
--- /dev/null
+++ b/lib/public/iurlgenerator.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Bart Visscher
+ * @copyright 2013 Bart Visscher bartv@thisnet.nl
+ *
+ * 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/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * URL generator interface
+ *
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP;
+
+/**
+ * Class to generate URLs
+ */
+interface IURLGenerator {
+ /**
+ * Returns the URL for a route
+ * @param string $routeName the name of the route
+ * @param array $arguments an array with arguments which will be filled into the url
+ * @return string the url
+ */
+ public function linkToRoute($routeName, $arguments = array());
+
+ /**
+ * Returns an URL for an image or file
+ * @param string $appName the name of the app
+ * @param string $file the name of the file
+ * @return string the url
+ */
+ public function linkTo($appName, $file);
+
+ /**
+ * Returns the link to an image, like linkTo but only with prepending img/
+ * @param string $appName the name of the app
+ * @param string $file the name of the file
+ * @return string the url
+ */
+ public function imagePath($appName, $file);
+
+
+ /**
+ * Makes an URL absolute
+ * @param string $url the url in the owncloud host
+ * @return string the absolute version of the url
+ */
+ public function getAbsoluteURL($url);
+}
diff --git a/lib/public/iusersession.php b/lib/public/iusersession.php
new file mode 100644
index 00000000000..131b326ab90
--- /dev/null
+++ b/lib/public/iusersession.php
@@ -0,0 +1,51 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Bart Visscher
+ * @copyright 2013 Bart Visscher bartv@thisnet.nl
+ *
+ * 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/>.
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * User session interface
+ *
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP;
+
+/**
+ * User session
+ */
+interface IUserSession {
+ /**
+ * Do a user login
+ * @param string $user the username
+ * @param string $password the password
+ * @return bool true if successful
+ */
+ public function login($user, $password);
+
+ /**
+ * Logs the user out including all the session data
+ * Logout, destroys session
+ */
+ public function logout();
+
+}
diff --git a/lib/public/json.php b/lib/public/json.php
index 2186dd8ee49..134f724b0e6 100644
--- a/lib/public/json.php
+++ b/lib/public/json.php
@@ -1,24 +1,24 @@
<?php
/**
-* ownCloud
-*
-* @author Frank Karlitschek
-* @copyright 2012 Frank Karlitschek frank@owncloud.org
-*
-* 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/>.
-*
-*/
+ * ownCloud
+ *
+ * @author Frank Karlitschek
+ * @copyright 2012 Frank Karlitschek frank@owncloud.org
+ *
+ * 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/>.
+ *
+ */
/**
* Public interface of ownCloud for apps to use.
@@ -35,7 +35,7 @@ namespace OCP;
*/
class JSON {
/**
- * @brief Encode and print $data in JSON format
+ * Encode and print $data in JSON format
* @param array $data The data to use
* @param string $setContentType the optional content type
* @return string json formatted string.
@@ -123,7 +123,7 @@ class JSON {
}
/**
- * @brief set Content-Type header to jsonrequest
+ * Set Content-Type header to jsonrequest
* @param array $type The contwnt type header
* @return string json formatted string.
*/
diff --git a/lib/public/response.php b/lib/public/response.php
index de0c3f25347..2ca0a0c9fa4 100644
--- a/lib/public/response.php
+++ b/lib/public/response.php
@@ -1,24 +1,24 @@
<?php
/**
-* ownCloud
-*
-* @author Frank Karlitschek
-* @copyright 2012 Frank Karlitschek frank@owncloud.org
-*
-* 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/>.
-*
-*/
+ * ownCloud
+ *
+ * @author Frank Karlitschek
+ * @copyright 2012 Frank Karlitschek frank@owncloud.org
+ *
+ * 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/>.
+ *
+ */
/**
* Public interface of ownCloud for apps to use.
@@ -35,64 +35,64 @@ namespace OCP;
*/
class Response {
/**
- * @brief Enable response caching by sending correct HTTP headers
- * @param int $cache_time time to cache the response
- * >0 cache time in seconds
- * 0 and <0 enable default browser caching
- * null cache indefinitly
- */
+ * Enable response caching by sending correct HTTP headers
+ * @param int $cache_time time to cache the response
+ * >0 cache time in seconds
+ * 0 and <0 enable default browser caching
+ * null cache indefinitly
+ */
static public function enableCaching( $cache_time = null ) {
\OC_Response::enableCaching( $cache_time );
}
/**
- * Checks and set Last-Modified header, when the request matches sends a
- * 'not modified' response
- * @param string $lastModified time when the reponse was last modified
- */
+ * Checks and set Last-Modified header, when the request matches sends a
+ * 'not modified' response
+ * @param string $lastModified time when the reponse was last modified
+ */
static public function setLastModifiedHeader( $lastModified ) {
\OC_Response::setLastModifiedHeader( $lastModified );
}
/**
- * @brief disable browser caching
- * @see enableCaching with cache_time = 0
- */
+ * Disable browser caching
+ * @see enableCaching with cache_time = 0
+ */
static public function disableCaching() {
\OC_Response::disableCaching();
}
/**
- * Checks and set ETag header, when the request matches sends a
- * 'not modified' response
- * @param string $etag token to use for modification check
- */
+ * Checks and set ETag header, when the request matches sends a
+ * 'not modified' response
+ * @param string $etag token to use for modification check
+ */
static public function setETagHeader( $etag ) {
\OC_Response::setETagHeader( $etag );
}
/**
- * @brief Send file as response, checking and setting caching headers
- * @param string $filepath of file to send
- */
+ * Send file as response, checking and setting caching headers
+ * @param string $filepath of file to send
+ */
static public function sendFile( $filepath ) {
\OC_Response::sendFile( $filepath );
}
/**
- * @brief Set response expire time
- * @param string|\DateTime $expires date-time when the response expires
- * string for DateInterval from now
- * DateTime object when to expire response
- */
+ * Set response expire time
+ * @param string|\DateTime $expires date-time when the response expires
+ * string for DateInterval from now
+ * DateTime object when to expire response
+ */
static public function setExpiresHeader( $expires ) {
\OC_Response::setExpiresHeader( $expires );
}
/**
- * @brief Send redirect response
- * @param string $location to redirect to
- */
+ * Send redirect response
+ * @param string $location to redirect to
+ */
static public function redirect( $location ) {
\OC_Response::redirect( $location );
}
diff --git a/lib/public/share.php b/lib/public/share.php
index 63645e6fa34..f0fd8e1ab1b 100644
--- a/lib/public/share.php
+++ b/lib/public/share.php
@@ -1,32 +1,41 @@
<?php
/**
-* ownCloud
-*
-* @author Michael Gapczynski
-* @copyright 2012 Michael Gapczynski mtgap@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/>.
-*/
+ * ownCloud
+ *
+ * @author Michael Gapczynski
+ * @copyright 2012 Michael Gapczynski mtgap@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/>.
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Share Class
+ *
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
namespace OCP;
/**
-* 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
-*/
+ * 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 {
const SHARE_TYPE_USER = 0;
@@ -37,19 +46,19 @@ class Share {
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
- */
+ * 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;
@@ -64,13 +73,13 @@ class Share {
private static $isResharingAllowed;
/**
- * @brief 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
- */
+ * 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])) {
@@ -94,45 +103,45 @@ class Share {
}
/**
- * @brief Check if the Share API is enabled
- * @return Returns true if enabled or false
- *
- * The Share API is enabled by default if not configured
- *
- */
+ * 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;
}
-
+
/**
- * @brief Prepare a path to be passed to DB as file_target
- * @return string Prepared path
- */
+ * 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;
-
+
}
/**
- * @brief 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'
- */
+ * 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();
@@ -140,8 +149,13 @@ class Share {
$source = -1;
$cache = false;
- $view = new \OC\Files\View('/' . $user . '/files/');
- $meta = $view->getFileInfo(\OC\Files\Filesystem::normalizePath($path));
+ $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'];
@@ -150,13 +164,13 @@ class Share {
while ($source !== -1) {
- // Fetch all shares of this file path from DB
+ // Fetch all shares with another user
$query = \OC_DB::prepare(
'SELECT `share_with`
FROM
`*PREFIX*share`
WHERE
- `item_source` = ? AND `share_type` = ?'
+ `item_source` = ? AND `share_type` = ? AND `item_type` IN (\'file\', \'folder\')'
);
$result = $query->execute(array($source, self::SHARE_TYPE_USER));
@@ -175,7 +189,7 @@ class Share {
FROM
`*PREFIX*share`
WHERE
- `item_source` = ? AND `share_type` = ?'
+ `item_source` = ? AND `share_type` = ? AND `item_type` IN (\'file\', \'folder\')'
);
$result = $query->execute(array($source, self::SHARE_TYPE_GROUP));
@@ -196,7 +210,7 @@ class Share {
FROM
`*PREFIX*share`
WHERE
- `item_source` = ? AND `share_type` = ?'
+ `item_source` = ? AND `share_type` = ? AND `item_type` IN (\'file\', \'folder\')'
);
$result = $query->execute(array($source, self::SHARE_TYPE_LINK));
@@ -209,7 +223,7 @@ class Share {
}
}
}
-
+
// let's get the parent for the next round
$meta = $cache->get((int)$source);
if($meta !== false) {
@@ -227,12 +241,14 @@ class Share {
}
/**
- * @brief 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 int Number of items to return (optional) Returns all by default
- * @return Return depends on format
- */
+ * 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,
@@ -240,25 +256,78 @@ class Share {
}
/**
- * @brief Get the item of item type shared with the current user
- * @param string Item type
- * @param string Item target
- * @param int Format (optional) Format type must be defined by the backend
- * @return Return depends on format
- */
+ * 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);
}
-
+
/**
- * @brief 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
- * @return Return depends on format
- */
+ * 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,
@@ -266,19 +335,19 @@ class Share {
}
/**
- * @brief 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
- */
+ * 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);
}
/**
- * @brief Get the item shared by a token
+ * Get the item shared by a token
* @param string token
* @return Item
*/
@@ -288,11 +357,15 @@ class Share {
if (\OC_DB::isError($result)) {
\OC_Log::write('OCP\Share', \OC_DB::getErrorMessage($result) . ', token=' . $token, \OC_Log::ERROR);
}
- return $result->fetchRow();
+ $row = $result->fetchRow();
+ if (is_array($row) and self::expireItem($row)) {
+ return false;
+ }
+ return $row;
}
/**
- * @brief resolves reshares down to the last real share
+ * resolves reshares down to the last real share
* @param $linkItem
* @return $fileOwner
*/
@@ -315,12 +388,14 @@ class Share {
/**
- * @brief 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 int Number of items to return (optional) Returns all by default
- * @return Return depends on format
- */
+ * 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,
@@ -328,12 +403,14 @@ class Share {
}
/**
- * @brief 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
- * @return Return depends on format
- */
+ * 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,
@@ -341,16 +418,18 @@ class Share {
}
/**
- * Get all users an item is shared with
- * @param string Item type
- * @param string Item source
- * @param string Owner
- * @param bool Include collections
- * @return Return array of users
- */
- public static function getUsersItemShared($itemType, $itemSource, $uidOwner, $includeCollections = false) {
+ * 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);
+ $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) {
@@ -364,33 +443,45 @@ class Share {
}
/**
- * @brief Share an item with a user, group, or via 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
- * @param int CRUDS 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) {
+ * 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 share type and sharing conditions are met
if ($shareType === self::SHARE_TYPE_USER) {
if ($shareWith == $uidOwner) {
- $message = 'Sharing '.$itemSource.' failed, because the user '.$shareWith.' is the item owner';
+ $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 '.$itemSource.' failed, because the user '.$shareWith.' does not exist';
+ $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 '.$itemSource.' failed, because the user '
+ $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);
@@ -403,19 +494,19 @@ class Share {
// 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 '.$itemSource.' failed, because this item is already shared with '.$shareWith;
+ $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 '.$itemSource.' failed, because the group '.$shareWith.' does not exist';
+ $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 '.$itemSource.' failed, because '
+ $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);
@@ -428,7 +519,7 @@ class Share {
// 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 '.$itemSource.' failed, because this item is already shared with '.$shareWith;
+ $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);
}
@@ -445,6 +536,7 @@ class Share {
$uidOwner, self::FORMAT_NONE, null, 1)) {
// remember old token
$oldToken = $checkExists['token'];
+ $oldPermissions = $checkExists['permissions'];
//delete the old share
self::delete($checkExists['id']);
}
@@ -455,25 +547,28 @@ class Share {
$hasher = new \PasswordHash(8, $forcePortable);
$shareWith = $hasher->HashPassword($shareWith.\OC_Config::getValue('passwordsalt', ''));
} else {
- // reuse the already set password
- $shareWith = $checkExists['share_with'];
+ // 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::generate_random_bytes(self::TOKEN_LENGTH);
+ $token = \OC_Util::generateRandomBytes(self::TOKEN_LENGTH);
}
$result = self::put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions,
- null, $token);
+ null, $token, $itemSourceName);
if ($result) {
return $token;
} else {
return false;
}
}
- $message = 'Sharing '.$itemSource.' failed, because sharing with links is not allowed';
+ $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;
@@ -532,79 +627,59 @@ class Share {
// return false;
// } else {
// Put the item into the database
- return self::put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions);
+ return self::put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions, null, null, $itemSourceName);
// }
}
/**
- * @brief 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
- */
+ * 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) {
if ($item = self::getItems($itemType, $itemSource, $shareType, $shareWith, \OC_User::getUser(),
self::FORMAT_NONE, null, 1)) {
- // Pass all the vars we have for now, they may be useful
- \OC_Hook::emit('OCP\Share', 'pre_unshare', array(
- 'itemType' => $itemType,
- 'itemSource' => $itemSource,
- 'fileSource' => $item['file_source'],
- 'shareType' => $shareType,
- 'shareWith' => $shareWith,
- 'itemParent' => $item['parent'],
- ));
- self::delete($item['id']);
- \OC_Hook::emit('OCP\Share', 'post_unshare', array(
- 'itemType' => $itemType,
- 'itemSource' => $itemSource,
- 'shareType' => $shareType,
- 'shareWith' => $shareWith,
- 'itemParent' => $item['parent'],
- ));
+ self::unshareItem($item);
return true;
}
return false;
}
/**
- * @brief 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
- */
+ * 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) {
if ($shares = self::getItemShared($itemType, $itemSource)) {
// Pass all the vars we have for now, they may be useful
- \OC_Hook::emit('OCP\Share', 'pre_unshareAll', array(
+ $hookParams = array(
'itemType' => $itemType,
'itemSource' => $itemSource,
- 'shares' => $shares
- ));
+ 'shares' => $shares,
+ );
+ \OC_Hook::emit('OCP\Share', 'pre_unshareAll', $hookParams);
foreach ($shares as $share) {
- self::delete($share['id']);
+ self::unshareItem($share);
}
- \OC_Hook::emit('OCP\Share', 'post_unshareAll', array(
- 'itemType' => $itemType,
- 'itemSource' => $itemSource,
- 'shares' => $shares
- ));
+ \OC_Hook::emit('OCP\Share', 'post_unshareAll', $hookParams);
return true;
}
return false;
}
/**
- * @brief 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
- *
- */
+ * 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) {
if ($item = self::getItemSharedWith($itemType, $itemTarget)) {
if ((int)$item['share_type'] === self::SHARE_TYPE_GROUP) {
@@ -633,16 +708,37 @@ class Share {
}
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);
+ }
+ }
/**
- * @brief 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
- */
+ * 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)) {
@@ -718,6 +814,13 @@ class Share {
throw new \Exception($message);
}
+ /**
+ * Set expiration date for a share
+ * @param string $itemType
+ * @param string $itemSource
+ * @param string $date expiration date
+ * @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)) {
@@ -726,11 +829,12 @@ class Share {
$date = null;
} else {
$date = new \DateTime($date);
- $date = date('Y-m-d H:i', $date->format('U') - $date->getOffset());
}
$query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `expiration` = ? WHERE `id` = ?');
+ $query->bindValue(1, $date, 'datetime');
foreach ($items as $item) {
- $query->execute(array($date, $item['id']));
+ $query->bindValue(2, (int) $item['id']);
+ $query->execute();
}
return true;
}
@@ -739,11 +843,51 @@ class Share {
}
/**
- * @brief Get the backend class for the specified item type
- * @param string Item type
- * @return Sharing backend object
- */
- private static function getBackend($itemType) {
+ * 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);
+ }
+
+ /**
+ * Get the backend class for the specified item type
+ * @param string $itemType
+ * @return Share_Backend
+ */
+ public static function getBackend($itemType) {
if (isset(self::$backends[$itemType])) {
return self::$backends[$itemType];
} else if (isset(self::$backendTypes[$itemType]['class'])) {
@@ -768,12 +912,11 @@ class Share {
}
/**
- * @brief Check if resharing is allowed
- * @return Returns true if allowed or false
- *
- * Resharing is allowed by default if not configured
- *
- */
+ * 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') {
@@ -786,10 +929,10 @@ class Share {
}
/**
- * @brief Get a list of collection item types for the specified item type
- * @param string Item type
- * @return array
- */
+ * 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) {
@@ -810,24 +953,26 @@ class Share {
}
/**
- * @brief 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)
- * @return mixed
- *
- * See public functions getItem(s)... for parameter usage
- *
- */
+ * 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) {
+ $includeCollections = false, $itemShareWithBySource = false, $checkExpireDate = true) {
if (!self::isEnabled()) {
if ($limit == 1 || (isset($uidOwner) && isset($item))) {
return false;
@@ -840,7 +985,11 @@ class Share {
// 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') {
- $root = \OC\Files\Filesystem::getRoot();
+ 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';
@@ -865,6 +1014,10 @@ class Share {
$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)) {
@@ -958,20 +1111,20 @@ class Share {
// TODO Optimize selects
if ($format == self::FORMAT_STATUSES) {
if ($itemType == 'file' || $itemType == 'folder') {
- $select = '`*PREFIX*share`.`id`, `item_type`, `*PREFIX*share`.`parent`,'
- .' `share_type`, `file_source`, `path`, `expiration`, `storage`';
+ $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`, `expiration`';
+ $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`, `*PREFIX*share`.`parent`,'
+ $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `*PREFIX*share`.`parent`,'
.' `share_type`, `share_with`, `file_source`, `path`, `permissions`, `stime`,'
- .' `expiration`, `token`, `storage`';
+ .' `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`';
+ .' `stime`, `file_source`, `expiration`, `token`, `mail_send`, `uid_owner`';
}
} else {
if ($fileDependent) {
@@ -979,14 +1132,14 @@ class Share {
&& $format == \OC_Share_Backend_File::FORMAT_GET_FOLDER_CONTENTS
|| $format == \OC_Share_Backend_File::FORMAT_FILE_APP_ROOT
) {
- $select = '`*PREFIX*share`.`id`, `item_type`, `*PREFIX*share`.`parent`, `uid_owner`, '
+ $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`, `encrypted`, `etag`';
+ .'`name`, `mtime`, `mimetype`, `mimepart`, `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`';
+ `file_source`, `path`, `file_target`, `permissions`, `stime`, `expiration`, `token`, `storage`, `mail_send`';
}
} else {
$select = '*';
@@ -1085,10 +1238,8 @@ class Share {
}
}
}
- if (isset($row['expiration'])) {
- $time = new \DateTime();
- if ($row['expiration'] < date('Y-m-d H:i', $time->format('U') - $time->getOffset())) {
- self::delete($row['id']);
+ if($checkExpireDate) {
+ if (self::expireItem($row)) {
continue;
}
}
@@ -1211,30 +1362,35 @@ class Share {
}
/**
- * @brief 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 int CRUDS permissions
- * @param bool|array Parent folder target (optional)
- * @return bool Returns true on success or false on failure
- */
+ * 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) {
+ $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 '.$itemSource.' failed, because the user '.$shareWith.' is the original sharer';
+ $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 '.$itemSource
+ $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);
@@ -1248,7 +1404,7 @@ class Share {
$filePath = $checkReshare['file_target'];
}
} else {
- $message = 'Sharing '.$itemSource.' failed, because resharing is not allowed';
+ $message = 'Sharing '.$itemSourceName.' failed, because resharing is not allowed';
\OC_Log::write('OCP\Share', $message, \OC_Log::ERROR);
throw new \Exception($message);
}
@@ -1303,11 +1459,11 @@ class Share {
'run' => &$run,
'error' => &$error
));
-
+
if ($run === false) {
throw new \Exception($error);
}
-
+
if (isset($fileSource)) {
if ($parentFolder) {
if ($parentFolder === true) {
@@ -1376,6 +1532,7 @@ class Share {
'id' => $parent,
'token' => $token
));
+
if ($parentFolder === true) {
// Return parent folders to preserve file target paths for potential children
return $parentFolders;
@@ -1398,11 +1555,11 @@ class Share {
'run' => &$run,
'error' => &$error
));
-
+
if ($run === false) {
throw new \Exception($error);
}
-
+
if (isset($fileSource)) {
if ($parentFolder) {
if ($parentFolder === true) {
@@ -1447,15 +1604,16 @@ class Share {
}
/**
- * @brief 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 The suggested target originating from a reshare (optional)
- * @param int The id of the parent group share (optional)
- * @return string Item target
- */
+ * 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
+ */
private static function generateTarget($itemType, $itemSource, $shareType, $shareWith, $uidOwner,
$suggestedTarget = null, $groupParent = null) {
$backend = self::getBackend($itemType);
@@ -1563,11 +1721,11 @@ class Share {
}
/**
- * @brief 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)
- */
+ * 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);
@@ -1623,9 +1781,25 @@ class Share {
}
/**
- * Hook Listeners
- */
+ * 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`'
@@ -1639,6 +1813,11 @@ class Share {
}
}
+ /**
+ * 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` = ?');
@@ -1669,6 +1848,10 @@ class 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`'
@@ -1685,6 +1868,10 @@ class Share {
}
}
+ /**
+ * 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']));
@@ -1696,87 +1883,86 @@ class Share {
}
/**
-* Interface that apps must implement to share content.
-*/
+ * Interface that apps must implement to share content.
+ */
interface Share_Backend {
/**
- * @brief Get the source of the item to be stored in the database
- * @param string Item source
- * @param string Owner of the item
- * @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
- *
- * The formatItems() function will translate the source returned back into the item
- */
+ * Get the source of the item to be stored in the database
+ * @param string Item source
+ * @param string Owner of the item
+ * @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
+ *
+ * The formatItems() function will translate the source returned back into the item
+ */
public function isValidSource($itemSource, $uidOwner);
/**
- * @brief Get a unique name of the item for the specified user
- * @param string Item source
- * @param string|false User the item is being shared with
- * @param array|null List of similar item names already existing as shared items
- * @return string Target name
- *
- * This function needs to verify that the user does not already have an item with this name.
- * If it does generate a new name e.g. name_#
- */
+ * Get a unique name of the item for the specified user
+ * @param string Item source
+ * @param string|false User the item is being shared with
+ * @param array|null List of similar item names already existing as shared items
+ * @return string Target name
+ *
+ * This function needs to verify that the user does not already have an item with this name.
+ * If it does generate a new name e.g. name_#
+ */
public function generateTarget($itemSource, $shareWith, $exclude = null);
/**
- * @brief Converts the shared item sources back into the item in the specified format
- * @param array Shared items
- * @param int Format
- * @return ?
- *
- * The items array is a 3-dimensional array with the item_source as the
- * first key and the share id as the second key to an array with the share
- * info.
- *
- * The key/value pairs included in the share info depend on the function originally called:
- * If called by getItem(s)Shared: id, item_type, item, item_source,
- * share_type, share_with, permissions, stime, file_source
- *
- * If called by getItem(s)SharedWith: id, item_type, item, item_source,
- * item_target, share_type, share_with, permissions, stime, file_source,
- * file_target
- *
- * This function allows the backend to control the output of shared items with custom formats.
- * It is only called through calls to the public getItem(s)Shared(With) functions.
- */
+ * Converts the shared item sources back into the item in the specified format
+ * @param array Shared items
+ * @param int Format
+ * @return TODO
+ *
+ * The items array is a 3-dimensional array with the item_source as the
+ * first key and the share id as the second key to an array with the share
+ * info.
+ *
+ * The key/value pairs included in the share info depend on the function originally called:
+ * If called by getItem(s)Shared: id, item_type, item, item_source,
+ * share_type, share_with, permissions, stime, file_source
+ *
+ * If called by getItem(s)SharedWith: id, item_type, item, item_source,
+ * item_target, share_type, share_with, permissions, stime, file_source,
+ * file_target
+ *
+ * This function allows the backend to control the output of shared items with custom formats.
+ * It is only called through calls to the public getItem(s)Shared(With) functions.
+ */
public function formatItems($items, $format, $parameters = null);
}
/**
-* Interface for share backends that share content that is dependent on files.
-* Extends the Share_Backend interface.
-*/
+ * Interface for share backends that share content that is dependent on files.
+ * Extends the Share_Backend interface.
+ */
interface Share_Backend_File_Dependent extends Share_Backend {
/**
- * @brief Get the file path of the item
- * @param
- * @param
- * @return
- */
+ * Get the file path of the item
+ * @param string Item source
+ * @param string User that is the owner of shared item
+ */
public function getFilePath($itemSource, $uidOwner);
}
/**
-* Interface for collections of of items implemented by another share backend.
-* Extends the Share_Backend interface.
-*/
+ * Interface for collections of of items implemented by another share backend.
+ * Extends the Share_Backend interface.
+ */
interface Share_Backend_Collection extends Share_Backend {
/**
- * @brief Get the sources of the children of the item
- * @param string Item source
- * @return array Returns an array of children each inside an array with the keys: source, target, and file_path if applicable
- */
+ * Get the sources of the children of the item
+ * @param string Item source
+ * @return array Returns an array of children each inside an array with the keys: source, target, and file_path if applicable
+ */
public function getChildren($itemSource);
}
diff --git a/lib/public/template.php b/lib/public/template.php
index ab1089c332d..320b7c6393f 100644
--- a/lib/public/template.php
+++ b/lib/public/template.php
@@ -1,24 +1,24 @@
<?php
/**
-* ownCloud
-*
-* @author Frank Karlitschek
-* @copyright 2012 Frank Karlitschek frank@owncloud.org
-*
-* 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/>.
-*
-*/
+ * ownCloud
+ *
+ * @author Frank Karlitschek
+ * @copyright 2012 Frank Karlitschek frank@owncloud.org
+ *
+ * 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/>.
+ *
+ */
/**
* Public interface of ownCloud for apps to use.
@@ -32,12 +32,12 @@ namespace OCP;
/**
- * @brief make OC_Helper::imagePath available as a simple function
- * @param $app app
- * @param $image image
- * @returns link to the image
+ * Make OC_Helper::imagePath available as a simple function
+ * @param string app
+ * @param string image
+ * @return link to the image
*
- * For further information have a look at OC_Helper::imagePath
+ * @see OC_Helper::imagePath
*/
function image_path( $app, $image ) {
return(\image_path( $app, $image ));
@@ -45,21 +45,39 @@ function image_path( $app, $image ) {
/**
- * @brief make OC_Helper::mimetypeIcon available as a simple function
- * Returns the path to the image of this file type.
- * @param $mimetype mimetype
- * @returns link to the image
+ * Make OC_Helper::mimetypeIcon available as a simple function
+ * @param string mimetype
+ * @return path to the image of this file type.
*/
function mimetype_icon( $mimetype ) {
return(\mimetype_icon( $mimetype ));
}
+/**
+ * Make preview_icon available as a simple function
+ * @param string path of file
+ * @return path to the preview of the image
+ */
+function preview_icon( $path ) {
+ return(\preview_icon( $path ));
+}
+
+/**
+ * Make publicpreview_icon available as a simple function
+ * Returns the path to the preview of the image.
+ * @param string path of file
+ * @param string token
+ * @return link to the preview
+ */
+function publicPreview_icon ( $path, $token ) {
+ return(\publicPreview_icon( $path, $token ));
+}
/**
- * @brief make OC_Helper::humanFileSize available as a simple function
- * Makes 2048 to 2 kB.
- * @param $bytes size in bytes
- * @returns size as string
+ * Make OC_Helper::humanFileSize available as a simple function
+ * Example: 2048 to 2 kB.
+ * @param int size in bytes
+ * @return size as string
*/
function human_file_size( $bytes ) {
return(\human_file_size( $bytes ));
@@ -67,20 +85,21 @@ function human_file_size( $bytes ) {
/**
- * @brief Return the relative date in relation to today. Returns something like "last hour" or "two month ago"
- * @param $timestamp unix timestamp
- * @returns human readable interpretation of the timestamp
+ * Return the relative date in relation to today. Returns something like "last hour" or "two month ago"
+ * @param int unix timestamp
+ * @param boolean date only
+ * @return human readable interpretation of the timestamp
*/
-function relative_modified_date($timestamp) {
- return(\relative_modified_date($timestamp));
+function relative_modified_date( $timestamp, $dateOnly = false ) {
+ return(\relative_modified_date($timestamp, null, $dateOnly));
}
/**
- * @brief DEPRECATED Return a human readable outout for a file size.
+ * Return a human readable outout for a file size.
* @deprecated human_file_size() instead
- * @param $byte size of a file in byte
- * @returns human readable interpretation of a file size
+ * @param integer size of a file in byte
+ * @return human readable interpretation of a file size
*/
function simple_file_size($bytes) {
return(\human_file_size($bytes));
@@ -88,11 +107,11 @@ function simple_file_size($bytes) {
/**
- * @brief Generate html code for an options block.
+ * Generate html code for an options block.
* @param $options the options
* @param $selected which one is selected?
- * @param $params the parameters
- * @returns html options
+ * @param array the parameters
+ * @return html options
*/
function html_select_options($options, $selected, $params=array()) {
return(\html_select_options($options, $selected, $params));
diff --git a/lib/public/user.php b/lib/public/user.php
index 23ff991642d..acc0e3b737b 100644
--- a/lib/public/user.php
+++ b/lib/public/user.php
@@ -1,28 +1,28 @@
<?php
/**
-* ownCloud
-*
-* @author Frank Karlitschek
-* @copyright 2012 Frank Karlitschek frank@owncloud.org
-*
-* 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/>.
-*
-*/
+ * ownCloud
+ *
+ * @author Frank Karlitschek
+ * @copyright 2012 Frank Karlitschek frank@owncloud.org
+ *
+ * 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/>.
+ *
+ */
/**
* Public interface of ownCloud for apps to use.
- * User Class.
+ * User Class
*
*/
@@ -36,7 +36,7 @@ namespace OCP;
*/
class User {
/**
- * @brief get the user id of the user currently logged in.
+ * Get the user id of the user currently logged in.
* @return string uid or false
*/
public static function getUser() {
@@ -44,45 +44,46 @@ class User {
}
/**
- * @brief Get a list of all users
- * @returns array with all uids
- *
- * Get a list of all users.
+ * Get a list of all users
+ * @param string search pattern
+ * @param int limit
+ * @param int offset
+ * @return array with all uids
*/
- public static function getUsers($search = '', $limit = null, $offset = null) {
- return \OC_User::getUsers($search, $limit, $offset);
+ public static function getUsers( $search = '', $limit = null, $offset = null ) {
+ return \OC_User::getUsers( $search, $limit, $offset );
}
/**
- * @brief get the user display name of the user currently logged in.
+ * Get the user display name of the user currently logged in.
+ * @param string user id or null for current user
* @return string display name
*/
- public static function getDisplayName($user=null) {
- return \OC_User::getDisplayName($user);
+ public static function getDisplayName( $user = null ) {
+ return \OC_User::getDisplayName( $user );
}
/**
- * @brief Get a list of all display names
- * @returns array with all display names (value) and the correspondig uids (key)
- *
* Get a list of all display names and user ids.
+ * @param string search pattern
+ * @param int limit
+ * @param int offset
+ * @return array with all display names (value) and the correspondig uids (key)
*/
- public static function getDisplayNames($search = '', $limit = null, $offset = null) {
- return \OC_User::getDisplayNames($search, $limit, $offset);
+ public static function getDisplayNames( $search = '', $limit = null, $offset = null ) {
+ return \OC_User::getDisplayNames( $search, $limit, $offset );
}
/**
- * @brief Check if the user is logged in
- * @returns true/false
- *
- * Checks if the user is logged in
+ * Check if the user is logged in
+ * @return boolean
*/
public static function isLoggedIn() {
return \OC_User::isLoggedIn();
}
/**
- * @brief check if a user exists
+ * Check if a user exists
* @param string $uid the username
* @param string $excludingBackend (default none)
* @return boolean
@@ -91,7 +92,7 @@ class User {
return \OC_User::userExists( $uid, $excludingBackend );
}
/**
- * @brief Loggs the user out including all the session data
+ * Logs the user out including all the session data
* Logout, destroys session
*/
public static function logout() {
@@ -99,10 +100,10 @@ class User {
}
/**
- * @brief Check if the password is correct
- * @param $uid The username
- * @param $password The password
- * @returns true/false
+ * Check if the password is correct
+ * @param string The username
+ * @param string The password
+ * @return mixed username on success, false otherwise
*
* Check if the password is correct without logging in the user
*/
diff --git a/lib/public/userinterface.php b/lib/public/userinterface.php
index b73a8f8d8b0..1f6c2f7292b 100644
--- a/lib/public/userinterface.php
+++ b/lib/public/userinterface.php
@@ -1,31 +1,33 @@
<?php
/**
-* ownCloud
-*
-* @author Arthur Schiwon
-* @copyright 2012 Arthur Schiwon blizzz@owncloud.org
-*
-* 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/>.
-*
-*/
+ * ownCloud
+ *
+ * @author Arthur Schiwon
+ * @copyright 2012 Arthur Schiwon blizzz@owncloud.org
+ *
+ * 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/>.
+ *
+ */
/**
* Public interface of ownCloud for apps to use.
- * User Class.
+ * User Interface
*
*/
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
namespace OCP;
-interface UserInterface extends \OC_User_Interface {} \ No newline at end of file
+interface UserInterface extends \OC_User_Interface {}
diff --git a/lib/public/util.php b/lib/public/util.php
index 693805946ea..1d76fd1e1f7 100644
--- a/lib/public/util.php
+++ b/lib/public/util.php
@@ -1,24 +1,24 @@
<?php
/**
-* ownCloud
-*
-* @author Frank Karlitschek
-* @copyright 2012 Frank Karlitschek frank@owncloud.org
-*
-* 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/>.
-*
-*/
+ * ownCloud
+ *
+ * @author Frank Karlitschek
+ * @copyright 2012 Frank Karlitschek frank@owncloud.org
+ *
+ * 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/>.
+ *
+ */
/**
* Public interface of ownCloud for apps to use.
@@ -42,7 +42,7 @@ class Util {
const FATAL=4;
/**
- * @brief get the current installed version of ownCloud
+ * get the current installed version of ownCloud
* @return array
*/
public static function getVersion() {
@@ -50,7 +50,7 @@ class Util {
}
/**
- * @brief send an email
+ * send an email
* @param string $toaddress
* @param string $toname
* @param string $subject
@@ -58,6 +58,10 @@ class Util {
* @param string $fromaddress
* @param string $fromname
* @param bool $html
+ * @param string $altbody
+ * @param string $ccaddress
+ * @param string $ccname
+ * @param string $bcc
*/
public static function sendMail( $toaddress, $toname, $subject, $mailtext, $fromaddress, $fromname,
$html = 0, $altbody = '', $ccaddress = '', $ccname = '', $bcc = '') {
@@ -67,7 +71,7 @@ class Util {
}
/**
- * @brief write a message in the log
+ * write a message in the log
* @param string $app
* @param string $message
* @param int $level
@@ -78,8 +82,42 @@ class Util {
}
/**
- * @brief get l10n object
- * @param string $app
+ * write exception into the log. Include the stack trace
+ * if DEBUG mode is enabled
+ * @param string $app app name
+ * @param Exception $ex exception to log
+ */
+ public static function logException( $app, \Exception $ex ) {
+ $message = $ex->getMessage();
+ if ($ex->getCode()) {
+ $message .= ' [' . $ex->getCode() . ']';
+ }
+ \OCP\Util::writeLog($app, 'Exception: ' . $message, \OCP\Util::FATAL);
+ if (defined('DEBUG') and DEBUG) {
+ // also log stack trace
+ $stack = explode('#', $ex->getTraceAsString());
+ // first element is empty
+ array_shift($stack);
+ foreach ($stack as $s) {
+ \OCP\Util::writeLog($app, 'Exception: ' . $s, \OCP\Util::FATAL);
+ }
+
+ // include cause
+ $l = \OC_L10N::get('lib');
+ while (method_exists($ex, 'getPrevious') && $ex = $ex->getPrevious()) {
+ $message .= ' - '.$l->t('Caused by:').' ';
+ $message .= $ex->getMessage();
+ if ($ex->getCode()) {
+ $message .= '[' . $ex->getCode() . '] ';
+ }
+ \OCP\Util::writeLog($app, 'Exception: ' . $message, \OCP\Util::FATAL);
+ }
+ }
+ }
+
+ /**
+ * get l10n object
+ * @param string $application
* @return OC_L10N
*/
public static function getL10N( $application ) {
@@ -87,24 +125,25 @@ class Util {
}
/**
- * @brief add a css file
- * @param string $url
+ * add a css file
+ * @param string $application
+ * @param string $file
*/
public static function addStyle( $application, $file = null ) {
\OC_Util::addStyle( $application, $file );
}
/**
- * @brief add a javascript file
+ * add a javascript file
* @param string $application
- * @param string $file
+ * @param string $file
*/
public static function addScript( $application, $file = null ) {
\OC_Util::addScript( $application, $file );
}
/**
- * @brief Add a custom element to the header
+ * Add a custom element to the header
* @param string $tag tag name of the element
* @param array $attributes array of attributes for the element
* @param string $text the text content for the element
@@ -114,7 +153,7 @@ class Util {
}
/**
- * @brief formats a timestamp in the "right" way
+ * formats a timestamp in the "right" way
* @param int $timestamp $timestamp
* @param bool $dateOnly option to omit time from the result
*/
@@ -123,85 +162,78 @@ class Util {
}
/**
- * @brief Creates an absolute url
+ * check if some encrypted files are stored
+ * @return bool
+ */
+ public static function encryptedFiles() {
+ return \OC_Util::encryptedFiles();
+ }
+
+ /**
+ * Creates an absolute url to the given app and file.
* @param string $app app
* @param string $file file
* @param array $args array with param=>value, will be appended to the returned url
* The value of $args will be urlencoded
- * @returns string the url
- *
- * Returns a absolute url to the given app and file.
+ * @return string the url
*/
public static function linkToAbsolute( $app, $file, $args = array() ) {
return(\OC_Helper::linkToAbsolute( $app, $file, $args ));
}
/**
- * @brief Creates an absolute url for remote use
+ * Creates an absolute url for remote use.
* @param string $service id
- * @returns string the url
- *
- * Returns a absolute url to the given app and file.
+ * @return string the url
*/
public static function linkToRemote( $service ) {
return(\OC_Helper::linkToRemote( $service ));
}
/**
- * @brief Creates an absolute url for public use
+ * Creates an absolute url for public use
* @param string $service id
- * @returns string the url
- *
- * Returns a absolute url to the given app and file.
+ * @return string the url
*/
public static function linkToPublic($service) {
return \OC_Helper::linkToPublic($service);
}
/**
- * @brief Creates an url using a defined route
+ * Creates an url using a defined route
* @param $route
* @param array $parameters
* @return
* @internal param array $args with param=>value, will be appended to the returned url
- * @returns the url
- *
- * Returns a url to the given app and file.
+ * @return the url
*/
public static function linkToRoute( $route, $parameters = array() ) {
return \OC_Helper::linkToRoute($route, $parameters);
}
/**
- * @brief Creates an url
+ * Creates an url to the given app and file
* @param string $app app
* @param string $file file
* @param array $args array with param=>value, will be appended to the returned url
* The value of $args will be urlencoded
- * @returns string the url
- *
- * Returns a url to the given app and file.
+ * @return string the url
*/
public static function linkTo( $app, $file, $args = array() ) {
return(\OC_Helper::linkTo( $app, $file, $args ));
}
/**
- * @brief Returns the server host
- * @returns string the server host
- *
- * Returns the server host, even if the website uses one or more
- * reverse proxies
+ * Returns the server host, even if the website uses one or more reverse proxy
+ * @return string the server host
*/
public static function getServerHost() {
return(\OC_Request::serverHost());
}
/**
- * @brief returns the server hostname
- * @returns string the server hostname
- *
* Returns the server host name without an eventual port number
+ * @return string the server hostname
*/
public static function getServerHostName() {
$host_name = self::getServerHost();
@@ -214,9 +246,9 @@ class Util {
}
/**
- * @brief Returns the default email address
+ * Returns the default email address
* @param string $user_part the user part of the address
- * @returns string the default email address
+ * @return string the default email address
*
* Assembles a default email address (using the server hostname
* and the given user part, and returns it
@@ -238,66 +270,54 @@ class Util {
}
/**
- * @brief Returns the server protocol
- * @returns string the server protocol
- *
* Returns the server protocol. It respects reverse proxy servers and load balancers
+ * @return string the server protocol
*/
public static function getServerProtocol() {
return(\OC_Request::serverProtocol());
}
/**
- * @brief Returns the request uri
- * @returns the request uri
+ * Returns the request uri, even if the website uses one or more reverse proxies
*
- * Returns the request uri, even if the website uses one or more
- * reverse proxies
+ * @return the request uri
*/
public static function getRequestUri() {
return(\OC_Request::requestUri());
}
/**
- * @brief Returns the script name
- * @returns the script name
+ * Returns the script name, even if the website uses one or more reverse proxies
*
- * Returns the script name, even if the website uses one or more
- * reverse proxies
+ * @return the script name
*/
public static function getScriptName() {
return(\OC_Request::scriptName());
}
/**
- * @brief Creates path to an image
+ * Creates path to an image
* @param string $app app
* @param string $image image name
- * @returns string the url
- *
- * Returns the path to the image.
+ * @return string the url
*/
public static function imagePath( $app, $image ) {
return(\OC_Helper::imagePath( $app, $image ));
}
/**
- * @brief Make a human file size
+ * Make a human file size (2048 to 2 kB)
* @param int $bytes file size in bytes
- * @returns string a human readable file size
- *
- * Makes 2048 to 2 kB.
+ * @return string a human readable file size
*/
public static function humanFileSize( $bytes ) {
return(\OC_Helper::humanFileSize( $bytes ));
}
/**
- * @brief Make a computer file size
+ * Make a computer file size (2 kB to 2048)
* @param string $str file size in a fancy format
- * @returns int a file size in bytes
- *
- * Makes 2kB to 2048.
+ * @return int a file size in bytes
*
* Inspired by: http://www.php.net/manual/en/function.filesize.php#92418
*/
@@ -306,12 +326,12 @@ class Util {
}
/**
- * @brief connects a function to a hook
+ * connects a function to a hook
* @param string $signalclass class name of emitter
* @param string $signalname name of signal
* @param string $slotclass class name of slot
* @param string $slotname name of slot
- * @returns bool
+ * @return bool
*
* This function makes it very easy to connect to use hooks.
*
@@ -322,13 +342,11 @@ class Util {
}
/**
- * @brief emitts a signal
+ * Emits a signal. To get data from the slot use references!
* @param string $signalclass class name of emitter
* @param string $signalname name of signal
* @param string $params defautl: array() array with additional data
- * @returns bool true if slots exists or false if not
- *
- * Emits a signal. To get data from the slot use references!
+ * @return bool true if slots exists or false if not
*
* TODO: write example
*/
@@ -353,7 +371,7 @@ class Util {
}
/**
- * @brief Used to sanitize HTML
+ * Used to sanitize HTML
*
* This function is used to sanitize HTML and should be applied on any
* string or array of strings before displaying it on a web page.
@@ -364,78 +382,75 @@ class Util {
public static function sanitizeHTML( $value ) {
return(\OC_Util::sanitizeHTML($value));
}
-
+
/**
- * @brief Public function to encode url parameters
+ * Public function to encode url parameters
*
* This function is used to encode path to file before output.
* Encoding is done according to RFC 3986 with one exception:
- * Character '/' is preserved as is.
+ * Character '/' is preserved as is.
*
* @param string $component part of URI to encode
- * @return string
+ * @return string
*/
public static function encodePath($component) {
return(\OC_Util::encodePath($component));
}
/**
- * @brief Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is.
- *
- * @param array $input The array to work on
- * @param int $case Either MB_CASE_UPPER or MB_CASE_LOWER (default)
- * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
- * @return array
- *
- *
- */
+ * Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is.
+ *
+ * @param array $input The array to work on
+ * @param int $case Either MB_CASE_UPPER or MB_CASE_LOWER (default)
+ * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
+ * @return array
+ */
public static function mb_array_change_key_case($input, $case = MB_CASE_LOWER, $encoding = 'UTF-8') {
return(\OC_Helper::mb_array_change_key_case($input, $case, $encoding));
}
/**
- * @brief replaces a copy of string delimited by the start and (optionally) length parameters with the string given in replacement.
- *
- * @param string $input The input string. .Opposite to the PHP build-in function does not accept an array.
- * @param string $replacement The replacement string.
- * @param int $start If start is positive, the replacing will begin at the start'th offset into string. If start is negative, the replacing will begin at the start'th character from the end of string.
- * @param int $length Length of the part to be replaced
- * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
- * @return string
- *
- */
+ * replaces a copy of string delimited by the start and (optionally) length parameters with the string given in replacement.
+ *
+ * @param string $string The input string. Opposite to the PHP build-in function does not accept an array.
+ * @param string $replacement The replacement string.
+ * @param int $start If start is positive, the replacing will begin at the start'th offset into string. If start is negative, the replacing will begin at the start'th character from the end of string.
+ * @param int $length Length of the part to be replaced
+ * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
+ * @return string
+ */
public static function mb_substr_replace($string, $replacement, $start, $length = null, $encoding = 'UTF-8') {
return(\OC_Helper::mb_substr_replace($string, $replacement, $start, $length, $encoding));
}
/**
- * @brief Replace all occurrences of the search string with the replacement string
- *
- * @param string $search The value being searched for, otherwise known as the needle. String.
- * @param string $replace The replacement string.
- * @param string $subject The string or array being searched and replaced on, otherwise known as the haystack.
- * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
- * @param int $count If passed, this will be set to the number of replacements performed.
- * @return string
- *
- */
+ * Replace all occurrences of the search string with the replacement string
+ *
+ * @param string $search The value being searched for, otherwise known as the needle. String.
+ * @param string $replace The replacement string.
+ * @param string $subject The string or array being searched and replaced on, otherwise known as the haystack.
+ * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
+ * @param int $count If passed, this will be set to the number of replacements performed.
+ * @return string
+ */
public static function mb_str_replace($search, $replace, $subject, $encoding = 'UTF-8', &$count = null) {
return(\OC_Helper::mb_str_replace($search, $replace, $subject, $encoding, $count));
}
/**
- * @brief performs a search in a nested array
- * @param array $haystack the array to be searched
- * @param string $needle the search string
- * @param int $index optional, only search this key name
- * @return mixed the key of the matching field, otherwise false
- */
+ * performs a search in a nested array
+ *
+ * @param array $haystack the array to be searched
+ * @param string $needle the search string
+ * @param int $index optional, only search this key name
+ * @return mixed the key of the matching field, otherwise false
+ */
public static function recursiveArraySearch($haystack, $needle, $index = null) {
return(\OC_Helper::recursiveArraySearch($haystack, $needle, $index));
}
/**
- * @brief calculates the maximum upload size respecting system settings, free space and user quota
+ * calculates the maximum upload size respecting system settings, free space and user quota
*
* @param $dir the current folder where the user currently operates
* @return number of bytes representing
diff --git a/lib/util.php b/lib/util.php
deleted file mode 100755
index b9d678dced8..00000000000
--- a/lib/util.php
+++ /dev/null
@@ -1,908 +0,0 @@
-<?php
-
-/**
- * Class for utility functions
- *
- */
-
-class OC_Util {
- public static $scripts=array();
- public static $styles=array();
- public static $headers=array();
- private static $rootMounted=false;
- private static $fsSetup=false;
- public static $core_styles=array();
- public static $core_scripts=array();
-
- // Can be set up
- public static function setupFS( $user = '' ) {// configure the initial filesystem based on the configuration
- if(self::$fsSetup) {//setting up the filesystem twice can only lead to trouble
- return false;
- }
-
- // If we are not forced to load a specific user we load the one that is logged in
- if( $user == "" && OC_User::isLoggedIn()) {
- $user = OC_User::getUser();
- }
-
- // load all filesystem apps before, so no setup-hook gets lost
- if(!isset($RUNTIME_NOAPPS) || !$RUNTIME_NOAPPS) {
- 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
- // OC_Filesystem
- if ($user != '') {
- self::$fsSetup=true;
- }
-
- $CONFIG_DATADIRECTORY = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" );
- //first set up the local "root" storage
- \OC\Files\Filesystem::initMounts();
- if(!self::$rootMounted) {
- \OC\Files\Filesystem::mount('\OC\Files\Storage\Local', array('datadir'=>$CONFIG_DATADIRECTORY), '/');
- self::$rootMounted=true;
- }
-
- if( $user != "" ) { //if we aren't logged in, there is no use to set up the filesystem
- $user_dir = '/'.$user.'/files';
- $user_root = OC_User::getHome($user);
- $userdirectory = $user_root . '/files';
- if( !is_dir( $userdirectory )) {
- mkdir( $userdirectory, 0755, true );
- }
- //jail the user into his "home" directory
- \OC\Files\Filesystem::init($user, $user_dir);
-
- $quotaProxy=new OC_FileProxy_Quota();
- $fileOperationProxy = new OC_FileProxy_FileOperations();
- OC_FileProxy::register($quotaProxy);
- OC_FileProxy::register($fileOperationProxy);
-
- OC_Hook::emit('OC_Filesystem', 'setup', array('user' => $user, 'user_dir' => $user_dir));
- }
- return true;
- }
-
- public static function tearDownFS() {
- \OC\Files\Filesystem::tearDown();
- self::$fsSetup=false;
- self::$rootMounted=false;
- }
-
- /**
- * get the current installed version of ownCloud
- * @return array
- */
- public static function getVersion() {
- // hint: We only can count up. Reset minor/patchlevel when
- // updating major/minor version number.
- return array(5, 80, 05);
- }
-
- /**
- * get the current installed version string of ownCloud
- * @return string
- */
- public static function getVersionString() {
- return '6.0 pre alpha';
- }
-
- /**
- * get the current installed edition of ownCloud. There is the community
- * edition that just returns an empty string and the enterprise edition
- * that returns "Enterprise".
- * @return string
- */
- public static function getEditionString() {
- return '';
- }
-
- /**
- * add a javascript file
- *
- * @param appid $application
- * @param filename $file
- */
- public static function addScript( $application, $file = null ) {
- if( is_null( $file )) {
- $file = $application;
- $application = "";
- }
- if( !empty( $application )) {
- self::$scripts[] = "$application/js/$file";
- }else{
- self::$scripts[] = "js/$file";
- }
- }
-
- /**
- * add a css file
- *
- * @param appid $application
- * @param filename $file
- */
- public static function addStyle( $application, $file = null ) {
- if( is_null( $file )) {
- $file = $application;
- $application = "";
- }
- if( !empty( $application )) {
- self::$styles[] = "$application/css/$file";
- }else{
- self::$styles[] = "css/$file";
- }
- }
-
- /**
- * @brief Add a custom element to the header
- * @param string tag tag name of the element
- * @param array $attributes array of attributes for the element
- * @param string $text the text content for the element
- */
- public static function addHeader( $tag, $attributes, $text='') {
- self::$headers[] = array('tag'=>$tag, 'attributes'=>$attributes, 'text'=>$text);
- }
-
- /**
- * formats a timestamp in the "right" way
- *
- * @param int timestamp $timestamp
- * @param bool dateOnly option to omit time from the result
- */
- public static function formatDate( $timestamp, $dateOnly=false) {
- if(\OC::$session->exists('timezone')) {//adjust to clients timezone if we know it
- $systemTimeZone = intval(date('O'));
- $systemTimeZone=(round($systemTimeZone/100, 0)*60)+($systemTimeZone%100);
- $clientTimeZone=\OC::$session->get('timezone')*60;
- $offset=$clientTimeZone-$systemTimeZone;
- $timestamp=$timestamp+$offset*60;
- }
- $l=OC_L10N::get('lib');
- return $l->l($dateOnly ? 'date' : 'datetime', $timestamp);
- }
-
- /**
- * check if the current server configuration is suitable for ownCloud
- * @return array arrays with error messages and hints
- */
- public static function checkServer() {
- $errors=array();
-
- $defaults = new \OC_Defaults();
-
- $web_server_restart= false;
- //check for database drivers
- if(!(is_callable('sqlite_open') or class_exists('SQLite3'))
- and !is_callable('mysql_connect')
- and !is_callable('pg_connect')
- and !is_callable('oci_connect')) {
- $errors[]=array('error'=>'No database drivers (sqlite, mysql, or postgresql) installed.',
- 'hint'=>'');//TODO: sane hint
- $web_server_restart= true;
- }
-
- //common hint for all file permissons error messages
- $permissionsHint = 'Permissions can usually be fixed by '
- .'<a href="' . $defaults->getDocBaseUrl() . '/server/5.0/admin_manual/installation/installation_source.html#set-the-directory-permissions" target="_blank">giving the webserver write access to the root directory</a>.';
-
- // Check if config folder is writable.
- if(!is_writable(OC::$SERVERROOT."/config/") or !is_readable(OC::$SERVERROOT."/config/")) {
- $errors[] = array(
- 'error' => "Can't write into config directory",
- 'hint' => 'This can usually be fixed by '
- .'<a href="' . $defaults->getDocBaseUrl() . '/server/5.0/admin_manual/installation/installation_source.html#set-the-directory-permissions" target="_blank">giving the webserver write access to the config directory</a>.'
- );
- }
-
- // Check if there is a writable install folder.
- if(OC_Config::getValue('appstoreenabled', true)) {
- if( OC_App::getInstallPath() === null
- || !is_writable(OC_App::getInstallPath())
- || !is_readable(OC_App::getInstallPath()) ) {
- $errors[] = array(
- 'error' => "Can't write into apps directory",
- 'hint' => 'This can usually be fixed by '
- .'<a href="' . $defaults->getDocBaseUrl() . '/server/5.0/admin_manual/installation/installation_source.html#set-the-directory-permissions" target="_blank">giving the webserver write access to the apps directory</a> '
- .'or disabling the appstore in the config file.'
- );
- }
- }
- $CONFIG_DATADIRECTORY = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" );
- // Create root dir.
- if(!is_dir($CONFIG_DATADIRECTORY)) {
- $success=@mkdir($CONFIG_DATADIRECTORY);
- if ($success) {
- $errors = array_merge($errors, self::checkDataDirectoryPermissions($CONFIG_DATADIRECTORY));
- } else {
- $errors[] = array(
- 'error' => "Can't create data directory (".$CONFIG_DATADIRECTORY.")",
- 'hint' => 'This can usually be fixed by '
- .'<a href="' . $defaults->getDocBaseUrl() . '/server/5.0/admin_manual/installation/installation_source.html#set-the-directory-permissions" target="_blank">giving the webserver write access to the root directory</a>.'
- );
- }
- } else if(!is_writable($CONFIG_DATADIRECTORY) or !is_readable($CONFIG_DATADIRECTORY)) {
- $errors[]=array('error'=>'Data directory ('.$CONFIG_DATADIRECTORY.') not writable by ownCloud',
- 'hint'=>$permissionsHint);
- } else {
- $errors = array_merge($errors, self::checkDataDirectoryPermissions($CONFIG_DATADIRECTORY));
- }
- // check if all required php modules are present
- if(!class_exists('ZipArchive')) {
- $errors[]=array('error'=>'PHP module zip not installed.',
- 'hint'=>'Please ask your server administrator to install the module.');
- $web_server_restart=true;
- }
- if(!class_exists('DOMDocument')) {
- $errors[] = array('error' => 'PHP module dom not installed.',
- 'hint' => 'Please ask your server administrator to install the module.');
- $web_server_restart =true;
- }
- if(!function_exists('xml_parser_create')) {
- $errors[] = array('error' => 'PHP module libxml not installed.',
- 'hint' => 'Please ask your server administrator to install the module.');
- $web_server_restart =true;
- }
- if(!function_exists('mb_detect_encoding')) {
- $errors[]=array('error'=>'PHP module mb multibyte not installed.',
- 'hint'=>'Please ask your server administrator to install the module.');
- $web_server_restart=true;
- }
- if(!function_exists('ctype_digit')) {
- $errors[]=array('error'=>'PHP module ctype is not installed.',
- 'hint'=>'Please ask your server administrator to install the module.');
- $web_server_restart=true;
- }
- if(!function_exists('json_encode')) {
- $errors[]=array('error'=>'PHP module JSON is not installed.',
- 'hint'=>'Please ask your server administrator to install the module.');
- $web_server_restart=true;
- }
- if(!extension_loaded('gd') || !function_exists('gd_info')) {
- $errors[]=array('error'=>'PHP module GD is not installed.',
- 'hint'=>'Please ask your server administrator to install the module.');
- $web_server_restart=true;
- }
- if(!function_exists('gzencode')) {
- $errors[]=array('error'=>'PHP module zlib is not installed.',
- 'hint'=>'Please ask your server administrator to install the module.');
- $web_server_restart=true;
- }
- if(!function_exists('iconv')) {
- $errors[]=array('error'=>'PHP module iconv is not installed.',
- 'hint'=>'Please ask your server administrator to install the module.');
- $web_server_restart=true;
- }
- if(!function_exists('simplexml_load_string')) {
- $errors[]=array('error'=>'PHP module SimpleXML is not installed.',
- 'hint'=>'Please ask your server administrator to install the module.');
- $web_server_restart=true;
- }
- if(floatval(phpversion())<5.3) {
- $errors[]=array('error'=>'PHP 5.3 is required.',
- 'hint'=>'Please ask your server administrator to update PHP to version 5.3 or higher.'
- .' PHP 5.2 is no longer supported by ownCloud and the PHP community.');
- $web_server_restart=true;
- }
- if(!defined('PDO::ATTR_DRIVER_NAME')) {
- $errors[]=array('error'=>'PHP PDO module is not installed.',
- 'hint'=>'Please ask your server administrator to install the module.');
- $web_server_restart=true;
- }
- if (((strtolower(@ini_get('safe_mode')) == 'on')
- || (strtolower(@ini_get('safe_mode')) == 'yes')
- || (strtolower(@ini_get('safe_mode')) == 'true')
- || (ini_get("safe_mode") == 1 ))) {
- $errors[]=array('error'=>'PHP Safe Mode is enabled. ownCloud requires that it is disabled to work properly.',
- 'hint'=>'PHP Safe Mode is a deprecated and mostly useless setting that should be disabled. Please ask your server administrator to disable it in php.ini or in your webserver config.');
- $web_server_restart=true;
- }
- if (get_magic_quotes_gpc() == 1 ) {
- $errors[]=array('error'=>'Magic Quotes is enabled. ownCloud requires that it is disabled to work properly.',
- 'hint'=>'Magic Quotes is a deprecated and mostly useless setting that should be disabled. Please ask your server administrator to disable it in php.ini or in your webserver config.');
- $web_server_restart=true;
- }
-
- if($web_server_restart) {
- $errors[]=array('error'=>'PHP modules have been installed, but they are still listed as missing?',
- 'hint'=>'Please ask your server administrator to restart the web server.');
- }
-
- return $errors;
- }
-
- /**
- * Check for correct file permissions of data directory
- * @return array arrays with error messages and hints
- */
- public static function checkDataDirectoryPermissions($dataDirectory) {
- $errors = array();
- if (stristr(PHP_OS, 'WIN')) {
- //TODO: permissions checks for windows hosts
- } else {
- $permissionsModHint = 'Please change the permissions to 0770 so that the directory'
- .' cannot be listed by other users.';
- $prems = substr(decoct(@fileperms($dataDirectory)), -3);
- if (substr($prems, -1) != '0') {
- OC_Helper::chmodr($dataDirectory, 0770);
- clearstatcache();
- $prems = substr(decoct(@fileperms($dataDirectory)), -3);
- if (substr($prems, 2, 1) != '0') {
- $errors[] = array('error' => 'Data directory ('.$dataDirectory.') is readable for other users',
- 'hint' => $permissionsModHint);
- }
- }
- }
- return $errors;
- }
-
- public static function displayLoginPage($errors = array()) {
- $parameters = array();
- foreach( $errors as $key => $value ) {
- $parameters[$value] = true;
- }
- if (!empty($_POST['user'])) {
- $parameters["username"] = $_POST['user'];
- $parameters['user_autofocus'] = false;
- } else {
- $parameters["username"] = '';
- $parameters['user_autofocus'] = true;
- }
- if (isset($_REQUEST['redirect_url'])) {
- $redirect_url = $_REQUEST['redirect_url'];
- $parameters['redirect_url'] = urlencode($redirect_url);
- }
-
- $parameters['alt_login'] = OC_App::getAlternativeLogIns();
- OC_Template::printGuestPage("", "login", $parameters);
- }
-
-
- /**
- * Check if the app is enabled, redirects to home if not
- */
- public static function checkAppEnabled($app) {
- if( !OC_App::isEnabled($app)) {
- header( 'Location: '.OC_Helper::linkToAbsolute( '', 'index.php' ));
- exit();
- }
- }
-
- /**
- * Check if the user is logged in, redirects to home if not. With
- * redirect URL parameter to the request URI.
- */
- public static function checkLoggedIn() {
- // Check if we are a user
- if( !OC_User::isLoggedIn()) {
- header( 'Location: '.OC_Helper::linkToAbsolute( '', 'index.php',
- array('redirect_url' => OC_Request::requestUri())));
- exit();
- }
- }
-
- /**
- * Check if the user is a admin, redirects to home if not
- */
- public static function checkAdminUser() {
- if( !OC_User::isAdminUser(OC_User::getUser())) {
- header( 'Location: '.OC_Helper::linkToAbsolute( '', 'index.php' ));
- exit();
- }
- }
-
- /**
- * Check if the user is a subadmin, redirects to home if not
- * @return array $groups where the current user is subadmin
- */
- public static function checkSubAdminUser() {
- if(!OC_SubAdmin::isSubAdmin(OC_User::getUser())) {
- header( 'Location: '.OC_Helper::linkToAbsolute( '', 'index.php' ));
- exit();
- }
- return true;
- }
-
- /**
- * Redirect to the user default page
- */
- public static function redirectToDefaultPage() {
- if(isset($_REQUEST['redirect_url'])) {
- $location = OC_Helper::makeURLAbsolute(urldecode($_REQUEST['redirect_url']));
- }
- else if (isset(OC::$REQUESTEDAPP) && !empty(OC::$REQUESTEDAPP)) {
- $location = OC_Helper::linkToAbsolute( OC::$REQUESTEDAPP, 'index.php' );
- }
- else {
- $defaultpage = OC_Appconfig::getValue('core', 'defaultpage');
- if ($defaultpage) {
- $location = OC_Helper::makeURLAbsolute(OC::$WEBROOT.'/'.$defaultpage);
- }
- else {
- $location = OC_Helper::linkToAbsolute( 'files', 'index.php' );
- }
- }
- OC_Log::write('core', 'redirectToDefaultPage: '.$location, OC_Log::DEBUG);
- header( 'Location: '.$location );
- exit();
- }
-
- /**
- * get an id unique for this instance
- * @return string
- */
- public static function getInstanceId() {
- $id = OC_Config::getValue('instanceid', null);
- if(is_null($id)) {
- // We need to guarantee at least one letter in instanceid so it can be used as the session_name
- $id = 'oc' . OC_Util::generate_random_bytes(10);
- OC_Config::setValue('instanceid', $id);
- }
- return $id;
- }
-
- /**
- * @brief Static lifespan (in seconds) when a request token expires.
- * @see OC_Util::callRegister()
- * @see OC_Util::isCallRegistered()
- * @description
- * Also required for the client side to compute the piont in time when to
- * request a fresh token. The client will do so when nearly 97% of the
- * timespan coded here has expired.
- */
- public static $callLifespan = 3600; // 3600 secs = 1 hour
-
- /**
- * @brief Register an get/post call. Important to prevent CSRF attacks.
- * @todo Write howto: CSRF protection guide
- * @return $token Generated token.
- * @description
- * Creates a 'request token' (random) and stores it inside the session.
- * Ever subsequent (ajax) request must use such a valid token to succeed,
- * otherwise the request will be denied as a protection against CSRF.
- * The tokens expire after a fixed lifespan.
- * @see OC_Util::$callLifespan
- * @see OC_Util::isCallRegistered()
- */
- public static function callRegister() {
- // Check if a token exists
- if(!\OC::$session->exists('requesttoken')) {
- // No valid token found, generate a new one.
- $requestToken = self::generate_random_bytes(20);
- \OC::$session->set('requesttoken', $requestToken);
- } else {
- // Valid token already exists, send it
- $requestToken = \OC::$session->get('requesttoken');
- }
- return($requestToken);
- }
-
- /**
- * @brief Check an ajax get/post call if the request token is valid.
- * @return boolean False if request token is not set or is invalid.
- * @see OC_Util::$callLifespan
- * @see OC_Util::callRegister()
- */
- public static function isCallRegistered() {
- if(!\OC::$session->exists('requesttoken')) {
- return false;
- }
-
- if(isset($_GET['requesttoken'])) {
- $token=$_GET['requesttoken'];
- } elseif(isset($_POST['requesttoken'])) {
- $token=$_POST['requesttoken'];
- } elseif(isset($_SERVER['HTTP_REQUESTTOKEN'])) {
- $token=$_SERVER['HTTP_REQUESTTOKEN'];
- } else {
- //no token found.
- return false;
- }
-
- // Check if the token is valid
- if($token !== \OC::$session->get('requesttoken')) {
- // Not valid
- return false;
- } else {
- // Valid token
- return true;
- }
- }
-
- /**
- * @brief Check an ajax get/post call if the request token is valid. exit if not.
- * Todo: Write howto
- */
- public static function callCheck() {
- if(!OC_Util::isCallRegistered()) {
- exit;
- }
- }
-
- /**
- * @brief Public function to sanitize HTML
- *
- * This function is used to sanitize HTML and should be applied on any
- * string or array of strings before displaying it on a web page.
- *
- * @param string or array of strings
- * @return array with sanitized strings or a single sanitized string, depends on the input parameter.
- */
- public static function sanitizeHTML( &$value ) {
- if (is_array($value)) {
- array_walk_recursive($value, 'OC_Util::sanitizeHTML');
- } else {
- $value = htmlentities((string)$value, ENT_QUOTES, 'UTF-8'); //Specify encoding for PHP<5.4
- }
- return $value;
- }
-
- /**
- * @brief Public function to encode url parameters
- *
- * This function is used to encode path to file before output.
- * Encoding is done according to RFC 3986 with one exception:
- * Character '/' is preserved as is.
- *
- * @param string $component part of URI to encode
- * @return string
- */
- public static function encodePath($component) {
- $encoded = rawurlencode($component);
- $encoded = str_replace('%2F', '/', $encoded);
- return $encoded;
- }
-
- /**
- * Check if the htaccess file is working by creating a test file in the data directory and trying to access via http
- */
- public static function ishtaccessworking() {
- // testdata
- $filename='/htaccesstest.txt';
- $testcontent='testcontent';
-
- // creating a test file
- $testfile = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" ).'/'.$filename;
-
- if(file_exists($testfile)) {// already running this test, possible recursive call
- return false;
- }
-
- $fp = @fopen($testfile, 'w');
- @fwrite($fp, $testcontent);
- @fclose($fp);
-
- // accessing the file via http
- $url = OC_Helper::makeURLAbsolute(OC::$WEBROOT.'/data'.$filename);
- $fp = @fopen($url, 'r');
- $content=@fread($fp, 2048);
- @fclose($fp);
-
- // cleanup
- @unlink($testfile);
-
- // does it work ?
- if($content==$testcontent) {
- return(false);
- }else{
- return(true);
- }
- }
-
- /**
- * we test if webDAV is working properly
- *
- * The basic assumption is that if the server returns 401/Not Authenticated for an unauthenticated PROPFIND
- * the web server it self is setup properly.
- *
- * Why not an authenticated PROFIND and other verbs?
- * - We don't have the password available
- * - We have no idea about other auth methods implemented (e.g. OAuth with Bearer header)
- *
- */
- public static function isWebDAVWorking() {
- if (!function_exists('curl_init')) {
- return true;
- }
- $settings = array(
- 'baseUri' => OC_Helper::linkToRemote('webdav'),
- );
-
- // save the old timeout so that we can restore it later
- $old_timeout=ini_get("default_socket_timeout");
-
- // use a 5 sec timeout for the check. Should be enough for local requests.
- ini_set("default_socket_timeout", 5);
-
- $client = new \Sabre_DAV_Client($settings);
-
- // for this self test we don't care if the ssl certificate is self signed and the peer cannot be verified.
- $client->setVerifyPeer(false);
-
- $return = true;
- try {
- // test PROPFIND
- $client->propfind('', array('{DAV:}resourcetype'));
- } catch(\Sabre_DAV_Exception_NotAuthenticated $e) {
- $return = true;
- } catch(\Exception $e) {
- OC_Log::write('core', 'isWebDAVWorking: NO - Reason: '.$e->getMessage(). ' ('.get_class($e).')', OC_Log::WARN);
- $return = false;
- }
-
- // restore the original timeout
- ini_set("default_socket_timeout", $old_timeout);
-
- return $return;
- }
-
- /**
- * Check if the setlocal call doesn't work. This can happen if the right
- * local packages are not available on the server.
- */
- public static function issetlocaleworking() {
- // setlocale test is pointless on Windows
- if (OC_Util::runningOnWindows() ) {
- return true;
- }
-
- $result = setlocale(LC_ALL, 'en_US.UTF-8', 'en_US.UTF8');
- if($result == false) {
- return false;
- }
- return true;
- }
-
- /**
- * Check if the PHP module fileinfo is loaded.
- * @return bool
- */
- public static function fileInfoLoaded() {
- return function_exists('finfo_open');
- }
-
- /**
- * Check if the ownCloud server can connect to the internet
- */
- public static function isInternetConnectionWorking() {
- // in case there is no internet connection on purpose return false
- if (self::isInternetConnectionEnabled() === false) {
- return false;
- }
-
- // try to connect to owncloud.org to see if http connections to the internet are possible.
- $connected = @fsockopen("www.owncloud.org", 80);
- if ($connected) {
- fclose($connected);
- return true;
- }else{
-
- // second try in case one server is down
- $connected = @fsockopen("apps.owncloud.com", 80);
- if ($connected) {
- fclose($connected);
- return true;
- }else{
- return false;
- }
-
- }
-
- }
-
- /**
- * Check if the connection to the internet is disabled on purpose
- */
- public static function isInternetConnectionEnabled(){
- return \OC_Config::getValue("has_internet_connection", true);
- }
-
- /**
- * clear all levels of output buffering
- */
- public static function obEnd(){
- while (ob_get_level()) {
- ob_end_clean();
- }
- }
-
-
- /**
- * @brief Generates a cryptographical secure pseudorandom string
- * @param Int with the length of the random string
- * @return String
- * Please also update secureRNG_available if you change something here
- */
- public static function generate_random_bytes($length = 30) {
-
- // Try to use openssl_random_pseudo_bytes
- if(function_exists('openssl_random_pseudo_bytes')) {
- $pseudo_byte = bin2hex(openssl_random_pseudo_bytes($length, $strong));
- if($strong == true) {
- return substr($pseudo_byte, 0, $length); // Truncate it to match the length
- }
- }
-
- // Try to use /dev/urandom
- $fp = @file_get_contents('/dev/urandom', false, null, 0, $length);
- if ($fp !== false) {
- $string = substr(bin2hex($fp), 0, $length);
- return $string;
- }
-
- // Fallback to mt_rand()
- $characters = '0123456789';
- $characters .= 'abcdefghijklmnopqrstuvwxyz';
- $charactersLength = strlen($characters)-1;
- $pseudo_byte = "";
-
- // Select some random characters
- for ($i = 0; $i < $length; $i++) {
- $pseudo_byte .= $characters[mt_rand(0, $charactersLength)];
- }
- return $pseudo_byte;
- }
-
- /**
- * @brief Checks if a secure random number generator is available
- * @return bool
- */
- public static function secureRNG_available() {
-
- // Check openssl_random_pseudo_bytes
- if(function_exists('openssl_random_pseudo_bytes')) {
- openssl_random_pseudo_bytes(1, $strong);
- if($strong == true) {
- return true;
- }
- }
-
- // Check /dev/urandom
- $fp = @file_get_contents('/dev/urandom', false, null, 0, 1);
- if ($fp !== false) {
- return true;
- }
-
- return false;
- }
-
- /**
- * @Brief Get file content via curl.
- * @param string $url Url to get content
- * @return string of the response or false on error
- * This function get the content of a page via curl, if curl is enabled.
- * If not, file_get_element is used.
- */
-
- public static function getUrlContent($url){
-
- if (function_exists('curl_init')) {
-
- $curl = curl_init();
-
- 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', '')<>'') {
- curl_setopt($curl, CURLOPT_PROXY, OC_Config::getValue('proxy'));
- }
- if(OC_Config::getValue('proxyuserpwd', '')<>'') {
- curl_setopt($curl, CURLOPT_PROXYUSERPWD, OC_Config::getValue('proxyuserpwd'));
- }
- $data = curl_exec($curl);
- curl_close($curl);
-
- } else {
- $contextArray = null;
-
- if(OC_Config::getValue('proxy', '')<>'') {
- $contextArray = array(
- 'http' => array(
- 'timeout' => 10,
- 'proxy' => OC_Config::getValue('proxy')
- )
- );
- } else {
- $contextArray = array(
- 'http' => array(
- 'timeout' => 10
- )
- );
- }
-
-
- $ctx = stream_context_create(
- $contextArray
- );
- $data=@file_get_contents($url, 0, $ctx);
-
- }
- return $data;
- }
-
- /**
- * @return bool - well are we running on windows or not
- */
- public static function runningOnWindows() {
- return (substr(PHP_OS, 0, 3) === "WIN");
- }
-
-
- /**
- * Handles the case that there may not be a theme, then check if a "default"
- * theme exists and take that one
- * @return string the theme
- */
- public static function getTheme() {
- $theme = OC_Config::getValue("theme", '');
-
- if($theme === '') {
-
- if(is_dir(OC::$SERVERROOT . '/themes/default')) {
- $theme = 'default';
- }
-
- }
-
- return $theme;
- }
-
- /**
- * Clear the opcode cache if one exists
- * This is necessary for writing to the config file
- * in case the opcode cache doesn't revalidate files
- */
- public static function clearOpcodeCache() {
- // APC
- if (function_exists('apc_clear_cache')) {
- apc_clear_cache();
- }
- // Zend Opcache
- if (function_exists('accelerator_reset')) {
- accelerator_reset();
- }
- // XCache
- if (function_exists('xcache_clear_cache')) {
- if (ini_get('xcache.admin.enable_auth')) {
- OC_Log::write('core', 'XCache opcode cache will not be cleared because "xcache.admin.enable_auth" is enabled.', \OC_Log::WARN);
- } else {
- xcache_clear_cache(XC_TYPE_PHP, 0);
- }
- }
- // Opcache (PHP >= 5.5)
- if (function_exists('opcache_reset')) {
- opcache_reset();
- }
- }
-
- /**
- * Normalize a unicode string
- * @param string $value a not normalized string
- * @return bool|string
- */
- public static function normalizeUnicode($value) {
- if(class_exists('Patchwork\PHP\Shim\Normalizer')) {
- $normalizedValue = \Patchwork\PHP\Shim\Normalizer::normalize($value);
- if($normalizedValue === false) {
- \OC_Log::write( 'core', 'normalizing failed for "' . $value . '"', \OC_Log::WARN);
- } else {
- $value = $normalizedValue;
- }
- }
-
- return $value;
- }
-
- public static function basename($file)
- {
- $file = rtrim($file, '/');
- $t = explode('/', $file);
- return array_pop($t);
- }
-}
diff --git a/lib/vcategories.php b/lib/vcategories.php
deleted file mode 100644
index 84036958359..00000000000
--- a/lib/vcategories.php
+++ /dev/null
@@ -1,821 +0,0 @@
-<?php
-/**
-* ownCloud
-*
-* @author Thomas Tanghus
-* @copyright 2012 Thomas Tanghus <thomas@tanghus.net>
-* @copyright 2012 Bart Visscher bartv@thisnet.nl
-*
-* 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/>.
-*
-*/
-
-OC_Hook::connect('OC_User', 'post_deleteUser', 'OC_VCategories', 'post_deleteUser');
-
-/**
- * Class for easy access to categories in VCARD, VEVENT, VTODO and VJOURNAL.
- * A Category can be e.g. 'Family', 'Work', 'Chore', 'Special Occation' or
- * anything else that is either parsed from a vobject or that the user chooses
- * to add.
- * Category names are not case-sensitive, but will be saved with the case they
- * are entered in. If a user already has a category 'family' for a type, and
- * tries to add a category named 'Family' it will be silently ignored.
- */
-class OC_VCategories {
-
- /**
- * Categories
- */
- private $categories = array();
-
- /**
- * Used for storing objectid/categoryname pairs while rescanning.
- */
- private static $relations = array();
-
- private $type = null;
- private $user = null;
-
- const CATEGORY_TABLE = '*PREFIX*vcategory';
- const RELATION_TABLE = '*PREFIX*vcategory_to_object';
-
- const CATEGORY_FAVORITE = '_$!<Favorite>!$_';
-
- const FORMAT_LIST = 0;
- const FORMAT_MAP = 1;
-
- /**
- * @brief Constructor.
- * @param $type The type identifier e.g. 'contact' or 'event'.
- * @param $user The user whos data the object will operate on. This
- * parameter should normally be omitted but to make an app able to
- * update categories for all users it is made possible to provide it.
- * @param $defcategories An array of default categories to be used if none is stored.
- */
- public function __construct($type, $user=null, $defcategories=array()) {
- $this->type = $type;
- $this->user = is_null($user) ? OC_User::getUser() : $user;
-
- $this->loadCategories();
- OCP\Util::writeLog('core', __METHOD__ . ', categories: '
- . print_r($this->categories, true),
- OCP\Util::DEBUG
- );
-
- if($defcategories && count($this->categories) === 0) {
- $this->addMulti($defcategories, true);
- }
- }
-
- /**
- * @brief Load categories from db.
- */
- private function loadCategories() {
- $this->categories = array();
- $result = null;
- $sql = 'SELECT `id`, `category` FROM `' . self::CATEGORY_TABLE . '` '
- . 'WHERE `uid` = ? AND `type` = ? ORDER BY `category`';
- try {
- $stmt = OCP\DB::prepare($sql);
- $result = $stmt->execute(array($this->user, $this->type));
- if (OC_DB::isError($result)) {
- OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR);
- }
- } catch(Exception $e) {
- OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
- OCP\Util::ERROR);
- }
-
- if(!is_null($result)) {
- while( $row = $result->fetchRow()) {
- // The keys are prefixed because array_search wouldn't work otherwise :-/
- $this->categories[$row['id']] = $row['category'];
- }
- }
- OCP\Util::writeLog('core', __METHOD__.', categories: ' . print_r($this->categories, true),
- OCP\Util::DEBUG);
- }
-
-
- /**
- * @brief Check if any categories are saved for this type and user.
- * @returns boolean.
- * @param $type The type identifier e.g. 'contact' or 'event'.
- * @param $user The user whos categories will be checked. If not set current user will be used.
- */
- public static function isEmpty($type, $user = null) {
- $user = is_null($user) ? OC_User::getUser() : $user;
- $sql = 'SELECT COUNT(*) FROM `' . self::CATEGORY_TABLE . '` '
- . 'WHERE `uid` = ? AND `type` = ?';
- try {
- $stmt = OCP\DB::prepare($sql);
- $result = $stmt->execute(array($user, $type));
- if (OC_DB::isError($result)) {
- OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR);
- return false;
- }
- return ($result->numRows() === 0);
- } catch(Exception $e) {
- OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
- OCP\Util::ERROR);
- return false;
- }
- }
-
- /**
- * @brief Get the categories for a specific user.
- * @param
- * @returns array containing the categories as strings.
- */
- public function categories($format = null) {
- if(!$this->categories) {
- return array();
- }
- $categories = array_values($this->categories);
- uasort($categories, 'strnatcasecmp');
- if($format == self::FORMAT_MAP) {
- $catmap = array();
- foreach($categories as $category) {
- if($category !== self::CATEGORY_FAVORITE) {
- $catmap[] = array(
- 'id' => $this->array_searchi($category, $this->categories),
- 'name' => $category
- );
- }
- }
- return $catmap;
- }
-
- // Don't add favorites to normal categories.
- $favpos = array_search(self::CATEGORY_FAVORITE, $categories);
- if($favpos !== false) {
- return array_splice($categories, $favpos);
- } else {
- return $categories;
- }
- }
-
- /**
- * Get the a list if items belonging to $category.
- *
- * Throws an exception if the category could not be found.
- *
- * @param string|integer $category Category id or name.
- * @returns array An array of object ids or false on error.
- */
- public function idsForCategory($category) {
- $result = null;
- if(is_numeric($category)) {
- $catid = $category;
- } elseif(is_string($category)) {
- $catid = $this->array_searchi($category, $this->categories);
- }
- OCP\Util::writeLog('core', __METHOD__.', category: '.$catid.' '.$category, OCP\Util::DEBUG);
- if($catid === false) {
- $l10n = OC_L10N::get('core');
- throw new Exception(
- $l10n->t('Could not find category "%s"', $category)
- );
- }
-
- $ids = array();
- $sql = 'SELECT `objid` FROM `' . self::RELATION_TABLE
- . '` WHERE `categoryid` = ?';
-
- try {
- $stmt = OCP\DB::prepare($sql);
- $result = $stmt->execute(array($catid));
- if (OC_DB::isError($result)) {
- OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR);
- return false;
- }
- } catch(Exception $e) {
- OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
- OCP\Util::ERROR);
- return false;
- }
-
- if(!is_null($result)) {
- while( $row = $result->fetchRow()) {
- $ids[] = (int)$row['objid'];
- }
- }
-
- return $ids;
- }
-
- /**
- * Get the a list if items belonging to $category.
- *
- * Throws an exception if the category could not be found.
- *
- * @param string|integer $category Category id or name.
- * @param array $tableinfo Array in the form {'tablename' => table, 'fields' => ['field1', 'field2']}
- * @param int $limit
- * @param int $offset
- *
- * This generic method queries a table assuming that the id
- * field is called 'id' and the table name provided is in
- * the form '*PREFIX*table_name'.
- *
- * If the category name cannot be resolved an exception is thrown.
- *
- * TODO: Maybe add the getting permissions for objects?
- *
- * @returns array containing the resulting items or false on error.
- */
- public function itemsForCategory($category, $tableinfo, $limit = null, $offset = null) {
- $result = null;
- if(is_numeric($category)) {
- $catid = $category;
- } elseif(is_string($category)) {
- $catid = $this->array_searchi($category, $this->categories);
- }
- OCP\Util::writeLog('core', __METHOD__.', category: '.$catid.' '.$category, OCP\Util::DEBUG);
- if($catid === false) {
- $l10n = OC_L10N::get('core');
- throw new Exception(
- $l10n->t('Could not find category "%s"', $category)
- );
- }
- $fields = '';
- foreach($tableinfo['fields'] as $field) {
- $fields .= '`' . $tableinfo['tablename'] . '`.`' . $field . '`,';
- }
- $fields = substr($fields, 0, -1);
-
- $items = array();
- $sql = 'SELECT `' . self::RELATION_TABLE . '`.`categoryid`, ' . $fields
- . ' FROM `' . $tableinfo['tablename'] . '` JOIN `'
- . self::RELATION_TABLE . '` ON `' . $tableinfo['tablename']
- . '`.`id` = `' . self::RELATION_TABLE . '`.`objid` WHERE `'
- . self::RELATION_TABLE . '`.`categoryid` = ?';
-
- try {
- $stmt = OCP\DB::prepare($sql, $limit, $offset);
- $result = $stmt->execute(array($catid));
- if (OC_DB::isError($result)) {
- OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR);
- return false;
- }
- } catch(Exception $e) {
- OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
- OCP\Util::ERROR);
- return false;
- }
-
- if(!is_null($result)) {
- while( $row = $result->fetchRow()) {
- $items[] = $row;
- }
- }
- //OCP\Util::writeLog('core', __METHOD__.', count: ' . count($items), OCP\Util::DEBUG);
- //OCP\Util::writeLog('core', __METHOD__.', sql: ' . $sql, OCP\Util::DEBUG);
-
- return $items;
- }
-
- /**
- * @brief Checks whether a category is already saved.
- * @param $name The name to check for.
- * @returns bool
- */
- public function hasCategory($name) {
- return $this->in_arrayi($name, $this->categories);
- }
-
- /**
- * @brief Add a new category.
- * @param $name A string with a name of the category
- * @returns int the id of the added category or false if it already exists.
- */
- public function add($name) {
- OCP\Util::writeLog('core', __METHOD__.', name: ' . $name, OCP\Util::DEBUG);
- if($this->hasCategory($name)) {
- OCP\Util::writeLog('core', __METHOD__.', name: ' . $name. ' exists already', OCP\Util::DEBUG);
- return false;
- }
- try {
- OCP\DB::insertIfNotExist(self::CATEGORY_TABLE,
- array(
- 'uid' => $this->user,
- 'type' => $this->type,
- 'category' => $name,
- ));
- } catch(Exception $e) {
- OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
- OCP\Util::ERROR);
- return false;
- }
- $id = OCP\DB::insertid(self::CATEGORY_TABLE);
- OCP\Util::writeLog('core', __METHOD__.', id: ' . $id, OCP\Util::DEBUG);
- $this->categories[$id] = $name;
- return $id;
- }
-
- /**
- * @brief Rename category.
- * @param string $from The name of the existing category
- * @param string $to The new name of the category.
- * @returns bool
- */
- public function rename($from, $to) {
- $id = $this->array_searchi($from, $this->categories);
- if($id === false) {
- OCP\Util::writeLog('core', __METHOD__.', category: ' . $from. ' does not exist', OCP\Util::DEBUG);
- return false;
- }
-
- $sql = 'UPDATE `' . self::CATEGORY_TABLE . '` SET `category` = ? '
- . 'WHERE `uid` = ? AND `type` = ? AND `id` = ?';
- try {
- $stmt = OCP\DB::prepare($sql);
- $result = $stmt->execute(array($to, $this->user, $this->type, $id));
- if (OC_DB::isError($result)) {
- OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR);
- return false;
- }
- } catch(Exception $e) {
- OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
- OCP\Util::ERROR);
- return false;
- }
- $this->categories[$id] = $to;
- return true;
- }
-
- /**
- * @brief Add a new category.
- * @param $names A string with a name or an array of strings containing
- * the name(s) of the categor(y|ies) to add.
- * @param $sync bool When true, save the categories
- * @param $id int Optional object id to add to this|these categor(y|ies)
- * @returns bool Returns false on error.
- */
- public function addMulti($names, $sync=false, $id = null) {
- if(!is_array($names)) {
- $names = array($names);
- }
- $names = array_map('trim', $names);
- $newones = array();
- foreach($names as $name) {
- if(($this->in_arrayi(
- $name, $this->categories) == false) && $name != '') {
- $newones[] = $name;
- }
- if(!is_null($id) ) {
- // Insert $objectid, $categoryid pairs if not exist.
- self::$relations[] = array('objid' => $id, 'category' => $name);
- }
- }
- $this->categories = array_merge($this->categories, $newones);
- if($sync === true) {
- $this->save();
- }
-
- return true;
- }
-
- /**
- * @brief Extracts categories from a vobject and add the ones not already present.
- * @param $vobject The instance of OC_VObject to load the categories from.
- */
- public function loadFromVObject($id, $vobject, $sync=false) {
- $this->addMulti($vobject->getAsArray('CATEGORIES'), $sync, $id);
- }
-
- /**
- * @brief Reset saved categories and rescan supplied vobjects for categories.
- * @param $objects An array of vobjects (as text).
- * To get the object array, do something like:
- * // For Addressbook:
- * $categories = new OC_VCategories('contacts');
- * $stmt = OC_DB::prepare( 'SELECT `carddata` FROM `*PREFIX*contacts_cards`' );
- * $result = $stmt->execute();
- * $objects = array();
- * if(!is_null($result)) {
- * while( $row = $result->fetchRow()){
- * $objects[] = array($row['id'], $row['carddata']);
- * }
- * }
- * $categories->rescan($objects);
- */
- public function rescan($objects, $sync=true, $reset=true) {
-
- if($reset === true) {
- $result = null;
- // Find all objectid/categoryid pairs.
- try {
- $stmt = OCP\DB::prepare('SELECT `id` FROM `' . self::CATEGORY_TABLE . '` '
- . 'WHERE `uid` = ? AND `type` = ?');
- $result = $stmt->execute(array($this->user, $this->type));
- if (OC_DB::isError($result)) {
- OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR);
- return false;
- }
- } catch(Exception $e) {
- OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
- OCP\Util::ERROR);
- }
-
- // And delete them.
- if(!is_null($result)) {
- $stmt = OCP\DB::prepare('DELETE FROM `' . self::RELATION_TABLE . '` '
- . 'WHERE `categoryid` = ? AND `type`= ?');
- while( $row = $result->fetchRow()) {
- $stmt->execute(array($row['id'], $this->type));
- }
- }
- try {
- $stmt = OCP\DB::prepare('DELETE FROM `' . self::CATEGORY_TABLE . '` '
- . 'WHERE `uid` = ? AND `type` = ?');
- $result = $stmt->execute(array($this->user, $this->type));
- if (OC_DB::isError($result)) {
- OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR);
- return;
- }
- } catch(Exception $e) {
- OCP\Util::writeLog('core', __METHOD__ . ', exception: '
- . $e->getMessage(), OCP\Util::ERROR);
- return;
- }
- $this->categories = array();
- }
- // Parse all the VObjects
- foreach($objects as $object) {
- $vobject = OC_VObject::parse($object[1]);
- if(!is_null($vobject)) {
- // Load the categories
- $this->loadFromVObject($object[0], $vobject, $sync);
- } else {
- OC_Log::write('core', __METHOD__ . ', unable to parse. ID: ' . ', '
- . substr($object, 0, 100) . '(...)', OC_Log::DEBUG);
- }
- }
- $this->save();
- }
-
- /**
- * @brief Save the list with categories
- */
- private function save() {
- if(is_array($this->categories)) {
- foreach($this->categories as $category) {
- try {
- OCP\DB::insertIfNotExist(self::CATEGORY_TABLE,
- array(
- 'uid' => $this->user,
- 'type' => $this->type,
- 'category' => $category,
- ));
- } catch(Exception $e) {
- OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
- OCP\Util::ERROR);
- }
- }
- // reload categories to get the proper ids.
- $this->loadCategories();
- // Loop through temporarily cached objectid/categoryname pairs
- // and save relations.
- $categories = $this->categories;
- // For some reason this is needed or array_search(i) will return 0..?
- ksort($categories);
- foreach(self::$relations as $relation) {
- $catid = $this->array_searchi($relation['category'], $categories);
- OC_Log::write('core', __METHOD__ . 'catid, ' . $relation['category'] . ' ' . $catid, OC_Log::DEBUG);
- if($catid) {
- try {
- OCP\DB::insertIfNotExist(self::RELATION_TABLE,
- array(
- 'objid' => $relation['objid'],
- 'categoryid' => $catid,
- 'type' => $this->type,
- ));
- } catch(Exception $e) {
- OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
- OCP\Util::ERROR);
- }
- }
- }
- self::$relations = array(); // reset
- } else {
- OC_Log::write('core', __METHOD__.', $this->categories is not an array! '
- . print_r($this->categories, true), OC_Log::ERROR);
- }
- }
-
- /**
- * @brief Delete categories and category/object relations for a user.
- * For hooking up on post_deleteUser
- * @param string $uid The user id for which entries should be purged.
- */
- public static function post_deleteUser($arguments) {
- // Find all objectid/categoryid pairs.
- $result = null;
- try {
- $stmt = OCP\DB::prepare('SELECT `id` FROM `' . self::CATEGORY_TABLE . '` '
- . 'WHERE `uid` = ?');
- $result = $stmt->execute(array($arguments['uid']));
- if (OC_DB::isError($result)) {
- OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR);
- }
- } catch(Exception $e) {
- OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
- OCP\Util::ERROR);
- }
-
- if(!is_null($result)) {
- try {
- $stmt = OCP\DB::prepare('DELETE FROM `' . self::RELATION_TABLE . '` '
- . 'WHERE `categoryid` = ?');
- while( $row = $result->fetchRow()) {
- try {
- $stmt->execute(array($row['id']));
- } catch(Exception $e) {
- OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
- OCP\Util::ERROR);
- }
- }
- } catch(Exception $e) {
- OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
- OCP\Util::ERROR);
- }
- }
- try {
- $stmt = OCP\DB::prepare('DELETE FROM `' . self::CATEGORY_TABLE . '` '
- . 'WHERE `uid` = ?');
- $result = $stmt->execute(array($arguments['uid']));
- if (OC_DB::isError($result)) {
- OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR);
- }
- } catch(Exception $e) {
- OCP\Util::writeLog('core', __METHOD__ . ', exception: '
- . $e->getMessage(), OCP\Util::ERROR);
- }
- }
-
- /**
- * @brief Delete category/object relations from the db
- * @param array $ids The ids of the objects
- * @param string $type The type of object (event/contact/task/journal).
- * Defaults to the type set in the instance
- * @returns boolean Returns false on error.
- */
- public function purgeObjects(array $ids, $type = null) {
- $type = is_null($type) ? $this->type : $type;
- if(count($ids) === 0) {
- // job done ;)
- return true;
- }
- $updates = $ids;
- try {
- $query = 'DELETE FROM `' . self::RELATION_TABLE . '` ';
- $query .= 'WHERE `objid` IN (' . str_repeat('?,', count($ids)-1) . '?) ';
- $query .= 'AND `type`= ?';
- $updates[] = $type;
- $stmt = OCP\DB::prepare($query);
- $result = $stmt->execute($updates);
- if (OC_DB::isError($result)) {
- OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR);
- return false;
- }
- } catch(Exception $e) {
- OCP\Util::writeLog('core', __METHOD__.', exception: ' . $e->getMessage(),
- OCP\Util::ERROR);
- return false;
- }
- return true;
- }
-
- /**
- * Get favorites for an object type
- *
- * @param string $type The type of object (event/contact/task/journal).
- * Defaults to the type set in the instance
- * @returns array An array of object ids.
- */
- public function getFavorites($type = null) {
- $type = is_null($type) ? $this->type : $type;
-
- try {
- return $this->idsForCategory(self::CATEGORY_FAVORITE);
- } catch(Exception $e) {
- // No favorites
- return array();
- }
- }
-
- /**
- * Add an object to favorites
- *
- * @param int $objid The id of the object
- * @param string $type The type of object (event/contact/task/journal).
- * Defaults to the type set in the instance
- * @returns boolean
- */
- public function addToFavorites($objid, $type = null) {
- $type = is_null($type) ? $this->type : $type;
- if(!$this->hasCategory(self::CATEGORY_FAVORITE)) {
- $this->add(self::CATEGORY_FAVORITE, true);
- }
- return $this->addToCategory($objid, self::CATEGORY_FAVORITE, $type);
- }
-
- /**
- * Remove an object from favorites
- *
- * @param int $objid The id of the object
- * @param string $type The type of object (event/contact/task/journal).
- * Defaults to the type set in the instance
- * @returns boolean
- */
- public function removeFromFavorites($objid, $type = null) {
- $type = is_null($type) ? $this->type : $type;
- return $this->removeFromCategory($objid, self::CATEGORY_FAVORITE, $type);
- }
-
- /**
- * @brief Creates a category/object relation.
- * @param int $objid The id of the object
- * @param int|string $category The id or name of the category
- * @param string $type The type of object (event/contact/task/journal).
- * Defaults to the type set in the instance
- * @returns boolean Returns false on database error.
- */
- public function addToCategory($objid, $category, $type = null) {
- $type = is_null($type) ? $this->type : $type;
- if(is_string($category) && !is_numeric($category)) {
- if(!$this->hasCategory($category)) {
- $this->add($category, true);
- }
- $categoryid = $this->array_searchi($category, $this->categories);
- } else {
- $categoryid = $category;
- }
- try {
- OCP\DB::insertIfNotExist(self::RELATION_TABLE,
- array(
- 'objid' => $objid,
- 'categoryid' => $categoryid,
- 'type' => $type,
- ));
- } catch(Exception $e) {
- OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
- OCP\Util::ERROR);
- return false;
- }
- return true;
- }
-
- /**
- * @brief Delete single category/object relation from the db
- * @param int $objid The id of the object
- * @param int|string $category The id or name of the category
- * @param string $type The type of object (event/contact/task/journal).
- * Defaults to the type set in the instance
- * @returns boolean
- */
- public function removeFromCategory($objid, $category, $type = null) {
- $type = is_null($type) ? $this->type : $type;
- $categoryid = (is_string($category) && !is_numeric($category))
- ? $this->array_searchi($category, $this->categories)
- : $category;
- try {
- $sql = 'DELETE FROM `' . self::RELATION_TABLE . '` '
- . 'WHERE `objid` = ? AND `categoryid` = ? AND `type` = ?';
- OCP\Util::writeLog('core', __METHOD__.', sql: ' . $objid . ' ' . $categoryid . ' ' . $type,
- OCP\Util::DEBUG);
- $stmt = OCP\DB::prepare($sql);
- $stmt->execute(array($objid, $categoryid, $type));
- } catch(Exception $e) {
- OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
- OCP\Util::ERROR);
- return false;
- }
- return true;
- }
-
- /**
- * @brief Delete categories from the db and from all the vobject supplied
- * @param $names An array of categories to delete
- * @param $objects An array of arrays with [id,vobject] (as text) pairs suitable for updating the apps object table.
- */
- public function delete($names, array &$objects=null) {
- if(!is_array($names)) {
- $names = array($names);
- }
-
- OC_Log::write('core', __METHOD__ . ', before: '
- . print_r($this->categories, true), OC_Log::DEBUG);
- foreach($names as $name) {
- $id = null;
- OC_Log::write('core', __METHOD__.', '.$name, OC_Log::DEBUG);
- if($this->hasCategory($name)) {
- $id = $this->array_searchi($name, $this->categories);
- unset($this->categories[$id]);
- }
- try {
- $stmt = OCP\DB::prepare('DELETE FROM `' . self::CATEGORY_TABLE . '` WHERE '
- . '`uid` = ? AND `type` = ? AND `category` = ?');
- $result = $stmt->execute(array($this->user, $this->type, $name));
- if (OC_DB::isError($result)) {
- OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR);
- }
- } catch(Exception $e) {
- OCP\Util::writeLog('core', __METHOD__ . ', exception: '
- . $e->getMessage(), OCP\Util::ERROR);
- }
- if(!is_null($id) && $id !== false) {
- try {
- $sql = 'DELETE FROM `' . self::RELATION_TABLE . '` '
- . 'WHERE `categoryid` = ?';
- $stmt = OCP\DB::prepare($sql);
- $result = $stmt->execute(array($id));
- if (OC_DB::isError($result)) {
- OC_Log::write('core',
- __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result),
- OC_Log::ERROR);
- }
- } catch(Exception $e) {
- OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(),
- OCP\Util::ERROR);
- return false;
- }
- }
- }
- OC_Log::write('core', __METHOD__.', after: '
- . print_r($this->categories, true), OC_Log::DEBUG);
- if(!is_null($objects)) {
- foreach($objects as $key=>&$value) {
- $vobject = OC_VObject::parse($value[1]);
- if(!is_null($vobject)) {
- $object = null;
- $componentname = '';
- if (isset($vobject->VEVENT)) {
- $object = $vobject->VEVENT;
- $componentname = 'VEVENT';
- } else
- if (isset($vobject->VTODO)) {
- $object = $vobject->VTODO;
- $componentname = 'VTODO';
- } else
- if (isset($vobject->VJOURNAL)) {
- $object = $vobject->VJOURNAL;
- $componentname = 'VJOURNAL';
- } else {
- $object = $vobject;
- }
- $categories = $object->getAsArray('CATEGORIES');
- foreach($names as $name) {
- $idx = $this->array_searchi($name, $categories);
- if($idx !== false) {
- OC_Log::write('core', __METHOD__
- .', unsetting: '
- . $categories[$this->array_searchi($name, $categories)],
- OC_Log::DEBUG);
- unset($categories[$this->array_searchi($name, $categories)]);
- }
- }
-
- $object->setString('CATEGORIES', implode(',', $categories));
- if($vobject !== $object) {
- $vobject[$componentname] = $object;
- }
- $value[1] = $vobject->serialize();
- $objects[$key] = $value;
- } else {
- OC_Log::write('core', __METHOD__
- .', unable to parse. ID: ' . $value[0] . ', '
- . substr($value[1], 0, 50) . '(...)', OC_Log::DEBUG);
- }
- }
- }
- }
-
- // case-insensitive in_array
- private function in_arrayi($needle, $haystack) {
- if(!is_array($haystack)) {
- return false;
- }
- return in_array(strtolower($needle), array_map('strtolower', $haystack));
- }
-
- // case-insensitive array_search
- private function array_searchi($needle, $haystack) {
- if(!is_array($haystack)) {
- return false;
- }
- return array_search(strtolower($needle), array_map('strtolower', $haystack));
- }
-}