summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.htaccess7
m---------3rdparty0
-rw-r--r--apps/comments/activity/extension.php301
-rw-r--r--apps/comments/activity/listener.php128
-rw-r--r--apps/comments/appinfo/app.php18
-rw-r--r--apps/comments/appinfo/info.xml8
-rw-r--r--apps/comments/css/comments.css41
-rw-r--r--apps/comments/js/commentcollection.js61
-rw-r--r--apps/comments/js/commentmodel.js16
-rw-r--r--apps/comments/js/commentstabview.js274
-rw-r--r--apps/comments/js/commentsummarymodel.js65
-rw-r--r--apps/comments/js/filesplugin.js84
-rw-r--r--apps/comments/tests/js/commentscollectionSpec.js44
-rw-r--r--apps/comments/tests/js/commentstabviewSpec.js264
-rw-r--r--apps/comments/tests/js/filespluginSpec.js102
-rw-r--r--apps/dav/appinfo/info.xml1
-rw-r--r--apps/dav/appinfo/register_command.php2
-rw-r--r--apps/dav/command/createcalendar.php15
-rw-r--r--apps/dav/lib/caldav/caldavbackend.php90
-rw-r--r--apps/dav/lib/caldav/calendar.php102
-rw-r--r--apps/dav/lib/caldav/calendarhome.php78
-rw-r--r--apps/dav/lib/caldav/calendarroot.php10
-rw-r--r--apps/dav/lib/carddav/addressbook.php29
-rw-r--r--apps/dav/lib/carddav/carddavbackend.php29
-rw-r--r--apps/dav/lib/comments/commentnode.php14
-rw-r--r--apps/dav/lib/comments/commentsplugin.php5
-rw-r--r--apps/dav/lib/dav/sharing/backend.php33
-rw-r--r--apps/dav/lib/dav/sharing/plugin.php27
-rw-r--r--apps/dav/lib/dav/sharing/xml/invite.php149
-rw-r--r--apps/dav/lib/rootcollection.php4
-rw-r--r--apps/dav/tests/travis/caldav/install.sh1
-rw-r--r--apps/dav/tests/travis/caldav/script.sh4
-rw-r--r--apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/1.xml8
-rw-r--r--apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/4.xml8
-rw-r--r--apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/5.ics29
-rw-r--r--apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/5.xml6
-rw-r--r--apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/6.ics29
-rw-r--r--apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/7.ics29
-rw-r--r--apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/8.ics29
-rw-r--r--apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/9.ics29
-rw-r--r--apps/dav/tests/travis/caldavtest/tests/CalDAV/sharing-calendars.xml180
-rw-r--r--apps/dav/tests/travis/caldavtest/tests/CardDAV/sharing-addressbooks.xml65
-rw-r--r--apps/dav/tests/unit/caldav/caldavbackendtest.php132
-rw-r--r--apps/dav/tests/unit/caldav/calendartest.php64
-rw-r--r--apps/dav/tests/unit/carddav/addressbooktest.php64
-rw-r--r--apps/dav/tests/unit/carddav/carddavbackendtest.php33
-rw-r--r--apps/dav/tests/unit/comments/commentnode.php171
-rw-r--r--apps/dav/tests/unit/comments/commentsplugin.php4
-rw-r--r--apps/encryption/appinfo/info.xml2
-rw-r--r--apps/files/appinfo/info.xml3
-rw-r--r--apps/files/appinfo/install.php2
-rw-r--r--apps/files/appinfo/update.php2
-rw-r--r--apps/files/css/files.css4
-rw-r--r--apps/files/lib/backgroundjob/deleteorphaneditems.php (renamed from apps/files/lib/backgroundjob/deleteorphanedtagsjob.php)59
-rw-r--r--apps/files/tests/backgroundjob/DeleteOrphanedItemsJobTest.php (renamed from apps/files/tests/backgroundjob/DeleteOrphanedTagsJobTest.php)110
-rw-r--r--apps/files_external/appinfo/application.php1
-rw-r--r--apps/files_external/appinfo/routes.php7
-rw-r--r--apps/files_external/controller/ajaxcontroller.php10
-rw-r--r--apps/files_external/controller/storagescontroller.php3
-rw-r--r--apps/files_external/js/settings.js27
-rw-r--r--apps/files_external/js/statusmanager.js263
-rw-r--r--apps/files_external/l10n/af_ZA.js1
-rw-r--r--apps/files_external/l10n/af_ZA.json1
-rw-r--r--apps/files_external/l10n/ar.js6
-rw-r--r--apps/files_external/l10n/ar.json6
-rw-r--r--apps/files_external/l10n/ast.js6
-rw-r--r--apps/files_external/l10n/ast.json6
-rw-r--r--apps/files_external/l10n/az.js6
-rw-r--r--apps/files_external/l10n/az.json6
-rw-r--r--apps/files_external/l10n/bg_BG.js6
-rw-r--r--apps/files_external/l10n/bg_BG.json6
-rw-r--r--apps/files_external/l10n/bn_BD.js6
-rw-r--r--apps/files_external/l10n/bn_BD.json6
-rw-r--r--apps/files_external/l10n/bn_IN.js2
-rw-r--r--apps/files_external/l10n/bn_IN.json2
-rw-r--r--apps/files_external/l10n/bs.js4
-rw-r--r--apps/files_external/l10n/bs.json4
-rw-r--r--apps/files_external/l10n/ca.js6
-rw-r--r--apps/files_external/l10n/ca.json6
-rw-r--r--apps/files_external/l10n/cs_CZ.js10
-rw-r--r--apps/files_external/l10n/cs_CZ.json10
-rw-r--r--apps/files_external/l10n/cy_GB.js4
-rw-r--r--apps/files_external/l10n/cy_GB.json4
-rw-r--r--apps/files_external/l10n/da.js6
-rw-r--r--apps/files_external/l10n/da.json6
-rw-r--r--apps/files_external/l10n/de.js6
-rw-r--r--apps/files_external/l10n/de.json6
-rw-r--r--apps/files_external/l10n/de_AT.js1
-rw-r--r--apps/files_external/l10n/de_AT.json1
-rw-r--r--apps/files_external/l10n/de_DE.js6
-rw-r--r--apps/files_external/l10n/de_DE.json6
-rw-r--r--apps/files_external/l10n/el.js6
-rw-r--r--apps/files_external/l10n/el.json6
-rw-r--r--apps/files_external/l10n/en_GB.js6
-rw-r--r--apps/files_external/l10n/en_GB.json6
-rw-r--r--apps/files_external/l10n/eo.js6
-rw-r--r--apps/files_external/l10n/eo.json6
-rw-r--r--apps/files_external/l10n/es.js6
-rw-r--r--apps/files_external/l10n/es.json6
-rw-r--r--apps/files_external/l10n/es_AR.js4
-rw-r--r--apps/files_external/l10n/es_AR.json4
-rw-r--r--apps/files_external/l10n/es_MX.js4
-rw-r--r--apps/files_external/l10n/es_MX.json4
-rw-r--r--apps/files_external/l10n/et_EE.js6
-rw-r--r--apps/files_external/l10n/et_EE.json6
-rw-r--r--apps/files_external/l10n/eu.js6
-rw-r--r--apps/files_external/l10n/eu.json6
-rw-r--r--apps/files_external/l10n/fa.js6
-rw-r--r--apps/files_external/l10n/fa.json6
-rw-r--r--apps/files_external/l10n/fi_FI.js7
-rw-r--r--apps/files_external/l10n/fi_FI.json7
-rw-r--r--apps/files_external/l10n/fr.js6
-rw-r--r--apps/files_external/l10n/fr.json6
-rw-r--r--apps/files_external/l10n/gl.js6
-rw-r--r--apps/files_external/l10n/gl.json6
-rw-r--r--apps/files_external/l10n/he.js9
-rw-r--r--apps/files_external/l10n/he.json9
-rw-r--r--apps/files_external/l10n/hi.js2
-rw-r--r--apps/files_external/l10n/hi.json2
-rw-r--r--apps/files_external/l10n/hr.js6
-rw-r--r--apps/files_external/l10n/hr.json6
-rw-r--r--apps/files_external/l10n/hu_HU.js6
-rw-r--r--apps/files_external/l10n/hu_HU.json6
-rw-r--r--apps/files_external/l10n/hy.js1
-rw-r--r--apps/files_external/l10n/hy.json1
-rw-r--r--apps/files_external/l10n/ia.js2
-rw-r--r--apps/files_external/l10n/ia.json2
-rw-r--r--apps/files_external/l10n/id.js6
-rw-r--r--apps/files_external/l10n/id.json6
-rw-r--r--apps/files_external/l10n/is.js4
-rw-r--r--apps/files_external/l10n/is.json4
-rw-r--r--apps/files_external/l10n/it.js9
-rw-r--r--apps/files_external/l10n/it.json9
-rw-r--r--apps/files_external/l10n/ja.js6
-rw-r--r--apps/files_external/l10n/ja.json6
-rw-r--r--apps/files_external/l10n/ka_GE.js4
-rw-r--r--apps/files_external/l10n/ka_GE.json4
-rw-r--r--apps/files_external/l10n/km.js4
-rw-r--r--apps/files_external/l10n/km.json4
-rw-r--r--apps/files_external/l10n/kn.js4
-rw-r--r--apps/files_external/l10n/kn.json4
-rw-r--r--apps/files_external/l10n/ko.js6
-rw-r--r--apps/files_external/l10n/ko.json6
-rw-r--r--apps/files_external/l10n/ku_IQ.js4
-rw-r--r--apps/files_external/l10n/ku_IQ.json4
-rw-r--r--apps/files_external/l10n/lb.js2
-rw-r--r--apps/files_external/l10n/lb.json2
-rw-r--r--apps/files_external/l10n/lt_LT.js4
-rw-r--r--apps/files_external/l10n/lt_LT.json4
-rw-r--r--apps/files_external/l10n/lv.js4
-rw-r--r--apps/files_external/l10n/lv.json4
-rw-r--r--apps/files_external/l10n/mk.js4
-rw-r--r--apps/files_external/l10n/mk.json4
-rw-r--r--apps/files_external/l10n/mn.js1
-rw-r--r--apps/files_external/l10n/mn.json1
-rw-r--r--apps/files_external/l10n/ms_MY.js2
-rw-r--r--apps/files_external/l10n/ms_MY.json2
-rw-r--r--apps/files_external/l10n/nb_NO.js6
-rw-r--r--apps/files_external/l10n/nb_NO.json6
-rw-r--r--apps/files_external/l10n/nds.js5
-rw-r--r--apps/files_external/l10n/nds.json5
-rw-r--r--apps/files_external/l10n/nl.js6
-rw-r--r--apps/files_external/l10n/nl.json6
-rw-r--r--apps/files_external/l10n/nn_NO.js2
-rw-r--r--apps/files_external/l10n/nn_NO.json2
-rw-r--r--apps/files_external/l10n/oc.js6
-rw-r--r--apps/files_external/l10n/oc.json6
-rw-r--r--apps/files_external/l10n/pa.js1
-rw-r--r--apps/files_external/l10n/pa.json1
-rw-r--r--apps/files_external/l10n/pl.js6
-rw-r--r--apps/files_external/l10n/pl.json6
-rw-r--r--apps/files_external/l10n/pt_BR.js12
-rw-r--r--apps/files_external/l10n/pt_BR.json12
-rw-r--r--apps/files_external/l10n/pt_PT.js9
-rw-r--r--apps/files_external/l10n/pt_PT.json9
-rw-r--r--apps/files_external/l10n/ro.js4
-rw-r--r--apps/files_external/l10n/ro.json4
-rw-r--r--apps/files_external/l10n/ru.js7
-rw-r--r--apps/files_external/l10n/ru.json7
-rw-r--r--apps/files_external/l10n/si_LK.js4
-rw-r--r--apps/files_external/l10n/si_LK.json4
-rw-r--r--apps/files_external/l10n/sk_SK.js6
-rw-r--r--apps/files_external/l10n/sk_SK.json6
-rw-r--r--apps/files_external/l10n/sl.js6
-rw-r--r--apps/files_external/l10n/sl.json6
-rw-r--r--apps/files_external/l10n/sq.js12
-rw-r--r--apps/files_external/l10n/sq.json12
-rw-r--r--apps/files_external/l10n/sr.js6
-rw-r--r--apps/files_external/l10n/sr.json6
-rw-r--r--apps/files_external/l10n/sr@latin.js6
-rw-r--r--apps/files_external/l10n/sr@latin.json6
-rw-r--r--apps/files_external/l10n/sv.js6
-rw-r--r--apps/files_external/l10n/sv.json6
-rw-r--r--apps/files_external/l10n/ta_LK.js4
-rw-r--r--apps/files_external/l10n/ta_LK.json4
-rw-r--r--apps/files_external/l10n/te.js1
-rw-r--r--apps/files_external/l10n/te.json1
-rw-r--r--apps/files_external/l10n/th_TH.js11
-rw-r--r--apps/files_external/l10n/th_TH.json11
-rw-r--r--apps/files_external/l10n/tr.js6
-rw-r--r--apps/files_external/l10n/tr.json6
-rw-r--r--apps/files_external/l10n/ug.js4
-rw-r--r--apps/files_external/l10n/ug.json4
-rw-r--r--apps/files_external/l10n/uk.js6
-rw-r--r--apps/files_external/l10n/uk.json6
-rw-r--r--apps/files_external/l10n/ur_PK.js2
-rw-r--r--apps/files_external/l10n/ur_PK.json2
-rw-r--r--apps/files_external/l10n/vi.js4
-rw-r--r--apps/files_external/l10n/vi.json4
-rw-r--r--apps/files_external/l10n/zh_CN.js4
-rw-r--r--apps/files_external/l10n/zh_CN.json4
-rw-r--r--apps/files_external/l10n/zh_HK.js4
-rw-r--r--apps/files_external/l10n/zh_HK.json4
-rw-r--r--apps/files_external/l10n/zh_TW.js6
-rw-r--r--apps/files_external/l10n/zh_TW.json6
-rw-r--r--apps/files_external/lib/auth/password/globalauth.php88
-rw-r--r--apps/files_external/lib/config/configadapter.php10
-rw-r--r--apps/files_external/lib/failedcache.php7
-rw-r--r--apps/files_external/lib/insufficientdataformeaningfulanswerexception.php11
-rw-r--r--apps/files_external/lib/smb.php13
-rw-r--r--apps/files_external/lib/storageconfig.php2
-rw-r--r--apps/files_external/personal.php4
-rw-r--r--apps/files_external/settings.php4
-rw-r--r--apps/files_external/templates/settings.php17
-rw-r--r--apps/files_sharing/api/share20ocs.php102
-rw-r--r--apps/files_sharing/js/public.js6
-rw-r--r--apps/files_sharing/lib/controllers/sharecontroller.php21
-rw-r--r--apps/files_sharing/lib/updater.php6
-rw-r--r--apps/files_sharing/templates/settings-personal.php2
-rw-r--r--apps/files_sharing/tests/api/share20ocstest.php167
-rw-r--r--apps/files_sharing/tests/controller/sharecontroller.php46
-rw-r--r--apps/files_sharing/tests/js/publicAppSpec.js8
-rw-r--r--apps/systemtags/appinfo/info.xml3
-rw-r--r--apps/user_ldap/group_ldap.php81
-rw-r--r--apps/user_ldap/js/wizard/wizardTabAdvanced.js13
-rw-r--r--apps/user_ldap/l10n/he.js11
-rw-r--r--apps/user_ldap/l10n/he.json11
-rw-r--r--apps/user_ldap/l10n/it.js2
-rw-r--r--apps/user_ldap/l10n/it.json2
-rw-r--r--apps/user_ldap/l10n/pt_BR.js2
-rw-r--r--apps/user_ldap/l10n/pt_BR.json2
-rw-r--r--apps/user_ldap/l10n/pt_PT.js2
-rw-r--r--apps/user_ldap/l10n/pt_PT.json2
-rw-r--r--apps/user_ldap/l10n/sq.js4
-rw-r--r--apps/user_ldap/l10n/sq.json4
-rw-r--r--apps/user_ldap/lib/configuration.php6
-rw-r--r--apps/user_ldap/templates/settings.php1
-rw-r--r--apps/user_ldap/tests/group_ldap.php13
-rw-r--r--build/integration/features/sharing-v1.feature25
-rw-r--r--config/config.sample.php9
-rw-r--r--console.php2
-rw-r--r--core/ajax/update.php6
-rw-r--r--core/command/integrity/signcore.php10
-rw-r--r--core/command/upgrade.php6
-rw-r--r--core/css/systemtags.css8
-rw-r--r--core/img/actions/comment.pngbin0 -> 169 bytes
-rw-r--r--core/img/actions/comment.svg4
-rw-r--r--core/img/appstore.pngbin2302 -> 0 bytes
-rw-r--r--core/img/appstore.svg129
-rw-r--r--core/img/desktopapp.svg34
-rw-r--r--core/img/googleplay.pngbin6491 -> 22758 bytes
-rw-r--r--core/js/files/client.js4
-rw-r--r--core/js/js.js21
-rw-r--r--core/js/mimetypelist.js4
-rw-r--r--core/js/setupchecks.js2
-rw-r--r--core/js/tests/specs/files/clientSpec.js286
-rw-r--r--core/l10n/th_TH.js5
-rw-r--r--core/l10n/th_TH.json5
-rw-r--r--core/shipped.json1
-rw-r--r--lib/l10n/fi_FI.js1
-rw-r--r--lib/l10n/fi_FI.json1
-rw-r--r--lib/l10n/it.js1
-rw-r--r--lib/l10n/it.json1
-rw-r--r--lib/l10n/pt_BR.js1
-rw-r--r--lib/l10n/pt_BR.json1
-rw-r--r--lib/l10n/pt_PT.js1
-rw-r--r--lib/l10n/pt_PT.json1
-rw-r--r--lib/l10n/sq.js1
-rw-r--r--lib/l10n/sq.json1
-rw-r--r--lib/private/appframework/dependencyinjection/dicontainer.php4
-rw-r--r--lib/private/comments/comment.php4
-rw-r--r--lib/private/comments/manager.php56
-rw-r--r--lib/private/comments/managerfactory.php3
-rw-r--r--lib/private/console/application.php21
-rw-r--r--lib/private/db/mdb2schemamanager.php3
-rw-r--r--lib/private/db/querybuilder/expressionbuilder/expressionbuilder.php (renamed from lib/private/db/querybuilder/expressionbuilder.php)19
-rw-r--r--lib/private/db/querybuilder/expressionbuilder/ociexpressionbuilder.php (renamed from lib/private/db/querybuilder/ociexpressionbuilder.php)25
-rw-r--r--lib/private/db/querybuilder/expressionbuilder/pgsqlexpressionbuilder.php45
-rw-r--r--lib/private/db/querybuilder/querybuilder.php6
-rw-r--r--lib/private/diagnostics/querylogger.php2
-rw-r--r--lib/private/files.php10
-rw-r--r--lib/private/files/cache/cache.php91
-rw-r--r--lib/private/files/cache/wrapper/cachejail.php7
-rw-r--r--lib/private/files/cache/wrapper/cachewrapper.php23
-rw-r--r--lib/private/files/node/root.php2
-rw-r--r--lib/private/files/storage/common.php8
-rw-r--r--lib/private/files/storage/wrapper/availability.php11
-rw-r--r--lib/private/files/storage/wrapper/jail.php11
-rw-r--r--lib/private/files/storage/wrapper/wrapper.php11
-rw-r--r--lib/private/files/stream/dir.php1
-rw-r--r--lib/private/files/type/detection.php4
-rw-r--r--lib/private/integritycheck/checker.php22
-rw-r--r--lib/private/integritycheck/iterator/excludefoldersbypathfilteriterator.php9
-rw-r--r--lib/private/repair/dropoldjobs.php1
-rw-r--r--lib/private/repair/repairmimetypes.php17
-rw-r--r--lib/private/server.php4
-rw-r--r--lib/private/share/hooks.php2
-rw-r--r--lib/private/share20/defaultshareprovider.php141
-rw-r--r--lib/private/share20/manager.php174
-rw-r--r--lib/private/share20/share.php98
-rw-r--r--lib/private/user/manager.php4
-rw-r--r--lib/private/user/user.php2
-rw-r--r--lib/public/comments/commentsevent.php70
-rw-r--r--lib/public/comments/icomment.php4
-rw-r--r--lib/public/comments/icommentsmanager.php12
-rw-r--r--lib/public/console/consoleevent.php69
-rw-r--r--lib/public/db/querybuilder/iexpressionbuilder.php10
-rw-r--r--lib/public/files/cache/icache.php22
-rw-r--r--lib/public/files/storage.php9
-rw-r--r--lib/public/files/storage/istorage.php19
-rw-r--r--lib/public/share/exceptions/genericshareexception.php28
-rw-r--r--lib/public/share/exceptions/sharenotfound.php (renamed from lib/private/share20/exception/sharenotfound.php)11
-rw-r--r--lib/public/share/imanager.php20
-rw-r--r--lib/public/share/ishare.php54
-rw-r--r--lib/public/share/ishareprovider.php22
-rw-r--r--resources/codesigning/core.crt50
-rw-r--r--resources/codesigning/core.key51
-rw-r--r--resources/codesigning/root.crt90
-rw-r--r--resources/codesigning/root.key51
-rw-r--r--resources/config/mimetypealiases.dist.json4
-rw-r--r--resources/config/mimetypemapping.dist.json4
-rw-r--r--settings/css/settings.css4
-rw-r--r--settings/js/users/users.js32
-rw-r--r--settings/templates/personal.php4
-rw-r--r--tests/karma.config.js3
-rw-r--r--tests/lib/appframework/AppTest.php6
-rw-r--r--tests/lib/command/integrity/SignCoreTest.php19
-rw-r--r--tests/lib/comments/comment.php8
-rw-r--r--tests/lib/comments/manager.php56
-rw-r--r--tests/lib/db/querybuilder/expressionbuildertest.php2
-rw-r--r--tests/lib/files/storage/home.php12
-rw-r--r--tests/lib/files/storage/storage.php3
-rw-r--r--tests/lib/integritycheck/checkertest.php12
-rw-r--r--tests/lib/repair/repairmimetypes.php29
-rw-r--r--tests/lib/share/share.php8
-rw-r--r--tests/lib/share20/defaultshareprovidertest.php461
-rw-r--r--tests/lib/share20/managertest.php549
-rw-r--r--version.php2
348 files changed, 6106 insertions, 1962 deletions
diff --git a/.htaccess b/.htaccess
index 4a4adce144c..725efa0971a 100644
--- a/.htaccess
+++ b/.htaccess
@@ -1,9 +1,12 @@
<IfModule mod_headers.c>
- <IfModule mod_fcgid.c>
- <IfModule mod_setenvif.c>
+ <IfModule mod_setenvif.c>
+ <IfModule mod_fcgid.c>
SetEnvIfNoCase ^Authorization$ "(.+)" XAUTHORIZATION=$1
RequestHeader set XAuthorization %{XAUTHORIZATION}e env=XAUTHORIZATION
</IfModule>
+ <IfModule mod_proxy_fcgi.c>
+ SetEnvIfNoCase Authorization "(.+)" HTTP_AUTHORIZATION=$1
+ </IfModule>
</IfModule>
<IfModule mod_env.c>
diff --git a/3rdparty b/3rdparty
-Subproject 177daad35de835dafacc6e84f09e6335cc229a7
+Subproject 7e0c3708d7b44a132e2e360fd39a663af7c1f13
diff --git a/apps/comments/activity/extension.php b/apps/comments/activity/extension.php
new file mode 100644
index 00000000000..b65f1911d17
--- /dev/null
+++ b/apps/comments/activity/extension.php
@@ -0,0 +1,301 @@
+<?php
+/**
+ * @author Joas Schilling <nickvergessen@owncloud.com>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\Comments\Activity;
+
+use OCP\Activity\IExtension;
+use OCP\Activity\IManager;
+use OCP\Comments\ICommentsManager;
+use OCP\Comments\NotFoundException;
+use OCP\IL10N;
+use OCP\IURLGenerator;
+use OCP\L10N\IFactory;
+
+/**
+ * Class Extension
+ *
+ * @package OCA\Comments\Activity
+ */
+class Extension implements IExtension {
+ const APP_NAME = 'comments';
+
+ const ADD_COMMENT_SUBJECT = 'add_comment_subject';
+ const ADD_COMMENT_MESSAGE = 'add_comment_message';
+
+ /** @var IFactory */
+ protected $languageFactory;
+
+ /** @var IManager */
+ protected $activityManager;
+
+ /** @var ICommentsManager */
+ protected $commentsManager;
+
+ /** @var IURLGenerator */
+ protected $URLGenerator;
+
+ /**
+ * @param IFactory $languageFactory
+ * @param IManager $activityManager
+ * @param ICommentsManager $commentsManager
+ * @param IURLGenerator $URLGenerator
+ */
+ public function __construct(IFactory $languageFactory, IManager $activityManager, ICommentsManager $commentsManager, IURLGenerator $URLGenerator) {
+ $this->languageFactory = $languageFactory;
+ $this->activityManager = $activityManager;
+ $this->commentsManager = $commentsManager;
+ $this->URLGenerator = $URLGenerator;
+ }
+
+ protected function getL10N($languageCode = null) {
+ return $this->languageFactory->get(self::APP_NAME, $languageCode);
+ }
+
+ /**
+ * The extension can return an array of additional notification types.
+ * If no additional types are to be added false is to be returned
+ *
+ * @param string $languageCode
+ * @return array|false
+ */
+ public function getNotificationTypes($languageCode) {
+ $l = $this->getL10N($languageCode);
+
+ return array(
+ self::APP_NAME => (string) $l->t('<strong>Comments</strong> for files'),
+ );
+ }
+
+ /**
+ * For a given method additional types to be displayed in the settings can be returned.
+ * In case no additional types are to be added false is to be returned.
+ *
+ * @param string $method
+ * @return array|false
+ */
+ public function getDefaultTypes($method) {
+ return $method === self::METHOD_STREAM ? [self::APP_NAME] : false;
+ }
+
+ /**
+ * A string naming the css class for the icon to be used can be returned.
+ * If no icon is known for the given type false is to be returned.
+ *
+ * @param string $type
+ * @return string|false
+ */
+ public function getTypeIcon($type) {
+ switch ($type) {
+ case self::APP_NAME:
+ return false;
+ }
+
+ return false;
+ }
+
+ /**
+ * The extension can translate a given message to the requested languages.
+ * If no translation is available false is to be returned.
+ *
+ * @param string $app
+ * @param string $text
+ * @param array $params
+ * @param boolean $stripPath
+ * @param boolean $highlightParams
+ * @param string $languageCode
+ * @return string|false
+ */
+ public function translate($app, $text, $params, $stripPath, $highlightParams, $languageCode) {
+ if ($app !== self::APP_NAME) {
+ return false;
+ }
+
+ $l = $this->getL10N($languageCode);
+
+ if ($this->activityManager->isFormattingFilteredObject()) {
+ $translation = $this->translateShort($text, $l, $params);
+ if ($translation !== false) {
+ return $translation;
+ }
+ }
+
+ return $this->translateLong($text, $l, $params);
+ }
+
+ /**
+ * @param string $text
+ * @param IL10N $l
+ * @param array $params
+ * @return bool|string
+ */
+ protected function translateShort($text, IL10N $l, array $params) {
+
+ switch ($text) {
+ case self::ADD_COMMENT_SUBJECT:
+ return (string) $l->t('%1$s commented', $params);
+ case self::ADD_COMMENT_MESSAGE:
+ return $this->convertParameterToComment($params[0], 120);
+ }
+
+ return false;
+ }
+
+ /**
+ * @param string $text
+ * @param IL10N $l
+ * @param array $params
+ * @return bool|string
+ */
+ protected function translateLong($text, IL10N $l, array $params) {
+
+ switch ($text) {
+ case self::ADD_COMMENT_SUBJECT:
+ return (string) $l->t('%1$s commented on %2$s', $params);
+ case self::ADD_COMMENT_MESSAGE:
+ return $this->convertParameterToComment($params[0]);
+ }
+
+ return false;
+ }
+
+ /**
+ * The extension can define the type of parameters for translation
+ *
+ * Currently known types are:
+ * * file => will strip away the path of the file and add a tooltip with it
+ * * username => will add the avatar of the user
+ *
+ * @param string $app
+ * @param string $text
+ * @return array|false
+ */
+ public function getSpecialParameterList($app, $text) {
+ if ($app === self::APP_NAME) {
+ switch ($text) {
+ case self::ADD_COMMENT_SUBJECT:
+ return [
+ 0 => 'username',
+ 1 => 'file',
+ ];
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * The extension can define the parameter grouping by returning the index as integer.
+ * In case no grouping is required false is to be returned.
+ *
+ * @param array $activity
+ * @return integer|false
+ */
+ public function getGroupParameter($activity) {
+ return false;
+ }
+
+ /**
+ * The extension can define additional navigation entries. The array returned has to contain two keys 'top'
+ * and 'apps' which hold arrays with the relevant entries.
+ * If no further entries are to be added false is no be returned.
+ *
+ * @return array|false
+ */
+ public function getNavigation() {
+ $l = $this->getL10N();
+ return [
+ 'apps' => [],
+ 'top' => [
+ self::APP_NAME => [
+ 'id' => self::APP_NAME,
+ 'name' => (string) $l->t('Comments'),
+ 'url' => $this->URLGenerator->linkToRoute('activity.Activities.showList', ['filter' => self::APP_NAME]),
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * The extension can check if a custom filter (given by a query string like filter=abc) is valid or not.
+ *
+ * @param string $filterValue
+ * @return boolean
+ */
+ public function isFilterValid($filterValue) {
+ return $filterValue === self::APP_NAME;
+ }
+
+ /**
+ * The extension can filter the types based on the filter if required.
+ * In case no filter is to be applied false is to be returned unchanged.
+ *
+ * @param array $types
+ * @param string $filter
+ * @return array|false
+ */
+ public function filterNotificationTypes($types, $filter) {
+ if ($filter === self::APP_NAME) {
+ return array_intersect($types, [self::APP_NAME]);
+ }
+ return false;
+ }
+
+ /**
+ * For a given filter the extension can specify the sql query conditions including parameters for that query.
+ * In case the extension does not know the filter false is to be returned.
+ * The query condition and the parameters are to be returned as array with two elements.
+ * E.g. return array('`app` = ? and `message` like ?', array('mail', 'ownCloud%'));
+ *
+ * @param string $filter
+ * @return array|false
+ */
+ public function getQueryForFilter($filter) {
+ return false;
+ }
+
+ /**
+ * @param string $parameter
+ * @return string
+ */
+ protected function convertParameterToComment($parameter, $maxLength = 0) {
+ if (preg_match('/^\<parameter\>(\d*)\<\/parameter\>$/', $parameter, $matches)) {
+ try {
+ $comment = $this->commentsManager->get((int) $matches[1]);
+ $message = $comment->getMessage();
+ $message = str_replace("\n", '<br />', str_replace(['<', '>'], ['&lt;', '&gt;'], $message));
+
+ if ($maxLength && isset($message[$maxLength + 20])) {
+ $findSpace = strpos($message, ' ', $maxLength);
+ if ($findSpace !== false && $findSpace < $maxLength + 20) {
+ return substr($message, 0, $findSpace) . '…';
+ }
+ return substr($message, 0, $maxLength + 20) . '…';
+ }
+
+ return $message;
+ } catch (NotFoundException $e) {
+ return '';
+ }
+ }
+
+ return '';
+ }
+}
diff --git a/apps/comments/activity/listener.php b/apps/comments/activity/listener.php
new file mode 100644
index 00000000000..7c6970df837
--- /dev/null
+++ b/apps/comments/activity/listener.php
@@ -0,0 +1,128 @@
+<?php
+/**
+ * @author Joas Schilling <nickvergessen@owncloud.com>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\Comments\Activity;
+
+use OCP\Activity\IManager;
+use OCP\App\IAppManager;
+use OCP\Comments\CommentsEvent;
+use OCP\Files\Config\IMountProviderCollection;
+use OCP\Files\IRootFolder;
+use OCP\Files\Node;
+use OCP\IUser;
+use OCP\IUserSession;
+use OCP\Share;
+
+class Listener {
+ /** @var IManager */
+ protected $activityManager;
+ /** @var IUserSession */
+ protected $session;
+ /** @var \OCP\App\IAppManager */
+ protected $appManager;
+ /** @var \OCP\Files\Config\IMountProviderCollection */
+ protected $mountCollection;
+ /** @var \OCP\Files\IRootFolder */
+ protected $rootFolder;
+
+ /**
+ * Listener constructor.
+ *
+ * @param IManager $activityManager
+ * @param IUserSession $session
+ * @param IAppManager $appManager
+ * @param IMountProviderCollection $mountCollection
+ * @param IRootFolder $rootFolder
+ */
+ public function __construct(IManager $activityManager,
+ IUserSession $session,
+ IAppManager $appManager,
+ IMountProviderCollection $mountCollection,
+ IRootFolder $rootFolder) {
+ $this->activityManager = $activityManager;
+ $this->session = $session;
+ $this->appManager = $appManager;
+ $this->mountCollection = $mountCollection;
+ $this->rootFolder = $rootFolder;
+ }
+
+ /**
+ * @param CommentsEvent $event
+ */
+ public function commentEvent(CommentsEvent $event) {
+ if ($event->getComment()->getObjectType() !== 'files'
+ || !in_array($event->getEvent(), [CommentsEvent::EVENT_ADD])
+ || !$this->appManager->isInstalled('activity')) {
+ // Comment not for file, not adding a comment or no activity-app enabled (save the energy)
+ return;
+ }
+
+ // Get all mount point owners
+ $cache = $this->mountCollection->getMountCache();
+ $mounts = $cache->getMountsForFileId($event->getComment()->getObjectId());
+ if (empty($mounts)) {
+ return;
+ }
+
+ $users = [];
+ foreach ($mounts as $mount) {
+ $owner = $mount->getUser()->getUID();
+ $ownerFolder = $this->rootFolder->getUserFolder($owner);
+ $nodes = $ownerFolder->getById($event->getComment()->getObjectId());
+ if (!empty($nodes)) {
+ /** @var Node $node */
+ $node = array_shift($nodes);
+ $path = $node->getPath();
+ if (strpos($path, '/' . $owner . '/files/') === 0) {
+ $path = substr($path, strlen('/' . $owner . '/files'));
+ }
+ // Get all users that have access to the mount point
+ $users = array_merge($users, Share::getUsersSharingFile($path, $owner, true, true));
+ }
+ }
+
+ $actor = $this->session->getUser();
+ if ($actor instanceof IUser) {
+ $actor = $actor->getUID();
+ } else {
+ $actor = '';
+ }
+
+ $activity = $this->activityManager->generateEvent();
+ $activity->setApp(Extension::APP_NAME)
+ ->setType(Extension::APP_NAME)
+ ->setAuthor($actor)
+ ->setObject($event->getComment()->getObjectType(), $event->getComment()->getObjectId())
+ ->setMessage(Extension::ADD_COMMENT_MESSAGE, [
+ $event->getComment()->getId(),
+ ]);
+
+ foreach ($users as $user => $path) {
+ $activity->setAffectedUser($user);
+
+ $activity->setSubject(Extension::ADD_COMMENT_SUBJECT, [
+ $actor,
+ $path,
+ ]);
+ $this->activityManager->publish($activity);
+ }
+ }
+}
diff --git a/apps/comments/appinfo/app.php b/apps/comments/appinfo/app.php
index c6f36567c51..e76f598c807 100644
--- a/apps/comments/appinfo/app.php
+++ b/apps/comments/appinfo/app.php
@@ -27,8 +27,26 @@ $eventDispatcher->addListener(
\OCP\Util::addScript('comments', 'app');
\OCP\Util::addScript('comments', 'commentmodel');
\OCP\Util::addScript('comments', 'commentcollection');
+ \OCP\Util::addScript('comments', 'commentsummarymodel');
\OCP\Util::addScript('comments', 'commentstabview');
\OCP\Util::addScript('comments', 'filesplugin');
\OCP\Util::addStyle('comments', 'comments');
}
);
+
+$activityManager = \OC::$server->getActivityManager();
+$activityManager->registerExtension(function() {
+ $application = new \OCP\AppFramework\App('comments');
+ /** @var \OCA\Comments\Activity\Extension $extension */
+ $extension = $application->getContainer()->query('OCA\Comments\Activity\Extension');
+ return $extension;
+});
+
+$managerListener = function(\OCP\Comments\CommentsEvent $event) use ($activityManager) {
+ $application = new \OCP\AppFramework\App('comments');
+ /** @var \OCA\Comments\Activity\Listener $listener */
+ $listener = $application->getContainer()->query('OCA\Comments\Activity\Listener');
+ $listener->commentEvent($event);
+};
+
+$eventDispatcher->addListener(\OCP\Comments\CommentsEvent::EVENT_ADD, $managerListener);
diff --git a/apps/comments/appinfo/info.xml b/apps/comments/appinfo/info.xml
index 550c79448cf..2003fc5c096 100644
--- a/apps/comments/appinfo/info.xml
+++ b/apps/comments/appinfo/info.xml
@@ -6,11 +6,11 @@
<licence>AGPL</licence>
<author>Arthur Shiwon, Vincent Petry</author>
<default_enable/>
- <version>0.1</version>
+ <version>0.2</version>
<dependencies>
<owncloud min-version="9.0" max-version="9.0" />
</dependencies>
- <documentation>
- <user>user-comments</user>
- </documentation>
+ <types>
+ <logging/>
+ </types>
</info>
diff --git a/apps/comments/css/comments.css b/apps/comments/css/comments.css
index c1624dcc57b..85569102e1d 100644
--- a/apps/comments/css/comments.css
+++ b/apps/comments/css/comments.css
@@ -14,7 +14,7 @@
#commentsTabView .newCommentForm .message {
width: 90%;
- resize: none;
+ resize: vertical;
}
#commentsTabView .newCommentForm .submitLoading {
@@ -49,3 +49,42 @@
position: absolute;
right: 0;
}
+
+#commentsTabView .comment .action {
+ opacity: 0;
+ vertical-align: middle;
+ display: inline-block;
+}
+
+#commentsTabView .comment:hover .action {
+ opacity: 0.3;
+}
+
+#commentsTabView .comment .action:hover {
+ opacity: 1;
+}
+
+#commentsTabView .comment .action.delete {
+ position: absolute;
+ right: 0;
+}
+
+#commentsTabView .comment.disabled {
+ opacity: 0.3;
+}
+
+#commentsTabView .comment.disabled .action {
+ visibility: hidden;
+}
+
+#commentsTabView .message.error {
+ color: #e9322d;
+ border-color: #e9322d;
+ -webkit-box-shadow: 0 0 6px #f8b9b7;
+ -moz-box-shadow: 0 0 6px #f8b9b7;
+ box-shadow: 0 0 6px #f8b9b7;
+}
+
+.app-files .action-comment>img {
+ margin-right: 5px;
+}
diff --git a/apps/comments/js/commentcollection.js b/apps/comments/js/commentcollection.js
index d10e5e00865..a15039cf484 100644
--- a/apps/comments/js/commentcollection.js
+++ b/apps/comments/js/commentcollection.js
@@ -10,8 +10,6 @@
(function(OC, OCA) {
- var NS_OWNCLOUD = 'http://owncloud.org/ns';
-
/**
* @class OCA.Comments.CommentCollection
* @classdesc
@@ -26,12 +24,40 @@
model: OCA.Comments.CommentModel,
+ /**
+ * Object type
+ *
+ * @type string
+ */
_objectType: 'files',
+
+ /**
+ * Object id
+ *
+ * @type string
+ */
_objectId: null,
+ /**
+ * True if there are no more page results left to fetch
+ *
+ * @type bool
+ */
_endReached: false,
+
+ /**
+ * Number of comments to fetch per page
+ *
+ * @type int
+ */
_limit : 20,
+ /**
+ * Initializes the collection
+ *
+ * @param {string} [options.objectType] object type
+ * @param {string} [options.objectId] object id
+ */
initialize: function(models, options) {
options = options || {};
if (options.objectType) {
@@ -58,6 +84,7 @@
reset: function() {
this._endReached = false;
+ this._summaryModel = null;
return OC.Backbone.Collection.prototype.reset.apply(this, arguments);
},
@@ -81,6 +108,7 @@
var success = options.success;
options = _.extend({
remove: false,
+ parse: true,
data: body,
davProperties: CommentCollection.prototype.model.prototype.davProperties,
success: function(resp) {
@@ -102,6 +130,35 @@
}, options);
return this.sync('REPORT', this, options);
+ },
+
+ /**
+ * Returns the matching summary model
+ *
+ * @return {OCA.Comments.CommentSummaryModel} summary model
+ */
+ getSummaryModel: function() {
+ if (!this._summaryModel) {
+ this._summaryModel = new OCA.Comments.CommentSummaryModel({
+ id: this._objectId,
+ objectType: this._objectType
+ });
+ }
+ return this._summaryModel;
+ },
+
+ /**
+ * Updates the read marker for this comment thread
+ *
+ * @param {Date} [date] optional date, defaults to now
+ * @param {Object} [options] backbone options
+ */
+ updateReadMarker: function(date, options) {
+ options = options || {};
+
+ return this.getSummaryModel().save({
+ readMarker: (date || new Date()).toUTCString()
+ }, options);
}
});
diff --git a/apps/comments/js/commentmodel.js b/apps/comments/js/commentmodel.js
index b945f71fdd2..89492707b61 100644
--- a/apps/comments/js/commentmodel.js
+++ b/apps/comments/js/commentmodel.js
@@ -34,12 +34,22 @@
'actorDisplayName': '{' + NS_OWNCLOUD + '}actorDisplayName',
'creationDateTime': '{' + NS_OWNCLOUD + '}creationDateTime',
'objectType': '{' + NS_OWNCLOUD + '}objectType',
- 'objectId': '{' + NS_OWNCLOUD + '}objectId'
+ 'objectId': '{' + NS_OWNCLOUD + '}objectId',
+ 'isUnread': '{' + NS_OWNCLOUD + '}isUnread'
},
parse: function(data) {
- // TODO: parse non-string values
- return data;
+ return {
+ id: data.id,
+ message: data.message,
+ actorType: data.actorType,
+ actorId: data.actorId,
+ actorDisplayName: data.actorDisplayName,
+ creationDateTime: data.creationDateTime,
+ objectType: data.objectType,
+ objectId: data.objectId,
+ isUnread: (data.isUnread === 'true')
+ };
}
});
diff --git a/apps/comments/js/commentstabview.js b/apps/comments/js/commentstabview.js
index 463ac2d76ef..d75cf39538c 100644
--- a/apps/comments/js/commentstabview.js
+++ b/apps/comments/js/commentstabview.js
@@ -8,35 +8,48 @@
*
*/
+/* global Handlebars */
+
(function(OC, OCA) {
var TEMPLATE =
- '<div class="newCommentRow comment">' +
+ '<ul class="comments">' +
+ '</ul>' +
+ '<div class="empty hidden">{{emptyResultLabel}}</div>' +
+ '<input type="button" class="showMore hidden" value="{{moreLabel}}"' +
+ ' name="show-more" id="show-more" />' +
+ '<div class="loading hidden" style="height: 50px"></div>';
+
+ var EDIT_COMMENT_TEMPLATE =
+ '<div class="newCommentRow comment" data-id="{{id}}">' +
' <div class="authorRow">' +
' {{#if avatarEnabled}}' +
- ' <div class="avatar" data-username="{{userId}}"></div>' +
+ ' <div class="avatar" data-username="{{actorId}}"></div>' +
' {{/if}}' +
- ' <div class="author">{{userDisplayName}}</div>' +
+ ' <div class="author">{{actorDisplayName}}</div>' +
+ '{{#if isEditMode}}' +
+ ' <a href="#" class="action delete icon icon-delete has-tooltip" title="{{deleteTooltip}}"></a>' +
+ '{{/if}}' +
' </div>' +
' <form class="newCommentForm">' +
- ' <textarea class="message" placeholder="{{newMessagePlaceholder}}"></textarea>' +
+ ' <textarea class="message" placeholder="{{newMessagePlaceholder}}">{{{message}}}</textarea>' +
' <input class="submit" type="submit" value="{{submitText}}" />' +
+ '{{#if isEditMode}}' +
+ ' <input class="cancel" type="button" value="{{cancelText}}" />' +
+ '{{/if}}' +
' <div class="submitLoading icon-loading-small hidden"></div>'+
' </form>' +
- ' <ul class="comments">' +
- ' </ul>' +
- '</div>' +
- '<div class="empty hidden">{{emptyResultLabel}}</div>' +
- '<input type="button" class="showMore hidden" value="{{moreLabel}}"' +
- ' name="show-more" id="show-more" />' +
- '<div class="loading hidden" style="height: 50px"></div>';
+ '</div>';
var COMMENT_TEMPLATE =
- '<li class="comment">' +
+ '<li class="comment{{#if isUnread}} unread{{/if}}" data-id="{{id}}">' +
' <div class="authorRow">' +
' {{#if avatarEnabled}}' +
- ' <div class="avatar" data-username="{{actorId}}"> </div>' +
+ ' <div class="avatar" {{#if actorId}}data-username="{{actorId}}"{{/if}}> </div>' +
' {{/if}}' +
' <div class="author">{{actorDisplayName}}</div>' +
+ '{{#if isUserAuthor}}' +
+ ' <a href="#" class="action edit icon icon-rename has-tooltip" title="{{editTooltip}}"></a>' +
+ '{{/if}}' +
' <div class="date has-tooltip" title="{{altDate}}">{{date}}</div>' +
' </div>' +
' <div class="message">{{{formattedMessage}}}</div>' +
@@ -52,9 +65,14 @@
events: {
'submit .newCommentForm': '_onSubmitComment',
- 'click .showMore': '_onClickShowMore'
+ 'click .showMore': '_onClickShowMore',
+ 'click .action.edit': '_onClickEditComment',
+ 'click .action.delete': '_onClickDeleteComment',
+ 'click .cancel': '_onClickCloseComment'
},
+ _commentMaxLength: 1000,
+
initialize: function() {
OCA.Files.DetailTabView.prototype.initialize.apply(this, arguments);
this.collection = new OCA.Comments.CommentCollection();
@@ -64,8 +82,10 @@
this._avatarsEnabled = !!OC.config.enable_avatars;
+ this._commentMaxThreshold = this._commentMaxLength * 0.9;
+
// TODO: error handling
- _.bindAll(this, '_onSubmitComment');
+ _.bindAll(this, '_onTypeComment');
},
template: function(params) {
@@ -75,10 +95,24 @@
var currentUser = OC.getCurrentUser();
return this._template(_.extend({
avatarEnabled: this._avatarsEnabled,
- userId: currentUser.uid,
- userDisplayName: currentUser.displayName,
+ actorId: currentUser.uid,
+ actorDisplayName: currentUser.displayName
+ }, params));
+ },
+
+ editCommentTemplate: function(params) {
+ if (!this._editCommentTemplate) {
+ this._editCommentTemplate = Handlebars.compile(EDIT_COMMENT_TEMPLATE);
+ }
+ var currentUser = OC.getCurrentUser();
+ return this._editCommentTemplate(_.extend({
+ avatarEnabled: this._avatarsEnabled,
+ actorId: currentUser.uid,
+ actorDisplayName: currentUser.displayName,
newMessagePlaceholder: t('comments', 'Type in a new comment...'),
- submitText: t('comments', 'Post')
+ deleteTooltip: t('comments', 'Delete comment'),
+ submitText: t('comments', 'Post'),
+ cancelText: t('comments', 'Cancel')
}, params));
},
@@ -86,9 +120,20 @@
if (!this._commentTemplate) {
this._commentTemplate = Handlebars.compile(COMMENT_TEMPLATE);
}
- return this._commentTemplate(_.extend({
- avatarEnabled: this._avatarsEnabled
- }, params));
+
+ params = _.extend({
+ avatarEnabled: this._avatarsEnabled,
+ editTooltip: t('comments', 'Edit comment'),
+ isUserAuthor: OC.getCurrentUser().uid === params.actorId
+ }, params);
+
+ if (params.actorType === 'deleted_users') {
+ // makes the avatar a X
+ params.actorId = null;
+ params.actorDisplayName = t('comments', '[Deleted user]');
+ }
+
+ return this._commentTemplate(params);
},
getLabel: function() {
@@ -97,12 +142,14 @@
setFileInfo: function(fileInfo) {
if (fileInfo) {
+ this.model = fileInfo;
this.render();
this.collection.setObjectId(fileInfo.id);
// reset to first page
this.collection.reset([], {silent: true});
this.nextPage();
} else {
+ this.model = null;
this.render();
this.collection.reset();
}
@@ -113,10 +160,14 @@
emptyResultLabel: t('comments', 'No other comments available'),
moreLabel: t('comments', 'More comments...')
}));
+ this.$el.find('.comments').before(this.editCommentTemplate({}));
this.$el.find('.has-tooltip').tooltip();
this.$container = this.$el.find('ul.comments');
- this.$el.find('.avatar').avatar(OC.getCurrentUser().uid, 28);
+ if (this._avatarsEnabled) {
+ this.$el.find('.avatar').avatar(OC.getCurrentUser().uid, 28);
+ }
this.delegateEvents();
+ this.$el.find('textarea').on('keyup input change', this._onTypeComment);
},
_formatItem: function(commentModel) {
@@ -134,15 +185,36 @@
this.$el.find('.loading').toggleClass('hidden', !state);
},
- _onRequest: function() {
- this._toggleLoading(true);
- this.$el.find('.showMore').addClass('hidden');
+ _onRequest: function(type) {
+ if (type === 'REPORT') {
+ this._toggleLoading(true);
+ this.$el.find('.showMore').addClass('hidden');
+ }
},
- _onEndRequest: function() {
+ _onEndRequest: function(type) {
+ var fileInfoModel = this.model;
this._toggleLoading(false);
this.$el.find('.empty').toggleClass('hidden', !!this.collection.length);
this.$el.find('.showMore').toggleClass('hidden', !this.collection.hasMoreResults());
+
+ if (type !== 'REPORT') {
+ return;
+ }
+
+ // find first unread comment
+ var firstUnreadComment = this.collection.findWhere({isUnread: true});
+ if (firstUnreadComment) {
+ // update read marker
+ this.collection.updateReadMarker(
+ null,
+ {
+ success: function() {
+ fileInfoModel.set('commentsUnread', 0);
+ }
+ }
+ );
+ }
},
_onAddModel: function(model, collection, options) {
@@ -182,13 +254,91 @@
this.collection.fetchNext();
},
+ _onClickEditComment: function(ev) {
+ ev.preventDefault();
+ var $comment = $(ev.target).closest('.comment');
+ var commentId = $comment.data('id');
+ var commentToEdit = this.collection.get(commentId);
+ var $formRow = $(this.editCommentTemplate(_.extend({
+ isEditMode: true,
+ submitText: t('comments', 'Save')
+ }, commentToEdit.attributes)));
+
+ $comment.addClass('hidden');
+ // spawn form
+ $comment.after($formRow);
+ $formRow.data('commentEl', $comment);
+ $formRow.find('textarea').on('keyup input change', this._onTypeComment);
+
+ // copy avatar element from original to avoid flickering
+ $formRow.find('.avatar').replaceWith($comment.find('.avatar').clone());
+ $formRow.find('.has-tooltip').tooltip();
+
+ return false;
+ },
+
+ _onTypeComment: function(ev) {
+ var $field = $(ev.target);
+ var len = $field.val().length;
+ var $submitButton = $field.data('submitButtonEl');
+ if (!$submitButton) {
+ $submitButton = $field.closest('form').find('.submit');
+ $field.data('submitButtonEl', $submitButton);
+ }
+ $field.tooltip('hide');
+ if (len > this._commentMaxThreshold) {
+ $field.attr('data-original-title', t('comments', 'Allowed characters {count} of {max}', {count: len, max: this._commentMaxLength}));
+ $field.tooltip({trigger: 'manual'});
+ $field.tooltip('show');
+ $field.addClass('error');
+ }
+
+ var limitExceeded = (len > this._commentMaxLength);
+ $field.toggleClass('error', limitExceeded);
+ $submitButton.prop('disabled', limitExceeded);
+ },
+
+ _onClickCloseComment: function(ev) {
+ ev.preventDefault();
+ var $row = $(ev.target).closest('.comment');
+ $row.data('commentEl').removeClass('hidden');
+ $row.remove();
+ return false;
+ },
+
+ _onClickDeleteComment: function(ev) {
+ ev.preventDefault();
+ var $comment = $(ev.target).closest('.comment');
+ var commentId = $comment.data('id');
+ var $loading = $comment.find('.submitLoading');
+
+ $comment.addClass('disabled');
+ $loading.removeClass('hidden');
+ this.collection.get(commentId).destroy({
+ success: function() {
+ $comment.data('commentEl').remove();
+ $comment.remove();
+ },
+ error: function(msg) {
+ $loading.addClass('hidden');
+ $comment.removeClass('disabled');
+ OC.Notification.showTemporary(msg);
+ }
+ });
+
+
+ return false;
+ },
+
_onClickShowMore: function(ev) {
ev.preventDefault();
this.nextPage();
},
_onSubmitComment: function(e) {
+ var self = this;
var $form = $(e.target);
+ var commentId = $form.closest('.comment').data('id');
var currentUser = OC.getCurrentUser();
var $submit = $form.find('.submit');
var $loading = $form.find('.submitLoading');
@@ -196,7 +346,7 @@
var message = $textArea.val().trim();
e.preventDefault();
- if (!message.length) {
+ if (!message.length || message.length > this._commentMaxLength) {
return;
}
@@ -204,28 +354,56 @@
$submit.addClass('hidden');
$loading.removeClass('hidden');
- this.collection.create({
- actorId: currentUser.uid,
- actorDisplayName: currentUser.displayName,
- actorType: 'users',
- verb: 'comment',
- message: $textArea.val(),
- creationDateTime: (new Date()).getTime()
- }, {
- at: 0,
- success: function() {
- $submit.removeClass('hidden');
- $loading.addClass('hidden');
- $textArea.val('').prop('disabled', false);
- },
- error: function(msg) {
- $submit.removeClass('hidden');
- $loading.addClass('hidden');
- $textArea.prop('disabled', false);
+ if (commentId) {
+ // edit mode
+ var comment = this.collection.get(commentId);
+ comment.save({
+ message: $textArea.val()
+ }, {
+ success: function(model) {
+ var $row = $form.closest('.comment');
+ $submit.removeClass('hidden');
+ $loading.addClass('hidden');
+ $row.data('commentEl')
+ .removeClass('hidden')
+ .find('.message')
+ .html(self._formatMessage(model.get('message')));
+ $row.remove();
+ },
+ error: function(msg) {
+ $submit.removeClass('hidden');
+ $loading.addClass('hidden');
+ $textArea.prop('disabled', false);
- OC.Notification.showTemporary(msg);
- }
- });
+ OC.Notification.showTemporary(msg);
+ }
+ });
+ } else {
+ this.collection.create({
+ actorId: currentUser.uid,
+ actorDisplayName: currentUser.displayName,
+ actorType: 'users',
+ verb: 'comment',
+ message: $textArea.val(),
+ creationDateTime: (new Date()).toUTCString()
+ }, {
+ at: 0,
+ // wait for real creation before adding
+ wait: true,
+ success: function() {
+ $submit.removeClass('hidden');
+ $loading.addClass('hidden');
+ $textArea.val('').prop('disabled', false);
+ },
+ error: function(msg) {
+ $submit.removeClass('hidden');
+ $loading.addClass('hidden');
+ $textArea.prop('disabled', false);
+
+ OC.Notification.showTemporary(msg);
+ }
+ });
+ }
return false;
}
diff --git a/apps/comments/js/commentsummarymodel.js b/apps/comments/js/commentsummarymodel.js
new file mode 100644
index 00000000000..d405315ca1f
--- /dev/null
+++ b/apps/comments/js/commentsummarymodel.js
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2016
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+(function(OC, OCA) {
+ var NS_OWNCLOUD = 'http://owncloud.org/ns';
+ /**
+ * @class OCA.Comments.CommentSummaryModel
+ * @classdesc
+ *
+ * Model containing summary information related to comments
+ * like the read marker.
+ *
+ */
+ var CommentSummaryModel = OC.Backbone.Model.extend(
+ /** @lends OCA.Comments.CommentSummaryModel.prototype */ {
+ sync: OC.Backbone.davSync,
+
+ /**
+ * Object type
+ *
+ * @type string
+ */
+ _objectType: 'files',
+
+ /**
+ * Object id
+ *
+ * @type string
+ */
+ _objectId: null,
+
+ davProperties: {
+ 'readMarker': '{' + NS_OWNCLOUD + '}readMarker'
+ },
+
+ /**
+ * Initializes the summary model
+ *
+ * @param {string} [options.objectType] object type
+ * @param {string} [options.objectId] object id
+ */
+ initialize: function(attrs, options) {
+ options = options || {};
+ if (options.objectType) {
+ this._objectType = options.objectType;
+ }
+ },
+
+ url: function() {
+ return OC.linkToRemote('dav') + '/comments/' +
+ encodeURIComponent(this._objectType) + '/' +
+ encodeURIComponent(this.id) + '/';
+ }
+ });
+
+ OCA.Comments.CommentSummaryModel = CommentSummaryModel;
+})(OC, OCA);
+
diff --git a/apps/comments/js/filesplugin.js b/apps/comments/js/filesplugin.js
index c8d91e0ede3..bf6bb05146b 100644
--- a/apps/comments/js/filesplugin.js
+++ b/apps/comments/js/filesplugin.js
@@ -8,7 +8,15 @@
*
*/
+/* global Handlebars */
+
(function() {
+ var TEMPLATE_COMMENTS_UNREAD =
+ '<a class="action action-comment permanent" title="{{countMessage}}" href="#">' +
+ '<img class="svg" src="{{iconUrl}}"/>' +
+ '{{count}}' +
+ '</a>';
+
OCA.Comments = _.extend({}, OCA.Comments);
if (!OCA.Comments) {
/**
@@ -26,12 +34,88 @@
'favorites'
],
+ _formatCommentCount: function(count) {
+ if (!this._commentsUnreadTemplate) {
+ this._commentsUnreadTemplate = Handlebars.compile(TEMPLATE_COMMENTS_UNREAD);
+ }
+ return this._commentsUnreadTemplate({
+ count: count,
+ countMessage: t('comments', '{count} unread comments', {count: count}),
+ iconUrl: OC.imagePath('core', 'actions/comment')
+ });
+ },
+
attach: function(fileList) {
+ var self = this;
if (this.allowedLists.indexOf(fileList.id) < 0) {
return;
}
fileList.registerTabView(new OCA.Comments.CommentsTabView('commentsTabView'));
+
+ var NS_OC = 'http://owncloud.org/ns';
+
+ var oldGetWebdavProperties = fileList._getWebdavProperties;
+ fileList._getWebdavProperties = function() {
+ var props = oldGetWebdavProperties.apply(this, arguments);
+ props.push('{' + NS_OC + '}comments-unread');
+ return props;
+ };
+
+ fileList.filesClient.addFileInfoParser(function(response) {
+ var data = {};
+ var props = response.propStat[0].properties;
+ var commentsUnread = props['{' + NS_OC + '}comments-unread'];
+ if (!_.isUndefined(commentsUnread) && commentsUnread !== '') {
+ data.commentsUnread = parseInt(commentsUnread, 10);
+ }
+ return data;
+ });
+
+ fileList.$el.addClass('has-comments');
+ var oldCreateRow = fileList._createRow;
+ fileList._createRow = function(fileData) {
+ var $tr = oldCreateRow.apply(this, arguments);
+ if (fileData.commentsUnread) {
+ $tr.attr('data-comments-unread', fileData.commentsUnread);
+ }
+ return $tr;
+ };
+
+ // register "comment" action for reading comments
+ fileList.fileActions.registerAction({
+ name: 'Comment',
+ displayName: t('comments', 'Comment'),
+ mime: 'all',
+ permissions: OC.PERMISSION_READ,
+ type: OCA.Files.FileActions.TYPE_INLINE,
+ render: function(actionSpec, isDefault, context) {
+ var $file = context.$file;
+ var unreadComments = $file.data('comments-unread');
+ if (unreadComments) {
+ var $actionLink = $(self._formatCommentCount(unreadComments));
+ context.$file.find('a.name>span.fileactions').append($actionLink);
+ return $actionLink;
+ }
+ return '';
+ },
+ actionHandler: function(fileName, context) {
+ context.$file.find('.action-comment').tooltip('hide');
+ // open sidebar in comments section
+ context.fileList.showDetailsView(fileName, 'commentsTabView');
+ }
+ });
+
+ // add attribute to "elementToFile"
+ var oldElementToFile = fileList.elementToFile;
+ fileList.elementToFile = function($el) {
+ var fileInfo = oldElementToFile.apply(this, arguments);
+ var commentsUnread = $el.data('comments-unread');
+ if (commentsUnread) {
+ fileInfo.commentsUnread = commentsUnread;
+ }
+ return fileInfo;
+ };
}
};
diff --git a/apps/comments/tests/js/commentscollectionSpec.js b/apps/comments/tests/js/commentscollectionSpec.js
index 0dc68cc167c..2f41a272f67 100644
--- a/apps/comments/tests/js/commentscollectionSpec.js
+++ b/apps/comments/tests/js/commentscollectionSpec.js
@@ -100,5 +100,49 @@ describe('OCA.Comments.CommentCollection', function() {
expect(collection.hasMoreResults()).toEqual(true);
});
+ describe('resetting read marker', function() {
+ var updateStub;
+ var clock;
+
+ beforeEach(function() {
+ updateStub = sinon.stub(OCA.Comments.CommentSummaryModel.prototype, 'save');
+ clock = sinon.useFakeTimers(Date.UTC(2016, 1, 3, 10, 5, 9));
+ });
+ afterEach(function() {
+ updateStub.restore();
+ clock.restore();
+ });
+
+ it('resets read marker to the default date', function() {
+ var successStub = sinon.stub();
+ collection.updateReadMarker(null, {
+ success: successStub
+ });
+
+ expect(updateStub.calledOnce).toEqual(true);
+ expect(updateStub.lastCall.args[0]).toEqual({
+ readMarker: new Date(Date.UTC(2016, 1, 3, 10, 5, 9)).toUTCString()
+ });
+
+ updateStub.yieldTo('success');
+
+ expect(successStub.calledOnce).toEqual(true);
+ });
+ it('resets read marker to the given date', function() {
+ var successStub = sinon.stub();
+ collection.updateReadMarker(new Date(Date.UTC(2016, 1, 2, 3, 4, 5)), {
+ success: successStub
+ });
+
+ expect(updateStub.calledOnce).toEqual(true);
+ expect(updateStub.lastCall.args[0]).toEqual({
+ readMarker: new Date(Date.UTC(2016, 1, 2, 3, 4, 5)).toUTCString()
+ });
+
+ updateStub.yieldTo('success');
+
+ expect(successStub.calledOnce).toEqual(true);
+ });
+ });
});
diff --git a/apps/comments/tests/js/commentstabviewSpec.js b/apps/comments/tests/js/commentstabviewSpec.js
index 0fb5eec0653..70930da7520 100644
--- a/apps/comments/tests/js/commentstabviewSpec.js
+++ b/apps/comments/tests/js/commentstabviewSpec.js
@@ -25,6 +25,20 @@ describe('OCA.Comments.CommentsTabView tests', function() {
var testComments;
var clock;
+ /**
+ * Creates a dummy message with the given length
+ *
+ * @param {int} len length
+ * @return {string} message
+ */
+ function createMessageWithLength(len) {
+ var bigMessage = '';
+ for (var i = 0; i < len; i++) {
+ bigMessage += 'a';
+ }
+ return bigMessage;
+ }
+
beforeEach(function() {
clock = sinon.useFakeTimers(Date.UTC(2016, 1, 3, 10, 5, 9));
fetchStub = sinon.stub(OCA.Comments.CommentCollection.prototype, 'fetchNext');
@@ -48,7 +62,7 @@ describe('OCA.Comments.CommentsTabView tests', function() {
objectType: 'files',
objectId: 5,
message: 'First',
- creationDateTime: Date.UTC(2016, 1, 3, 10, 5, 0)
+ creationDateTime: new Date(Date.UTC(2016, 1, 3, 10, 5, 0)).toUTCString()
});
var comment2 = new OCA.Comments.CommentModel({
id: 2,
@@ -58,7 +72,7 @@ describe('OCA.Comments.CommentsTabView tests', function() {
objectType: 'files',
objectId: 5,
message: 'Second\nNewline',
- creationDateTime: Date.UTC(2016, 1, 3, 10, 0, 0)
+ creationDateTime: new Date(Date.UTC(2016, 1, 3, 10, 0, 0)).toUTCString()
});
testComments = [comment1, comment2];
@@ -84,7 +98,6 @@ describe('OCA.Comments.CommentsTabView tests', function() {
});
it('renders comments', function() {
-
view.setFileInfo(fileInfoModel);
view.collection.set(testComments);
@@ -100,6 +113,15 @@ describe('OCA.Comments.CommentsTabView tests', function() {
expect($item.find('.date').text()).toEqual('5 minutes ago');
expect($item.find('.message').html()).toEqual('Second<br>Newline');
});
+
+ it('renders comments from deleted user differently', function() {
+ testComments[0].set('actorType', 'deleted_users', {silent: true});
+ view.collection.set(testComments);
+
+ var $item = view.$el.find('.comment[data-id=1]');
+ expect($item.find('.author').text()).toEqual('[Deleted user]');
+ expect($item.find('.avatar').attr('data-username')).not.toBeDefined();
+ });
});
describe('more comments', function() {
var hasMoreResultsStub;
@@ -142,7 +164,7 @@ describe('OCA.Comments.CommentsTabView tests', function() {
objectType: 'files',
objectId: 5,
message: 'Third',
- creationDateTime: Date.UTC(2016, 1, 3, 5, 0, 0)
+ creationDateTime: new Date(Date.UTC(2016, 1, 3, 5, 0, 0)).toUTCString()
});
view.collection.add(comment3);
@@ -184,7 +206,7 @@ describe('OCA.Comments.CommentsTabView tests', function() {
actorType: 'users',
verb: 'comment',
message: 'New message',
- creationDateTime: Date.UTC(2016, 1, 3, 10, 5, 9)
+ creationDateTime: new Date(Date.UTC(2016, 1, 3, 10, 5, 9)).toUTCString()
});
});
it('does not create a comment if the field is empty', function() {
@@ -193,6 +215,238 @@ describe('OCA.Comments.CommentsTabView tests', function() {
expect(createStub.notCalled).toEqual(true);
});
+ it('does not create a comment if the field length is too large', function() {
+ var bigMessage = '';
+ for (var i = 0; i < view._commentMaxLength * 2; i++) {
+ bigMessage += 'a';
+ }
+ view.$el.find('.message').val(bigMessage);
+ view.$el.find('form').submit();
+
+ expect(createStub.notCalled).toEqual(true);
+ });
+ describe('limit indicator', function() {
+ var tooltipStub;
+ var $message;
+ var $submitButton;
+
+ beforeEach(function() {
+ tooltipStub = sinon.stub($.fn, 'tooltip');
+ $message = view.$el.find('.message');
+ $submitButton = view.$el.find('.submit');
+ });
+ afterEach(function() {
+ tooltipStub.restore();
+ });
+
+ it('does not displays tooltip when limit is far away', function() {
+ $message.val(createMessageWithLength(3));
+ $message.trigger('change');
+
+ expect(tooltipStub.calledWith('show')).toEqual(false);
+ expect($submitButton.prop('disabled')).toEqual(false);
+ expect($message.hasClass('error')).toEqual(false);
+ });
+ it('displays tooltip when limit is almost reached', function() {
+ $message.val(createMessageWithLength(view._commentMaxLength - 2));
+ $message.trigger('change');
+
+ expect(tooltipStub.calledWith('show')).toEqual(true);
+ expect($submitButton.prop('disabled')).toEqual(false);
+ expect($message.hasClass('error')).toEqual(false);
+ });
+ it('displays tooltip and disabled button when limit is exceeded', function() {
+ $message.val(createMessageWithLength(view._commentMaxLength + 2));
+ $message.trigger('change');
+
+ expect(tooltipStub.calledWith('show')).toEqual(true);
+ expect($submitButton.prop('disabled')).toEqual(true);
+ expect($message.hasClass('error')).toEqual(true);
+ });
+ });
+ });
+ describe('editing comments', function() {
+ var saveStub;
+ var currentUserStub;
+
+ beforeEach(function() {
+ saveStub = sinon.stub(OCA.Comments.CommentModel.prototype, 'save');
+ currentUserStub = sinon.stub(OC, 'getCurrentUser');
+ currentUserStub.returns({
+ uid: 'testuser',
+ displayName: 'Test User'
+ });
+ view.collection.add({
+ id: 1,
+ actorId: 'testuser',
+ actorDisplayName: 'Test User',
+ actorType: 'users',
+ verb: 'comment',
+ message: 'New message',
+ creationDateTime: new Date(Date.UTC(2016, 1, 3, 10, 5, 9)).toUTCString()
+ });
+ view.collection.add({
+ id: 2,
+ actorId: 'anotheruser',
+ actorDisplayName: 'Another User',
+ actorType: 'users',
+ verb: 'comment',
+ message: 'New message from another user',
+ creationDateTime: new Date(Date.UTC(2016, 1, 3, 10, 5, 9)).toUTCString()
+ });
+ });
+ afterEach(function() {
+ saveStub.restore();
+ currentUserStub.restore();
+ });
+
+ it('shows edit link for owner comments', function() {
+ var $comment = view.$el.find('.comment[data-id=1]');
+ expect($comment.length).toEqual(1);
+ expect($comment.find('.action.edit').length).toEqual(1);
+ });
+
+ it('does not show edit link for other user\'s comments', function() {
+ var $comment = view.$el.find('.comment[data-id=2]');
+ expect($comment.length).toEqual(1);
+ expect($comment.find('.action.edit').length).toEqual(0);
+ });
+ it('shows edit form when clicking edit', function() {
+ var $comment = view.$el.find('.comment[data-id=1]');
+ $comment.find('.action.edit').click();
+
+ expect($comment.hasClass('hidden')).toEqual(true);
+ var $formRow = view.$el.find('.newCommentRow.comment[data-id=1]');
+ expect($formRow.length).toEqual(1);
+ });
+
+ it('saves message and updates comment item when clicking save', function() {
+ var $comment = view.$el.find('.comment[data-id=1]');
+ $comment.find('.action.edit').click();
+
+ var $formRow = view.$el.find('.newCommentRow.comment[data-id=1]');
+ expect($formRow.length).toEqual(1);
+
+ $formRow.find('textarea').val('modified\nmessage');
+ $formRow.find('form').submit();
+
+ expect(saveStub.calledOnce).toEqual(true);
+ expect(saveStub.lastCall.args[0]).toEqual({
+ message: 'modified\nmessage'
+ });
+
+ var model = view.collection.get(1);
+ // simulate the fact that save sets the attribute
+ model.set('message', 'modified\nmessage');
+ saveStub.yieldTo('success', model);
+
+ // original comment element is visible again
+ expect($comment.hasClass('hidden')).toEqual(false);
+ // and its message was updated
+ expect($comment.find('.message').html()).toEqual('modified<br>message');
+
+ // form row is gone
+ $formRow = view.$el.find('.newCommentRow.comment[data-id=1]');
+ expect($formRow.length).toEqual(0);
+ });
+
+ it('restores original comment when cancelling', function() {
+ var $comment = view.$el.find('.comment[data-id=1]');
+ $comment.find('.action.edit').click();
+
+ var $formRow = view.$el.find('.newCommentRow.comment[data-id=1]');
+ expect($formRow.length).toEqual(1);
+
+ $formRow.find('textarea').val('modified\nmessage');
+ $formRow.find('.cancel').click();
+
+ expect(saveStub.notCalled).toEqual(true);
+
+ // original comment element is visible again
+ expect($comment.hasClass('hidden')).toEqual(false);
+ // and its message was not updated
+ expect($comment.find('.message').html()).toEqual('New message');
+
+ // form row is gone
+ $formRow = view.$el.find('.newCommentRow.comment[data-id=1]');
+ expect($formRow.length).toEqual(0);
+ });
+
+ it('destroys model when clicking delete', function() {
+ var destroyStub = sinon.stub(OCA.Comments.CommentModel.prototype, 'destroy');
+ var $comment = view.$el.find('.comment[data-id=1]');
+ $comment.find('.action.edit').click();
+
+ var $formRow = view.$el.find('.newCommentRow.comment[data-id=1]');
+ expect($formRow.length).toEqual(1);
+
+ $formRow.find('.delete').click();
+
+ expect(destroyStub.calledOnce).toEqual(true);
+ expect(destroyStub.thisValues[0].id).toEqual(1);
+
+ destroyStub.yieldTo('success');
+
+ // original comment element is gone
+ $comment = view.$el.find('.comment[data-id=1]');
+ expect($comment.length).toEqual(0);
+
+ // form row is gone
+ $formRow = view.$el.find('.newCommentRow.comment[data-id=1]');
+ expect($formRow.length).toEqual(0);
+
+ destroyStub.restore();
+ });
+ it('does not submit comment if the field is empty', function() {
+ var $comment = view.$el.find('.comment[data-id=1]');
+ $comment.find('.action.edit').click();
+ $comment.find('.message').val(' ');
+ $comment.find('form').submit();
+
+ expect(saveStub.notCalled).toEqual(true);
+ });
+ it('does not submit comment if the field length is too large', function() {
+ var $comment = view.$el.find('.comment[data-id=1]');
+ $comment.find('.action.edit').click();
+ $comment.find('.message').val(createMessageWithLength(view._commentMaxLength * 2));
+ $comment.find('form').submit();
+
+ expect(saveStub.notCalled).toEqual(true);
+ });
+ });
+ describe('read marker', function() {
+ var updateMarkerStub;
+
+ beforeEach(function() {
+ updateMarkerStub = sinon.stub(OCA.Comments.CommentCollection.prototype, 'updateReadMarker');
+ });
+ afterEach(function() {
+ updateMarkerStub.restore();
+ });
+
+ it('resets the read marker after REPORT', function() {
+ testComments[0].set('isUnread', true, {silent: true});
+ testComments[1].set('isUnread', true, {silent: true});
+ view.collection.set(testComments);
+ view.collection.trigger('sync', 'REPORT');
+
+ expect(updateMarkerStub.calledOnce).toEqual(true);
+ expect(updateMarkerStub.lastCall.args[0]).toBeFalsy();
+ });
+ it('does not reset the read marker if there was no unread comments', function() {
+ view.collection.set(testComments);
+ view.collection.trigger('sync', 'REPORT');
+
+ expect(updateMarkerStub.notCalled).toEqual(true);
+ });
+ it('does not reset the read marker when posting comments', function() {
+ testComments[0].set('isUnread', true, {silent: true});
+ testComments[1].set('isUnread', true, {silent: true});
+ view.collection.set(testComments);
+ view.collection.trigger('sync', 'POST');
+
+ expect(updateMarkerStub.notCalled).toEqual(true);
+ });
});
});
diff --git a/apps/comments/tests/js/filespluginSpec.js b/apps/comments/tests/js/filespluginSpec.js
new file mode 100644
index 00000000000..78becc5af09
--- /dev/null
+++ b/apps/comments/tests/js/filespluginSpec.js
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2016 Vincent Petry <pvince81@owncloud.com>
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+describe('OCA.Comments.FilesPlugin tests', function() {
+ var fileList;
+ var testFiles;
+
+ beforeEach(function() {
+ var $content = $('<div id="content"></div>');
+ $('#testArea').append($content);
+ // dummy file list
+ var $div = $(
+ '<div>' +
+ '<table id="filestable">' +
+ '<thead></thead>' +
+ '<tbody id="fileList"></tbody>' +
+ '</table>' +
+ '</div>');
+ $('#content').append($div);
+
+ fileList = new OCA.Files.FileList($div);
+ OCA.Comments.FilesPlugin.attach(fileList);
+
+ testFiles = [{
+ id: 1,
+ type: 'file',
+ name: 'One.txt',
+ path: '/subdir',
+ mimetype: 'text/plain',
+ size: 12,
+ permissions: OC.PERMISSION_ALL,
+ etag: 'abc',
+ shareOwner: 'User One',
+ isShareMountPoint: false,
+ commentsUnread: 3
+ }];
+ });
+ afterEach(function() {
+ fileList.destroy();
+ fileList = null;
+ });
+
+ describe('Comment icon', function() {
+ it('does not render icon when no unread comments available', function() {
+ testFiles[0].commentsUnread = 0;
+ fileList.setFiles(testFiles);
+ var $tr = fileList.findFileEl('One.txt');
+ expect($tr.find('.action-comment').length).toEqual(0);
+ });
+ it('renders comment icon and extra data', function() {
+ var $action, $tr;
+ fileList.setFiles(testFiles);
+ $tr = fileList.findFileEl('One.txt');
+ $action = $tr.find('.action-comment');
+ expect($action.length).toEqual(1);
+ expect($action.hasClass('permanent')).toEqual(true);
+
+ expect($tr.attr('data-comments-unread')).toEqual('3');
+ });
+ it('clicking icon opens sidebar', function() {
+ var sidebarStub = sinon.stub(fileList, 'showDetailsView');
+ var $action, $tr;
+ fileList.setFiles(testFiles);
+ $tr = fileList.findFileEl('One.txt');
+ $action = $tr.find('.action-comment');
+ $action.click();
+
+ expect(sidebarStub.calledOnce).toEqual(true);
+ expect(sidebarStub.lastCall.args[0]).toEqual('One.txt');
+ expect(sidebarStub.lastCall.args[1]).toEqual('commentsTabView');
+ });
+ });
+ describe('elementToFile', function() {
+ it('returns comment count', function() {
+ fileList.setFiles(testFiles);
+ var $tr = fileList.findFileEl('One.txt');
+ var data = fileList.elementToFile($tr);
+ expect(data.commentsUnread).toEqual(3);
+ });
+ it('does not set comment count when not set', function() {
+ delete testFiles[0].commentsUnread;
+ fileList.setFiles(testFiles);
+ var $tr = fileList.findFileEl('One.txt');
+ var data = fileList.elementToFile($tr);
+ expect(data.commentsUnread).not.toBeDefined();
+ });
+ it('does not set comment count when zero', function() {
+ testFiles[0].commentsUnread = 0;
+ fileList.setFiles(testFiles);
+ var $tr = fileList.findFileEl('One.txt');
+ var data = fileList.elementToFile($tr);
+ expect(data.commentsUnread).not.toBeDefined();
+ });
+ });
+});
diff --git a/apps/dav/appinfo/info.xml b/apps/dav/appinfo/info.xml
index 3a38feab59e..f035d19d862 100644
--- a/apps/dav/appinfo/info.xml
+++ b/apps/dav/appinfo/info.xml
@@ -6,7 +6,6 @@
<licence>AGPL</licence>
<author>owncloud.org</author>
<version>0.1.4</version>
- <standalone/>
<default_enable/>
<types>
<filesystem/>
diff --git a/apps/dav/appinfo/register_command.php b/apps/dav/appinfo/register_command.php
index e8fea5daf23..e8ca370f84f 100644
--- a/apps/dav/appinfo/register_command.php
+++ b/apps/dav/appinfo/register_command.php
@@ -36,7 +36,7 @@ $app = new Application();
/** @var Symfony\Component\Console\Application $application */
$application->add(new CreateAddressBook($userManager, $groupManager, $dbConnection, $logger));
-$application->add(new CreateCalendar($userManager, $dbConnection));
+$application->add(new CreateCalendar($userManager, $groupManager, $dbConnection));
$application->add(new SyncSystemAddressBook($app->getSyncService()));
// the occ tool is *for now* only available in debug mode for developers to test
diff --git a/apps/dav/command/createcalendar.php b/apps/dav/command/createcalendar.php
index 34bc061c45b..d7f82dd0e52 100644
--- a/apps/dav/command/createcalendar.php
+++ b/apps/dav/command/createcalendar.php
@@ -21,7 +21,9 @@
namespace OCA\DAV\Command;
use OCA\DAV\CalDAV\CalDavBackend;
+use OCA\DAV\Connector\Sabre\Principal;
use OCP\IDBConnection;
+use OCP\IGroupManager;
use OCP\IUserManager;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
@@ -33,6 +35,9 @@ class CreateCalendar extends Command {
/** @var IUserManager */
protected $userManager;
+ /** @var IGroupManager $groupManager */
+ private $groupManager;
+
/** @var \OCP\IDBConnection */
protected $dbConnection;
@@ -40,9 +45,10 @@ class CreateCalendar extends Command {
* @param IUserManager $userManager
* @param IDBConnection $dbConnection
*/
- function __construct(IUserManager $userManager, IDBConnection $dbConnection) {
+ function __construct(IUserManager $userManager, IGroupManager $groupManager, IDBConnection $dbConnection) {
parent::__construct();
$this->userManager = $userManager;
+ $this->groupManager = $groupManager;
$this->dbConnection = $dbConnection;
}
@@ -63,8 +69,13 @@ class CreateCalendar extends Command {
if (!$this->userManager->userExists($user)) {
throw new \InvalidArgumentException("User <$user> in unknown.");
}
+ $principalBackend = new Principal(
+ $this->userManager,
+ $this->groupManager
+ );
+
$name = $input->getArgument('name');
- $caldav = new CalDavBackend($this->dbConnection);
+ $caldav = new CalDavBackend($this->dbConnection, $principalBackend);
$caldav->createCalendar("principals/users/$user", $name, []);
}
}
diff --git a/apps/dav/lib/caldav/caldavbackend.php b/apps/dav/lib/caldav/caldavbackend.php
index 0b70b37967f..3aa493e5087 100644
--- a/apps/dav/lib/caldav/caldavbackend.php
+++ b/apps/dav/lib/caldav/caldavbackend.php
@@ -23,6 +23,8 @@
namespace OCA\DAV\CalDAV;
use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCA\DAV\Connector\Sabre\Principal;
+use OCA\DAV\DAV\Sharing\Backend;
use Sabre\CalDAV\Backend\AbstractBackend;
use Sabre\CalDAV\Backend\SchedulingSupport;
use Sabre\CalDAV\Backend\SubscriptionSupport;
@@ -32,6 +34,7 @@ use Sabre\CalDAV\Xml\Property\ScheduleCalendarTransp;
use Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet;
use Sabre\DAV;
use Sabre\DAV\Exception\Forbidden;
+use Sabre\HTTP\URLUtil;
use Sabre\VObject\DateTimeParser;
use Sabre\VObject\Reader;
use Sabre\VObject\RecurrenceIterator;
@@ -86,8 +89,24 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
'{http://calendarserver.org/ns/}subscribed-strip-attachments' => 'stripattachments',
];
- public function __construct(\OCP\IDBConnection $db) {
+ /** @var \OCP\IDBConnection */
+ private $db;
+
+ /** @var Backend */
+ private $sharingBackend;
+
+ /** @var Principal */
+ private $principalBackend;
+
+ /**
+ * CalDavBackend constructor.
+ *
+ * @param \OCP\IDBConnection $db
+ */
+ public function __construct(\OCP\IDBConnection $db, Principal $principalBackend) {
$this->db = $db;
+ $this->principalBackend = $principalBackend;
+ $this->sharingBackend = new Backend($this->db, 'calendar');
}
/**
@@ -153,10 +172,60 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$calendar[$xmlName] = $row[$dbName];
}
- $calendars[] = $calendar;
+ $calendars[$calendar['id']] = $calendar;
+ }
+
+ $stmt->closeCursor();
+
+ // query for shared calendars
+ $principals = $this->principalBackend->getGroupMembership($principalUri);
+ $principals[]= $principalUri;
+
+ $fields = array_values($this->propertyMap);
+ $fields[] = 'a.id';
+ $fields[] = 'a.uri';
+ $fields[] = 'a.synctoken';
+ $fields[] = 'a.components';
+ $fields[] = 'a.principaluri';
+ $fields[] = 'a.transparent';
+ $query = $this->db->getQueryBuilder();
+ $result = $query->select($fields)
+ ->from('dav_shares', 's')
+ ->join('s', 'calendars', 'a', $query->expr()->eq('s.resourceid', 'a.id'))
+ ->where($query->expr()->in('s.principaluri', $query->createParameter('principaluri')))
+ ->andWhere($query->expr()->eq('s.type', $query->createParameter('type')))
+ ->setParameter('type', 'calendar')
+ ->setParameter('principaluri', $principals, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY)
+ ->execute();
+
+ while($row = $result->fetch()) {
+ list(, $name) = URLUtil::splitPath($row['principaluri']);
+ $uri = $row['uri'] . '_shared_by_' . $name;
+ $row['displayname'] = $row['displayname'] . "($name)";
+ $components = [];
+ if ($row['components']) {
+ $components = explode(',',$row['components']);
+ }
+ $calendar = [
+ 'id' => $row['id'],
+ 'uri' => $uri,
+ 'principaluri' => $principalUri,
+ '{' . Plugin::NS_CALENDARSERVER . '}getctag' => 'http://sabre.io/ns/sync/' . ($row['synctoken']?$row['synctoken']:'0'),
+ '{http://sabredav.org/ns}sync-token' => $row['synctoken']?$row['synctoken']:'0',
+ '{' . Plugin::NS_CALDAV . '}supported-calendar-component-set' => new SupportedCalendarComponentSet($components),
+ '{' . Plugin::NS_CALDAV . '}schedule-calendar-transp' => new ScheduleCalendarTransp($row['transparent']?'transparent':'opaque'),
+ '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}owner-principal' => $row['principaluri'],
+ ];
+
+ foreach($this->propertyMap as $xmlName=>$dbName) {
+ $calendar[$xmlName] = $row[$dbName];
+ }
+
+ $calendars[$calendar['id']] = $calendar;
}
+ $result->closeCursor();
- return $calendars;
+ return array_values($calendars);
}
/**
@@ -271,6 +340,8 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$stmt = $this->db->prepare('DELETE FROM `*PREFIX*calendarchanges` WHERE `calendarid` = ?');
$stmt->execute([$calendarId]);
+
+ $this->sharingBackend->deleteAllShares($calendarId);
}
/**
@@ -1173,4 +1244,17 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
return $cardData;
}
+
+ public function updateShares($shareable, $add, $remove) {
+ $this->sharingBackend->updateShares($shareable, $add, $remove);
+ }
+
+ public function getShares($resourceId) {
+ return $this->sharingBackend->getShares($resourceId);
+ }
+
+ public function applyShareAcl($addressBookId, $acl) {
+ return $this->sharingBackend->applyShareAcl($addressBookId, $acl);
+ }
+
}
diff --git a/apps/dav/lib/caldav/calendar.php b/apps/dav/lib/caldav/calendar.php
new file mode 100644
index 00000000000..8ed5b6563d0
--- /dev/null
+++ b/apps/dav/lib/caldav/calendar.php
@@ -0,0 +1,102 @@
+<?php
+
+namespace OCA\DAV\CalDAV;
+
+use OCA\DAV\DAV\Sharing\IShareable;
+use Sabre\DAV\Exception\Forbidden;
+
+class Calendar extends \Sabre\CalDAV\Calendar implements IShareable {
+
+ /**
+ * Updates the list of shares.
+ *
+ * The first array is a list of people that are to be added to the
+ * resource.
+ *
+ * Every element in the add array has the following properties:
+ * * href - A url. Usually a mailto: address
+ * * commonName - Usually a first and last name, or false
+ * * summary - A description of the share, can also be false
+ * * readOnly - A boolean value
+ *
+ * Every element in the remove array is just the address string.
+ *
+ * @param array $add
+ * @param array $remove
+ * @return void
+ */
+ function updateShares(array $add, array $remove) {
+ /** @var CalDavBackend $calDavBackend */
+ $calDavBackend = $this->caldavBackend;
+ $calDavBackend->updateShares($this, $add, $remove);
+ }
+
+ /**
+ * Returns the list of people whom this resource is shared with.
+ *
+ * Every element in this array should have the following properties:
+ * * href - Often a mailto: address
+ * * commonName - Optional, for example a first + last name
+ * * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants.
+ * * readOnly - boolean
+ * * summary - Optional, a description for the share
+ *
+ * @return array
+ */
+ function getShares() {
+ /** @var CalDavBackend $calDavBackend */
+ $calDavBackend = $this->caldavBackend;
+ return $calDavBackend->getShares($this->getResourceId());
+ }
+
+ /**
+ * @return int
+ */
+ public function getResourceId() {
+ return $this->calendarInfo['id'];
+ }
+
+ function getACL() {
+ $acl = parent::getACL();
+
+ /** @var CalDavBackend $calDavBackend */
+ $calDavBackend = $this->caldavBackend;
+ return $calDavBackend->applyShareAcl($this->getResourceId(), $acl);
+ }
+
+ function getChildACL() {
+ $acl = parent::getChildACL();
+
+ /** @var CalDavBackend $calDavBackend */
+ $calDavBackend = $this->caldavBackend;
+ return $calDavBackend->applyShareAcl($this->getResourceId(), $acl);
+ }
+
+ function getOwner() {
+ if (isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal'])) {
+ return $this->calendarInfo['{http://owncloud.org/ns}owner-principal'];
+ }
+ return parent::getOwner();
+ }
+
+ function delete() {
+ if (isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal'])) {
+ $principal = 'principal:' . parent::getOwner();
+ $shares = $this->getShares();
+ $shares = array_filter($shares, function($share) use ($principal){
+ return $share['href'] === $principal;
+ });
+ if (empty($shares)) {
+ throw new Forbidden();
+ }
+
+ /** @var CalDavBackend $calDavBackend */
+ $calDavBackend = $this->caldavBackend;
+ $calDavBackend->updateShares($this, [], [
+ 'href' => $principal
+ ]);
+ return;
+ }
+ parent::delete();
+ }
+}
diff --git a/apps/dav/lib/caldav/calendarhome.php b/apps/dav/lib/caldav/calendarhome.php
new file mode 100644
index 00000000000..7f98dfb94e0
--- /dev/null
+++ b/apps/dav/lib/caldav/calendarhome.php
@@ -0,0 +1,78 @@
+<?php
+
+namespace OCA\DAV\CalDAV;
+
+use Sabre\CalDAV\Backend\NotificationSupport;
+use Sabre\CalDAV\Backend\SchedulingSupport;
+use Sabre\CalDAV\Backend\SubscriptionSupport;
+use Sabre\CalDAV\Schedule\Inbox;
+use Sabre\CalDAV\Schedule\Outbox;
+use Sabre\CalDAV\Subscriptions\Subscription;
+use Sabre\DAV\Exception\NotFound;
+
+class CalendarHome extends \Sabre\CalDAV\CalendarHome {
+
+ /**
+ * @inheritdoc
+ */
+ function getChildren() {
+ $calendars = $this->caldavBackend->getCalendarsForUser($this->principalInfo['uri']);
+ $objs = [];
+ foreach ($calendars as $calendar) {
+ $objs[] = new Calendar($this->caldavBackend, $calendar);
+ }
+
+ if ($this->caldavBackend instanceof SchedulingSupport) {
+ $objs[] = new Inbox($this->caldavBackend, $this->principalInfo['uri']);
+ $objs[] = new Outbox($this->principalInfo['uri']);
+ }
+
+ // We're adding a notifications node, if it's supported by the backend.
+ if ($this->caldavBackend instanceof NotificationSupport) {
+ $objs[] = new \Sabre\CalDAV\Notifications\Collection($this->caldavBackend, $this->principalInfo['uri']);
+ }
+
+ // If the backend supports subscriptions, we'll add those as well,
+ if ($this->caldavBackend instanceof SubscriptionSupport) {
+ foreach ($this->caldavBackend->getSubscriptionsForUser($this->principalInfo['uri']) as $subscription) {
+ $objs[] = new Subscription($this->caldavBackend, $subscription);
+ }
+ }
+
+ return $objs;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ function getChild($name) {
+ // Special nodes
+ if ($name === 'inbox' && $this->caldavBackend instanceof SchedulingSupport) {
+ return new Inbox($this->caldavBackend, $this->principalInfo['uri']);
+ }
+ if ($name === 'outbox' && $this->caldavBackend instanceof SchedulingSupport) {
+ return new Outbox($this->principalInfo['uri']);
+ }
+ if ($name === 'notifications' && $this->caldavBackend instanceof NotificationSupport) {
+ return new \Sabre\CalDAv\Notifications\Collection($this->caldavBackend, $this->principalInfo['uri']);
+ }
+
+ // Calendars
+ foreach ($this->caldavBackend->getCalendarsForUser($this->principalInfo['uri']) as $calendar) {
+ if ($calendar['uri'] === $name) {
+ return new Calendar($this->caldavBackend, $calendar);
+ }
+ }
+
+ if ($this->caldavBackend instanceof SubscriptionSupport) {
+ foreach ($this->caldavBackend->getSubscriptionsForUser($this->principalInfo['uri']) as $subscription) {
+ if ($subscription['uri'] === $name) {
+ return new Subscription($this->caldavBackend, $subscription);
+ }
+ }
+
+ }
+
+ throw new NotFound('Node with name \'' . $name . '\' could not be found');
+ }
+} \ No newline at end of file
diff --git a/apps/dav/lib/caldav/calendarroot.php b/apps/dav/lib/caldav/calendarroot.php
new file mode 100644
index 00000000000..ae5fc54cdf3
--- /dev/null
+++ b/apps/dav/lib/caldav/calendarroot.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace OCA\DAV\CalDAV;
+
+class CalendarRoot extends \Sabre\CalDAV\CalendarRoot {
+
+ function getChildForPrincipal(array $principal) {
+ return new CalendarHome($this->caldavBackend, $principal);
+ }
+} \ No newline at end of file
diff --git a/apps/dav/lib/carddav/addressbook.php b/apps/dav/lib/carddav/addressbook.php
index 513eae4d723..ca3f5ba0ef6 100644
--- a/apps/dav/lib/carddav/addressbook.php
+++ b/apps/dav/lib/carddav/addressbook.php
@@ -21,6 +21,7 @@
namespace OCA\DAV\CardDAV;
use OCA\DAV\DAV\Sharing\IShareable;
+use Sabre\DAV\Exception\Forbidden;
use Sabre\DAV\Exception\NotFound;
class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable {
@@ -132,4 +133,32 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable {
public function getResourceId() {
return $this->addressBookInfo['id'];
}
+
+ function getOwner() {
+ if (isset($this->addressBookInfo['{http://owncloud.org/ns}owner-principal'])) {
+ return $this->addressBookInfo['{http://owncloud.org/ns}owner-principal'];
+ }
+ return parent::getOwner();
+ }
+
+ function delete() {
+ if (isset($this->addressBookInfo['{http://owncloud.org/ns}owner-principal'])) {
+ $principal = 'principal:' . parent::getOwner();
+ $shares = $this->getShares();
+ $shares = array_filter($shares, function($share) use ($principal){
+ return $share['href'] === $principal;
+ });
+ if (empty($shares)) {
+ throw new Forbidden();
+ }
+
+ /** @var CardDavBackend $cardDavBackend */
+ $cardDavBackend = $this->carddavBackend;
+ $cardDavBackend->updateShares($this, [], [
+ 'href' => $principal
+ ]);
+ return;
+ }
+ parent::delete();
+ }
}
diff --git a/apps/dav/lib/carddav/carddavbackend.php b/apps/dav/lib/carddav/carddavbackend.php
index 3dc5c00e10b..9ca166c22a2 100644
--- a/apps/dav/lib/carddav/carddavbackend.php
+++ b/apps/dav/lib/carddav/carddavbackend.php
@@ -103,7 +103,7 @@ class CardDavBackend implements BackendInterface, SyncSupport {
$result = $query->execute();
while($row = $result->fetch()) {
- $addressBooks[] = [
+ $addressBooks[$row['id']] = [
'id' => $row['id'],
'uri' => $row['uri'],
'principaluri' => $row['principaluri'],
@@ -133,7 +133,7 @@ class CardDavBackend implements BackendInterface, SyncSupport {
list(, $name) = URLUtil::splitPath($row['principaluri']);
$uri = $row['uri'] . '_shared_by_' . $name;
$displayName = $row['displayname'] . "($name)";
- $addressBooks[] = [
+ $addressBooks[$row['id']] = [
'id' => $row['id'],
'uri' => $uri,
'principaluri' => $principalUri,
@@ -147,7 +147,7 @@ class CardDavBackend implements BackendInterface, SyncSupport {
}
$result->closeCursor();
- return $addressBooks;
+ return array_values($addressBooks);
}
/**
@@ -336,10 +336,7 @@ class CardDavBackend implements BackendInterface, SyncSupport {
->setParameter('id', $addressBookId)
->execute();
- $query->delete('dav_shares')
- ->where($query->expr()->eq('resourceid', $query->createNamedParameter($addressBookId)))
- ->andWhere($query->expr()->eq('type', $query->createNamedParameter('addressbook')))
- ->execute();
+ $this->sharingBackend->deleteAllShares($addressBookId);
$query->delete($this->dbCardsPropertiesTable)
->where($query->expr()->eq('addressbookid', $query->createNamedParameter($addressBookId)))
@@ -920,22 +917,6 @@ class CardDavBackend implements BackendInterface, SyncSupport {
* @return array
*/
public function applyShareAcl($addressBookId, $acl) {
-
- $shares = $this->getShares($addressBookId);
- foreach ($shares as $share) {
- $acl[] = [
- 'privilege' => '{DAV:}read',
- 'principal' => $share['{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}principal'],
- 'protected' => true,
- ];
- if (!$share['readOnly']) {
- $acl[] = [
- 'privilege' => '{DAV:}write',
- 'principal' => $share['{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}principal'],
- 'protected' => true,
- ];
- }
- }
- return $acl;
+ return $this->sharingBackend->applyShareAcl($addressBookId, $acl);
}
}
diff --git a/apps/dav/lib/comments/commentnode.php b/apps/dav/lib/comments/commentnode.php
index a5d508dd198..d3cd53bceb1 100644
--- a/apps/dav/lib/comments/commentnode.php
+++ b/apps/dav/lib/comments/commentnode.php
@@ -27,6 +27,7 @@ use OCP\Comments\ICommentsManager;
use OCP\ILogger;
use OCP\IUserManager;
use OCP\IUserSession;
+use Sabre\DAV\Exception\Forbidden;
use Sabre\DAV\Exception\MethodNotAllowed;
use Sabre\DAV\PropPatch;
@@ -112,12 +113,23 @@ class CommentNode implements \Sabre\DAV\INode, \Sabre\DAV\IProperties {
];
}
+ protected function checkWriteAccessOnComment() {
+ $user = $this->userSession->getUser();
+ if( $this->comment->getActorType() !== 'users'
+ || is_null($user)
+ || $this->comment->getActorId() !== $user->getUID()
+ ) {
+ throw new Forbidden('Only authors are allowed to edit their comment.');
+ }
+ }
+
/**
* Deleted the current node
*
* @return void
*/
function delete() {
+ $this->checkWriteAccessOnComment();
$this->commentsManager->delete($this->comment->getId());
}
@@ -156,8 +168,10 @@ class CommentNode implements \Sabre\DAV\INode, \Sabre\DAV\IProperties {
*
* @param $propertyValue
* @return bool
+ * @throws Forbidden
*/
public function updateComment($propertyValue) {
+ $this->checkWriteAccessOnComment();
try {
$this->comment->setMessage($propertyValue);
$this->commentsManager->save($this->comment);
diff --git a/apps/dav/lib/comments/commentsplugin.php b/apps/dav/lib/comments/commentsplugin.php
index 282c14df1e8..56d94cc33e9 100644
--- a/apps/dav/lib/comments/commentsplugin.php
+++ b/apps/dav/lib/comments/commentsplugin.php
@@ -116,6 +116,11 @@ class CommentsPlugin extends ServerPlugin {
$data,
$request->getHeader('Content-Type')
);
+
+ // update read marker for the current user/poster to avoid
+ // having their own comments marked as unread
+ $node->setReadMarker(null);
+
$url = $request->getUrl() . '/' . urlencode($comment->getId());
$response->setHeader('Content-Location', $url);
diff --git a/apps/dav/lib/dav/sharing/backend.php b/apps/dav/lib/dav/sharing/backend.php
index fee864ffe6f..0b28891fbc4 100644
--- a/apps/dav/lib/dav/sharing/backend.php
+++ b/apps/dav/lib/dav/sharing/backend.php
@@ -58,7 +58,7 @@ class Backend {
$this->shareWith($shareable, $element);
}
foreach($remove as $element) {
- $this->unshare($shareable->getResourceId(), $element);
+ $this->unshare($shareable, $element);
}
}
@@ -73,8 +73,13 @@ class Backend {
return;
}
+ // don't share with owner
+ if ($shareable->getOwner() === $parts[1]) {
+ return;
+ }
+
// remove the share if it already exists
- $this->unshare($shareable->getResourceId(), $element['href']);
+ $this->unshare($shareable, $element['href']);
$access = self::ACCESS_READ;
if (isset($element['readOnly'])) {
$access = $element['readOnly'] ? self::ACCESS_READ : self::ACCESS_READ_WRITE;
@@ -92,18 +97,34 @@ class Backend {
}
/**
- * @param int $resourceId
+ * @param $resourceId
+ */
+ public function deleteAllShares($resourceId) {
+ $query = $this->db->getQueryBuilder();
+ $query->delete('dav_shares')
+ ->where($query->expr()->eq('resourceid', $query->createNamedParameter($resourceId)))
+ ->andWhere($query->expr()->eq('type', $query->createNamedParameter($this->resourceType)))
+ ->execute();
+ }
+
+ /**
+ * @param IShareable $shareable
* @param string $element
*/
- private function unshare($resourceId, $element) {
+ private function unshare($shareable, $element) {
$parts = explode(':', $element, 2);
if ($parts[0] !== 'principal') {
return;
}
+ // don't share with owner
+ if ($shareable->getOwner() === $parts[1]) {
+ return;
+ }
+
$query = $this->db->getQueryBuilder();
$query->delete('dav_shares')
- ->where($query->expr()->eq('resourceid', $query->createNamedParameter($resourceId)))
+ ->where($query->expr()->eq('resourceid', $query->createNamedParameter($shareable->getResourceId())))
->andWhere($query->expr()->eq('type', $query->createNamedParameter($this->resourceType)))
->andWhere($query->expr()->eq('principaluri', $query->createNamedParameter($parts[1])))
;
@@ -136,7 +157,7 @@ class Backend {
'href' => "principal:${row['principaluri']}",
// 'commonName' => isset($p['{DAV:}displayname']) ? $p['{DAV:}displayname'] : '',
'status' => 1,
- 'readOnly' => ($row['access'] === self::ACCESS_READ),
+ 'readOnly' => ($row['access'] == self::ACCESS_READ),
'{'.\OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD.'}principal' => $row['principaluri']
];
}
diff --git a/apps/dav/lib/dav/sharing/plugin.php b/apps/dav/lib/dav/sharing/plugin.php
index cbb4408e29b..f6e2cceebd9 100644
--- a/apps/dav/lib/dav/sharing/plugin.php
+++ b/apps/dav/lib/dav/sharing/plugin.php
@@ -23,9 +23,12 @@
namespace OCA\DAV\DAV\Sharing;
use OCA\DAV\Connector\Sabre\Auth;
+use OCA\DAV\DAV\Sharing\Xml\Invite;
use OCP\IRequest;
use Sabre\DAV\Exception\BadRequest;
use Sabre\DAV\Exception\NotFound;
+use Sabre\DAV\INode;
+use Sabre\DAV\PropFind;
use Sabre\DAV\Server;
use Sabre\DAV\ServerPlugin;
use Sabre\HTTP\RequestInterface;
@@ -97,8 +100,10 @@ class Plugin extends ServerPlugin {
function initialize(Server $server) {
$this->server = $server;
$this->server->xml->elementMap['{' . Plugin::NS_OWNCLOUD . '}share'] = 'OCA\\DAV\\DAV\\Sharing\\Xml\\ShareRequest';
+ $this->server->xml->elementMap['{' . Plugin::NS_OWNCLOUD . '}invite'] = 'OCA\\DAV\\DAV\\Sharing\\Xml\\Invite';
$this->server->on('method:POST', [$this, 'httpPost']);
+ $this->server->on('propFind', [$this, 'propFind']);
}
/**
@@ -174,6 +179,28 @@ class Plugin extends ServerPlugin {
}
}
+ /**
+ * This event is triggered when properties are requested for a certain
+ * node.
+ *
+ * This allows us to inject any properties early.
+ *
+ * @param PropFind $propFind
+ * @param INode $node
+ * @return void
+ */
+ function propFind(PropFind $propFind, INode $node) {
+ if ($node instanceof IShareable) {
+
+ $propFind->handle('{' . Plugin::NS_OWNCLOUD . '}invite', function() use ($node) {
+ return new Invite(
+ $node->getShares()
+ );
+ });
+
+ }
+ }
+
private function protectAgainstCSRF() {
$user = $this->auth->getCurrentUser();
if ($this->auth->isDavAuthenticated($user)) {
diff --git a/apps/dav/lib/dav/sharing/xml/invite.php b/apps/dav/lib/dav/sharing/xml/invite.php
new file mode 100644
index 00000000000..659f95d8074
--- /dev/null
+++ b/apps/dav/lib/dav/sharing/xml/invite.php
@@ -0,0 +1,149 @@
+<?php
+
+namespace OCA\DAV\DAV\Sharing\Xml;
+
+use OCA\DAV\DAV\Sharing\Plugin;
+use Sabre\Xml\Writer;
+use Sabre\Xml\XmlSerializable;
+
+/**
+ * Invite property
+ *
+ * This property encodes the 'invite' property, as defined by
+ * the 'caldav-sharing-02' spec, in the http://calendarserver.org/ns/
+ * namespace.
+ *
+ * @see https://trac.calendarserver.org/browser/CalendarServer/trunk/doc/Extensions/caldav-sharing-02.txt
+ * @copyright Copyright (C) fruux GmbH (https://fruux.com/)
+ * @author Evert Pot (http://evertpot.com/)
+ * @license http://sabre.io/license/ Modified BSD License
+ */
+class Invite implements XmlSerializable {
+
+ /**
+ * The list of users a calendar has been shared to.
+ *
+ * @var array
+ */
+ protected $users;
+
+ /**
+ * The organizer contains information about the person who shared the
+ * object.
+ *
+ * @var array
+ */
+ protected $organizer;
+
+ /**
+ * Creates the property.
+ *
+ * Users is an array. Each element of the array has the following
+ * properties:
+ *
+ * * href - Often a mailto: address
+ * * commonName - Optional, for example a first and lastname for a user.
+ * * status - One of the SharingPlugin::STATUS_* constants.
+ * * readOnly - true or false
+ * * summary - Optional, description of the share
+ *
+ * The organizer key is optional to specify. It's only useful when a
+ * 'sharee' requests the sharing information.
+ *
+ * The organizer may have the following properties:
+ * * href - Often a mailto: address.
+ * * commonName - Optional human-readable name.
+ * * firstName - Optional first name.
+ * * lastName - Optional last name.
+ *
+ * If you wonder why these two structures are so different, I guess a
+ * valid answer is that the current spec is still a draft.
+ *
+ * @param array $users
+ */
+ function __construct(array $users, array $organizer = null) {
+
+ $this->users = $users;
+ $this->organizer = $organizer;
+
+ }
+
+ /**
+ * Returns the list of users, as it was passed to the constructor.
+ *
+ * @return array
+ */
+ function getValue() {
+
+ return $this->users;
+
+ }
+
+ /**
+ * The xmlSerialize metod is called during xml writing.
+ *
+ * Use the $writer argument to write its own xml serialization.
+ *
+ * An important note: do _not_ create a parent element. Any element
+ * implementing XmlSerializble should only ever write what's considered
+ * its 'inner xml'.
+ *
+ * The parent of the current element is responsible for writing a
+ * containing element.
+ *
+ * This allows serializers to be re-used for different element names.
+ *
+ * If you are opening new elements, you must also close them again.
+ *
+ * @param Writer $writer
+ * @return void
+ */
+ function xmlSerialize(Writer $writer) {
+
+ $cs = '{' . Plugin::NS_OWNCLOUD . '}';
+
+ if (!is_null($this->organizer)) {
+
+ $writer->startElement($cs . 'organizer');
+ $writer->writeElement('{DAV:}href', $this->organizer['href']);
+
+ if (isset($this->organizer['commonName']) && $this->organizer['commonName']) {
+ $writer->writeElement($cs . 'common-name', $this->organizer['commonName']);
+ }
+ if (isset($this->organizer['firstName']) && $this->organizer['firstName']) {
+ $writer->writeElement($cs . 'first-name', $this->organizer['firstName']);
+ }
+ if (isset($this->organizer['lastName']) && $this->organizer['lastName']) {
+ $writer->writeElement($cs . 'last-name', $this->organizer['lastName']);
+ }
+ $writer->endElement(); // organizer
+
+ }
+
+ foreach ($this->users as $user) {
+
+ $writer->startElement($cs . 'user');
+ $writer->writeElement('{DAV:}href', $user['href']);
+ if (isset($user['commonName']) && $user['commonName']) {
+ $writer->writeElement($cs . 'common-name', $user['commonName']);
+ }
+ $writer->writeElement($cs . 'invite-accepted');
+
+ $writer->startElement($cs . 'access');
+ if ($user['readOnly']) {
+ $writer->writeElement($cs . 'read');
+ } else {
+ $writer->writeElement($cs . 'read-write');
+ }
+ $writer->endElement(); // access
+
+ if (isset($user['summary']) && $user['summary']) {
+ $writer->writeElement($cs . 'summary', $user['summary']);
+ }
+
+ $writer->endElement(); //user
+
+ }
+
+ }
+}
diff --git a/apps/dav/lib/rootcollection.php b/apps/dav/lib/rootcollection.php
index 5be469e7b0c..2a8f63a2270 100644
--- a/apps/dav/lib/rootcollection.php
+++ b/apps/dav/lib/rootcollection.php
@@ -22,12 +22,12 @@
namespace OCA\DAV;
use OCA\DAV\CalDAV\CalDavBackend;
+use OCA\DAV\CalDAV\CalendarRoot;
use OCA\DAV\CardDAV\AddressBookRoot;
use OCA\DAV\CardDAV\CardDavBackend;
use OCA\DAV\Connector\Sabre\Principal;
use OCA\DAV\DAV\GroupPrincipalBackend;
use OCA\DAV\DAV\SystemPrincipalBackend;
-use Sabre\CalDAV\CalendarRoot;
use Sabre\CalDAV\Principal\Collection;
use Sabre\DAV\SimpleCollection;
@@ -55,7 +55,7 @@ class RootCollection extends SimpleCollection {
$systemPrincipals->disableListing = $disableListing;
$filesCollection = new Files\RootCollection($userPrincipalBackend, 'principals/users');
$filesCollection->disableListing = $disableListing;
- $caldavBackend = new CalDavBackend($db);
+ $caldavBackend = new CalDavBackend($db, $userPrincipalBackend);
$calendarRoot = new CalendarRoot($userPrincipalBackend, $caldavBackend, 'principals/users');
$calendarRoot->disableListing = $disableListing;
diff --git a/apps/dav/tests/travis/caldav/install.sh b/apps/dav/tests/travis/caldav/install.sh
index e836e37f86f..9688ec660de 100644
--- a/apps/dav/tests/travis/caldav/install.sh
+++ b/apps/dav/tests/travis/caldav/install.sh
@@ -15,6 +15,7 @@ fi
cd "$SCRIPTPATH/../../../../../"
OC_PASS=user01 php occ user:add --password-from-env user01
php occ dav:create-calendar user01 calendar
+php occ dav:create-calendar user01 shared
OC_PASS=user02 php occ user:add --password-from-env user02
php occ dav:create-calendar user02 calendar
cd "$SCRIPTPATH/../../../../../"
diff --git a/apps/dav/tests/travis/caldav/script.sh b/apps/dav/tests/travis/caldav/script.sh
index fe3391d5a06..aa5fc732922 100644
--- a/apps/dav/tests/travis/caldav/script.sh
+++ b/apps/dav/tests/travis/caldav/script.sh
@@ -10,9 +10,7 @@ sleep 30
# run the tests
cd "$SCRIPTPATH/CalDAVTester"
PYTHONPATH="$SCRIPTPATH/pycalendar/src" python testcaldav.py --print-details-onfail --basedir "$SCRIPTPATH/../caldavtest/" -o cdt.txt \
- "CalDAV/current-user-principal.xml" \
- "CalDAV/sync-report.xml"
-
+ "CalDAV/sharing-calendars.xml"
RESULT=$?
diff --git a/apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/1.xml b/apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/1.xml
new file mode 100644
index 00000000000..3bcf9dc47f9
--- /dev/null
+++ b/apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/1.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<CS:share xmlns:D="DAV:" xmlns:CS="http://owncloud.org/ns">
+ <CS:set>
+ <D:href>principal:principals/users/user02</D:href>
+ <CS:summary>My Shared Calendar</CS:summary>
+ <CS:read-write/>
+ </CS:set>
+</CS:share>
diff --git a/apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/4.xml b/apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/4.xml
new file mode 100644
index 00000000000..fd0f248bb31
--- /dev/null
+++ b/apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/4.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<D:propfind xmlns:D="DAV:">
+<D:prop>
+<D:resourcetype/>
+<D:owner/>
+<D:current-user-privilege-set/>
+</D:prop>
+</D:propfind>
diff --git a/apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/5.ics b/apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/5.ics
new file mode 100644
index 00000000000..ae21adac8b2
--- /dev/null
+++ b/apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/5.ics
@@ -0,0 +1,29 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//PYVOBJECT//NONSGML Version 1//EN
+BEGIN:VTIMEZONE
+TZID:US/Eastern
+LAST-MODIFIED:20040110T032845Z
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+UID:$uid1:
+DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
+DURATION:PT1H
+DTSTAMP:20051222T205953Z
+SUMMARY:event 1
+END:VEVENT
+END:VCALENDAR
diff --git a/apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/5.xml b/apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/5.xml
new file mode 100644
index 00000000000..4862ed195f8
--- /dev/null
+++ b/apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/5.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<D:propfind xmlns:D="DAV:" xmlns:CS="http://owncloud.org/ns">
+<D:prop>
+<CS:invite/>
+</D:prop>
+</D:propfind>
diff --git a/apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/6.ics b/apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/6.ics
new file mode 100644
index 00000000000..145f5f14c7b
--- /dev/null
+++ b/apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/6.ics
@@ -0,0 +1,29 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//PYVOBJECT//NONSGML Version 1//EN
+BEGIN:VTIMEZONE
+TZID:US/Eastern
+LAST-MODIFIED:20040110T032845Z
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+UID:$uid1:
+DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
+DURATION:PT4H
+DTSTAMP:20051222T205953Z
+SUMMARY:event 4
+END:VEVENT
+END:VCALENDAR
diff --git a/apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/7.ics b/apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/7.ics
new file mode 100644
index 00000000000..c4e816210df
--- /dev/null
+++ b/apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/7.ics
@@ -0,0 +1,29 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//PYVOBJECT//NONSGML Version 1//EN
+BEGIN:VTIMEZONE
+TZID:US/Eastern
+LAST-MODIFIED:20040110T032845Z
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+UID:$uid2:
+DTSTART;TZID=US/Eastern:$now.year.1:0201T100000
+DURATION:PT1H
+DTSTAMP:20051222T205953Z
+SUMMARY:event 7
+END:VEVENT
+END:VCALENDAR
diff --git a/apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/8.ics b/apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/8.ics
new file mode 100644
index 00000000000..2da72d2f601
--- /dev/null
+++ b/apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/8.ics
@@ -0,0 +1,29 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//PYVOBJECT//NONSGML Version 1//EN
+BEGIN:VTIMEZONE
+TZID:US/Eastern
+LAST-MODIFIED:20040110T032845Z
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+UID:$uid2:
+DTSTART;TZID=US/Eastern:$now.year.1:0201T100000
+DURATION:PT7H
+DTSTAMP:20051222T205953Z
+SUMMARY:event 7-1
+END:VEVENT
+END:VCALENDAR
diff --git a/apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/9.ics b/apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/9.ics
new file mode 100644
index 00000000000..dfc21bb9c5b
--- /dev/null
+++ b/apps/dav/tests/travis/caldavtest/data/Resource/CalDAV/sharing/calendars/read-write/9.ics
@@ -0,0 +1,29 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//PYVOBJECT//NONSGML Version 1//EN
+BEGIN:VTIMEZONE
+TZID:US/Eastern
+LAST-MODIFIED:20040110T032845Z
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+UID:$uid3:
+DTSTART;TZID=US/Eastern:$now.year.1:0201T100000
+DURATION:PT7H
+DTSTAMP:20051222T205953Z
+SUMMARY:event 9.ics
+END:VEVENT
+END:VCALENDAR
diff --git a/apps/dav/tests/travis/caldavtest/tests/CalDAV/sharing-calendars.xml b/apps/dav/tests/travis/caldavtest/tests/CalDAV/sharing-calendars.xml
index fa20a6e4862..334fa561aec 100644
--- a/apps/dav/tests/travis/caldavtest/tests/CalDAV/sharing-calendars.xml
+++ b/apps/dav/tests/travis/caldavtest/tests/CalDAV/sharing-calendars.xml
@@ -27,6 +27,7 @@
</require-feature>
<start>
+ <!--
<request user="$userid1:" pswd="$pswd1:">
<method>DELETEALL</method>
<ruri>$notificationpath1:/</ruri>
@@ -50,6 +51,7 @@
<filepath>Resource/Common/PROPPATCH/calendar-transp-opaque.xml</filepath>
</data>
</request>
+ -->
</start>
<test-suite name='Read-write calendar'>
@@ -67,56 +69,11 @@
</verify>
</request>
</test>
- <test name='2'>
- <description>Check Sharee notification collection</description>
- <request user="$userid2:" pswd="$pswd2:">
- <method>WAITCOUNT 1</method>
- <ruri>$notificationpath2:/</ruri>
- </request>
- <request user="$userid2:" pswd="$pswd2:">
- <method>GETNEW</method>
- <ruri>$notificationpath2:/</ruri>
- <verify>
- <callback>xmlDataMatch</callback>
- <arg>
- <name>filepath</name>
- <value>Resource/CalDAV/sharing/calendars/read-write/2.xml</value>
- </arg>
- <arg>
- <name>filter</name>
- <value>{http://calendarserver.org/ns/}dtstamp</value>
- <value>{http://calendarserver.org/ns/}uid</value>
- </arg>
- </verify>
- <grabelement>
- <name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
- <variable>$inviteuid:</variable>
- </grabelement>
- </request>
- </test>
- <test name='3'>
- <description>Sharee replies ACCEPTED</description>
- <request user="$userid2:" pswd="$pswd2:">
- <method>POST</method>
- <ruri>$calendarhome2:/</ruri>
- <data>
- <content-type>application/xml; charset=utf-8</content-type>
- <filepath>Resource/CalDAV/sharing/calendars/read-write/3.xml</filepath>
- </data>
- <verify>
- <callback>statusCode</callback>
- </verify>
- <grabelement>
- <name>{DAV:}href</name>
- <variable>$sharedcalendar:</variable>
- </grabelement>
- </request>
- </test>
<test name='4'>
<description>Shared calendar exists</description>
<request user="$userid2:" pswd="$pswd2:">
<method>PROPFIND</method>
- <ruri>$sharedcalendar:/</ruri>
+ <ruri>$calendarhome1:/shared/</ruri>
<header>
<name>Depth</name>
<value>0</value>
@@ -132,12 +89,12 @@
<value>$verify-property-prefix:/{DAV:}owner/{DAV:}href[=$principaluri1:]</value>
<value>$verify-property-prefix:/{DAV:}resourcetype/{DAV:}collection</value>
<value>$verify-property-prefix:/{DAV:}resourcetype/{urn:ietf:params:xml:ns:caldav}calendar</value>
- <value>$verify-property-prefix:/{DAV:}resourcetype/{http://calendarserver.org/ns/}shared</value>
+ <!-- value>$verify-property-prefix:/{DAV:}resourcetype/{http://calendarserver.org/ns/}shared</value -->
<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}read</value>
<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}write</value>
<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}bind</value>
<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}unbind</value>
- <value>$verify-property-prefix:/{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp/{urn:ietf:params:xml:ns:caldav}transparent</value>
+ <!-- value>$verify-property-prefix:/{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp/{urn:ietf:params:xml:ns:caldav}transparent</value -->
</arg>
<arg>
<name>notexists</name>
@@ -151,7 +108,7 @@
<description>Shared calendar exists Depth:1</description>
<request user="$userid2:" pswd="$pswd2:">
<method>PROPFIND</method>
- <ruri>$calendarhome2:/</ruri>
+ <ruri>$calendarhome2:</ruri>
<header>
<name>Depth</name>
<value>1</value>
@@ -164,19 +121,19 @@
<callback>xmlElementMatch</callback>
<arg>
<name>parent</name>
- <value>$multistatus-response-prefix:[^{DAV:}href=$sharedcalendar:/]</value>
+ <value>$multistatus-response-prefix:[^{DAV:}href=$calendarhome2:/shared_shared_by_user01/]</value>
</arg>
<arg>
<name>exists</name>
<value>$verify-response-prefix:/{DAV:}owner/{DAV:}href[=$principaluri1:]</value>
<value>$verify-response-prefix:/{DAV:}resourcetype/{DAV:}collection</value>
<value>$verify-response-prefix:/{DAV:}resourcetype/{urn:ietf:params:xml:ns:caldav}calendar</value>
- <value>$verify-response-prefix:/{DAV:}resourcetype/{http://calendarserver.org/ns/}shared</value>
+ <!-- value>$verify-response-prefix:/{DAV:}resourcetype/{http://calendarserver.org/ns/}shared</value -->
<value>$verify-response-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}read</value>
<value>$verify-response-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}write</value>
<value>$verify-response-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}bind</value>
<value>$verify-response-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}unbind</value>
- <value>$verify-response-prefix:/{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp/{urn:ietf:params:xml:ns:caldav}transparent</value>
+ <!-- value>$verify-response-prefix:/{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp/{urn:ietf:params:xml:ns:caldav}transparent</value -->
</arg>
<arg>
<name>notexists</name>
@@ -186,44 +143,31 @@
</verify>
</request>
</test>
- <test name='4b'>
- <description>Shared calendar has invite property</description>
- <request user="$userid2:" pswd="$pswd2:">
+ <test name='5'>
+ <description>Original calendar unchanged</description>
+ <request>
<method>PROPFIND</method>
- <ruri>$sharedcalendar:/</ruri>
+ <ruri>$calendarhome1:/shared/</ruri>
<header>
<name>Depth</name>
<value>0</value>
</header>
<data>
<content-type>text/xml; charset=utf-8</content-type>
- <filepath>Resource/CalDAV/sharing/calendars/read-write/5.xml</filepath>
+ <filepath>Resource/CalDAV/sharing/calendars/read-write/4.xml</filepath>
</data>
<verify>
- <callback>propfindItems</callback>
- <arg>
- <name>okprops</name>
- <value>{http://calendarserver.org/ns/}invite</value>
- </arg>
- </verify>
- <verify>
<callback>xmlElementMatch</callback>
<arg>
<name>exists</name>
- <value>$verify-property-prefix:/{http://calendarserver.org/ns/}invite</value>
- <value>$verify-property-prefix:/{http://calendarserver.org/ns/}invite/{http://calendarserver.org/ns/}organizer</value>
- <value>$verify-property-prefix:/{http://calendarserver.org/ns/}invite/{http://calendarserver.org/ns/}organizer/{DAV:}href[=$principaluri1:]</value>
- <value>$verify-property-prefix:/{http://calendarserver.org/ns/}invite/{http://calendarserver.org/ns/}organizer/{http://calendarserver.org/ns/}common-name[=$username1:]</value>
- <value>$verify-property-prefix:/{http://calendarserver.org/ns/}invite/{http://calendarserver.org/ns/}user</value>
- <value>$verify-property-prefix:/{http://calendarserver.org/ns/}invite/{http://calendarserver.org/ns/}user/{DAV:}href[=$cuaddrurn2:]</value>
- <value>$verify-property-prefix:/{http://calendarserver.org/ns/}invite/{http://calendarserver.org/ns/}user/{http://calendarserver.org/ns/}access/{http://calendarserver.org/ns/}read-write</value>
- <value>$verify-property-prefix:/{http://calendarserver.org/ns/}invite/{http://calendarserver.org/ns/}user/{http://calendarserver.org/ns/}invite-accepted</value>
+ <value>$verify-property-prefix:/{DAV:}owner/{DAV:}href[=$principaluri1:]</value>
+ <!--<value>$verify-property-prefix:/{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp/{urn:ietf:params:xml:ns:caldav}opaque</value>-->
</arg>
</verify>
</request>
</test>
- <test name='5'>
- <description>Original calendar unchanged</description>
+ <test name='5a'>
+ <description>Invite propfind returns sharees</description>
<request>
<method>PROPFIND</method>
<ruri>$calendarhome1:/shared/</ruri>
@@ -233,14 +177,14 @@
</header>
<data>
<content-type>text/xml; charset=utf-8</content-type>
- <filepath>Resource/CalDAV/sharing/calendars/read-write/4.xml</filepath>
+ <filepath>Resource/CalDAV/sharing/calendars/read-write/5.xml</filepath>
</data>
<verify>
<callback>xmlElementMatch</callback>
<arg>
<name>exists</name>
- <value>$verify-property-prefix:/{DAV:}owner/{DAV:}href[=$principaluri1:]</value>
- <value>$verify-property-prefix:/{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp/{urn:ietf:params:xml:ns:caldav}opaque</value>
+ <value>$verify-property-prefix:/{http://owncloud.org/ns}invite/{http://owncloud.org/ns}user/{DAV:}href</value>
+ <value>$verify-property-prefix:/{http://owncloud.org/ns}invite/{http://owncloud.org/ns}user/{http://owncloud.org/ns}invite-accepted</value>
</arg>
</verify>
</request>
@@ -249,7 +193,7 @@
<description>Sharee creates event</description>
<request user="$userid2:" pswd="$pswd2:">
<method>PUT</method>
- <ruri>$sharedcalendar:/1.ics</ruri>
+ <ruri>$calendarhome1:/shared/1.ics</ruri>
<data>
<content-type>text/calendar; charset=utf-8</content-type>
<filepath>Resource/CalDAV/sharing/calendars/read-write/5.ics</filepath>
@@ -291,7 +235,7 @@
<description>Sharee sees changed event</description>
<request user="$userid2:" pswd="$pswd2:">
<method>GET</method>
- <ruri>$sharedcalendar:/1.ics</ruri>
+ <ruri>$calendarhome1:/shared/1.ics</ruri>
<verify>
<callback>calendarDataMatch</callback>
<arg>
@@ -319,7 +263,7 @@
<description>Sharee sees new event</description>
<request user="$userid2:" pswd="$pswd2:">
<method>GET</method>
- <ruri>$sharedcalendar:/2.ics</ruri>
+ <ruri>$calendarhome1:/shared/2.ics</ruri>
<verify>
<callback>calendarDataMatch</callback>
<arg>
@@ -333,7 +277,7 @@
<description>Sharee changes event</description>
<request user="$userid2:" pswd="$pswd2:">
<method>PUT</method>
- <ruri>$sharedcalendar:/2.ics</ruri>
+ <ruri>$calendarhome1:/shared/2.ics</ruri>
<data>
<content-type>text/calendar; charset=utf-8</content-type>
<filepath>Resource/CalDAV/sharing/calendars/read-write/8.ics</filepath>
@@ -357,8 +301,76 @@
</verify>
</request>
</test>
+ <test name='14'>
+ <description>Un-share by delete</description>
+ <request user="$userid2:" pswd="$pswd2:">
+ <method>DELETE</method>
+ <ruri>$calendarhome2:/shared_shared_by_user01/</ruri>
+ <verify>
+ <callback>statusCode</callback>
+ </verify>
+ </request>
+ </test>
+ <test name='15'>
+ <description>Original calendar still exists</description>
+ <request>
+ <method>PROPFIND</method>
+ <ruri>$calendarhome1:/shared/</ruri>
+ <header>
+ <name>Depth</name>
+ <value>0</value>
+ </header>
+ <data>
+ <content-type>text/xml; charset=utf-8</content-type>
+ <filepath>Resource/CalDAV/sharing/calendars/read-write/4.xml</filepath>
+ </data>
+ <verify>
+ <callback>xmlElementMatch</callback>
+ <arg>
+ <name>exists</name>
+ <value>$verify-property-prefix:/{DAV:}owner/{DAV:}href[=$principaluri1:]</value>
+ <value>$verify-property-prefix:/{DAV:}resourcetype/{DAV:}collection</value>
+ <value>$verify-property-prefix:/{DAV:}resourcetype/{urn:ietf:params:xml:ns:caldav}calendar</value>
+ <!-- value>$verify-property-prefix:/{DAV:}resourcetype/{http://calendarserver.org/ns/}shared</value -->
+ <value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}read</value>
+ <value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}write</value>
+ <value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}bind</value>
+ <value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}unbind</value>
+ <!-- value>$verify-property-prefix:/{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp/{urn:ietf:params:xml:ns:caldav}transparent</value -->
+ </arg>
+ <arg>
+ <name>notexists</name>
+ <value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}admin</value>
+ <value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}all</value>
+ </arg>
+ </verify>
+ </request>
+ </test>
+ <test name='16'>
+ <description>Shared calendar no longer exists Depth:1</description>
+ <request user="$userid2:" pswd="$pswd2:">
+ <method>PROPFIND</method>
+ <ruri>$calendarhome2:</ruri>
+ <header>
+ <name>Depth</name>
+ <value>1</value>
+ </header>
+ <data>
+ <content-type>text/xml; charset=utf-8</content-type>
+ <filepath>Resource/CalDAV/sharing/calendars/read-write/4.xml</filepath>
+ </data>
+ <verify>
+ <callback>xmlElementMatch</callback>
+ <arg>
+ <name>notexists</name>
+ <value>$multistatus-response-prefix:[^{DAV:}href=$calendarhome2:/shared_shared_by_user01/]</value>
+ </arg>
+ </verify>
+ </request>
+ </test>
</test-suite>
-
+
+ <!--
<test-suite name='Default calendar cannot be shared calendar'>
<test name='1'>
<description>Set property on Inbox</description>
@@ -560,7 +572,10 @@
</test>
</test-suite>
+-->
+
<end>
+ <!--
<request user="$useradmin:" pswd="$pswdadmin:">
<method>DELETEALL</method>
<ruri>$notificationpath1:/</ruri>
@@ -568,6 +583,7 @@
<ruri>$notificationpath3:/</ruri>
<ruri>$notificationpath4:/</ruri>
</request>
+ -->
</end>
</caldavtest>
diff --git a/apps/dav/tests/travis/caldavtest/tests/CardDAV/sharing-addressbooks.xml b/apps/dav/tests/travis/caldavtest/tests/CardDAV/sharing-addressbooks.xml
index 37b4941b9f1..84ee6265017 100644
--- a/apps/dav/tests/travis/caldavtest/tests/CardDAV/sharing-addressbooks.xml
+++ b/apps/dav/tests/travis/caldavtest/tests/CardDAV/sharing-addressbooks.xml
@@ -238,7 +238,70 @@
</verify>
</request>
</test>
- </test-suite>
+ <test name='14'>
+ <description>Un-share by delete</description>
+ <request user="$userid2:" pswd="$pswd2:">
+ <method>DELETE</method>
+ <ruri>$addressbookhome2:/addressbook_shared_by_user01/</ruri>
+ <verify>
+ <callback>statusCode</callback>
+ </verify>
+ </request>
+ </test>
+ <test name='15'>
+ <description>Original address book still exists</description>
+ <request>
+ <method>PROPFIND</method>
+ <ruri>$addressbookhome1:/addressbook/</ruri>
+ <header>
+ <name>Depth</name>
+ <value>0</value>
+ </header>
+ <data>
+ <content-type>text/xml; charset=utf-8</content-type>
+ <filepath>Resource/CardDAV/sharing/read-write/4.xml</filepath>
+ </data>
+ <verify>
+ <callback>xmlElementMatch</callback>
+ <arg>
+ <name>exists</name>
+ <value>$verify-property-prefix:/{DAV:}owner/{DAV:}href[=$principaluri1:]</value>
+ <value>$verify-property-prefix:/{DAV:}resourcetype/{DAV:}collection</value>
+ <value>$verify-property-prefix:/{DAV:}resourcetype/{urn:ietf:params:xml:ns:carddav}addressbook</value>
+ <value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}read</value>
+ <value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}write</value>
+ <value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}bind</value>
+ <value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}unbind</value>
+ </arg>
+ <arg>
+ <name>notexists</name>
+ <value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}admin</value>
+ <value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}all</value>
+ </arg>
+ </verify> </request>
+ </test>
+ <test name='16'>
+ <description>Shared calendar no longer exists Depth:1</description>
+ <request user="$userid2:" pswd="$pswd2:">
+ <method>PROPFIND</method>
+ <ruri>$addressbookhome2:</ruri>
+ <header>
+ <name>Depth</name>
+ <value>1</value>
+ </header>
+ <data>
+ <content-type>text/xml; charset=utf-8</content-type>
+ <filepath>Resource/CardDAV/sharing/read-write/4.xml</filepath>
+ </data>
+ <verify>
+ <callback>xmlElementMatch</callback>
+ <arg>
+ <name>notexists</name>
+ <value>$multistatus-response-prefix:[^{DAV:}href=$addressbookhome2:/addressbook_shared_by_user01/]</value>
+ </arg>
+ </verify>
+ </request>
+ </test> </test-suite>
<end>
</end>
diff --git a/apps/dav/tests/unit/caldav/caldavbackendtest.php b/apps/dav/tests/unit/caldav/caldavbackendtest.php
index 939fd36fba8..aece738166a 100644
--- a/apps/dav/tests/unit/caldav/caldavbackendtest.php
+++ b/apps/dav/tests/unit/caldav/caldavbackendtest.php
@@ -23,9 +23,12 @@ namespace Tests\Connector\Sabre;
use DateTime;
use DateTimeZone;
use OCA\DAV\CalDAV\CalDavBackend;
+use OCA\DAV\CalDAV\Calendar;
+use OCA\DAV\Connector\Sabre\Principal;
use Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet;
use Sabre\DAV\PropPatch;
use Sabre\DAV\Xml\Property\Href;
+use Sabre\DAVACL\IACL;
use Test\TestCase;
/**
@@ -40,14 +43,30 @@ class CalDavBackendTest extends TestCase {
/** @var CalDavBackend */
private $backend;
- const UNIT_TEST_USER = 'caldav-unit-test';
+ /** @var Principal | \PHPUnit_Framework_MockObject_MockObject */
+ private $principal;
+ const UNIT_TEST_USER = 'principals/users/caldav-unit-test';
+ const UNIT_TEST_USER1 = 'principals/users/caldav-unit-test1';
+ const UNIT_TEST_GROUP = 'principals/groups/caldav-unit-test-group';
public function setUp() {
parent::setUp();
+ $this->principal = $this->getMockBuilder('OCA\DAV\Connector\Sabre\Principal')
+ ->disableOriginalConstructor()
+ ->setMethods(['getPrincipalByPath', 'getGroupMembership'])
+ ->getMock();
+ $this->principal->method('getPrincipalByPath')
+ ->willReturn([
+ 'uri' => 'principals/best-friend'
+ ]);
+ $this->principal->method('getGroupMembership')
+ ->withAnyParameters()
+ ->willReturn([self::UNIT_TEST_GROUP]);
+
$db = \OC::$server->getDatabaseConnection();
- $this->backend = new CalDavBackend($db);
+ $this->backend = new CalDavBackend($db, $this->principal);
$this->tearDown();
}
@@ -90,6 +109,87 @@ class CalDavBackendTest extends TestCase {
$this->assertEquals(0, count($books));
}
+ public function providesSharingData() {
+ return [
+ [true, true, true, false, [
+ [
+ 'href' => 'principal:' . self::UNIT_TEST_USER1,
+ 'readOnly' => false
+ ],
+ [
+ 'href' => 'principal:' . self::UNIT_TEST_GROUP,
+ 'readOnly' => true
+ ]
+ ]],
+ [true, false, false, false, [
+ [
+ 'href' => 'principal:' . self::UNIT_TEST_USER1,
+ 'readOnly' => true
+ ],
+ ]],
+
+ ];
+ }
+
+ /**
+ * @dataProvider providesSharingData
+ */
+ public function testCalendarSharing($userCanRead, $userCanWrite, $groupCanRead, $groupCanWrite, $add) {
+
+ $calendarId = $this->createTestCalendar();
+ $books = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER);
+ $this->assertEquals(1, count($books));
+ $calendar = new Calendar($this->backend, $books[0]);
+ $this->backend->updateShares($calendar, $add, []);
+ $books = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER1);
+ $this->assertEquals(1, count($books));
+ $calendar = new Calendar($this->backend, $books[0]);
+ $acl = $calendar->getACL();
+ $this->assertAcl(self::UNIT_TEST_USER, '{DAV:}read', $acl);
+ $this->assertAcl(self::UNIT_TEST_USER, '{DAV:}write', $acl);
+ $this->assertAccess($userCanRead, self::UNIT_TEST_USER1, '{DAV:}read', $acl);
+ $this->assertAccess($userCanWrite, self::UNIT_TEST_USER1, '{DAV:}write', $acl);
+ $this->assertAccess($groupCanRead, self::UNIT_TEST_GROUP, '{DAV:}read', $acl);
+ $this->assertAccess($groupCanWrite, self::UNIT_TEST_GROUP, '{DAV:}write', $acl);
+ $this->assertEquals(self::UNIT_TEST_USER, $calendar->getOwner());
+
+ // test acls on the child
+ $uri = $this->getUniqueID('calobj');
+ $calData = <<<'EOD'
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:ownCloud Calendar
+BEGIN:VEVENT
+CREATED;VALUE=DATE-TIME:20130910T125139Z
+UID:47d15e3ec8
+LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z
+DTSTAMP;VALUE=DATE-TIME:20130910T125139Z
+SUMMARY:Test Event
+DTSTART;VALUE=DATE-TIME:20130912T130000Z
+DTEND;VALUE=DATE-TIME:20130912T140000Z
+CLASS:PUBLIC
+END:VEVENT
+END:VCALENDAR
+EOD;
+
+ $this->backend->createCalendarObject($calendarId, $uri, $calData);
+
+ /** @var IACL $child */
+ $child = $calendar->getChild($uri);
+ $acl = $child->getACL();
+ $this->assertAcl(self::UNIT_TEST_USER, '{DAV:}read', $acl);
+ $this->assertAcl(self::UNIT_TEST_USER, '{DAV:}write', $acl);
+ $this->assertAccess($userCanRead, self::UNIT_TEST_USER1, '{DAV:}read', $acl);
+ $this->assertAccess($userCanWrite, self::UNIT_TEST_USER1, '{DAV:}write', $acl);
+ $this->assertAccess($groupCanRead, self::UNIT_TEST_GROUP, '{DAV:}read', $acl);
+ $this->assertAccess($groupCanWrite, self::UNIT_TEST_GROUP, '{DAV:}write', $acl);
+
+ // delete the address book
+ $this->backend->deleteCalendar($books[0]['id']);
+ $books = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER);
+ $this->assertEquals(0, count($books));
+ }
+
public function testCalendarObjectsOperations() {
$calendarId = $this->createTestCalendar();
@@ -345,4 +445,32 @@ EOD;
$sos = $this->backend->getSchedulingObjects(self::UNIT_TEST_USER);
$this->assertEquals(0, count($sos));
}
+
+ private function assertAcl($principal, $privilege, $acl) {
+ foreach($acl as $a) {
+ if ($a['principal'] === $principal && $a['privilege'] === $privilege) {
+ $this->assertTrue(true);
+ return;
+ }
+ }
+ $this->fail("ACL does not contain $principal / $privilege");
+ }
+
+ private function assertNotAcl($principal, $privilege, $acl) {
+ foreach($acl as $a) {
+ if ($a['principal'] === $principal && $a['privilege'] === $privilege) {
+ $this->fail("ACL contains $principal / $privilege");
+ return;
+ }
+ }
+ $this->assertTrue(true);
+ }
+
+ private function assertAccess($shouldHaveAcl, $principal, $privilege, $acl) {
+ if ($shouldHaveAcl) {
+ $this->assertAcl($principal, $privilege, $acl);
+ } else {
+ $this->assertNotAcl($principal, $privilege, $acl);
+ }
+ }
}
diff --git a/apps/dav/tests/unit/caldav/calendartest.php b/apps/dav/tests/unit/caldav/calendartest.php
new file mode 100644
index 00000000000..93b3f4bff8c
--- /dev/null
+++ b/apps/dav/tests/unit/caldav/calendartest.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\DAV\Tests\Unit\CalDAV;
+
+use OCA\DAV\CalDAV\CalDavBackend;
+use OCA\DAV\CalDAV\Calendar;
+use Test\TestCase;
+
+class CalendarTest extends TestCase {
+
+ public function testDelete() {
+ /** @var \PHPUnit_Framework_MockObject_MockObject | CalDavBackend $backend */
+ $backend = $this->getMockBuilder('OCA\DAV\CalDAV\CalDavBackend')->disableOriginalConstructor()->getMock();
+ $backend->expects($this->once())->method('updateShares');
+ $backend->method('getShares')->willReturn([
+ ['href' => 'principal:user2']
+ ]);
+ $calendarInfo = [
+ '{http://owncloud.org/ns}owner-principal' => 'user1',
+ 'principaluri' => 'user2',
+ 'id' => 666
+ ];
+ $c = new Calendar($backend, $calendarInfo);
+ $c->delete();
+ }
+
+ /**
+ * @expectedException \Sabre\DAV\Exception\Forbidden
+ */
+ public function testDeleteFromGroup() {
+ /** @var \PHPUnit_Framework_MockObject_MockObject | CalDavBackend $backend */
+ $backend = $this->getMockBuilder('OCA\DAV\CalDAV\CalDavBackend')->disableOriginalConstructor()->getMock();
+ $backend->expects($this->never())->method('updateShares');
+ $backend->method('getShares')->willReturn([
+ ['href' => 'principal:group2']
+ ]);
+ $calendarInfo = [
+ '{http://owncloud.org/ns}owner-principal' => 'user1',
+ 'principaluri' => 'user2',
+ 'id' => 666
+ ];
+ $c = new Calendar($backend, $calendarInfo);
+ $c->delete();
+ }
+}
diff --git a/apps/dav/tests/unit/carddav/addressbooktest.php b/apps/dav/tests/unit/carddav/addressbooktest.php
new file mode 100644
index 00000000000..d714fc71679
--- /dev/null
+++ b/apps/dav/tests/unit/carddav/addressbooktest.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\DAV\Tests\Unit\CardDAV;
+
+use OCA\DAV\CardDAV\AddressBook;
+use OCA\DAV\CardDAV\CardDavBackend;
+use Test\TestCase;
+
+class AddressBookTest extends TestCase {
+
+ public function testDelete() {
+ /** @var \PHPUnit_Framework_MockObject_MockObject | CardDavBackend $backend */
+ $backend = $this->getMockBuilder('OCA\DAV\CardDAV\CardDavBackend')->disableOriginalConstructor()->getMock();
+ $backend->expects($this->once())->method('updateShares');
+ $backend->method('getShares')->willReturn([
+ ['href' => 'principal:user2']
+ ]);
+ $calendarInfo = [
+ '{http://owncloud.org/ns}owner-principal' => 'user1',
+ 'principaluri' => 'user2',
+ 'id' => 666
+ ];
+ $c = new AddressBook($backend, $calendarInfo);
+ $c->delete();
+ }
+
+ /**
+ * @expectedException \Sabre\DAV\Exception\Forbidden
+ */
+ public function testDeleteFromGroup() {
+ /** @var \PHPUnit_Framework_MockObject_MockObject | CardDavBackend $backend */
+ $backend = $this->getMockBuilder('OCA\DAV\CardDAV\CardDavBackend')->disableOriginalConstructor()->getMock();
+ $backend->expects($this->never())->method('updateShares');
+ $backend->method('getShares')->willReturn([
+ ['href' => 'principal:group2']
+ ]);
+ $calendarInfo = [
+ '{http://owncloud.org/ns}owner-principal' => 'user1',
+ 'principaluri' => 'user2',
+ 'id' => 666
+ ];
+ $c = new AddressBook($backend, $calendarInfo);
+ $c->delete();
+ }
+}
diff --git a/apps/dav/tests/unit/carddav/carddavbackendtest.php b/apps/dav/tests/unit/carddav/carddavbackendtest.php
index 0158330a194..86bc26b4c0d 100644
--- a/apps/dav/tests/unit/carddav/carddavbackendtest.php
+++ b/apps/dav/tests/unit/carddav/carddavbackendtest.php
@@ -27,7 +27,6 @@ use OCA\DAV\CardDAV\AddressBook;
use OCA\DAV\CardDAV\CardDavBackend;
use OCA\DAV\Connector\Sabre\Principal;
use OCP\IDBConnection;
-use OCP\ILogger;
use Sabre\DAV\PropPatch;
use Sabre\VObject\Component\VCard;
use Sabre\VObject\Property\Text;
@@ -57,19 +56,24 @@ class CardDavBackendTest extends TestCase {
/** @var string */
private $dbCardsPropertiesTable = 'cards_properties';
- const UNIT_TEST_USER = 'carddav-unit-test';
+ const UNIT_TEST_USER = 'principals/users/carddav-unit-test';
+ const UNIT_TEST_USER1 = 'principals/users/carddav-unit-test1';
+ const UNIT_TEST_GROUP = 'principals/groups/carddav-unit-test-group';
public function setUp() {
parent::setUp();
$this->principal = $this->getMockBuilder('OCA\DAV\Connector\Sabre\Principal')
->disableOriginalConstructor()
- ->setMethods(['getPrincipalByPath'])
+ ->setMethods(['getPrincipalByPath', 'getGroupMembership'])
->getMock();
$this->principal->method('getPrincipalByPath')
->willReturn([
'uri' => 'principals/best-friend'
]);
+ $this->principal->method('getGroupMembership')
+ ->withAnyParameters()
+ ->willReturn([self::UNIT_TEST_GROUP]);
$this->db = \OC::$server->getDatabaseConnection();
@@ -124,6 +128,29 @@ class CardDavBackendTest extends TestCase {
$this->assertEquals(0, count($books));
}
+ public function testAddressBookSharing() {
+
+ $this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []);
+ $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER);
+ $this->assertEquals(1, count($books));
+ $addressBook = new AddressBook($this->backend, $books[0]);
+ $this->backend->updateShares($addressBook, [
+ [
+ 'href' => 'principal:' . self::UNIT_TEST_USER1,
+ ],
+ [
+ 'href' => 'principal:' . self::UNIT_TEST_GROUP,
+ ]
+ ], []);
+ $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER1);
+ $this->assertEquals(1, count($books));
+
+ // delete the address book
+ $this->backend->deleteAddressBook($books[0]['id']);
+ $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER);
+ $this->assertEquals(0, count($books));
+ }
+
public function testCardOperations() {
/** @var CardDavBackend | \PHPUnit_Framework_MockObject_MockObject $backend */
diff --git a/apps/dav/tests/unit/comments/commentnode.php b/apps/dav/tests/unit/comments/commentnode.php
index 44ac54ae937..8d1bf06ab60 100644
--- a/apps/dav/tests/unit/comments/commentnode.php
+++ b/apps/dav/tests/unit/comments/commentnode.php
@@ -51,10 +51,28 @@ class CommentsNode extends \Test\TestCase {
}
public function testDelete() {
+ $user = $this->getMock('\OCP\IUser');
+
+ $user->expects($this->once())
+ ->method('getUID')
+ ->will($this->returnValue('alice'));
+
+ $this->userSession->expects($this->once())
+ ->method('getUser')
+ ->will($this->returnValue($user));
+
$this->comment->expects($this->once())
->method('getId')
->will($this->returnValue('19'));
+ $this->comment->expects($this->any())
+ ->method('getActorType')
+ ->will($this->returnValue('users'));
+
+ $this->comment->expects($this->any())
+ ->method('getActorId')
+ ->will($this->returnValue('alice'));
+
$this->commentsManager->expects($this->once())
->method('delete')
->with('19');
@@ -62,6 +80,37 @@ class CommentsNode extends \Test\TestCase {
$this->node->delete();
}
+ /**
+ * @expectedException \Sabre\DAV\Exception\Forbidden
+ */
+ public function testDeleteForbidden() {
+ $user = $this->getMock('\OCP\IUser');
+
+ $user->expects($this->once())
+ ->method('getUID')
+ ->will($this->returnValue('mallory'));
+
+ $this->userSession->expects($this->once())
+ ->method('getUser')
+ ->will($this->returnValue($user));
+
+ $this->comment->expects($this->never())
+ ->method('getId');
+
+ $this->comment->expects($this->any())
+ ->method('getActorType')
+ ->will($this->returnValue('users'));
+
+ $this->comment->expects($this->any())
+ ->method('getActorId')
+ ->will($this->returnValue('alice'));
+
+ $this->commentsManager->expects($this->never())
+ ->method('delete');
+
+ $this->node->delete();
+ }
+
public function testGetName() {
$id = '19';
$this->comment->expects($this->once())
@@ -85,10 +134,28 @@ class CommentsNode extends \Test\TestCase {
public function testUpdateComment() {
$msg = 'Hello Earth';
+ $user = $this->getMock('\OCP\IUser');
+
+ $user->expects($this->once())
+ ->method('getUID')
+ ->will($this->returnValue('alice'));
+
+ $this->userSession->expects($this->once())
+ ->method('getUser')
+ ->will($this->returnValue($user));
+
$this->comment->expects($this->once())
->method('setMessage')
->with($msg);
+ $this->comment->expects($this->any())
+ ->method('getActorType')
+ ->will($this->returnValue('users'));
+
+ $this->comment->expects($this->any())
+ ->method('getActorId')
+ ->will($this->returnValue('alice'));
+
$this->commentsManager->expects($this->once())
->method('save')
->with($this->comment);
@@ -96,14 +163,32 @@ class CommentsNode extends \Test\TestCase {
$this->assertTrue($this->node->updateComment($msg));
}
- public function testUpdateCommentException() {
+ public function testUpdateCommentLogException() {
$msg = null;
+ $user = $this->getMock('\OCP\IUser');
+
+ $user->expects($this->once())
+ ->method('getUID')
+ ->will($this->returnValue('alice'));
+
+ $this->userSession->expects($this->once())
+ ->method('getUser')
+ ->will($this->returnValue($user));
+
$this->comment->expects($this->once())
->method('setMessage')
->with($msg)
->will($this->throwException(new \Exception('buh!')));
+ $this->comment->expects($this->any())
+ ->method('getActorType')
+ ->will($this->returnValue('users'));
+
+ $this->comment->expects($this->any())
+ ->method('getActorId')
+ ->will($this->returnValue('alice'));
+
$this->commentsManager->expects($this->never())
->method('save');
@@ -113,6 +198,90 @@ class CommentsNode extends \Test\TestCase {
$this->assertFalse($this->node->updateComment($msg));
}
+ /**
+ * @expectedException \Sabre\DAV\Exception\Forbidden
+ */
+ public function testUpdateForbiddenByUser() {
+ $msg = 'HaXX0r';
+
+ $user = $this->getMock('\OCP\IUser');
+
+ $user->expects($this->once())
+ ->method('getUID')
+ ->will($this->returnValue('mallory'));
+
+ $this->userSession->expects($this->once())
+ ->method('getUser')
+ ->will($this->returnValue($user));
+
+ $this->comment->expects($this->never())
+ ->method('setMessage');
+
+ $this->comment->expects($this->any())
+ ->method('getActorType')
+ ->will($this->returnValue('users'));
+
+ $this->comment->expects($this->any())
+ ->method('getActorId')
+ ->will($this->returnValue('alice'));
+
+ $this->commentsManager->expects($this->never())
+ ->method('save');
+
+ $this->node->updateComment($msg);
+ }
+
+ /**
+ * @expectedException \Sabre\DAV\Exception\Forbidden
+ */
+ public function testUpdateForbiddenByType() {
+ $msg = 'HaXX0r';
+
+ $user = $this->getMock('\OCP\IUser');
+
+ $user->expects($this->never())
+ ->method('getUID');
+
+ $this->userSession->expects($this->once())
+ ->method('getUser')
+ ->will($this->returnValue($user));
+
+ $this->comment->expects($this->never())
+ ->method('setMessage');
+
+ $this->comment->expects($this->any())
+ ->method('getActorType')
+ ->will($this->returnValue('bots'));
+
+ $this->commentsManager->expects($this->never())
+ ->method('save');
+
+ $this->node->updateComment($msg);
+ }
+
+ /**
+ * @expectedException \Sabre\DAV\Exception\Forbidden
+ */
+ public function testUpdateForbiddenByNotLoggedIn() {
+ $msg = 'HaXX0r';
+
+ $this->userSession->expects($this->once())
+ ->method('getUser')
+ ->will($this->returnValue(null));
+
+ $this->comment->expects($this->never())
+ ->method('setMessage');
+
+ $this->comment->expects($this->any())
+ ->method('getActorType')
+ ->will($this->returnValue('users'));
+
+ $this->commentsManager->expects($this->never())
+ ->method('save');
+
+ $this->node->updateComment($msg);
+ }
+
public function testPropPatch() {
$propPatch = $this->getMockBuilder('Sabre\DAV\PropPatch')
->disableOriginalConstructor()
diff --git a/apps/dav/tests/unit/comments/commentsplugin.php b/apps/dav/tests/unit/comments/commentsplugin.php
index bd0b56fc650..9822137bbea 100644
--- a/apps/dav/tests/unit/comments/commentsplugin.php
+++ b/apps/dav/tests/unit/comments/commentsplugin.php
@@ -92,6 +92,10 @@ class CommentsPlugin extends \Test\TestCase {
->method('getId')
->will($this->returnValue('42'));
+ $node->expects($this->once())
+ ->method('setReadMarker')
+ ->with(null);
+
$this->commentsManager->expects($this->once())
->method('create')
->with('users', 'alice', 'files', '42')
diff --git a/apps/encryption/appinfo/info.xml b/apps/encryption/appinfo/info.xml
index 1fb4e93c508..970b58e3898 100644
--- a/apps/encryption/appinfo/info.xml
+++ b/apps/encryption/appinfo/info.xml
@@ -12,7 +12,7 @@
to enable server-side encryption.
</description>
<name>Default encryption module</name>
- <license>AGPL</license>
+ <licence>AGPL</licence>
<author>Bjoern Schiessle, Clark Tomlinson</author>
<documentation>
<user>user-encryption</user>
diff --git a/apps/files/appinfo/info.xml b/apps/files/appinfo/info.xml
index c0db1783235..b31232b799a 100644
--- a/apps/files/appinfo/info.xml
+++ b/apps/files/appinfo/info.xml
@@ -5,9 +5,8 @@
<description>File Management</description>
<licence>AGPL</licence>
<author>Robin Appelman, Vincent Petry</author>
- <standalone/>
<default_enable/>
- <version>1.4.2</version>
+ <version>1.4.3</version>
<types>
<filesystem/>
</types>
diff --git a/apps/files/appinfo/install.php b/apps/files/appinfo/install.php
index b9a893d1ee8..ae08e21a22e 100644
--- a/apps/files/appinfo/install.php
+++ b/apps/files/appinfo/install.php
@@ -21,4 +21,4 @@
// Cron job for scanning user storages
\OC::$server->getJobList()->add('OCA\Files\BackgroundJob\ScanFiles');
-\OC::$server->getJobList()->add('OCA\Files\BackgroundJob\DeleteOrphanedTagsJob');
+\OC::$server->getJobList()->add('OCA\Files\BackgroundJob\DeleteOrphanedItems');
diff --git a/apps/files/appinfo/update.php b/apps/files/appinfo/update.php
index 003f6916ac5..cb682cbc426 100644
--- a/apps/files/appinfo/update.php
+++ b/apps/files/appinfo/update.php
@@ -99,4 +99,4 @@ if ($installedVersion === '1.1.9' && (
// Add cron job for scanning user storages
\OC::$server->getJobList()->add('OCA\Files\BackgroundJob\ScanFiles');
-\OC::$server->getJobList()->add('OCA\Files\BackgroundJob\DeleteOrphanedTagsJob');
+\OC::$server->getJobList()->add('OCA\Files\BackgroundJob\DeleteOrphanedItems');
diff --git a/apps/files/css/files.css b/apps/files/css/files.css
index 4929039f837..389b7fae806 100644
--- a/apps/files/css/files.css
+++ b/apps/files/css/files.css
@@ -530,8 +530,8 @@ html.ie8 #fileList tr.selected td.filename>.selectCheckBox {
}
a.action > img {
- max-height: 16px;
- max-width: 16px;
+ height: 16px;
+ width: 16px;
vertical-align: text-bottom;
}
diff --git a/apps/files/lib/backgroundjob/deleteorphanedtagsjob.php b/apps/files/lib/backgroundjob/deleteorphaneditems.php
index 33f455b5b40..cefa1d655de 100644
--- a/apps/files/lib/backgroundjob/deleteorphanedtagsjob.php
+++ b/apps/files/lib/backgroundjob/deleteorphaneditems.php
@@ -22,11 +22,12 @@
namespace OCA\Files\BackgroundJob;
use OC\BackgroundJob\TimedJob;
+use OCP\DB\QueryBuilder\IQueryBuilder;
/**
* Delete all share entries that have no matching entries in the file cache table.
*/
-class DeleteOrphanedTagsJob extends TimedJob {
+class DeleteOrphanedItems extends TimedJob {
/** @var \OCP\IDBConnection */
protected $connection;
@@ -58,6 +59,8 @@ class DeleteOrphanedTagsJob extends TimedJob {
public function run($argument) {
$this->cleanSystemTags();
$this->cleanUserTags();
+ $this->cleanComments();
+ $this->cleanCommentMarkers();
}
/**
@@ -65,19 +68,29 @@ class DeleteOrphanedTagsJob extends TimedJob {
*
* @return int Number of deleted entries
*/
- protected function cleanSystemTags() {
+ protected function cleanUp($table, $idCol, $typeCol) {
$subQuery = $this->connection->getQueryBuilder();
$subQuery->select($subQuery->expr()->literal('1'))
->from('filecache', 'f')
- ->where($subQuery->expr()->eq('objectid', 'f.fileid'));
+ ->where($subQuery->expr()->eq($idCol, 'f.fileid'));
$query = $this->connection->getQueryBuilder();
- $deletedEntries = $query->delete('systemtag_object_mapping')
- ->where($query->expr()->eq('objecttype', $query->expr()->literal('files')))
+ $deletedEntries = $query->delete($table)
+ ->where($query->expr()->eq($typeCol, $query->expr()->literal('files')))
->andWhere($query->expr()->isNull($query->createFunction('(' . $subQuery->getSql() . ')')))
->execute();
- $this->logger->debug("$deletedEntries orphaned system tag relations deleted", ['app' => 'DeleteOrphanedTagsJob']);
+ return $deletedEntries;
+ }
+
+ /**
+ * Deleting orphaned system tag mappings
+ *
+ * @return int Number of deleted entries
+ */
+ protected function cleanSystemTags() {
+ $deletedEntries = $this->cleanUp('systemtag_object_mapping', 'objectid', 'objecttype');
+ $this->logger->debug("$deletedEntries orphaned system tag relations deleted", ['app' => 'DeleteOrphanedItems']);
return $deletedEntries;
}
@@ -87,18 +100,32 @@ class DeleteOrphanedTagsJob extends TimedJob {
* @return int Number of deleted entries
*/
protected function cleanUserTags() {
- $subQuery = $this->connection->getQueryBuilder();
- $subQuery->select($subQuery->expr()->literal('1'))
- ->from('filecache', 'f')
- ->where($subQuery->expr()->eq('objid', 'f.fileid'));
+ $deletedEntries = $this->cleanUp('vcategory_to_object', 'objid', 'type');
+ $this->logger->debug("$deletedEntries orphaned user tag relations deleted", ['app' => 'DeleteOrphanedItems']);
+ return $deletedEntries;
+ }
- $query = $this->connection->getQueryBuilder();
- $deletedEntries = $query->delete('vcategory_to_object')
- ->where($query->expr()->eq('type', $query->expr()->literal('files')))
- ->andWhere($query->expr()->isNull($query->createFunction('(' . $subQuery->getSql() . ')')))
- ->execute();
+ /**
+ * Deleting orphaned comments
+ *
+ * @return int Number of deleted entries
+ */
+ protected function cleanComments() {
+ $qb = $this->connection->getQueryBuilder();
+ $deletedEntries = $this->cleanUp('comments', $qb->expr()->castColumn('object_id', IQueryBuilder::PARAM_INT), 'object_type');
+ $this->logger->debug("$deletedEntries orphaned comments deleted", ['app' => 'DeleteOrphanedItems']);
+ return $deletedEntries;
+ }
- $this->logger->debug("$deletedEntries orphaned user tag relations deleted", ['app' => 'DeleteOrphanedTagsJob']);
+ /**
+ * Deleting orphaned comment read markers
+ *
+ * @return int Number of deleted entries
+ */
+ protected function cleanCommentMarkers() {
+ $qb = $this->connection->getQueryBuilder();
+ $deletedEntries = $this->cleanUp('comments_read_markers', $qb->expr()->castColumn('object_id', IQueryBuilder::PARAM_INT), 'object_type');
+ $this->logger->debug("$deletedEntries orphaned comment read marks deleted", ['app' => 'DeleteOrphanedItems']);
return $deletedEntries;
}
diff --git a/apps/files/tests/backgroundjob/DeleteOrphanedTagsJobTest.php b/apps/files/tests/backgroundjob/DeleteOrphanedItemsJobTest.php
index d2e9d77cb20..8d8e5d3be52 100644
--- a/apps/files/tests/backgroundjob/DeleteOrphanedTagsJobTest.php
+++ b/apps/files/tests/backgroundjob/DeleteOrphanedItemsJobTest.php
@@ -21,17 +21,17 @@
namespace OCA\Files\Tests\BackgroundJob;
-use OCA\Files\BackgroundJob\DeleteOrphanedTagsJob;
+use OCA\Files\BackgroundJob\DeleteOrphanedItems;
use OCP\DB\QueryBuilder\IQueryBuilder;
/**
- * Class DeleteOrphanedTagsJobTest
+ * Class DeleteOrphanedItemsJobTest
*
* @group DB
*
* @package Test\BackgroundJob
*/
-class DeleteOrphanedTagsJobTest extends \Test\TestCase {
+class DeleteOrphanedItemsJobTest extends \Test\TestCase {
/** @var \OCP\IDBConnection */
protected $connection;
@@ -93,7 +93,7 @@ class DeleteOrphanedTagsJobTest extends \Test\TestCase {
$mapping = $this->getMappings('systemtag_object_mapping');
$this->assertCount(2, $mapping);
- $job = new DeleteOrphanedTagsJob();
+ $job = new DeleteOrphanedItems();
$this->invokePrivate($job, 'cleanSystemTags');
$mapping = $this->getMappings('systemtag_object_mapping');
@@ -142,7 +142,7 @@ class DeleteOrphanedTagsJobTest extends \Test\TestCase {
$mapping = $this->getMappings('vcategory_to_object');
$this->assertCount(2, $mapping);
- $job = new DeleteOrphanedTagsJob();
+ $job = new DeleteOrphanedItems();
$this->invokePrivate($job, 'cleanUserTags');
$mapping = $this->getMappings('vcategory_to_object');
@@ -155,4 +155,104 @@ class DeleteOrphanedTagsJobTest extends \Test\TestCase {
$this->cleanMapping('vcategory_to_object');
}
+ /**
+ * Test clearing orphaned system tag mappings
+ */
+ public function testClearComments() {
+ $this->cleanMapping('comments');
+
+ $query = $this->connection->getQueryBuilder();
+ $query->insert('filecache')
+ ->values([
+ 'storage' => $query->createNamedParameter(1337, IQueryBuilder::PARAM_INT),
+ 'path' => $query->createNamedParameter('apps/files/tests/deleteorphanedtagsjobtest.php'),
+ 'path_hash' => $query->createNamedParameter(md5('apps/files/tests/deleteorphanedtagsjobtest.php')),
+ ])->execute();
+ $fileId = $query->getLastInsertId();
+
+ // Existing file
+ $query = $this->connection->getQueryBuilder();
+ $query->insert('comments')
+ ->values([
+ 'object_id' => $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT),
+ 'object_type' => $query->createNamedParameter('files'),
+ 'actor_id' => $query->createNamedParameter('Alice', IQueryBuilder::PARAM_INT),
+ 'actor_type' => $query->createNamedParameter('users'),
+ ])->execute();
+
+ // Non-existing file
+ $query = $this->connection->getQueryBuilder();
+ $query->insert('comments')
+ ->values([
+ 'object_id' => $query->createNamedParameter($fileId + 1, IQueryBuilder::PARAM_INT),
+ 'object_type' => $query->createNamedParameter('files'),
+ 'actor_id' => $query->createNamedParameter('Alice', IQueryBuilder::PARAM_INT),
+ 'actor_type' => $query->createNamedParameter('users'),
+ ])->execute();
+
+ $mapping = $this->getMappings('comments');
+ $this->assertCount(2, $mapping);
+
+ $job = new DeleteOrphanedItems();
+ $this->invokePrivate($job, 'cleanComments');
+
+ $mapping = $this->getMappings('comments');
+ $this->assertCount(1, $mapping);
+
+ $query = $this->connection->getQueryBuilder();
+ $query->delete('filecache')
+ ->where($query->expr()->eq('fileid', $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)))
+ ->execute();
+ $this->cleanMapping('comments');
+ }
+
+ /**
+ * Test clearing orphaned system tag mappings
+ */
+ public function testClearCommentReadMarks() {
+ $this->cleanMapping('comments_read_markers');
+
+ $query = $this->connection->getQueryBuilder();
+ $query->insert('filecache')
+ ->values([
+ 'storage' => $query->createNamedParameter(1337, IQueryBuilder::PARAM_INT),
+ 'path' => $query->createNamedParameter('apps/files/tests/deleteorphanedtagsjobtest.php'),
+ 'path_hash' => $query->createNamedParameter(md5('apps/files/tests/deleteorphanedtagsjobtest.php')),
+ ])->execute();
+ $fileId = $query->getLastInsertId();
+
+ // Existing file
+ $query = $this->connection->getQueryBuilder();
+ $query->insert('comments_read_markers')
+ ->values([
+ 'object_id' => $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT),
+ 'object_type' => $query->createNamedParameter('files'),
+ 'user_id' => $query->createNamedParameter('Alice', IQueryBuilder::PARAM_INT),
+ ])->execute();
+
+ // Non-existing file
+ $query = $this->connection->getQueryBuilder();
+ $query->insert('comments_read_markers')
+ ->values([
+ 'object_id' => $query->createNamedParameter($fileId + 1, IQueryBuilder::PARAM_INT),
+ 'object_type' => $query->createNamedParameter('files'),
+ 'user_id' => $query->createNamedParameter('Alice', IQueryBuilder::PARAM_INT),
+ ])->execute();
+
+ $mapping = $this->getMappings('comments_read_markers');
+ $this->assertCount(2, $mapping);
+
+ $job = new DeleteOrphanedItems();
+ $this->invokePrivate($job, 'cleanCommentMarkers');
+
+ $mapping = $this->getMappings('comments_read_markers');
+ $this->assertCount(1, $mapping);
+
+ $query = $this->connection->getQueryBuilder();
+ $query->delete('filecache')
+ ->where($query->expr()->eq('fileid', $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)))
+ ->execute();
+ $this->cleanMapping('comments_read_markers');
+ }
+
}
diff --git a/apps/files_external/appinfo/application.php b/apps/files_external/appinfo/application.php
index 1bf258c48b4..d6552fa680c 100644
--- a/apps/files_external/appinfo/application.php
+++ b/apps/files_external/appinfo/application.php
@@ -110,6 +110,7 @@ class Application extends App {
$container->query('OCA\Files_External\Lib\Auth\Password\SessionCredentials'),
$container->query('OCA\Files_External\Lib\Auth\Password\LoginCredentials'),
$container->query('OCA\Files_External\Lib\Auth\Password\UserProvided'),
+ $container->query('OCA\Files_External\Lib\Auth\Password\GlobalAuth'),
// AuthMechanism::SCHEME_OAUTH1 mechanisms
$container->query('OCA\Files_External\Lib\Auth\OAuth1\OAuth1'),
diff --git a/apps/files_external/appinfo/routes.php b/apps/files_external/appinfo/routes.php
index c3149a300cf..d5b927c0227 100644
--- a/apps/files_external/appinfo/routes.php
+++ b/apps/files_external/appinfo/routes.php
@@ -44,7 +44,12 @@ namespace OCA\Files_External\AppInfo;
'url' => '/ajax/public_key.php',
'verb' => 'POST',
'requirements' => array()
- )
+ ),
+ [
+ 'name' => 'Ajax#saveGlobalCredentials',
+ 'url' => '/globalcredentials',
+ 'verb' => 'POST'
+ ]
)
)
);
diff --git a/apps/files_external/controller/ajaxcontroller.php b/apps/files_external/controller/ajaxcontroller.php
index cfccacb03ea..86c1b657c91 100644
--- a/apps/files_external/controller/ajaxcontroller.php
+++ b/apps/files_external/controller/ajaxcontroller.php
@@ -23,6 +23,7 @@
namespace OCA\Files_External\Controller;
+use OCA\Files_External\Lib\Auth\Password\GlobalAuth;
use OCP\AppFramework\Controller;
use OCP\IRequest;
use OCP\AppFramework\Http\JSONResponse;
@@ -31,10 +32,13 @@ use OCA\Files_External\Lib\Auth\PublicKey\RSA;
class AjaxController extends Controller {
/** @var RSA */
private $rsaMechanism;
+ /** @var GlobalAuth */
+ private $globalAuth;
- public function __construct($appName, IRequest $request, RSA $rsaMechanism) {
+ public function __construct($appName, IRequest $request, RSA $rsaMechanism, GlobalAuth $globalAuth) {
parent::__construct($appName, $request);
$this->rsaMechanism = $rsaMechanism;
+ $this->globalAuth = $globalAuth;
}
private function generateSshKeys() {
@@ -61,4 +65,8 @@ class AjaxController extends Controller {
));
}
+ public function saveGlobalCredentials($uid, $user, $password) {
+ $this->globalAuth->saveAuth($uid, $user, $password);
+ return true;
+ }
}
diff --git a/apps/files_external/controller/storagescontroller.php b/apps/files_external/controller/storagescontroller.php
index db1cdeb23b9..65ceba21454 100644
--- a/apps/files_external/controller/storagescontroller.php
+++ b/apps/files_external/controller/storagescontroller.php
@@ -255,8 +255,9 @@ abstract class StoragesController extends Controller {
)
);
} catch (InsufficientDataForMeaningfulAnswerException $e) {
+ $status = $e->getCode() ? $e->getCode() : StorageNotAvailableException::STATUS_INDETERMINATE;
$storage->setStatus(
- StorageNotAvailableException::STATUS_INDETERMINATE,
+ $status,
$this->l10n->t('Insufficient data: %s', [$e->getMessage()])
);
} catch (StorageNotAvailableException $e) {
diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js
index 26df203091e..0837555f534 100644
--- a/apps/files_external/js/settings.js
+++ b/apps/files_external/js/settings.js
@@ -1338,6 +1338,33 @@ $(document).ready(function() {
}
});
+ $('#global_credentials').on('submit', function() {
+ var $form = $(this);
+ var uid = $form.find('[name=uid]').val();
+ var user = $form.find('[name=username]').val();
+ var password = $form.find('[name=password]').val();
+ var $submit = $form.find('[type=submit]');
+ $submit.val(t('files_external', 'Saving...'));
+ $.ajax({
+ type: 'POST',
+ contentType: 'application/json',
+ data: JSON.stringify({
+ uid: uid,
+ user: user,
+ password: password
+ }),
+ url: OC.generateUrl('apps/files_external/globalcredentials'),
+ dataType: 'json',
+ success: function() {
+ $submit.val(t('files_external', 'Saved'));
+ setTimeout(function(){
+ $submit.val(t('files_external', 'Save'));
+ }, 2500);
+ }
+ });
+ return false;
+ });
+
// global instance
OCA.External.Settings.mountConfig = mountConfigListView;
diff --git a/apps/files_external/js/statusmanager.js b/apps/files_external/js/statusmanager.js
index 27635d2f1df..33d2ea104be 100644
--- a/apps/files_external/js/statusmanager.js
+++ b/apps/files_external/js/statusmanager.js
@@ -22,15 +22,15 @@ if (!OCA.External.StatusManager) {
OCA.External.StatusManager = {
- mountStatus : null,
- mountPointList : null,
+ mountStatus: null,
+ mountPointList: null,
/**
* Function
* @param {callback} afterCallback
*/
- getMountStatus : function(afterCallback) {
+ getMountStatus: function (afterCallback) {
var self = this;
if (typeof afterCallback !== 'function' || self.isGetMountStatusRunning) {
return;
@@ -46,9 +46,9 @@ OCA.External.StatusManager = {
* @param {string} mount_point
*/
- getMountPointListElement : function(mount_point) {
+ getMountPointListElement: function (mount_point) {
var element;
- $.each(this.mountPointList, function(key, value){
+ $.each(this.mountPointList, function (key, value) {
if (value.mount_point === mount_point) {
element = value;
return false;
@@ -63,7 +63,7 @@ OCA.External.StatusManager = {
* @param {string} mount_point
*/
- getMountStatusForMount : function(mountData, afterCallback) {
+ getMountStatusForMount: function (mountData, afterCallback) {
var self = this;
if (typeof afterCallback !== 'function' || self.isGetMountStatusRunning) {
return $.Deferred().resolve();
@@ -72,41 +72,46 @@ OCA.External.StatusManager = {
var defObj;
if (self.mountStatus[mountData.mount_point]) {
defObj = $.Deferred();
- afterCallback(mountData, self.mountStatus[mountData.mount_point]);
+ afterCallback(mountData, self.mountStatus[mountData.mount_point]);
defObj.resolve(); // not really useful, but it'll keep the same behaviour
} else {
defObj = $.ajax({
- type : 'GET',
+ type: 'GET',
url: OC.webroot + '/index.php/apps/files_external/' + ((mountData.type === 'personal') ? 'userstorages' : 'userglobalstorages') + '/' + mountData.id,
- success : function(response) {
+ success: function (response) {
if (response && response.status === 0) {
self.mountStatus[mountData.mount_point] = response;
} else {
- if (response && response.statusMessage) {
- // failure response with error message
- self.mountStatus[mountData.mount_point] = { type: mountData.type,
- status: 1,
- error: response.statusMessage};
- } else {
- self.mountStatus[mountData.mount_point] = { type: mountData.type,
- status: 1,
- error: t('files_external', 'Empty response from the server')};
- }
+ var statusCode = response.status ? response.status : 1;
+ var statusMessage = response.statusMessage ? response.statusMessage : t('files_external', 'Empty response from the server')
+ // failure response with error message
+ self.mountStatus[mountData.mount_point] = {
+ type: mountData.type,
+ status: statusCode,
+ id: mountData.id,
+ error: statusMessage,
+ userProvided: response.userProvided
+ };
}
afterCallback(mountData, self.mountStatus[mountData.mount_point]);
},
- error : function(jqxhr, state, error) {
+ error: function (jqxhr, state, error) {
var message;
- if(mountData.location === 3){
+ if (mountData.location === 3) {
// In this case the error is because mount point use Login credentials and don't exist in the session
message = t('files_external', 'Couldn\'t access. Please logout and login to activate this mount point');
} else {
- message = t('files_external', 'Couldn\'t get the information from the ownCloud server: {code} {type}', {code: jqxhr.status, type: error});
+ message = t('files_external', 'Couldn\'t get the information from the ownCloud server: {code} {type}', {
+ code: jqxhr.status,
+ type: error
+ });
}
- self.mountStatus[mountData.mount_point] = { type: mountData.type,
- status: 1,
- location: mountData.location,
- error: message};
+ self.mountStatus[mountData.mount_point] = {
+ type: mountData.type,
+ status: 1,
+ location: mountData.location,
+ error: message
+ };
afterCallback(mountData, self.mountStatus[mountData.mount_point]);
}
});
@@ -119,7 +124,7 @@ OCA.External.StatusManager = {
* @param {function} afterCallback function to be executed
*/
- getMountPointList : function(afterCallback) {
+ getMountPointList: function (afterCallback) {
var self = this;
if (typeof afterCallback !== 'function' || self.isGetMountPointListRunning) {
return;
@@ -130,11 +135,11 @@ OCA.External.StatusManager = {
} else {
self.isGetMountPointListRunning = true;
$.ajax({
- type : 'GET',
- url : OC.linkToOCS('apps/files_external/api/v1') + 'mounts?format=json',
- success : function(response) {
+ type: 'GET',
+ url: OC.linkToOCS('apps/files_external/api/v1') + 'mounts?format=json',
+ success: function (response) {
self.mountPointList = [];
- _.each(response.ocs.data, function(mount){
+ _.each(response.ocs.data, function (mount) {
var element = {};
element.mount_point = mount.name;
element.type = mount.scope;
@@ -147,11 +152,11 @@ OCA.External.StatusManager = {
});
afterCallback(self.mountPointList);
},
- error : function(jqxhr, state, error) {
+ error: function (jqxhr, state, error) {
self.mountPointList = [];
- OC.Notification.showTemporary(t('files_external', 'Couldn\'t get the list of external mount points: {type}', {type : error}));
+ OC.Notification.showTemporary(t('files_external', 'Couldn\'t get the list of external mount points: {type}', {type: error}));
},
- complete : function() {
+ complete: function () {
self.isGetMountPointListRunning = false;
}
});
@@ -163,21 +168,25 @@ OCA.External.StatusManager = {
* @param {string} name MountPoint Name
*/
- manageMountPointError : function(name) {
- var self = this;
- this.getMountStatus($.proxy(function(allMountStatus) {
- if (typeof allMountStatus[name] !== 'undefined' || allMountStatus[name].status === 1) {
+ manageMountPointError: function (name) {
+ this.getMountStatus($.proxy(function (allMountStatus) {
+ if (allMountStatus.hasOwnProperty(name) && allMountStatus[name].status > 0 && allMountStatus[name].status < 7) {
var mountData = allMountStatus[name];
if (mountData.type === "system") {
- OC.dialogs.confirm(t('files_external', 'There was an error with message: ') + mountData.error + '. Do you want to review mount point config in admin settings page?', t('files_external', 'External mount error'), function(e){
- if(e === true) {
- window.location.href = OC.generateUrl('/settings/admin#files_external');
- }
- });
+ if (mountData.userProvided) {
+ // personal mount whit credentials problems
+ this.showCredentialsDialog(name, mountData);
+ } else {
+ OC.dialogs.confirm(t('files_external', 'There was an error with message: ') + mountData.error + '. Do you want to review mount point config in admin settings page?', t('files_external', 'External mount error'), function (e) {
+ if (e === true) {
+ OC.redirect(OC.generateUrl('/settings/admin#files_external'));
+ }
+ });
+ }
} else {
- OC.dialogs.confirm(t('files_external', 'There was an error with message: ') + mountData.error + '. Do you want to review mount point config in personal settings page?', t('files_external', 'External mount error'), function(e){
- if(e === true) {
- window.location.href = OC.generateUrl('/settings/personal#external-storage');
+ OC.dialogs.confirm(t('files_external', 'There was an error with message: ') + mountData.error + '. Do you want to review mount point config in personal settings page?', t('files_external', 'External mount error'), function (e) {
+ if (e === true) {
+ OC.redirect(OC.generateUrl('/settings/personal#' + t('files_external', 'external-storage')));
}
});
}
@@ -191,13 +200,13 @@ OCA.External.StatusManager = {
* @param {object} mountStatus
*/
- processMountStatusIndividual : function(mountData, mountStatus) {
+ processMountStatusIndividual: function (mountData, mountStatus) {
var mountPoint = mountData.mount_point;
- if (mountStatus.status === 1) {
+ if (mountStatus.status > 0) {
var trElement = FileList.findFileEl(OCA.External.StatusManager.Utils.jqSelEscape(mountPoint));
- route = OCA.External.StatusManager.Utils.getIconRoute(trElement) + '-error';
+ var route = OCA.External.StatusManager.Utils.getIconRoute(trElement) + '-error';
if (OCA.External.StatusManager.Utils.isCorrectViewAndRootFolder()) {
OCA.External.StatusManager.Utils.showIconError(mountPoint, $.proxy(OCA.External.StatusManager.manageMountPointError, OCA.External.StatusManager), route);
@@ -218,9 +227,9 @@ OCA.External.StatusManager = {
* @param {object} mountStatus
*/
- processMountList : function(mountList) {
+ processMountList: function (mountList) {
var elementList = null;
- $.each(mountList, function(name, value){
+ $.each(mountList, function (name, value) {
var trElement = $('#fileList tr[data-file=\"' + OCA.External.StatusManager.Utils.jqSelEscape(value.mount_point) + '\"]'); //FileList.findFileEl(OCA.External.StatusManager.Utils.jqSelEscape(value.mount_point));
trElement.attr('data-external-backend', value.backend);
if (elementList) {
@@ -247,9 +256,9 @@ OCA.External.StatusManager = {
* Function to process the whole mount point list in relation with their status (Async queue)
*/
- launchFullConnectivityCheckOneByOne : function() {
+ launchFullConnectivityCheckOneByOne: function () {
var self = this;
- this.getMountPointList(function(list){
+ this.getMountPointList(function (list) {
// check if we have a list first
if (list === undefined && !self.emptyWarningShown) {
self.emptyWarningShown = true;
@@ -264,17 +273,19 @@ OCA.External.StatusManager = {
}
var ajaxQueue = [];
- $.each(list, function(key, value){
- var queueElement = {funcName: $.proxy(self.getMountStatusForMount, self),
- funcArgs: [value,
- $.proxy(self.processMountStatusIndividual, self)]};
+ $.each(list, function (key, value) {
+ var queueElement = {
+ funcName: $.proxy(self.getMountStatusForMount, self),
+ funcArgs: [value,
+ $.proxy(self.processMountStatusIndividual, self)]
+ };
ajaxQueue.push(queueElement);
});
- var rolQueue = new OCA.External.StatusManager.RollingQueue(ajaxQueue, 4, function(){
+ var rolQueue = new OCA.External.StatusManager.RollingQueue(ajaxQueue, 4, function () {
if (!self.notificationHasShown) {
var showNotification = false;
- $.each(self.mountStatus, function(key, value){
+ $.each(self.mountStatus, function (key, value) {
if (value.status === 1) {
self.notificationHasShown = true;
showNotification = true;
@@ -297,20 +308,22 @@ OCA.External.StatusManager = {
* @param {boolean} recheck delete cached info and force api call to check mount point status
*/
- launchPartialConnectivityCheck : function(mountListData, recheck) {
+ launchPartialConnectivityCheck: function (mountListData, recheck) {
if (mountListData.length === 0) {
return;
}
var self = this;
var ajaxQueue = [];
- $.each(mountListData, function(key, value){
+ $.each(mountListData, function (key, value) {
if (recheck && value.mount_point in self.mountStatus) {
delete self.mountStatus[value.mount_point];
}
- var queueElement = {funcName: $.proxy(self.getMountStatusForMount, self),
- funcArgs: [value,
- $.proxy(self.processMountStatusIndividual, self)]};
+ var queueElement = {
+ funcName: $.proxy(self.getMountStatusForMount, self),
+ funcArgs: [value,
+ $.proxy(self.processMountStatusIndividual, self)]
+ };
ajaxQueue.push(queueElement);
});
new OCA.External.StatusManager.RollingQueue(ajaxQueue, 4).runQueue();
@@ -323,21 +336,19 @@ OCA.External.StatusManager = {
* @param {boolean} recheck delete cached info and force api call to check mount point status
*/
- recheckConnectivityForMount : function(mountListNames, recheck) {
+ recheckConnectivityForMount: function (mountListNames, recheck) {
if (mountListNames.length === 0) {
return;
}
var self = this;
var mountListData = [];
- var recheckPersonalGlobal = false;
- var recheckAdminGlobal = false;
if (!self.mountStatus) {
self.mountStatus = {};
}
- $.each(mountListNames, function(key, value){
+ $.each(mountListNames, function (key, value) {
var mountData = self.getMountPointListElement(value);
if (mountData) {
mountListData.push(mountData);
@@ -346,7 +357,7 @@ OCA.External.StatusManager = {
// for all mounts in the list, delete the cached status values
if (recheck) {
- $.each(mountListData, function(key, value){
+ $.each(mountListData, function (key, value) {
if (value.mount_point in self.mountStatus) {
delete self.mountStatus[value.mount_point];
}
@@ -355,12 +366,96 @@ OCA.External.StatusManager = {
self.processMountList(mountListData);
self.launchPartialConnectivityCheck(mountListData, recheck);
+ },
+
+ credentialsDialogTemplate:
+ '<div id="files_external_div_form"><div>' +
+ '<div>{{credentials_text}}</div>' +
+ '<form>' +
+ '<input type="text" name="username" placeholder="{{placeholder_username}}"/>' +
+ '<input type="password" name="password" placeholder="{{placeholder_password}}"/>' +
+ '</form>' +
+ '</div></div>',
+
+ /**
+ * Function to display custom dialog to enter credentials
+ * @param mountPoint
+ * @param mountData
+ */
+ showCredentialsDialog: function (mountPoint, mountData) {
+ var template = Handlebars.compile(OCA.External.StatusManager.credentialsDialogTemplate);
+ var dialog = $(template({
+ credentials_text: t('files_external', 'Please enter the credentials for the {mount} mount', {
+ 'mount': mountPoint
+ }),
+ placeholder_username: t('files_external', 'Username'),
+ placeholder_password: t('files_external', 'Password')
+ }));
+
+ $('body').append(dialog);
+
+ var apply = function () {
+ var username = dialog.find('[name=username]').val();
+ var password = dialog.find('[name=password]').val();
+ var endpoint = OC.generateUrl('apps/files_external/userglobalstorages/{id}', {
+ id: mountData.id
+ });
+ $('.oc-dialog-close').hide();
+ $.ajax({
+ type: 'PUT',
+ url: endpoint,
+ data: {
+ backendOptions: {
+ user: username,
+ password: password
+ }
+ },
+ success: function (data) {
+ OC.Notification.showTemporary(t('files_external', 'Credentials saved'));
+ dialog.ocdialog('close');
+ /* Trigger status check again */
+ OCA.External.StatusManager.recheckConnectivityForMount([OC.basename(data.mountPoint)], true);
+ },
+ error: function () {
+ $('.oc-dialog-close').show();
+ OC.Notification.showTemporary(t('files_external', 'Credentials saving failed'));
+ }
+ });
+ return false;
+ };
+
+ var ocdialogParams = {
+ modal: true,
+ title: t('files_external', 'Credentials required'),
+ buttons: [{
+ text: t('files_external', 'Save'),
+ click: apply,
+ closeOnEscape: true
+ }],
+ closeOnExcape: true
+ };
+
+ dialog.ocdialog(ocdialogParams)
+ .bind('ocdialogclose', function () {
+ dialog.ocdialog('destroy').remove();
+ });
+
+ dialog.find('form').on('submit', apply);
+ dialog.find('form input:first').focus();
+ dialog.find('form input').keyup(function (e) {
+ if ((e.which && e.which === 13) || (e.keyCode && e.keyCode === 13)) {
+ $(e.target).closest('form').submit();
+ return false;
+ } else {
+ return true;
+ }
+ });
}
};
OCA.External.StatusManager.Utils = {
- showIconError: function(folder, clickAction, errorImageUrl) {
+ showIconError: function (folder, clickAction, errorImageUrl) {
var imageUrl = "url(" + errorImageUrl + ")";
var trFolder = $('#fileList tr[data-file=\"' + OCA.External.StatusManager.Utils.jqSelEscape(folder) + '\"]'); //FileList.findFileEl(OCA.External.StatusManager.Utils.jqSelEscape(folder));
this.changeFolderIcon(folder, imageUrl);
@@ -371,14 +466,14 @@ OCA.External.StatusManager.Utils = {
/**
* @param folder string with the folder or jQuery element pointing to the tr element
*/
- storeDefaultFolderIconAndBgcolor: function(folder) {
+ storeDefaultFolderIconAndBgcolor: function (folder) {
var trFolder;
if (folder instanceof $) {
trFolder = folder;
} else {
trFolder = $('#fileList tr[data-file=\"' + OCA.External.StatusManager.Utils.jqSelEscape(folder) + '\"]'); //FileList.findFileEl(OCA.External.StatusManager.Utils.jqSelEscape(folder)); //$('#fileList tr[data-file=\"' + OCA.External.StatusManager.Utils.jqSelEscape(folder) + '\"]');
}
- trFolder.each(function(){
+ trFolder.each(function () {
var thisElement = $(this);
if (thisElement.data('oldbgcolor') === undefined) {
thisElement.data('oldbgcolor', thisElement.css('background-color'));
@@ -386,7 +481,7 @@ OCA.External.StatusManager.Utils = {
});
var icon = trFolder.find('td:first-child div.thumbnail');
- icon.each(function(){
+ icon.each(function () {
var thisElement = $(this);
if (thisElement.data('oldImage') === undefined) {
thisElement.data('oldImage', thisElement.css('background-image'));
@@ -397,7 +492,7 @@ OCA.External.StatusManager.Utils = {
/**
* @param folder string with the folder or jQuery element pointing to the tr element
*/
- restoreFolder: function(folder) {
+ restoreFolder: function (folder) {
var trFolder;
if (folder instanceof $) {
trFolder = folder;
@@ -407,7 +502,7 @@ OCA.External.StatusManager.Utils = {
}
trFolder.removeClass('externalErroredRow').removeClass('externalDisabledRow');
tdChilds = trFolder.find("td:first-child div.thumbnail");
- tdChilds.each(function(){
+ tdChilds.each(function () {
var thisElement = $(this);
thisElement.css('background-image', thisElement.data('oldImage'));
});
@@ -417,12 +512,12 @@ OCA.External.StatusManager.Utils = {
* @param folder string with the folder or jQuery element pointing to the first td element
* of the tr matching the folder name
*/
- changeFolderIcon: function(filename) {
+ changeFolderIcon: function (filename) {
var file;
var route;
if (filename instanceof $) {
//trElementList
- $.each(filename, function(index){
+ $.each(filename, function (index) {
route = OCA.External.StatusManager.Utils.getIconRoute($(this));
$(this).attr("data-icon", route);
$(this).find('td:first-child div.thumbnail').css('background-image', "url(" + route + ")").css('display', 'none').css('display', 'inline');
@@ -440,7 +535,7 @@ OCA.External.StatusManager.Utils = {
* @param backend string with the name of the external storage backend
* of the tr matching the folder name
*/
- getIconRoute: function(tr) {
+ getIconRoute: function (tr) {
var icon = OC.imagePath('core', 'filetypes/folder-external');
var backend = null;
@@ -460,7 +555,7 @@ OCA.External.StatusManager.Utils = {
return icon;
},
- toggleLink: function(filename, active, action) {
+ toggleLink: function (filename, active, action) {
var link;
if (filename instanceof $) {
link = filename;
@@ -473,7 +568,7 @@ OCA.External.StatusManager.Utils = {
} else {
link.find('.fileactions, .nametext .action').remove(); // from files/js/fileactions (display)
link.off('click.connectivity');
- link.on('click.connectivity', function(e){
+ link.on('click.connectivity', function (e) {
if (action && $.isFunction(action)) {
action(filename);
}
@@ -483,7 +578,7 @@ OCA.External.StatusManager.Utils = {
}
},
- isCorrectViewAndRootFolder: function() {
+ isCorrectViewAndRootFolder: function () {
// correct views = files & extstoragemounts
if (OCA.Files.App.getActiveView() === 'files' || OCA.Files.App.getActiveView() === 'extstoragemounts') {
return OCA.Files.App.getCurrentAppContainer().find('#dir').val() === '/';
@@ -492,15 +587,15 @@ OCA.External.StatusManager.Utils = {
},
/* escape a selector expression for jQuery */
- jqSelEscape: function(expression) {
- if(expression){
+ jqSelEscape: function (expression) {
+ if (expression) {
return expression.replace(/[!"#$%&'()*+,.\/:;<=>?@\[\\\]^`{|}~]/g, '\\$&');
}
return null;
},
/* Copied from http://stackoverflow.com/questions/2631001/javascript-test-for-existence-of-nested-object-key */
- checkNested: function(cobj /*, level1, level2, ... levelN*/) {
+ checkNested: function (cobj /*, level1, level2, ... levelN*/) {
var args = Array.prototype.slice.call(arguments),
obj = args.shift();
diff --git a/apps/files_external/l10n/af_ZA.js b/apps/files_external/l10n/af_ZA.js
index d28e14d67ce..25117ae0ea7 100644
--- a/apps/files_external/l10n/af_ZA.js
+++ b/apps/files_external/l10n/af_ZA.js
@@ -2,6 +2,7 @@ OC.L10N.register(
"files_external",
{
"Personal" : "Persoonlik",
+ "Saving..." : "Stoor...",
"Username" : "Gebruikersnaam",
"Password" : "Wagwoord",
"Share" : "Deel"
diff --git a/apps/files_external/l10n/af_ZA.json b/apps/files_external/l10n/af_ZA.json
index 53622f796ff..f55ea5fd515 100644
--- a/apps/files_external/l10n/af_ZA.json
+++ b/apps/files_external/l10n/af_ZA.json
@@ -1,5 +1,6 @@
{ "translations": {
"Personal" : "Persoonlik",
+ "Saving..." : "Stoor...",
"Username" : "Gebruikersnaam",
"Password" : "Wagwoord",
"Share" : "Deel"
diff --git a/apps/files_external/l10n/ar.js b/apps/files_external/l10n/ar.js
index 3e7438796f4..5317a463fd5 100644
--- a/apps/files_external/l10n/ar.js
+++ b/apps/files_external/l10n/ar.js
@@ -5,11 +5,13 @@ OC.L10N.register(
"System" : "النظام",
"Never" : "أبدا",
"Saved" : "حفظ",
+ "Saving..." : "جاري الحفظ...",
+ "Save" : "حفظ",
+ "Username" : "إسم المستخدم",
+ "Password" : "كلمة السر",
"None" : "لا شيء",
"App key" : "مفتاح التطبيق",
"App secret" : "التطبيق السري",
- "Username" : "إسم المستخدم",
- "Password" : "كلمة السر",
"Bucket" : "الحزمة",
"Hostname" : "إسم الإستضافة",
"Port" : "المنفذ",
diff --git a/apps/files_external/l10n/ar.json b/apps/files_external/l10n/ar.json
index 29423a07906..35573c98be5 100644
--- a/apps/files_external/l10n/ar.json
+++ b/apps/files_external/l10n/ar.json
@@ -3,11 +3,13 @@
"System" : "النظام",
"Never" : "أبدا",
"Saved" : "حفظ",
+ "Saving..." : "جاري الحفظ...",
+ "Save" : "حفظ",
+ "Username" : "إسم المستخدم",
+ "Password" : "كلمة السر",
"None" : "لا شيء",
"App key" : "مفتاح التطبيق",
"App secret" : "التطبيق السري",
- "Username" : "إسم المستخدم",
- "Password" : "كلمة السر",
"Bucket" : "الحزمة",
"Hostname" : "إسم الإستضافة",
"Port" : "المنفذ",
diff --git a/apps/files_external/l10n/ast.js b/apps/files_external/l10n/ast.js
index f67309631e8..e39088432a3 100644
--- a/apps/files_external/l10n/ast.js
+++ b/apps/files_external/l10n/ast.js
@@ -11,13 +11,15 @@ OC.L10N.register(
"All users. Type to select user or group." : "Tolos usuarios. Escribe pa seleccionar usuariu o grupu.",
"(group)" : "(grupu)",
"Saved" : "Guardáu",
+ "Saving..." : "Guardando...",
+ "Save" : "Guardar",
+ "Username" : "Nome d'usuariu",
+ "Password" : "Contraseña",
"None" : "Dengún",
"App key" : "App principal",
"App secret" : "App secreta",
"Client ID" : "ID de veceru",
"Client secret" : "Veceru secretu",
- "Username" : "Nome d'usuariu",
- "Password" : "Contraseña",
"API key" : "clave API",
"Public key" : "Clave pública",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/ast.json b/apps/files_external/l10n/ast.json
index b4bc4355bc4..66b7beff665 100644
--- a/apps/files_external/l10n/ast.json
+++ b/apps/files_external/l10n/ast.json
@@ -9,13 +9,15 @@
"All users. Type to select user or group." : "Tolos usuarios. Escribe pa seleccionar usuariu o grupu.",
"(group)" : "(grupu)",
"Saved" : "Guardáu",
+ "Saving..." : "Guardando...",
+ "Save" : "Guardar",
+ "Username" : "Nome d'usuariu",
+ "Password" : "Contraseña",
"None" : "Dengún",
"App key" : "App principal",
"App secret" : "App secreta",
"Client ID" : "ID de veceru",
"Client secret" : "Veceru secretu",
- "Username" : "Nome d'usuariu",
- "Password" : "Contraseña",
"API key" : "clave API",
"Public key" : "Clave pública",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/az.js b/apps/files_external/l10n/az.js
index 42c9a496185..409d5e52425 100644
--- a/apps/files_external/l10n/az.js
+++ b/apps/files_external/l10n/az.js
@@ -16,13 +16,15 @@ OC.L10N.register(
"All users. Type to select user or group." : "Sistem istifadəçiləri. Daxil edin ki, istifadəçi və ya qrupu seçəsiniz.",
"(group)" : "(qrup)",
"Saved" : "Saxlanıldı",
+ "Saving..." : "Saxlama...",
+ "Save" : "Saxla",
+ "Username" : "İstifadəçi adı",
+ "Password" : "Şifrə",
"None" : "Heç bir",
"App key" : "Proqram açarı",
"App secret" : "Proqram sirri",
"Client ID" : "Müştəri İD-s",
"Client secret" : "Müxtəri sirri",
- "Username" : "İstifadəçi adı",
- "Password" : "Şifrə",
"Public key" : "İctimai açar",
"Amazon S3" : "Amazon S3",
"Bucket" : "Vedrə",
diff --git a/apps/files_external/l10n/az.json b/apps/files_external/l10n/az.json
index 4e01cdf954c..cb8e6bdbfd8 100644
--- a/apps/files_external/l10n/az.json
+++ b/apps/files_external/l10n/az.json
@@ -14,13 +14,15 @@
"All users. Type to select user or group." : "Sistem istifadəçiləri. Daxil edin ki, istifadəçi və ya qrupu seçəsiniz.",
"(group)" : "(qrup)",
"Saved" : "Saxlanıldı",
+ "Saving..." : "Saxlama...",
+ "Save" : "Saxla",
+ "Username" : "İstifadəçi adı",
+ "Password" : "Şifrə",
"None" : "Heç bir",
"App key" : "Proqram açarı",
"App secret" : "Proqram sirri",
"Client ID" : "Müştəri İD-s",
"Client secret" : "Müxtəri sirri",
- "Username" : "İstifadəçi adı",
- "Password" : "Şifrə",
"Public key" : "İctimai açar",
"Amazon S3" : "Amazon S3",
"Bucket" : "Vedrə",
diff --git a/apps/files_external/l10n/bg_BG.js b/apps/files_external/l10n/bg_BG.js
index cc52682f956..c3c608449f4 100644
--- a/apps/files_external/l10n/bg_BG.js
+++ b/apps/files_external/l10n/bg_BG.js
@@ -15,13 +15,15 @@ OC.L10N.register(
"All users. Type to select user or group." : "Всички потребители. Пиши, за да избереш потребител или група.",
"(group)" : "(група)",
"Saved" : "Запазено",
+ "Saving..." : "Запазване...",
+ "Save" : "Запазване",
+ "Username" : "Потребителско Име",
+ "Password" : "Парола",
"None" : "Няма",
"App key" : "App key",
"App secret" : "App secret",
"Client ID" : "Client ID",
"Client secret" : "Client secret",
- "Username" : "Потребителско Име",
- "Password" : "Парола",
"API key" : "API ключ",
"Public key" : "Публичен ключ",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/bg_BG.json b/apps/files_external/l10n/bg_BG.json
index df3fe1c20e8..d2495ea1e90 100644
--- a/apps/files_external/l10n/bg_BG.json
+++ b/apps/files_external/l10n/bg_BG.json
@@ -13,13 +13,15 @@
"All users. Type to select user or group." : "Всички потребители. Пиши, за да избереш потребител или група.",
"(group)" : "(група)",
"Saved" : "Запазено",
+ "Saving..." : "Запазване...",
+ "Save" : "Запазване",
+ "Username" : "Потребителско Име",
+ "Password" : "Парола",
"None" : "Няма",
"App key" : "App key",
"App secret" : "App secret",
"Client ID" : "Client ID",
"Client secret" : "Client secret",
- "Username" : "Потребителско Име",
- "Password" : "Парола",
"API key" : "API ключ",
"Public key" : "Публичен ключ",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/bn_BD.js b/apps/files_external/l10n/bn_BD.js
index 32d40f3fb8a..6236acedb4d 100644
--- a/apps/files_external/l10n/bn_BD.js
+++ b/apps/files_external/l10n/bn_BD.js
@@ -8,12 +8,14 @@ OC.L10N.register(
"Access granted" : "অধিগমনের অনুমতি প্রদান করা হলো",
"(group)" : "(গোষ্ঠি)",
"Saved" : "সংরক্ষণ করা হলো",
+ "Saving..." : "সংরক্ষণ করা হচ্ছে..",
+ "Save" : "সংরক্ষণ",
+ "Username" : "ব্যবহারকারী",
+ "Password" : "কূটশব্দ",
"None" : "কোনটিই নয়",
"App key" : "অ্যাপ কি",
"App secret" : "অ্যাপ সিক্রেট",
"Client ID" : "ক্লায়েন্ট পরিচিতি",
- "Username" : "ব্যবহারকারী",
- "Password" : "কূটশব্দ",
"Amazon S3" : "আমাজন S3",
"Bucket" : "বালতি",
"Hostname" : "হোস্টনেম",
diff --git a/apps/files_external/l10n/bn_BD.json b/apps/files_external/l10n/bn_BD.json
index 3a2d8d4f2af..0ffdadc6c00 100644
--- a/apps/files_external/l10n/bn_BD.json
+++ b/apps/files_external/l10n/bn_BD.json
@@ -6,12 +6,14 @@
"Access granted" : "অধিগমনের অনুমতি প্রদান করা হলো",
"(group)" : "(গোষ্ঠি)",
"Saved" : "সংরক্ষণ করা হলো",
+ "Saving..." : "সংরক্ষণ করা হচ্ছে..",
+ "Save" : "সংরক্ষণ",
+ "Username" : "ব্যবহারকারী",
+ "Password" : "কূটশব্দ",
"None" : "কোনটিই নয়",
"App key" : "অ্যাপ কি",
"App secret" : "অ্যাপ সিক্রেট",
"Client ID" : "ক্লায়েন্ট পরিচিতি",
- "Username" : "ব্যবহারকারী",
- "Password" : "কূটশব্দ",
"Amazon S3" : "আমাজন S3",
"Bucket" : "বালতি",
"Hostname" : "হোস্টনেম",
diff --git a/apps/files_external/l10n/bn_IN.js b/apps/files_external/l10n/bn_IN.js
index 31f903204aa..68b491e3ff5 100644
--- a/apps/files_external/l10n/bn_IN.js
+++ b/apps/files_external/l10n/bn_IN.js
@@ -2,6 +2,8 @@ OC.L10N.register(
"files_external",
{
"Saved" : "সংরক্ষিত",
+ "Saving..." : "সংরক্ষণ করা হচ্ছে ...",
+ "Save" : "সেভ",
"Username" : "ইউজারনেম",
"URL" : "URL",
"Host" : "হোস্ট",
diff --git a/apps/files_external/l10n/bn_IN.json b/apps/files_external/l10n/bn_IN.json
index be89b6f43ea..c34e1711140 100644
--- a/apps/files_external/l10n/bn_IN.json
+++ b/apps/files_external/l10n/bn_IN.json
@@ -1,5 +1,7 @@
{ "translations": {
"Saved" : "সংরক্ষিত",
+ "Saving..." : "সংরক্ষণ করা হচ্ছে ...",
+ "Save" : "সেভ",
"Username" : "ইউজারনেম",
"URL" : "URL",
"Host" : "হোস্ট",
diff --git a/apps/files_external/l10n/bs.js b/apps/files_external/l10n/bs.js
index 2cd3cf47509..26ad4915e96 100644
--- a/apps/files_external/l10n/bs.js
+++ b/apps/files_external/l10n/bs.js
@@ -3,9 +3,11 @@ OC.L10N.register(
{
"Personal" : "Osobno",
"Saved" : "Spremljeno",
- "None" : "Ništa",
+ "Saving..." : "Spremanje...",
+ "Save" : "Spremi",
"Username" : "Korisničko ime",
"Password" : "Lozinka",
+ "None" : "Ništa",
"Port" : "Priključak",
"WebDAV" : "WebDAV",
"Local" : "Lokalno",
diff --git a/apps/files_external/l10n/bs.json b/apps/files_external/l10n/bs.json
index e2d76555f08..94edcb1ea59 100644
--- a/apps/files_external/l10n/bs.json
+++ b/apps/files_external/l10n/bs.json
@@ -1,9 +1,11 @@
{ "translations": {
"Personal" : "Osobno",
"Saved" : "Spremljeno",
- "None" : "Ništa",
+ "Saving..." : "Spremanje...",
+ "Save" : "Spremi",
"Username" : "Korisničko ime",
"Password" : "Lozinka",
+ "None" : "Ništa",
"Port" : "Priključak",
"WebDAV" : "WebDAV",
"Local" : "Lokalno",
diff --git a/apps/files_external/l10n/ca.js b/apps/files_external/l10n/ca.js
index ff11ac0228b..72f8bb62c9b 100644
--- a/apps/files_external/l10n/ca.js
+++ b/apps/files_external/l10n/ca.js
@@ -21,13 +21,15 @@ OC.L10N.register(
"All users. Type to select user or group." : "Tots els usuaris. Escriu per seleccionar un usuari o grup.",
"(group)" : "(grup)",
"Saved" : "Desat",
+ "Saving..." : "Desant...",
+ "Save" : "Desa",
+ "Username" : "Nom d'usuari",
+ "Password" : "Contrasenya",
"None" : "Cap",
"App key" : "Clau de l'aplicació",
"App secret" : "Secret de l'aplicació",
"Client ID" : "Client ID",
"Client secret" : "Secret del client",
- "Username" : "Nom d'usuari",
- "Password" : "Contrasenya",
"API key" : "codi API",
"Public key" : "Clau pública",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/ca.json b/apps/files_external/l10n/ca.json
index a64721a4bf5..647d2ea27b8 100644
--- a/apps/files_external/l10n/ca.json
+++ b/apps/files_external/l10n/ca.json
@@ -19,13 +19,15 @@
"All users. Type to select user or group." : "Tots els usuaris. Escriu per seleccionar un usuari o grup.",
"(group)" : "(grup)",
"Saved" : "Desat",
+ "Saving..." : "Desant...",
+ "Save" : "Desa",
+ "Username" : "Nom d'usuari",
+ "Password" : "Contrasenya",
"None" : "Cap",
"App key" : "Clau de l'aplicació",
"App secret" : "Secret de l'aplicació",
"Client ID" : "Client ID",
"Client secret" : "Secret del client",
- "Username" : "Nom d'usuari",
- "Password" : "Contrasenya",
"API key" : "codi API",
"Public key" : "Clau pública",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/cs_CZ.js b/apps/files_external/l10n/cs_CZ.js
index 56a8147fd99..039d4882c84 100644
--- a/apps/files_external/l10n/cs_CZ.js
+++ b/apps/files_external/l10n/cs_CZ.js
@@ -29,6 +29,7 @@ OC.L10N.register(
"Error generating key pair" : "Chyba při vytváření páru klíčů",
"Enable encryption" : "Povolit šifrování",
"Enable previews" : "Povolit náhledy",
+ "Enable sharing" : "Povolit sdílení",
"Check for changes" : "Zkontrolovat změny",
"Never" : "Nikdy",
"Once every direct access" : "Jednou pro každý přímý přístup",
@@ -36,6 +37,8 @@ OC.L10N.register(
"(group)" : "(skupina)",
"Admin defined" : "Nastaveno administrátorem",
"Saved" : "Uloženo",
+ "Saving..." : "Ukládám...",
+ "Save" : "Uložit",
"Empty response from the server" : "Prázdná odpověď serveru",
"Couldn't access. Please logout and login to activate this mount point" : "Nelze připojit. Pro aktivaci tohoto přípojného bodu se prosím odhlašte a znovu přihlašte",
"Couldn't get the information from the ownCloud server: {code} {type}" : "Nelze obdržet informaci z ownCloud serveru: {code} {type}",
@@ -44,6 +47,8 @@ OC.L10N.register(
"External mount error" : "Chyba vzdáleného úložiště",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "Nelze obdržet seznam síťových úložišť systému Windows: prázdná odpověď serveru",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Některá z nastavených vzdálených úložišť nejsou připojena. Pro více informací prosím klikněte na červenou šipku(y)",
+ "Username" : "Uživatelské jméno",
+ "Password" : "Heslo",
"Access key" : "Přístupový klíč",
"Secret key" : "Tajný klíč",
"Builtin" : "Zabudované",
@@ -55,13 +60,14 @@ OC.L10N.register(
"Client ID" : "Klientské ID",
"Client secret" : "Klientské tajemství",
"OpenStack" : "OpenStack",
- "Username" : "Uživatelské jméno",
- "Password" : "Heslo",
"Tenant name" : "Jméno vlastníka",
"Identity endpoint URL" : "Identifikační koncový bod URL",
"Rackspace" : "Rackspace",
"API key" : "Klíč API",
+ "Log-in credentials, save in database" : "Přihlašovací údaje, ukládat do databáze",
"Username and password" : "Uživatelské jméno a heslo",
+ "Log-in credentials, save in session" : "Přihlašovací údaje, ukládat v sezení",
+ "User entered, store in database" : "Zadané uživatelem, ukládat v databázi",
"RSA public key" : "RSA veřejný klíč",
"Public key" : "Veřejný klíč",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/cs_CZ.json b/apps/files_external/l10n/cs_CZ.json
index f22bbc25e35..007a8bc17ca 100644
--- a/apps/files_external/l10n/cs_CZ.json
+++ b/apps/files_external/l10n/cs_CZ.json
@@ -27,6 +27,7 @@
"Error generating key pair" : "Chyba při vytváření páru klíčů",
"Enable encryption" : "Povolit šifrování",
"Enable previews" : "Povolit náhledy",
+ "Enable sharing" : "Povolit sdílení",
"Check for changes" : "Zkontrolovat změny",
"Never" : "Nikdy",
"Once every direct access" : "Jednou pro každý přímý přístup",
@@ -34,6 +35,8 @@
"(group)" : "(skupina)",
"Admin defined" : "Nastaveno administrátorem",
"Saved" : "Uloženo",
+ "Saving..." : "Ukládám...",
+ "Save" : "Uložit",
"Empty response from the server" : "Prázdná odpověď serveru",
"Couldn't access. Please logout and login to activate this mount point" : "Nelze připojit. Pro aktivaci tohoto přípojného bodu se prosím odhlašte a znovu přihlašte",
"Couldn't get the information from the ownCloud server: {code} {type}" : "Nelze obdržet informaci z ownCloud serveru: {code} {type}",
@@ -42,6 +45,8 @@
"External mount error" : "Chyba vzdáleného úložiště",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "Nelze obdržet seznam síťových úložišť systému Windows: prázdná odpověď serveru",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Některá z nastavených vzdálených úložišť nejsou připojena. Pro více informací prosím klikněte na červenou šipku(y)",
+ "Username" : "Uživatelské jméno",
+ "Password" : "Heslo",
"Access key" : "Přístupový klíč",
"Secret key" : "Tajný klíč",
"Builtin" : "Zabudované",
@@ -53,13 +58,14 @@
"Client ID" : "Klientské ID",
"Client secret" : "Klientské tajemství",
"OpenStack" : "OpenStack",
- "Username" : "Uživatelské jméno",
- "Password" : "Heslo",
"Tenant name" : "Jméno vlastníka",
"Identity endpoint URL" : "Identifikační koncový bod URL",
"Rackspace" : "Rackspace",
"API key" : "Klíč API",
+ "Log-in credentials, save in database" : "Přihlašovací údaje, ukládat do databáze",
"Username and password" : "Uživatelské jméno a heslo",
+ "Log-in credentials, save in session" : "Přihlašovací údaje, ukládat v sezení",
+ "User entered, store in database" : "Zadané uživatelem, ukládat v databázi",
"RSA public key" : "RSA veřejný klíč",
"Public key" : "Veřejný klíč",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/cy_GB.js b/apps/files_external/l10n/cy_GB.js
index 4364445be0c..50aaaad0ec9 100644
--- a/apps/files_external/l10n/cy_GB.js
+++ b/apps/files_external/l10n/cy_GB.js
@@ -2,9 +2,11 @@ OC.L10N.register(
"files_external",
{
"Personal" : "Personol",
- "None" : "Dim",
+ "Saving..." : "Yn cadw...",
+ "Save" : "Cadw",
"Username" : "Enw defnyddiwr",
"Password" : "Cyfrinair",
+ "None" : "Dim",
"URL" : "URL",
"Location" : "Lleoliad",
"ownCloud" : "ownCloud",
diff --git a/apps/files_external/l10n/cy_GB.json b/apps/files_external/l10n/cy_GB.json
index 4916cb270ab..258d72b5b6f 100644
--- a/apps/files_external/l10n/cy_GB.json
+++ b/apps/files_external/l10n/cy_GB.json
@@ -1,8 +1,10 @@
{ "translations": {
"Personal" : "Personol",
- "None" : "Dim",
+ "Saving..." : "Yn cadw...",
+ "Save" : "Cadw",
"Username" : "Enw defnyddiwr",
"Password" : "Cyfrinair",
+ "None" : "Dim",
"URL" : "URL",
"Location" : "Lleoliad",
"ownCloud" : "ownCloud",
diff --git a/apps/files_external/l10n/da.js b/apps/files_external/l10n/da.js
index 70f43819496..d3c6c895d96 100644
--- a/apps/files_external/l10n/da.js
+++ b/apps/files_external/l10n/da.js
@@ -32,6 +32,10 @@ OC.L10N.register(
"All users. Type to select user or group." : "Alle brugere. Indtast for at vælge bruger eller gruppe.",
"(group)" : "(gruppe)",
"Saved" : "Gemt",
+ "Saving..." : "Gemmer...",
+ "Save" : "Gem",
+ "Username" : "Brugernavn",
+ "Password" : "Kodeord",
"Access key" : "Adgangsnøgle",
"Secret key" : "Hemmelig nøgle",
"Builtin" : "Indbygget",
@@ -43,8 +47,6 @@ OC.L10N.register(
"Client ID" : "Klient-ID",
"Client secret" : "Klient hemmelighed",
"OpenStack" : "OpenStack",
- "Username" : "Brugernavn",
- "Password" : "Kodeord",
"Tenant name" : "Lejernavn",
"Identity endpoint URL" : "Identificer afslutnings URL",
"Rackspace" : "Hyldeplads",
diff --git a/apps/files_external/l10n/da.json b/apps/files_external/l10n/da.json
index aaeaaa58ae0..513533dd49e 100644
--- a/apps/files_external/l10n/da.json
+++ b/apps/files_external/l10n/da.json
@@ -30,6 +30,10 @@
"All users. Type to select user or group." : "Alle brugere. Indtast for at vælge bruger eller gruppe.",
"(group)" : "(gruppe)",
"Saved" : "Gemt",
+ "Saving..." : "Gemmer...",
+ "Save" : "Gem",
+ "Username" : "Brugernavn",
+ "Password" : "Kodeord",
"Access key" : "Adgangsnøgle",
"Secret key" : "Hemmelig nøgle",
"Builtin" : "Indbygget",
@@ -41,8 +45,6 @@
"Client ID" : "Klient-ID",
"Client secret" : "Klient hemmelighed",
"OpenStack" : "OpenStack",
- "Username" : "Brugernavn",
- "Password" : "Kodeord",
"Tenant name" : "Lejernavn",
"Identity endpoint URL" : "Identificer afslutnings URL",
"Rackspace" : "Hyldeplads",
diff --git a/apps/files_external/l10n/de.js b/apps/files_external/l10n/de.js
index 41b86dbeb48..709450948ee 100644
--- a/apps/files_external/l10n/de.js
+++ b/apps/files_external/l10n/de.js
@@ -28,7 +28,11 @@ OC.L10N.register(
"(group)" : "(group)",
"Admin defined" : "Administrator festlegen",
"Saved" : "Gespeichert",
+ "Saving..." : "Speichern…",
+ "Save" : "Speichern",
"There was an error with message: " : "Es ist ein Fehler mit folgender Meldung aufgetreten:",
+ "Username" : "Benutzername",
+ "Password" : "Passwort",
"Access key" : "Zugangsschlüssel",
"Secret key" : "Geheimer Schlüssel",
"None" : "Keine",
@@ -39,8 +43,6 @@ OC.L10N.register(
"Client ID" : "Client-ID",
"Client secret" : "Geheime Zeichenkette des Client",
"OpenStack" : "OpenStack",
- "Username" : "Benutzername",
- "Password" : "Passwort",
"Tenant name" : "Name des Mieters",
"Rackspace" : "Rackspace",
"API key" : "API-Schlüssel",
diff --git a/apps/files_external/l10n/de.json b/apps/files_external/l10n/de.json
index 2b50a822507..9c645c31298 100644
--- a/apps/files_external/l10n/de.json
+++ b/apps/files_external/l10n/de.json
@@ -26,7 +26,11 @@
"(group)" : "(group)",
"Admin defined" : "Administrator festlegen",
"Saved" : "Gespeichert",
+ "Saving..." : "Speichern…",
+ "Save" : "Speichern",
"There was an error with message: " : "Es ist ein Fehler mit folgender Meldung aufgetreten:",
+ "Username" : "Benutzername",
+ "Password" : "Passwort",
"Access key" : "Zugangsschlüssel",
"Secret key" : "Geheimer Schlüssel",
"None" : "Keine",
@@ -37,8 +41,6 @@
"Client ID" : "Client-ID",
"Client secret" : "Geheime Zeichenkette des Client",
"OpenStack" : "OpenStack",
- "Username" : "Benutzername",
- "Password" : "Passwort",
"Tenant name" : "Name des Mieters",
"Rackspace" : "Rackspace",
"API key" : "API-Schlüssel",
diff --git a/apps/files_external/l10n/de_AT.js b/apps/files_external/l10n/de_AT.js
index 6c71c45f217..962fbf116f0 100644
--- a/apps/files_external/l10n/de_AT.js
+++ b/apps/files_external/l10n/de_AT.js
@@ -2,6 +2,7 @@ OC.L10N.register(
"files_external",
{
"Personal" : "Persönlich",
+ "Save" : "Speichern",
"Username" : "Benutzername",
"Password" : "Passwort",
"Port" : "Port",
diff --git a/apps/files_external/l10n/de_AT.json b/apps/files_external/l10n/de_AT.json
index 0d956dc81c6..48154b4f189 100644
--- a/apps/files_external/l10n/de_AT.json
+++ b/apps/files_external/l10n/de_AT.json
@@ -1,5 +1,6 @@
{ "translations": {
"Personal" : "Persönlich",
+ "Save" : "Speichern",
"Username" : "Benutzername",
"Password" : "Passwort",
"Port" : "Port",
diff --git a/apps/files_external/l10n/de_DE.js b/apps/files_external/l10n/de_DE.js
index ef860918474..514a9dcd8ab 100644
--- a/apps/files_external/l10n/de_DE.js
+++ b/apps/files_external/l10n/de_DE.js
@@ -23,13 +23,15 @@ OC.L10N.register(
"All users. Type to select user or group." : "Alle Benutzer. Benutzer oder Gruppe zur Auswahl eingeben.",
"(group)" : "(group)",
"Saved" : "Gespeichert",
+ "Saving..." : "Speichervorgang…",
+ "Save" : "Speichern",
+ "Username" : "Benutzername",
+ "Password" : "Passwort",
"None" : "Keine",
"App key" : "App-Schlüssel",
"App secret" : "Geheime Zeichenkette der App",
"Client ID" : "Client-ID",
"Client secret" : "Geheime Zeichenkette des Client",
- "Username" : "Benutzername",
- "Password" : "Passwort",
"API key" : "API-Schlüssel",
"Username and password" : "Benutzername und Passwort",
"Public key" : "Öffentlicher Schlüssel",
diff --git a/apps/files_external/l10n/de_DE.json b/apps/files_external/l10n/de_DE.json
index 75a84334764..2c8af227c3b 100644
--- a/apps/files_external/l10n/de_DE.json
+++ b/apps/files_external/l10n/de_DE.json
@@ -21,13 +21,15 @@
"All users. Type to select user or group." : "Alle Benutzer. Benutzer oder Gruppe zur Auswahl eingeben.",
"(group)" : "(group)",
"Saved" : "Gespeichert",
+ "Saving..." : "Speichervorgang…",
+ "Save" : "Speichern",
+ "Username" : "Benutzername",
+ "Password" : "Passwort",
"None" : "Keine",
"App key" : "App-Schlüssel",
"App secret" : "Geheime Zeichenkette der App",
"Client ID" : "Client-ID",
"Client secret" : "Geheime Zeichenkette des Client",
- "Username" : "Benutzername",
- "Password" : "Passwort",
"API key" : "API-Schlüssel",
"Username and password" : "Benutzername und Passwort",
"Public key" : "Öffentlicher Schlüssel",
diff --git a/apps/files_external/l10n/el.js b/apps/files_external/l10n/el.js
index c04d3d015d3..c807978e7a2 100644
--- a/apps/files_external/l10n/el.js
+++ b/apps/files_external/l10n/el.js
@@ -34,6 +34,10 @@ OC.L10N.register(
"All users. Type to select user or group." : "Όλοι οι χρήστες. Πληκτρολογήστε για να επιλέξετε χρήστη ή ομάδα.",
"(group)" : "(ομάδα)",
"Saved" : "Αποθηκεύτηκαν",
+ "Saving..." : "Γίνεται αποθήκευση...",
+ "Save" : "Αποθήκευση",
+ "Username" : "Όνομα χρήστη",
+ "Password" : "Κωδικός πρόσβασης",
"Access key" : "Κλειδί πρόσβασης",
"Secret key" : "Μυστικό κλειδί",
"Builtin" : "Builtin",
@@ -45,8 +49,6 @@ OC.L10N.register(
"Client ID" : "ID πελάτη",
"Client secret" : "Μυστικό πελάτη",
"OpenStack" : "OpenStack",
- "Username" : "Όνομα χρήστη",
- "Password" : "Κωδικός πρόσβασης",
"Tenant name" : "Όνομα \"ένοικου\"",
"Identity endpoint URL" : "URL τελικού σημείου ταυτοποίησης",
"Rackspace" : "Rackspace",
diff --git a/apps/files_external/l10n/el.json b/apps/files_external/l10n/el.json
index 98a6d18bfc3..44c41265093 100644
--- a/apps/files_external/l10n/el.json
+++ b/apps/files_external/l10n/el.json
@@ -32,6 +32,10 @@
"All users. Type to select user or group." : "Όλοι οι χρήστες. Πληκτρολογήστε για να επιλέξετε χρήστη ή ομάδα.",
"(group)" : "(ομάδα)",
"Saved" : "Αποθηκεύτηκαν",
+ "Saving..." : "Γίνεται αποθήκευση...",
+ "Save" : "Αποθήκευση",
+ "Username" : "Όνομα χρήστη",
+ "Password" : "Κωδικός πρόσβασης",
"Access key" : "Κλειδί πρόσβασης",
"Secret key" : "Μυστικό κλειδί",
"Builtin" : "Builtin",
@@ -43,8 +47,6 @@
"Client ID" : "ID πελάτη",
"Client secret" : "Μυστικό πελάτη",
"OpenStack" : "OpenStack",
- "Username" : "Όνομα χρήστη",
- "Password" : "Κωδικός πρόσβασης",
"Tenant name" : "Όνομα \"ένοικου\"",
"Identity endpoint URL" : "URL τελικού σημείου ταυτοποίησης",
"Rackspace" : "Rackspace",
diff --git a/apps/files_external/l10n/en_GB.js b/apps/files_external/l10n/en_GB.js
index adba5abf88c..6390b2ffe7e 100644
--- a/apps/files_external/l10n/en_GB.js
+++ b/apps/files_external/l10n/en_GB.js
@@ -21,13 +21,15 @@ OC.L10N.register(
"All users. Type to select user or group." : "All users. Type to select user or group.",
"(group)" : "(group)",
"Saved" : "Saved",
+ "Saving..." : "Saving...",
+ "Save" : "Save",
+ "Username" : "Username",
+ "Password" : "Password",
"None" : "None",
"App key" : "App key",
"App secret" : "App secret",
"Client ID" : "Client ID",
"Client secret" : "Client secret",
- "Username" : "Username",
- "Password" : "Password",
"API key" : "API key",
"Public key" : "Public key",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/en_GB.json b/apps/files_external/l10n/en_GB.json
index 04d43cf4854..ab3cd25c571 100644
--- a/apps/files_external/l10n/en_GB.json
+++ b/apps/files_external/l10n/en_GB.json
@@ -19,13 +19,15 @@
"All users. Type to select user or group." : "All users. Type to select user or group.",
"(group)" : "(group)",
"Saved" : "Saved",
+ "Saving..." : "Saving...",
+ "Save" : "Save",
+ "Username" : "Username",
+ "Password" : "Password",
"None" : "None",
"App key" : "App key",
"App secret" : "App secret",
"Client ID" : "Client ID",
"Client secret" : "Client secret",
- "Username" : "Username",
- "Password" : "Password",
"API key" : "API key",
"Public key" : "Public key",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/eo.js b/apps/files_external/l10n/eo.js
index ddab2360a6d..556287de7b5 100644
--- a/apps/files_external/l10n/eo.js
+++ b/apps/files_external/l10n/eo.js
@@ -6,13 +6,15 @@ OC.L10N.register(
"Grant access" : "Doni alirpermeson",
"Access granted" : "Alirpermeso donita",
"Saved" : "Konservita",
+ "Saving..." : "Konservante...",
+ "Save" : "Konservi",
+ "Username" : "Uzantonomo",
+ "Password" : "Pasvorto",
"None" : "Nenio",
"App key" : "Aplikaĵoklavo",
"App secret" : "Aplikaĵosekreto",
"Client ID" : "Klientidentigilo",
"Client secret" : "Klientosekreto",
- "Username" : "Uzantonomo",
- "Password" : "Pasvorto",
"API key" : "API-klavo",
"Public key" : "Publika ŝlosilo",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/eo.json b/apps/files_external/l10n/eo.json
index ec91f40abac..aa944f959f7 100644
--- a/apps/files_external/l10n/eo.json
+++ b/apps/files_external/l10n/eo.json
@@ -4,13 +4,15 @@
"Grant access" : "Doni alirpermeson",
"Access granted" : "Alirpermeso donita",
"Saved" : "Konservita",
+ "Saving..." : "Konservante...",
+ "Save" : "Konservi",
+ "Username" : "Uzantonomo",
+ "Password" : "Pasvorto",
"None" : "Nenio",
"App key" : "Aplikaĵoklavo",
"App secret" : "Aplikaĵosekreto",
"Client ID" : "Klientidentigilo",
"Client secret" : "Klientosekreto",
- "Username" : "Uzantonomo",
- "Password" : "Pasvorto",
"API key" : "API-klavo",
"Public key" : "Publika ŝlosilo",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/es.js b/apps/files_external/l10n/es.js
index 8a49dd4ec05..42695f85a4b 100644
--- a/apps/files_external/l10n/es.js
+++ b/apps/files_external/l10n/es.js
@@ -35,6 +35,8 @@ OC.L10N.register(
"(group)" : "(grupo)",
"Admin defined" : "Admin definido",
"Saved" : "Guardado",
+ "Saving..." : "Guardando...",
+ "Save" : "Guardar",
"Empty response from the server" : "Respuesta vacía desde el servidor",
"Couldn't access. Please logout and login to activate this mount point" : "No se puede acceder. Por favor cierra sesión e iníciala de nuevo para activar este punto de montaje",
"Couldn't get the information from the ownCloud server: {code} {type}" : "No se puede obtener información acerca del servidor de OwnCloud: {code} {type}",
@@ -43,6 +45,8 @@ OC.L10N.register(
"External mount error" : "Error de montaje externo",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "No se puede obtener la lista de unidades de red y sus puntos de montaje de Windows: respuesta vacía desde el servidor",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Algunos de los puntos de montaje externos configurados no están conectados. Por favor, haga clic en la fila roja (s) para obtener más información",
+ "Username" : "Nombre de usuario",
+ "Password" : "Contraseña",
"Access key" : "Clave de acceso",
"Secret key" : "Clave secreta",
"Builtin" : "Incorporado",
@@ -54,8 +58,6 @@ OC.L10N.register(
"Client ID" : "ID de Cliente",
"Client secret" : "Cliente secreto",
"OpenStack" : "OpenStack",
- "Username" : "Nombre de usuario",
- "Password" : "Contraseña",
"Tenant name" : "Nombre del inquilino",
"Identity endpoint URL" : "Identidad de punto final URL",
"Rackspace" : "Espacio de Rack",
diff --git a/apps/files_external/l10n/es.json b/apps/files_external/l10n/es.json
index c3b81338776..24110d3f4a1 100644
--- a/apps/files_external/l10n/es.json
+++ b/apps/files_external/l10n/es.json
@@ -33,6 +33,8 @@
"(group)" : "(grupo)",
"Admin defined" : "Admin definido",
"Saved" : "Guardado",
+ "Saving..." : "Guardando...",
+ "Save" : "Guardar",
"Empty response from the server" : "Respuesta vacía desde el servidor",
"Couldn't access. Please logout and login to activate this mount point" : "No se puede acceder. Por favor cierra sesión e iníciala de nuevo para activar este punto de montaje",
"Couldn't get the information from the ownCloud server: {code} {type}" : "No se puede obtener información acerca del servidor de OwnCloud: {code} {type}",
@@ -41,6 +43,8 @@
"External mount error" : "Error de montaje externo",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "No se puede obtener la lista de unidades de red y sus puntos de montaje de Windows: respuesta vacía desde el servidor",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Algunos de los puntos de montaje externos configurados no están conectados. Por favor, haga clic en la fila roja (s) para obtener más información",
+ "Username" : "Nombre de usuario",
+ "Password" : "Contraseña",
"Access key" : "Clave de acceso",
"Secret key" : "Clave secreta",
"Builtin" : "Incorporado",
@@ -52,8 +56,6 @@
"Client ID" : "ID de Cliente",
"Client secret" : "Cliente secreto",
"OpenStack" : "OpenStack",
- "Username" : "Nombre de usuario",
- "Password" : "Contraseña",
"Tenant name" : "Nombre del inquilino",
"Identity endpoint URL" : "Identidad de punto final URL",
"Rackspace" : "Espacio de Rack",
diff --git a/apps/files_external/l10n/es_AR.js b/apps/files_external/l10n/es_AR.js
index 7fb87f1a1d3..6204947c3d3 100644
--- a/apps/files_external/l10n/es_AR.js
+++ b/apps/files_external/l10n/es_AR.js
@@ -6,9 +6,11 @@ OC.L10N.register(
"Grant access" : "Permitir acceso",
"Access granted" : "Acceso permitido",
"Saved" : "Guardado",
- "None" : "Ninguno",
+ "Saving..." : "Guardando...",
+ "Save" : "Guardar",
"Username" : "Nombre de usuario",
"Password" : "Contraseña",
+ "None" : "Ninguno",
"API key" : "clave API",
"Port" : "Puerto",
"Region" : "Provincia",
diff --git a/apps/files_external/l10n/es_AR.json b/apps/files_external/l10n/es_AR.json
index 9fb735f7a3a..e651ce0ec46 100644
--- a/apps/files_external/l10n/es_AR.json
+++ b/apps/files_external/l10n/es_AR.json
@@ -4,9 +4,11 @@
"Grant access" : "Permitir acceso",
"Access granted" : "Acceso permitido",
"Saved" : "Guardado",
- "None" : "Ninguno",
+ "Saving..." : "Guardando...",
+ "Save" : "Guardar",
"Username" : "Nombre de usuario",
"Password" : "Contraseña",
+ "None" : "Ninguno",
"API key" : "clave API",
"Port" : "Puerto",
"Region" : "Provincia",
diff --git a/apps/files_external/l10n/es_MX.js b/apps/files_external/l10n/es_MX.js
index c805ce16662..ca094579742 100644
--- a/apps/files_external/l10n/es_MX.js
+++ b/apps/files_external/l10n/es_MX.js
@@ -6,9 +6,11 @@ OC.L10N.register(
"Grant access" : "Conceder acceso",
"Access granted" : "Acceso concedido",
"Saved" : "Guardado",
- "None" : "Ninguno",
+ "Saving..." : "Guardando...",
+ "Save" : "Guardar",
"Username" : "Nombre de usuario",
"Password" : "Contraseña",
+ "None" : "Ninguno",
"API key" : "clave API",
"Public key" : "Llave pública",
"Port" : "Puerto",
diff --git a/apps/files_external/l10n/es_MX.json b/apps/files_external/l10n/es_MX.json
index 1df9bf70436..e120c71f62f 100644
--- a/apps/files_external/l10n/es_MX.json
+++ b/apps/files_external/l10n/es_MX.json
@@ -4,9 +4,11 @@
"Grant access" : "Conceder acceso",
"Access granted" : "Acceso concedido",
"Saved" : "Guardado",
- "None" : "Ninguno",
+ "Saving..." : "Guardando...",
+ "Save" : "Guardar",
"Username" : "Nombre de usuario",
"Password" : "Contraseña",
+ "None" : "Ninguno",
"API key" : "clave API",
"Public key" : "Llave pública",
"Port" : "Puerto",
diff --git a/apps/files_external/l10n/et_EE.js b/apps/files_external/l10n/et_EE.js
index 989ff604952..35c77c8ca07 100644
--- a/apps/files_external/l10n/et_EE.js
+++ b/apps/files_external/l10n/et_EE.js
@@ -26,9 +26,13 @@ OC.L10N.register(
"(group)" : "(grupp)",
"Admin defined" : "Admini poolt määratud",
"Saved" : "Salvestatud",
+ "Saving..." : "Salvestamine...",
+ "Save" : "Salvesta",
"Couldn't get the list of external mount points: {type}" : "Välise ühenduspunkti hankimine ebaõnnestus: {type}",
"There was an error with message: " : "Sõnumiga tekkis tõrge:",
"External mount error" : "Välise seostamise tõrge",
+ "Username" : "Kasutajanimi",
+ "Password" : "Parool",
"Access key" : "Ligipääsuvõti",
"Secret key" : "Salavõti",
"Builtin" : "Sisseehitatud",
@@ -40,8 +44,6 @@ OC.L10N.register(
"Client ID" : "Kliendi ID",
"Client secret" : "Kliendi salasõna",
"OpenStack" : "OpenStack",
- "Username" : "Kasutajanimi",
- "Password" : "Parool",
"API key" : "API võti",
"RSA public key" : "RSA avalik võti",
"Public key" : "Avalik võti",
diff --git a/apps/files_external/l10n/et_EE.json b/apps/files_external/l10n/et_EE.json
index ad8e87e55f9..5577f556844 100644
--- a/apps/files_external/l10n/et_EE.json
+++ b/apps/files_external/l10n/et_EE.json
@@ -24,9 +24,13 @@
"(group)" : "(grupp)",
"Admin defined" : "Admini poolt määratud",
"Saved" : "Salvestatud",
+ "Saving..." : "Salvestamine...",
+ "Save" : "Salvesta",
"Couldn't get the list of external mount points: {type}" : "Välise ühenduspunkti hankimine ebaõnnestus: {type}",
"There was an error with message: " : "Sõnumiga tekkis tõrge:",
"External mount error" : "Välise seostamise tõrge",
+ "Username" : "Kasutajanimi",
+ "Password" : "Parool",
"Access key" : "Ligipääsuvõti",
"Secret key" : "Salavõti",
"Builtin" : "Sisseehitatud",
@@ -38,8 +42,6 @@
"Client ID" : "Kliendi ID",
"Client secret" : "Kliendi salasõna",
"OpenStack" : "OpenStack",
- "Username" : "Kasutajanimi",
- "Password" : "Parool",
"API key" : "API võti",
"RSA public key" : "RSA avalik võti",
"Public key" : "Avalik võti",
diff --git a/apps/files_external/l10n/eu.js b/apps/files_external/l10n/eu.js
index 58742552e76..b80e05f2c40 100644
--- a/apps/files_external/l10n/eu.js
+++ b/apps/files_external/l10n/eu.js
@@ -11,13 +11,15 @@ OC.L10N.register(
"All users. Type to select user or group." : "Erabiltzaile guztiak. Idatzi erabiltzaile edo taldea hautatzeko.",
"(group)" : "(taldea)",
"Saved" : "Gordeta",
+ "Saving..." : "Gordetzen...",
+ "Save" : "Gorde",
+ "Username" : "Erabiltzaile izena",
+ "Password" : "Pasahitza",
"None" : "Ezer",
"App key" : "Aplikazio gakoa",
"App secret" : "App sekretua",
"Client ID" : "Bezero ID",
"Client secret" : "Bezeroaren Sekretua",
- "Username" : "Erabiltzaile izena",
- "Password" : "Pasahitza",
"API key" : "APIaren gakoa",
"Public key" : "Gako publikoa",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/eu.json b/apps/files_external/l10n/eu.json
index f039441b464..d6dac29bba7 100644
--- a/apps/files_external/l10n/eu.json
+++ b/apps/files_external/l10n/eu.json
@@ -9,13 +9,15 @@
"All users. Type to select user or group." : "Erabiltzaile guztiak. Idatzi erabiltzaile edo taldea hautatzeko.",
"(group)" : "(taldea)",
"Saved" : "Gordeta",
+ "Saving..." : "Gordetzen...",
+ "Save" : "Gorde",
+ "Username" : "Erabiltzaile izena",
+ "Password" : "Pasahitza",
"None" : "Ezer",
"App key" : "Aplikazio gakoa",
"App secret" : "App sekretua",
"Client ID" : "Bezero ID",
"Client secret" : "Bezeroaren Sekretua",
- "Username" : "Erabiltzaile izena",
- "Password" : "Pasahitza",
"API key" : "APIaren gakoa",
"Public key" : "Gako publikoa",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/fa.js b/apps/files_external/l10n/fa.js
index 0c1076fc994..f9e67ddb0af 100644
--- a/apps/files_external/l10n/fa.js
+++ b/apps/files_external/l10n/fa.js
@@ -18,6 +18,10 @@ OC.L10N.register(
"Never" : "هرگز",
"(group)" : "(گروه)",
"Saved" : "ذخیره شد",
+ "Saving..." : "در حال ذخیره سازی...",
+ "Save" : "ذخیره",
+ "Username" : "نام کاربری",
+ "Password" : "گذرواژه",
"Access key" : "کلید دسترسی",
"Secret key" : "کلید مخفی",
"None" : "هیچ‌کدام",
@@ -25,8 +29,6 @@ OC.L10N.register(
"App secret" : "کد برنامه",
"OAuth2" : "OAuth2",
"OpenStack" : "OpenStack",
- "Username" : "نام کاربری",
- "Password" : "گذرواژه",
"API key" : "کلید API ",
"Username and password" : "نام کاربری و رمز عبور",
"Public key" : "کلید عمومی",
diff --git a/apps/files_external/l10n/fa.json b/apps/files_external/l10n/fa.json
index 056bad259a6..e5292902c47 100644
--- a/apps/files_external/l10n/fa.json
+++ b/apps/files_external/l10n/fa.json
@@ -16,6 +16,10 @@
"Never" : "هرگز",
"(group)" : "(گروه)",
"Saved" : "ذخیره شد",
+ "Saving..." : "در حال ذخیره سازی...",
+ "Save" : "ذخیره",
+ "Username" : "نام کاربری",
+ "Password" : "گذرواژه",
"Access key" : "کلید دسترسی",
"Secret key" : "کلید مخفی",
"None" : "هیچ‌کدام",
@@ -23,8 +27,6 @@
"App secret" : "کد برنامه",
"OAuth2" : "OAuth2",
"OpenStack" : "OpenStack",
- "Username" : "نام کاربری",
- "Password" : "گذرواژه",
"API key" : "کلید API ",
"Username and password" : "نام کاربری و رمز عبور",
"Public key" : "کلید عمومی",
diff --git a/apps/files_external/l10n/fi_FI.js b/apps/files_external/l10n/fi_FI.js
index ec969586d6d..f7789dd81b8 100644
--- a/apps/files_external/l10n/fi_FI.js
+++ b/apps/files_external/l10n/fi_FI.js
@@ -24,6 +24,8 @@ OC.L10N.register(
"(group)" : "(ryhmä)",
"Admin defined" : "Ylläpitäjän määrittämä",
"Saved" : "Tallennettu",
+ "Saving..." : "Tallennetaan...",
+ "Save" : "Tallenna",
"Empty response from the server" : "Tyhjä vastaus palvelimelta",
"Couldn't access. Please logout and login to activate this mount point" : "Käyttö epäonnistui. Kirjaudu ulos ja takaisin sisään aktivoidaksesi tämän liitospisteen",
"Couldn't get the information from the ownCloud server: {code} {type}" : "Tietojen saaminen ownCloud-palvelimelta epäonnistui: {code} {type}",
@@ -32,6 +34,8 @@ OC.L10N.register(
"External mount error" : "Ulkoinen liitosvirhe",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "Windows-verkkoasemien liitospisteiden listauksen noutaminen epäonnistui: tyhjä vastaus palvelimelta",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Jotkin määritetyt erilliset liitospisteet eivät ole yhdistettynä. Napsauta punaisia rivejä saadaksesi lisätietoja",
+ "Username" : "Käyttäjätunnus",
+ "Password" : "Salasana",
"Builtin" : "Sisäänrakennettu",
"None" : "Ei mitään",
"OAuth1" : "OAuth1",
@@ -41,8 +45,6 @@ OC.L10N.register(
"Client ID" : "Asiakkaan tunniste",
"Client secret" : "Asiakassalaisuus",
"OpenStack" : "OpenStack",
- "Username" : "Käyttäjätunnus",
- "Password" : "Salasana",
"Rackspace" : "Rackspace",
"API key" : "API-avain",
"Log-in credentials, save in database" : "Kirjautumistiedot, tallenna tietokantaan",
@@ -85,6 +87,7 @@ OC.L10N.register(
"Name" : "Nimi",
"Storage type" : "Tallennustilan tyyppi",
"External Storage" : "Erillinen tallennusväline",
+ "Global Credentials" : "Globaalit kirjautumistiedot",
"Folder name" : "Kansion nimi",
"Authentication" : "Tunnistautuminen",
"Configuration" : "Asetukset",
diff --git a/apps/files_external/l10n/fi_FI.json b/apps/files_external/l10n/fi_FI.json
index 8c39acff034..022f36f635f 100644
--- a/apps/files_external/l10n/fi_FI.json
+++ b/apps/files_external/l10n/fi_FI.json
@@ -22,6 +22,8 @@
"(group)" : "(ryhmä)",
"Admin defined" : "Ylläpitäjän määrittämä",
"Saved" : "Tallennettu",
+ "Saving..." : "Tallennetaan...",
+ "Save" : "Tallenna",
"Empty response from the server" : "Tyhjä vastaus palvelimelta",
"Couldn't access. Please logout and login to activate this mount point" : "Käyttö epäonnistui. Kirjaudu ulos ja takaisin sisään aktivoidaksesi tämän liitospisteen",
"Couldn't get the information from the ownCloud server: {code} {type}" : "Tietojen saaminen ownCloud-palvelimelta epäonnistui: {code} {type}",
@@ -30,6 +32,8 @@
"External mount error" : "Ulkoinen liitosvirhe",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "Windows-verkkoasemien liitospisteiden listauksen noutaminen epäonnistui: tyhjä vastaus palvelimelta",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Jotkin määritetyt erilliset liitospisteet eivät ole yhdistettynä. Napsauta punaisia rivejä saadaksesi lisätietoja",
+ "Username" : "Käyttäjätunnus",
+ "Password" : "Salasana",
"Builtin" : "Sisäänrakennettu",
"None" : "Ei mitään",
"OAuth1" : "OAuth1",
@@ -39,8 +43,6 @@
"Client ID" : "Asiakkaan tunniste",
"Client secret" : "Asiakassalaisuus",
"OpenStack" : "OpenStack",
- "Username" : "Käyttäjätunnus",
- "Password" : "Salasana",
"Rackspace" : "Rackspace",
"API key" : "API-avain",
"Log-in credentials, save in database" : "Kirjautumistiedot, tallenna tietokantaan",
@@ -83,6 +85,7 @@
"Name" : "Nimi",
"Storage type" : "Tallennustilan tyyppi",
"External Storage" : "Erillinen tallennusväline",
+ "Global Credentials" : "Globaalit kirjautumistiedot",
"Folder name" : "Kansion nimi",
"Authentication" : "Tunnistautuminen",
"Configuration" : "Asetukset",
diff --git a/apps/files_external/l10n/fr.js b/apps/files_external/l10n/fr.js
index cc1c1bc693c..b456bc9bda0 100644
--- a/apps/files_external/l10n/fr.js
+++ b/apps/files_external/l10n/fr.js
@@ -36,6 +36,8 @@ OC.L10N.register(
"(group)" : "(groupe)",
"Admin defined" : "Défini par l'administrateur",
"Saved" : "Sauvegardé",
+ "Saving..." : "Enregistrement...",
+ "Save" : "Enregistrer",
"Empty response from the server" : "Réponse vide du serveur",
"Couldn't access. Please logout and login to activate this mount point" : "Impossible d'accéder. Veuillez vous déconnecter et vous reconnecter pour activer ce point de montage.",
"Couldn't get the information from the ownCloud server: {code} {type}" : "Impossible d'obtenir l'information depuis le serveur ownCloud : {code} {type}",
@@ -44,6 +46,8 @@ OC.L10N.register(
"External mount error" : "Erreur de point de montage externe",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "Impossible d'obtenir la liste des points de montage des disques réseaux Windows : Réponse vide du serveur",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Certains points de montage externes configurés ne sont pas connectés. Veuillez cliquer sur la(les) ligne(s) rouge(s) pour plus d'informations",
+ "Username" : "Nom d'utilisateur",
+ "Password" : "Mot de passe",
"Access key" : "Clé d'accès",
"Secret key" : "Clé secrète",
"Builtin" : "Intégré",
@@ -55,8 +59,6 @@ OC.L10N.register(
"Client ID" : "ID Client",
"Client secret" : "Secret client",
"OpenStack" : "OpenStack",
- "Username" : "Nom d'utilisateur",
- "Password" : "Mot de passe",
"Tenant name" : "Tenant name",
"Identity endpoint URL" : "Identity endpoint URL",
"Rackspace" : "Rackspace",
diff --git a/apps/files_external/l10n/fr.json b/apps/files_external/l10n/fr.json
index 47a70fcd12a..a519e8ec4cb 100644
--- a/apps/files_external/l10n/fr.json
+++ b/apps/files_external/l10n/fr.json
@@ -34,6 +34,8 @@
"(group)" : "(groupe)",
"Admin defined" : "Défini par l'administrateur",
"Saved" : "Sauvegardé",
+ "Saving..." : "Enregistrement...",
+ "Save" : "Enregistrer",
"Empty response from the server" : "Réponse vide du serveur",
"Couldn't access. Please logout and login to activate this mount point" : "Impossible d'accéder. Veuillez vous déconnecter et vous reconnecter pour activer ce point de montage.",
"Couldn't get the information from the ownCloud server: {code} {type}" : "Impossible d'obtenir l'information depuis le serveur ownCloud : {code} {type}",
@@ -42,6 +44,8 @@
"External mount error" : "Erreur de point de montage externe",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "Impossible d'obtenir la liste des points de montage des disques réseaux Windows : Réponse vide du serveur",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Certains points de montage externes configurés ne sont pas connectés. Veuillez cliquer sur la(les) ligne(s) rouge(s) pour plus d'informations",
+ "Username" : "Nom d'utilisateur",
+ "Password" : "Mot de passe",
"Access key" : "Clé d'accès",
"Secret key" : "Clé secrète",
"Builtin" : "Intégré",
@@ -53,8 +57,6 @@
"Client ID" : "ID Client",
"Client secret" : "Secret client",
"OpenStack" : "OpenStack",
- "Username" : "Nom d'utilisateur",
- "Password" : "Mot de passe",
"Tenant name" : "Tenant name",
"Identity endpoint URL" : "Identity endpoint URL",
"Rackspace" : "Rackspace",
diff --git a/apps/files_external/l10n/gl.js b/apps/files_external/l10n/gl.js
index 26e54ee7453..21298c9f542 100644
--- a/apps/files_external/l10n/gl.js
+++ b/apps/files_external/l10n/gl.js
@@ -21,13 +21,15 @@ OC.L10N.register(
"All users. Type to select user or group." : "Todos os usuarios. Escriba para seleccionar usuario ou grupo.",
"(group)" : "(grupo)",
"Saved" : "Gardado",
+ "Saving..." : "Gardando...",
+ "Save" : "Gardar",
+ "Username" : "Nome de usuario",
+ "Password" : "Contrasinal",
"None" : "Ningún",
"App key" : "Clave da API",
"App secret" : "Secreto da aplicación",
"Client ID" : "ID do cliente",
"Client secret" : "Secreto do cliente",
- "Username" : "Nome de usuario",
- "Password" : "Contrasinal",
"API key" : "Chave da API",
"Public key" : "Chave pública",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/gl.json b/apps/files_external/l10n/gl.json
index e9be28bfa18..da3ad490acd 100644
--- a/apps/files_external/l10n/gl.json
+++ b/apps/files_external/l10n/gl.json
@@ -19,13 +19,15 @@
"All users. Type to select user or group." : "Todos os usuarios. Escriba para seleccionar usuario ou grupo.",
"(group)" : "(grupo)",
"Saved" : "Gardado",
+ "Saving..." : "Gardando...",
+ "Save" : "Gardar",
+ "Username" : "Nome de usuario",
+ "Password" : "Contrasinal",
"None" : "Ningún",
"App key" : "Clave da API",
"App secret" : "Secreto da aplicación",
"Client ID" : "ID do cliente",
"Client secret" : "Secreto do cliente",
- "Username" : "Nome de usuario",
- "Password" : "Contrasinal",
"API key" : "Chave da API",
"Public key" : "Chave pública",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/he.js b/apps/files_external/l10n/he.js
index d963d796428..e748676589a 100644
--- a/apps/files_external/l10n/he.js
+++ b/apps/files_external/l10n/he.js
@@ -29,6 +29,7 @@ OC.L10N.register(
"Error generating key pair" : "שגיאה ביצירת זוג מפתחות",
"Enable encryption" : "אפשר הצפנה",
"Enable previews" : "מאפשר תצוגות מקדימות",
+ "Enable sharing" : "הפעלת שיתוף",
"Check for changes" : "בדיקה אחר שינויים",
"Never" : "לעולם לא",
"Once every direct access" : "פעם אחת כל כניסה ישירה",
@@ -36,6 +37,8 @@ OC.L10N.register(
"(group)" : "(קבוצה)",
"Admin defined" : "הוגדר מנהל",
"Saved" : "נשמר",
+ "Saving..." : "שמירה…",
+ "Save" : "שמירה",
"Empty response from the server" : "תגובה ריקה מהשרת",
"Couldn't access. Please logout and login to activate this mount point" : "לא ניתן להכנס. יש להתנתק ולהתחבר כדי להפעיל את נקודת העיגון הזו",
"Couldn't get the information from the ownCloud server: {code} {type}" : "לא ניתן היה לקבל את המידע משרת ה- ownCloud: {code} {type}",
@@ -44,6 +47,8 @@ OC.L10N.register(
"External mount error" : "שגיאת עגינה חיצונית",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "לא ניתן היה לקבל את רשימת נקודות העיגון של כונן הרשת של Window: תגובה ריקה מהשרת",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "חלק מנקודות העיגון החיצוניות שהוגדרו אינן מחוברות. יש ללחוץ על השורה/ות האדומה/ות למידע נוסף",
+ "Username" : "שם משתמש",
+ "Password" : "סיסמא",
"Access key" : "מפתח כניסה",
"Secret key" : "מפתח סודי",
"Builtin" : "מובנה",
@@ -55,12 +60,11 @@ OC.L10N.register(
"Client ID" : "זיהוי לקוח",
"Client secret" : "סוד לקוח",
"OpenStack" : "OpenStack",
- "Username" : "שם משתמש",
- "Password" : "סיסמא",
"Tenant name" : "שם דייר",
"Identity endpoint URL" : "זהות נתיב נקודת קצה",
"Rackspace" : "חץ אחורה",
"API key" : "מפתח API",
+ "Global Credentails" : "אישורי אימות גלובלים",
"Log-in credentials, save in database" : "אישורי התחברות, נשמרים במסד הנתונים",
"Username and password" : "שם משתמש וסיסמא",
"Log-in credentials, save in session" : "אישורי התחברות, נשמרים במידע שיחה - סשן",
@@ -107,6 +111,7 @@ OC.L10N.register(
"Storage type" : "סוג אחסון",
"Scope" : "היקף",
"External Storage" : "אחסון חיצוני",
+ "Global Credentials" : "אישורי אימות גלובלים",
"Folder name" : "שם התיקייה",
"Authentication" : "אימות",
"Configuration" : "הגדרות",
diff --git a/apps/files_external/l10n/he.json b/apps/files_external/l10n/he.json
index fbdcc287495..539534b3121 100644
--- a/apps/files_external/l10n/he.json
+++ b/apps/files_external/l10n/he.json
@@ -27,6 +27,7 @@
"Error generating key pair" : "שגיאה ביצירת זוג מפתחות",
"Enable encryption" : "אפשר הצפנה",
"Enable previews" : "מאפשר תצוגות מקדימות",
+ "Enable sharing" : "הפעלת שיתוף",
"Check for changes" : "בדיקה אחר שינויים",
"Never" : "לעולם לא",
"Once every direct access" : "פעם אחת כל כניסה ישירה",
@@ -34,6 +35,8 @@
"(group)" : "(קבוצה)",
"Admin defined" : "הוגדר מנהל",
"Saved" : "נשמר",
+ "Saving..." : "שמירה…",
+ "Save" : "שמירה",
"Empty response from the server" : "תגובה ריקה מהשרת",
"Couldn't access. Please logout and login to activate this mount point" : "לא ניתן להכנס. יש להתנתק ולהתחבר כדי להפעיל את נקודת העיגון הזו",
"Couldn't get the information from the ownCloud server: {code} {type}" : "לא ניתן היה לקבל את המידע משרת ה- ownCloud: {code} {type}",
@@ -42,6 +45,8 @@
"External mount error" : "שגיאת עגינה חיצונית",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "לא ניתן היה לקבל את רשימת נקודות העיגון של כונן הרשת של Window: תגובה ריקה מהשרת",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "חלק מנקודות העיגון החיצוניות שהוגדרו אינן מחוברות. יש ללחוץ על השורה/ות האדומה/ות למידע נוסף",
+ "Username" : "שם משתמש",
+ "Password" : "סיסמא",
"Access key" : "מפתח כניסה",
"Secret key" : "מפתח סודי",
"Builtin" : "מובנה",
@@ -53,12 +58,11 @@
"Client ID" : "זיהוי לקוח",
"Client secret" : "סוד לקוח",
"OpenStack" : "OpenStack",
- "Username" : "שם משתמש",
- "Password" : "סיסמא",
"Tenant name" : "שם דייר",
"Identity endpoint URL" : "זהות נתיב נקודת קצה",
"Rackspace" : "חץ אחורה",
"API key" : "מפתח API",
+ "Global Credentails" : "אישורי אימות גלובלים",
"Log-in credentials, save in database" : "אישורי התחברות, נשמרים במסד הנתונים",
"Username and password" : "שם משתמש וסיסמא",
"Log-in credentials, save in session" : "אישורי התחברות, נשמרים במידע שיחה - סשן",
@@ -105,6 +109,7 @@
"Storage type" : "סוג אחסון",
"Scope" : "היקף",
"External Storage" : "אחסון חיצוני",
+ "Global Credentials" : "אישורי אימות גלובלים",
"Folder name" : "שם התיקייה",
"Authentication" : "אימות",
"Configuration" : "הגדרות",
diff --git a/apps/files_external/l10n/hi.js b/apps/files_external/l10n/hi.js
index 3d3b750ebd8..43b29acaddc 100644
--- a/apps/files_external/l10n/hi.js
+++ b/apps/files_external/l10n/hi.js
@@ -2,6 +2,8 @@ OC.L10N.register(
"files_external",
{
"Personal" : "यक्तिगत",
+ "Saving..." : "सहेज रहे हैं...",
+ "Save" : "सहेजें",
"Username" : "प्रयोक्ता का नाम",
"Password" : "पासवर्ड",
"Share" : "साझा करें"
diff --git a/apps/files_external/l10n/hi.json b/apps/files_external/l10n/hi.json
index 6e1117f610e..c3b1ad8623b 100644
--- a/apps/files_external/l10n/hi.json
+++ b/apps/files_external/l10n/hi.json
@@ -1,5 +1,7 @@
{ "translations": {
"Personal" : "यक्तिगत",
+ "Saving..." : "सहेज रहे हैं...",
+ "Save" : "सहेजें",
"Username" : "प्रयोक्ता का नाम",
"Password" : "पासवर्ड",
"Share" : "साझा करें"
diff --git a/apps/files_external/l10n/hr.js b/apps/files_external/l10n/hr.js
index 8c632eba518..53a9c598c6d 100644
--- a/apps/files_external/l10n/hr.js
+++ b/apps/files_external/l10n/hr.js
@@ -11,13 +11,15 @@ OC.L10N.register(
"All users. Type to select user or group." : "Svi korisnici. Započnite unos za izbor korisnika ili grupe.",
"(group)" : "(grupa)",
"Saved" : "Spremljeno",
+ "Saving..." : "Spremanje...",
+ "Save" : "Spremi",
+ "Username" : "Korisničko ime",
+ "Password" : "Lozinka",
"None" : "Ništa",
"App key" : "Ključ za aplikacije",
"App secret" : "Tajna aplikacije",
"Client ID" : "ID klijenta",
"Client secret" : "Klijentski tajni ključ",
- "Username" : "Korisničko ime",
- "Password" : "Lozinka",
"Amazon S3" : "Amazon S3",
"Bucket" : "Kantica",
"Hostname" : "Naziv poslužitelja",
diff --git a/apps/files_external/l10n/hr.json b/apps/files_external/l10n/hr.json
index 610a42d46e2..cbb11276c24 100644
--- a/apps/files_external/l10n/hr.json
+++ b/apps/files_external/l10n/hr.json
@@ -9,13 +9,15 @@
"All users. Type to select user or group." : "Svi korisnici. Započnite unos za izbor korisnika ili grupe.",
"(group)" : "(grupa)",
"Saved" : "Spremljeno",
+ "Saving..." : "Spremanje...",
+ "Save" : "Spremi",
+ "Username" : "Korisničko ime",
+ "Password" : "Lozinka",
"None" : "Ništa",
"App key" : "Ključ za aplikacije",
"App secret" : "Tajna aplikacije",
"Client ID" : "ID klijenta",
"Client secret" : "Klijentski tajni ključ",
- "Username" : "Korisničko ime",
- "Password" : "Lozinka",
"Amazon S3" : "Amazon S3",
"Bucket" : "Kantica",
"Hostname" : "Naziv poslužitelja",
diff --git a/apps/files_external/l10n/hu_HU.js b/apps/files_external/l10n/hu_HU.js
index 4eb93dab872..4e8ceef7a4c 100644
--- a/apps/files_external/l10n/hu_HU.js
+++ b/apps/files_external/l10n/hu_HU.js
@@ -18,19 +18,21 @@ OC.L10N.register(
"(group)" : "(csoport)",
"Admin defined" : "Adminisztrátor definiálva",
"Saved" : "Elmentve",
+ "Saving..." : "Mentés...",
+ "Save" : "Mentés",
"Empty response from the server" : "Üres válasz a szervertől",
"Couldn't access. Please logout and login to activate this mount point" : "Nem férhető hozzá. Kérjük próbálj meg ki- és bejelentkezni a csatolási pont aktiválásához.",
"Couldn't get the information from the ownCloud server: {code} {type}" : "Nem sikerült lekérdezni az információkat az ownCloud szerverről: {code} {type}",
"There was an error with message: " : "Hiba történt ezzel az üzenettel:",
"External mount error" : "Külső csatolási hiba",
+ "Username" : "Felhasználónév",
+ "Password" : "Jelszó",
"Access key" : "Hozzáférési kulcs",
"Secret key" : "Titkos kulcs",
"None" : "Egyik sem",
"App key" : "App kulcs",
"App secret" : "App titkos kulcs",
"Client secret" : "Kliens titkos",
- "Username" : "Felhasználónév",
- "Password" : "Jelszó",
"API key" : "API kulcs",
"Username and password" : "Felhasználónév és jelszó",
"RSA public key" : "RSA publikus kulcs",
diff --git a/apps/files_external/l10n/hu_HU.json b/apps/files_external/l10n/hu_HU.json
index bc50176e5a3..6966c5720ab 100644
--- a/apps/files_external/l10n/hu_HU.json
+++ b/apps/files_external/l10n/hu_HU.json
@@ -16,19 +16,21 @@
"(group)" : "(csoport)",
"Admin defined" : "Adminisztrátor definiálva",
"Saved" : "Elmentve",
+ "Saving..." : "Mentés...",
+ "Save" : "Mentés",
"Empty response from the server" : "Üres válasz a szervertől",
"Couldn't access. Please logout and login to activate this mount point" : "Nem férhető hozzá. Kérjük próbálj meg ki- és bejelentkezni a csatolási pont aktiválásához.",
"Couldn't get the information from the ownCloud server: {code} {type}" : "Nem sikerült lekérdezni az információkat az ownCloud szerverről: {code} {type}",
"There was an error with message: " : "Hiba történt ezzel az üzenettel:",
"External mount error" : "Külső csatolási hiba",
+ "Username" : "Felhasználónév",
+ "Password" : "Jelszó",
"Access key" : "Hozzáférési kulcs",
"Secret key" : "Titkos kulcs",
"None" : "Egyik sem",
"App key" : "App kulcs",
"App secret" : "App titkos kulcs",
"Client secret" : "Kliens titkos",
- "Username" : "Felhasználónév",
- "Password" : "Jelszó",
"API key" : "API kulcs",
"Username and password" : "Felhasználónév és jelszó",
"RSA public key" : "RSA publikus kulcs",
diff --git a/apps/files_external/l10n/hy.js b/apps/files_external/l10n/hy.js
index 1092d48d575..ad4caac8057 100644
--- a/apps/files_external/l10n/hy.js
+++ b/apps/files_external/l10n/hy.js
@@ -3,6 +3,7 @@ OC.L10N.register(
{
"Personal" : "Անձնական",
"Never" : "Երբեք",
+ "Save" : "Պահպանել",
"Username" : "Օգտանուն",
"Password" : "Գաղտնաբառ",
"URL" : "URL",
diff --git a/apps/files_external/l10n/hy.json b/apps/files_external/l10n/hy.json
index 1fecd4f3da1..87c69207ad3 100644
--- a/apps/files_external/l10n/hy.json
+++ b/apps/files_external/l10n/hy.json
@@ -1,6 +1,7 @@
{ "translations": {
"Personal" : "Անձնական",
"Never" : "Երբեք",
+ "Save" : "Պահպանել",
"Username" : "Օգտանուն",
"Password" : "Գաղտնաբառ",
"URL" : "URL",
diff --git a/apps/files_external/l10n/ia.js b/apps/files_external/l10n/ia.js
index d13ee4ac10f..9e0c7cb322b 100644
--- a/apps/files_external/l10n/ia.js
+++ b/apps/files_external/l10n/ia.js
@@ -3,6 +3,8 @@ OC.L10N.register(
{
"Personal" : "Personal",
"Saved" : "Salveguardate",
+ "Saving..." : "Salveguardante...",
+ "Save" : "Salveguardar",
"Username" : "Nomine de usator",
"Password" : "Contrasigno",
"Region" : "Region",
diff --git a/apps/files_external/l10n/ia.json b/apps/files_external/l10n/ia.json
index 43562ce9e5b..a626ccda34f 100644
--- a/apps/files_external/l10n/ia.json
+++ b/apps/files_external/l10n/ia.json
@@ -1,6 +1,8 @@
{ "translations": {
"Personal" : "Personal",
"Saved" : "Salveguardate",
+ "Saving..." : "Salveguardante...",
+ "Save" : "Salveguardar",
"Username" : "Nomine de usator",
"Password" : "Contrasigno",
"Region" : "Region",
diff --git a/apps/files_external/l10n/id.js b/apps/files_external/l10n/id.js
index 15f33571ee6..5610025a9f6 100644
--- a/apps/files_external/l10n/id.js
+++ b/apps/files_external/l10n/id.js
@@ -32,6 +32,10 @@ OC.L10N.register(
"All users. Type to select user or group." : "Semua pengguna. Ketik untuk memilih pengguna atau grup.",
"(group)" : "(grup)",
"Saved" : "Disimpan",
+ "Saving..." : "Menyimpan...",
+ "Save" : "Simpan",
+ "Username" : "Nama Pengguna",
+ "Password" : "Sandi",
"Access key" : "Kunci akses",
"Secret key" : "Kunci rahasia",
"Builtin" : "Internal",
@@ -43,8 +47,6 @@ OC.L10N.register(
"Client ID" : "ID Klien",
"Client secret" : "Rahasia klien",
"OpenStack" : "OpenStack",
- "Username" : "Nama Pengguna",
- "Password" : "Sandi",
"Tenant name" : "Nama tenant",
"Identity endpoint URL" : "Identitas URL akhir",
"Rackspace" : "Rackspace",
diff --git a/apps/files_external/l10n/id.json b/apps/files_external/l10n/id.json
index 00f78599006..5722287c42c 100644
--- a/apps/files_external/l10n/id.json
+++ b/apps/files_external/l10n/id.json
@@ -30,6 +30,10 @@
"All users. Type to select user or group." : "Semua pengguna. Ketik untuk memilih pengguna atau grup.",
"(group)" : "(grup)",
"Saved" : "Disimpan",
+ "Saving..." : "Menyimpan...",
+ "Save" : "Simpan",
+ "Username" : "Nama Pengguna",
+ "Password" : "Sandi",
"Access key" : "Kunci akses",
"Secret key" : "Kunci rahasia",
"Builtin" : "Internal",
@@ -41,8 +45,6 @@
"Client ID" : "ID Klien",
"Client secret" : "Rahasia klien",
"OpenStack" : "OpenStack",
- "Username" : "Nama Pengguna",
- "Password" : "Sandi",
"Tenant name" : "Nama tenant",
"Identity endpoint URL" : "Identitas URL akhir",
"Rackspace" : "Rackspace",
diff --git a/apps/files_external/l10n/is.js b/apps/files_external/l10n/is.js
index a1edd11fc1c..0f60a1e3af3 100644
--- a/apps/files_external/l10n/is.js
+++ b/apps/files_external/l10n/is.js
@@ -5,9 +5,11 @@ OC.L10N.register(
"Grant access" : "Veita aðgengi",
"Access granted" : "Aðgengi veitt",
"Saved" : "Vistað",
- "None" : "Ekkert",
+ "Saving..." : "Er að vista ...",
+ "Save" : "Vista",
"Username" : "Notendanafn",
"Password" : "Lykilorð",
+ "None" : "Ekkert",
"WebDAV" : "WebDAV",
"URL" : "URL",
"Host" : "Netþjónn",
diff --git a/apps/files_external/l10n/is.json b/apps/files_external/l10n/is.json
index 6d52ed3a896..0a700436b7f 100644
--- a/apps/files_external/l10n/is.json
+++ b/apps/files_external/l10n/is.json
@@ -3,9 +3,11 @@
"Grant access" : "Veita aðgengi",
"Access granted" : "Aðgengi veitt",
"Saved" : "Vistað",
- "None" : "Ekkert",
+ "Saving..." : "Er að vista ...",
+ "Save" : "Vista",
"Username" : "Notendanafn",
"Password" : "Lykilorð",
+ "None" : "Ekkert",
"WebDAV" : "WebDAV",
"URL" : "URL",
"Host" : "Netþjónn",
diff --git a/apps/files_external/l10n/it.js b/apps/files_external/l10n/it.js
index d9adaad833b..29f0d45ee3d 100644
--- a/apps/files_external/l10n/it.js
+++ b/apps/files_external/l10n/it.js
@@ -29,6 +29,7 @@ OC.L10N.register(
"Error generating key pair" : "Errore durante la generazione della coppia di chiavi",
"Enable encryption" : "Abilita cifratura",
"Enable previews" : "Abilita le anteprime",
+ "Enable sharing" : "Abilita condivisione",
"Check for changes" : "Controlla le modifiche",
"Never" : "Mai",
"Once every direct access" : "Una volta per ogni accesso diretto",
@@ -36,6 +37,8 @@ OC.L10N.register(
"(group)" : "(gruppo)",
"Admin defined" : "Definito dall'amministratore",
"Saved" : "Salvato",
+ "Saving..." : "Salvataggio in corso...",
+ "Save" : "Salva",
"Empty response from the server" : "Risposta vuota dal server",
"Couldn't access. Please logout and login to activate this mount point" : "Impossibile accedere. Chiudi la sessione e accedi nuovamente per attivare questo punto di mount",
"Couldn't get the information from the ownCloud server: {code} {type}" : "Impossibile ottenere le informazioni dal server ownCloud: {code} {type}",
@@ -44,6 +47,8 @@ OC.L10N.register(
"External mount error" : "Errore di mount esterno",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "Impossibile ottenere l'elenco dei punti di mount delle unità di rete Windows: risposta vuota dal server",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Alcuni dei punti di mount esterni configurati non sono connessi. Fai clic sulle righe rosse per ulteriori informazioni",
+ "Username" : "Nome utente",
+ "Password" : "Password",
"Access key" : "Chiave di accesso",
"Secret key" : "Chiave segreta",
"Builtin" : "Integrata",
@@ -55,12 +60,11 @@ OC.L10N.register(
"Client ID" : "ID client",
"Client secret" : "Segreto del client",
"OpenStack" : "OpenStack",
- "Username" : "Nome utente",
- "Password" : "Password",
"Tenant name" : "Nome tenant",
"Identity endpoint URL" : "URL endpoint delle identità",
"Rackspace" : "Rackspace",
"API key" : "Chiave API",
+ "Global Credentails" : "Credenziali globali",
"Log-in credentials, save in database" : "Credenziali di accesso, salva nel database",
"Username and password" : "Nome utente e password",
"Log-in credentials, save in session" : "Credenziali di accesso, salva nella sessione",
@@ -107,6 +111,7 @@ OC.L10N.register(
"Storage type" : "Tipo di archiviazione",
"Scope" : "Ambito",
"External Storage" : "Archiviazione esterna",
+ "Global Credentials" : "Credenziali globali",
"Folder name" : "Nome della cartella",
"Authentication" : "Autenticazione",
"Configuration" : "Configurazione",
diff --git a/apps/files_external/l10n/it.json b/apps/files_external/l10n/it.json
index b228cd76604..c7863b8d139 100644
--- a/apps/files_external/l10n/it.json
+++ b/apps/files_external/l10n/it.json
@@ -27,6 +27,7 @@
"Error generating key pair" : "Errore durante la generazione della coppia di chiavi",
"Enable encryption" : "Abilita cifratura",
"Enable previews" : "Abilita le anteprime",
+ "Enable sharing" : "Abilita condivisione",
"Check for changes" : "Controlla le modifiche",
"Never" : "Mai",
"Once every direct access" : "Una volta per ogni accesso diretto",
@@ -34,6 +35,8 @@
"(group)" : "(gruppo)",
"Admin defined" : "Definito dall'amministratore",
"Saved" : "Salvato",
+ "Saving..." : "Salvataggio in corso...",
+ "Save" : "Salva",
"Empty response from the server" : "Risposta vuota dal server",
"Couldn't access. Please logout and login to activate this mount point" : "Impossibile accedere. Chiudi la sessione e accedi nuovamente per attivare questo punto di mount",
"Couldn't get the information from the ownCloud server: {code} {type}" : "Impossibile ottenere le informazioni dal server ownCloud: {code} {type}",
@@ -42,6 +45,8 @@
"External mount error" : "Errore di mount esterno",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "Impossibile ottenere l'elenco dei punti di mount delle unità di rete Windows: risposta vuota dal server",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Alcuni dei punti di mount esterni configurati non sono connessi. Fai clic sulle righe rosse per ulteriori informazioni",
+ "Username" : "Nome utente",
+ "Password" : "Password",
"Access key" : "Chiave di accesso",
"Secret key" : "Chiave segreta",
"Builtin" : "Integrata",
@@ -53,12 +58,11 @@
"Client ID" : "ID client",
"Client secret" : "Segreto del client",
"OpenStack" : "OpenStack",
- "Username" : "Nome utente",
- "Password" : "Password",
"Tenant name" : "Nome tenant",
"Identity endpoint URL" : "URL endpoint delle identità",
"Rackspace" : "Rackspace",
"API key" : "Chiave API",
+ "Global Credentails" : "Credenziali globali",
"Log-in credentials, save in database" : "Credenziali di accesso, salva nel database",
"Username and password" : "Nome utente e password",
"Log-in credentials, save in session" : "Credenziali di accesso, salva nella sessione",
@@ -105,6 +109,7 @@
"Storage type" : "Tipo di archiviazione",
"Scope" : "Ambito",
"External Storage" : "Archiviazione esterna",
+ "Global Credentials" : "Credenziali globali",
"Folder name" : "Nome della cartella",
"Authentication" : "Autenticazione",
"Configuration" : "Configurazione",
diff --git a/apps/files_external/l10n/ja.js b/apps/files_external/l10n/ja.js
index f14c07808ca..4d7f4a1c186 100644
--- a/apps/files_external/l10n/ja.js
+++ b/apps/files_external/l10n/ja.js
@@ -36,6 +36,8 @@ OC.L10N.register(
"(group)" : "(グループ)",
"Admin defined" : "管理者設定済",
"Saved" : "保存されました",
+ "Saving..." : "保存中...",
+ "Save" : "保存",
"Empty response from the server" : "サーバーから空の応答がありました",
"Couldn't access. Please logout and login to activate this mount point" : "アクセス出来ませんでした。このマウントポイントを有効にするには一度ログアウトしてからログインしてください。",
"Couldn't get the information from the ownCloud server: {code} {type}" : "ownCloud サーバーから情報を取得出来ませんでした。: {code} {type}",
@@ -44,6 +46,8 @@ OC.L10N.register(
"External mount error" : "外部マウントエラー",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "Windows ネットワークドライブのマウントポイントリストを取得出来ませんでした:サーバーから空の応答がありました",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "いくつかの設定済み外部マウントポイントに接続できませんでした。詳細情報は赤い行をクリックしてください",
+ "Username" : "ユーザー名",
+ "Password" : "パスワード",
"Access key" : "アクセスキー",
"Secret key" : "シークレットキー",
"Builtin" : "ビルトイン",
@@ -55,8 +59,6 @@ OC.L10N.register(
"Client ID" : "クライアントID",
"Client secret" : "クライアント秘密キー",
"OpenStack" : "OpenStack",
- "Username" : "ユーザー名",
- "Password" : "パスワード",
"Tenant name" : "テナント名",
"Identity endpoint URL" : "認証エンドポイントURL",
"Rackspace" : "Rackspace",
diff --git a/apps/files_external/l10n/ja.json b/apps/files_external/l10n/ja.json
index df6f7f44618..88101177e5d 100644
--- a/apps/files_external/l10n/ja.json
+++ b/apps/files_external/l10n/ja.json
@@ -34,6 +34,8 @@
"(group)" : "(グループ)",
"Admin defined" : "管理者設定済",
"Saved" : "保存されました",
+ "Saving..." : "保存中...",
+ "Save" : "保存",
"Empty response from the server" : "サーバーから空の応答がありました",
"Couldn't access. Please logout and login to activate this mount point" : "アクセス出来ませんでした。このマウントポイントを有効にするには一度ログアウトしてからログインしてください。",
"Couldn't get the information from the ownCloud server: {code} {type}" : "ownCloud サーバーから情報を取得出来ませんでした。: {code} {type}",
@@ -42,6 +44,8 @@
"External mount error" : "外部マウントエラー",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "Windows ネットワークドライブのマウントポイントリストを取得出来ませんでした:サーバーから空の応答がありました",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "いくつかの設定済み外部マウントポイントに接続できませんでした。詳細情報は赤い行をクリックしてください",
+ "Username" : "ユーザー名",
+ "Password" : "パスワード",
"Access key" : "アクセスキー",
"Secret key" : "シークレットキー",
"Builtin" : "ビルトイン",
@@ -53,8 +57,6 @@
"Client ID" : "クライアントID",
"Client secret" : "クライアント秘密キー",
"OpenStack" : "OpenStack",
- "Username" : "ユーザー名",
- "Password" : "パスワード",
"Tenant name" : "テナント名",
"Identity endpoint URL" : "認証エンドポイントURL",
"Rackspace" : "Rackspace",
diff --git a/apps/files_external/l10n/ka_GE.js b/apps/files_external/l10n/ka_GE.js
index e82c778862e..f6f98b1b5dd 100644
--- a/apps/files_external/l10n/ka_GE.js
+++ b/apps/files_external/l10n/ka_GE.js
@@ -5,9 +5,11 @@ OC.L10N.register(
"Personal" : "პირადი",
"Grant access" : "დაშვების მინიჭება",
"Access granted" : "დაშვება მინიჭებულია",
- "None" : "არა",
+ "Saving..." : "შენახვა...",
+ "Save" : "შენახვა",
"Username" : "მომხმარებლის სახელი",
"Password" : "პაროლი",
+ "None" : "არა",
"API key" : "API გასაღები",
"Port" : "პორტი",
"Region" : "რეგიონი",
diff --git a/apps/files_external/l10n/ka_GE.json b/apps/files_external/l10n/ka_GE.json
index a706d42225b..3ffba305a95 100644
--- a/apps/files_external/l10n/ka_GE.json
+++ b/apps/files_external/l10n/ka_GE.json
@@ -3,9 +3,11 @@
"Personal" : "პირადი",
"Grant access" : "დაშვების მინიჭება",
"Access granted" : "დაშვება მინიჭებულია",
- "None" : "არა",
+ "Saving..." : "შენახვა...",
+ "Save" : "შენახვა",
"Username" : "მომხმარებლის სახელი",
"Password" : "პაროლი",
+ "None" : "არა",
"API key" : "API გასაღები",
"Port" : "პორტი",
"Region" : "რეგიონი",
diff --git a/apps/files_external/l10n/km.js b/apps/files_external/l10n/km.js
index e5aad9697ae..2c7b69e872b 100644
--- a/apps/files_external/l10n/km.js
+++ b/apps/files_external/l10n/km.js
@@ -6,9 +6,11 @@ OC.L10N.register(
"Grant access" : "ទទួល​សិទ្ធិ​ចូល",
"Access granted" : "បាន​ទទួល​សិទ្ធិ​ចូល",
"Saved" : "បាន​រក្សាទុក",
- "None" : "គ្មាន",
+ "Saving..." : "កំពុង​រក្សាទុក",
+ "Save" : "រក្សាទុក",
"Username" : "ឈ្មោះ​អ្នកប្រើ",
"Password" : "ពាក្យសម្ងាត់",
+ "None" : "គ្មាន",
"Port" : "ច្រក",
"WebDAV" : "WebDAV",
"URL" : "URL",
diff --git a/apps/files_external/l10n/km.json b/apps/files_external/l10n/km.json
index 71213394d53..518d4ff260a 100644
--- a/apps/files_external/l10n/km.json
+++ b/apps/files_external/l10n/km.json
@@ -4,9 +4,11 @@
"Grant access" : "ទទួល​សិទ្ធិ​ចូល",
"Access granted" : "បាន​ទទួល​សិទ្ធិ​ចូល",
"Saved" : "បាន​រក្សាទុក",
- "None" : "គ្មាន",
+ "Saving..." : "កំពុង​រក្សាទុក",
+ "Save" : "រក្សាទុក",
"Username" : "ឈ្មោះ​អ្នកប្រើ",
"Password" : "ពាក្យសម្ងាត់",
+ "None" : "គ្មាន",
"Port" : "ច្រក",
"WebDAV" : "WebDAV",
"URL" : "URL",
diff --git a/apps/files_external/l10n/kn.js b/apps/files_external/l10n/kn.js
index 9d01033e356..b92c9382cd4 100644
--- a/apps/files_external/l10n/kn.js
+++ b/apps/files_external/l10n/kn.js
@@ -3,9 +3,11 @@ OC.L10N.register(
{
"Personal" : "ವೈಯಕ್ತಿಕ",
"Saved" : "ಉಳಿಸಿದ",
- "None" : "ಯಾವುದೂ ಇಲ್ಲ",
+ "Saving..." : "ಉಳಿಸಲಾಗುತ್ತಿದೆ ...",
+ "Save" : "ಉಳಿಸಿ",
"Username" : "ಬಳಕೆಯ ಹೆಸರು",
"Password" : "ಗುಪ್ತ ಪದ",
+ "None" : "ಯಾವುದೂ ಇಲ್ಲ",
"Port" : "ರೇವು",
"WebDAV" : "WebDAV",
"URL" : "ಜಾಲದ ಕೊಂಡಿ",
diff --git a/apps/files_external/l10n/kn.json b/apps/files_external/l10n/kn.json
index 0380f431d1e..9841df0ae93 100644
--- a/apps/files_external/l10n/kn.json
+++ b/apps/files_external/l10n/kn.json
@@ -1,9 +1,11 @@
{ "translations": {
"Personal" : "ವೈಯಕ್ತಿಕ",
"Saved" : "ಉಳಿಸಿದ",
- "None" : "ಯಾವುದೂ ಇಲ್ಲ",
+ "Saving..." : "ಉಳಿಸಲಾಗುತ್ತಿದೆ ...",
+ "Save" : "ಉಳಿಸಿ",
"Username" : "ಬಳಕೆಯ ಹೆಸರು",
"Password" : "ಗುಪ್ತ ಪದ",
+ "None" : "ಯಾವುದೂ ಇಲ್ಲ",
"Port" : "ರೇವು",
"WebDAV" : "WebDAV",
"URL" : "ಜಾಲದ ಕೊಂಡಿ",
diff --git a/apps/files_external/l10n/ko.js b/apps/files_external/l10n/ko.js
index df30d86ca13..4ce4907cbd0 100644
--- a/apps/files_external/l10n/ko.js
+++ b/apps/files_external/l10n/ko.js
@@ -33,6 +33,10 @@ OC.L10N.register(
"All users. Type to select user or group." : "모든 사용자입니다. 사용자나 그룹을 선택하려면 입력하십시오",
"(group)" : "(그룹)",
"Saved" : "저장됨",
+ "Saving..." : "저장 중...",
+ "Save" : "저장",
+ "Username" : "사용자 이름",
+ "Password" : "암호",
"Access key" : "접근 키",
"Secret key" : "비밀 키",
"Builtin" : "내장",
@@ -44,8 +48,6 @@ OC.L10N.register(
"Client ID" : "클라이언트 ID",
"Client secret" : "클라이언트 비밀 값",
"OpenStack" : "OpenStack",
- "Username" : "사용자 이름",
- "Password" : "암호",
"Tenant name" : "테넌트 이름",
"Identity endpoint URL" : "아이덴티티 끝점(Endpoint) URL",
"Rackspace" : "Rackspace",
diff --git a/apps/files_external/l10n/ko.json b/apps/files_external/l10n/ko.json
index a5f4b4946ca..a55e4f6da6d 100644
--- a/apps/files_external/l10n/ko.json
+++ b/apps/files_external/l10n/ko.json
@@ -31,6 +31,10 @@
"All users. Type to select user or group." : "모든 사용자입니다. 사용자나 그룹을 선택하려면 입력하십시오",
"(group)" : "(그룹)",
"Saved" : "저장됨",
+ "Saving..." : "저장 중...",
+ "Save" : "저장",
+ "Username" : "사용자 이름",
+ "Password" : "암호",
"Access key" : "접근 키",
"Secret key" : "비밀 키",
"Builtin" : "내장",
@@ -42,8 +46,6 @@
"Client ID" : "클라이언트 ID",
"Client secret" : "클라이언트 비밀 값",
"OpenStack" : "OpenStack",
- "Username" : "사용자 이름",
- "Password" : "암호",
"Tenant name" : "테넌트 이름",
"Identity endpoint URL" : "아이덴티티 끝점(Endpoint) URL",
"Rackspace" : "Rackspace",
diff --git a/apps/files_external/l10n/ku_IQ.js b/apps/files_external/l10n/ku_IQ.js
index 72c1e8313be..49211f62ef6 100644
--- a/apps/files_external/l10n/ku_IQ.js
+++ b/apps/files_external/l10n/ku_IQ.js
@@ -1,9 +1,11 @@
OC.L10N.register(
"files_external",
{
- "None" : "هیچ",
+ "Saving..." : "پاشکه‌وتده‌کات...",
+ "Save" : "پاشکه‌وتکردن",
"Username" : "ناوی به‌کارهێنه‌ر",
"Password" : "وشەی تێپەربو",
+ "None" : "هیچ",
"URL" : "ناونیشانی به‌سته‌ر",
"Location" : "شوێن",
"Share" : "هاوبەشی کردن",
diff --git a/apps/files_external/l10n/ku_IQ.json b/apps/files_external/l10n/ku_IQ.json
index 9ef5a71e818..cb73bd6b8b6 100644
--- a/apps/files_external/l10n/ku_IQ.json
+++ b/apps/files_external/l10n/ku_IQ.json
@@ -1,7 +1,9 @@
{ "translations": {
- "None" : "هیچ",
+ "Saving..." : "پاشکه‌وتده‌کات...",
+ "Save" : "پاشکه‌وتکردن",
"Username" : "ناوی به‌کارهێنه‌ر",
"Password" : "وشەی تێپەربو",
+ "None" : "هیچ",
"URL" : "ناونیشانی به‌سته‌ر",
"Location" : "شوێن",
"Share" : "هاوبەشی کردن",
diff --git a/apps/files_external/l10n/lb.js b/apps/files_external/l10n/lb.js
index 7e03d3b1b99..67558b46275 100644
--- a/apps/files_external/l10n/lb.js
+++ b/apps/files_external/l10n/lb.js
@@ -3,6 +3,8 @@ OC.L10N.register(
{
"Personal" : "Perséinlech",
"Saved" : "Gespäichert",
+ "Saving..." : "Speicheren...",
+ "Save" : "Späicheren",
"Username" : "Benotzernumm",
"Password" : "Passwuert",
"Port" : "Port",
diff --git a/apps/files_external/l10n/lb.json b/apps/files_external/l10n/lb.json
index 5c6797533b5..8d570532dd1 100644
--- a/apps/files_external/l10n/lb.json
+++ b/apps/files_external/l10n/lb.json
@@ -1,6 +1,8 @@
{ "translations": {
"Personal" : "Perséinlech",
"Saved" : "Gespäichert",
+ "Saving..." : "Speicheren...",
+ "Save" : "Späicheren",
"Username" : "Benotzernumm",
"Password" : "Passwuert",
"Port" : "Port",
diff --git a/apps/files_external/l10n/lt_LT.js b/apps/files_external/l10n/lt_LT.js
index 3a871070f45..c08e6d60781 100644
--- a/apps/files_external/l10n/lt_LT.js
+++ b/apps/files_external/l10n/lt_LT.js
@@ -9,9 +9,11 @@ OC.L10N.register(
"Grant access" : "Suteikti priėjimą",
"Access granted" : "Priėjimas suteiktas",
"Saved" : "Išsaugoti",
- "None" : "Nieko",
+ "Saving..." : "Saugoma...",
+ "Save" : "Išsaugoti",
"Username" : "Prisijungimo vardas",
"Password" : "Slaptažodis",
+ "None" : "Nieko",
"API key" : "API raktas",
"Port" : "Prievadas",
"Region" : "Regionas",
diff --git a/apps/files_external/l10n/lt_LT.json b/apps/files_external/l10n/lt_LT.json
index 854f753acaf..4fcc86df00b 100644
--- a/apps/files_external/l10n/lt_LT.json
+++ b/apps/files_external/l10n/lt_LT.json
@@ -7,9 +7,11 @@
"Grant access" : "Suteikti priėjimą",
"Access granted" : "Priėjimas suteiktas",
"Saved" : "Išsaugoti",
- "None" : "Nieko",
+ "Saving..." : "Saugoma...",
+ "Save" : "Išsaugoti",
"Username" : "Prisijungimo vardas",
"Password" : "Slaptažodis",
+ "None" : "Nieko",
"API key" : "API raktas",
"Port" : "Prievadas",
"Region" : "Regionas",
diff --git a/apps/files_external/l10n/lv.js b/apps/files_external/l10n/lv.js
index d6733a1d9c0..c3ae3cb2fce 100644
--- a/apps/files_external/l10n/lv.js
+++ b/apps/files_external/l10n/lv.js
@@ -7,9 +7,11 @@ OC.L10N.register(
"Access granted" : "Piešķirta pieeja",
"Enable encryption" : "Ieslēgt šifrēšanu",
"Saved" : "Saglabāts",
- "None" : "Nav",
+ "Saving..." : "Saglabā...",
+ "Save" : "Saglabāt",
"Username" : "Lietotājvārds",
"Password" : "Parole",
+ "None" : "Nav",
"Port" : "Ports",
"WebDAV" : "WebDAV",
"URL" : "URL",
diff --git a/apps/files_external/l10n/lv.json b/apps/files_external/l10n/lv.json
index 57fe7cbc048..61dfeffa0e1 100644
--- a/apps/files_external/l10n/lv.json
+++ b/apps/files_external/l10n/lv.json
@@ -5,9 +5,11 @@
"Access granted" : "Piešķirta pieeja",
"Enable encryption" : "Ieslēgt šifrēšanu",
"Saved" : "Saglabāts",
- "None" : "Nav",
+ "Saving..." : "Saglabā...",
+ "Save" : "Saglabāt",
"Username" : "Lietotājvārds",
"Password" : "Parole",
+ "None" : "Nav",
"Port" : "Ports",
"WebDAV" : "WebDAV",
"URL" : "URL",
diff --git a/apps/files_external/l10n/mk.js b/apps/files_external/l10n/mk.js
index e75f1afa620..a2826d5caea 100644
--- a/apps/files_external/l10n/mk.js
+++ b/apps/files_external/l10n/mk.js
@@ -5,9 +5,11 @@ OC.L10N.register(
"Grant access" : "Дозволи пристап",
"Access granted" : "Пристапот е дозволен",
"Saved" : "Снимено",
- "None" : "Ништо",
+ "Saving..." : "Снимам...",
+ "Save" : "Сними",
"Username" : "Корисничко име",
"Password" : "Лозинка",
+ "None" : "Ништо",
"API key" : "API key",
"Port" : "Порта",
"Region" : "Регион",
diff --git a/apps/files_external/l10n/mk.json b/apps/files_external/l10n/mk.json
index ae095b46310..e41cb7d4ae0 100644
--- a/apps/files_external/l10n/mk.json
+++ b/apps/files_external/l10n/mk.json
@@ -3,9 +3,11 @@
"Grant access" : "Дозволи пристап",
"Access granted" : "Пристапот е дозволен",
"Saved" : "Снимено",
- "None" : "Ништо",
+ "Saving..." : "Снимам...",
+ "Save" : "Сними",
"Username" : "Корисничко име",
"Password" : "Лозинка",
+ "None" : "Ништо",
"API key" : "API key",
"Port" : "Порта",
"Region" : "Регион",
diff --git a/apps/files_external/l10n/mn.js b/apps/files_external/l10n/mn.js
index a83f8310862..c451e4d7588 100644
--- a/apps/files_external/l10n/mn.js
+++ b/apps/files_external/l10n/mn.js
@@ -1,6 +1,7 @@
OC.L10N.register(
"files_external",
{
+ "Save" : "Хадгалах",
"Username" : "Хэрэглэгчийн нэр",
"Password" : "Нууц үг",
"Share" : "Түгээх"
diff --git a/apps/files_external/l10n/mn.json b/apps/files_external/l10n/mn.json
index e28fa6e52ad..2296b74bf50 100644
--- a/apps/files_external/l10n/mn.json
+++ b/apps/files_external/l10n/mn.json
@@ -1,4 +1,5 @@
{ "translations": {
+ "Save" : "Хадгалах",
"Username" : "Хэрэглэгчийн нэр",
"Password" : "Нууц үг",
"Share" : "Түгээх"
diff --git a/apps/files_external/l10n/ms_MY.js b/apps/files_external/l10n/ms_MY.js
index 1b28ef4226a..0736bcbd436 100644
--- a/apps/files_external/l10n/ms_MY.js
+++ b/apps/files_external/l10n/ms_MY.js
@@ -2,6 +2,8 @@ OC.L10N.register(
"files_external",
{
"Personal" : "Peribadi",
+ "Saving..." : "Sedang menyimpan...",
+ "Save" : "Simpan",
"Username" : "Nama pengguna",
"Password" : "Kata laluan",
"Region" : "Wilayah",
diff --git a/apps/files_external/l10n/ms_MY.json b/apps/files_external/l10n/ms_MY.json
index 79293106272..d84f5859451 100644
--- a/apps/files_external/l10n/ms_MY.json
+++ b/apps/files_external/l10n/ms_MY.json
@@ -1,5 +1,7 @@
{ "translations": {
"Personal" : "Peribadi",
+ "Saving..." : "Sedang menyimpan...",
+ "Save" : "Simpan",
"Username" : "Nama pengguna",
"Password" : "Kata laluan",
"Region" : "Wilayah",
diff --git a/apps/files_external/l10n/nb_NO.js b/apps/files_external/l10n/nb_NO.js
index fc791fe60ab..dcb9da4ac1f 100644
--- a/apps/files_external/l10n/nb_NO.js
+++ b/apps/files_external/l10n/nb_NO.js
@@ -35,6 +35,8 @@ OC.L10N.register(
"(group)" : "(gruppe)",
"Admin defined" : "Admin-definert",
"Saved" : "Lagret",
+ "Saving..." : "Lagrer...",
+ "Save" : "Lagre",
"Empty response from the server" : "Tomt svar fra serveren",
"Couldn't access. Please logout and login to activate this mount point" : "Fikk ikke tilgang. Vennligst logg ut og inn igjen for å aktivere dette oppkoblingspunktet.",
"Couldn't get the information from the ownCloud server: {code} {type}" : "Klarte ikke å hente informasjon fra ownCloud-serveren: {code} {type}",
@@ -43,6 +45,8 @@ OC.L10N.register(
"External mount error" : "Ekstern oppkoblingsfeil",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "Klarte ikke å hente listen over oppkoblingspunkter for Windows nettverk-disker: tomt svar fra serveren",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Noen av de konfigurerte eksterne oppkoblingspunktene er ikke tilkoblet. Klikk på de røde raden(e) for mer informasjon.",
+ "Username" : "Brukernavn",
+ "Password" : "Passord",
"Access key" : "Tilgangsnøkkel",
"Secret key" : "Hemmelig nøkkel",
"Builtin" : "Innebygget",
@@ -54,8 +58,6 @@ OC.L10N.register(
"Client ID" : "Client ID",
"Client secret" : "Client secret",
"OpenStack" : "OpenStack",
- "Username" : "Brukernavn",
- "Password" : "Passord",
"Tenant name" : "Prosjektnavn",
"Identity endpoint URL" : "URL for identitets-endepunkt",
"Rackspace" : "Rackspace",
diff --git a/apps/files_external/l10n/nb_NO.json b/apps/files_external/l10n/nb_NO.json
index 0e956952948..c7f56d21534 100644
--- a/apps/files_external/l10n/nb_NO.json
+++ b/apps/files_external/l10n/nb_NO.json
@@ -33,6 +33,8 @@
"(group)" : "(gruppe)",
"Admin defined" : "Admin-definert",
"Saved" : "Lagret",
+ "Saving..." : "Lagrer...",
+ "Save" : "Lagre",
"Empty response from the server" : "Tomt svar fra serveren",
"Couldn't access. Please logout and login to activate this mount point" : "Fikk ikke tilgang. Vennligst logg ut og inn igjen for å aktivere dette oppkoblingspunktet.",
"Couldn't get the information from the ownCloud server: {code} {type}" : "Klarte ikke å hente informasjon fra ownCloud-serveren: {code} {type}",
@@ -41,6 +43,8 @@
"External mount error" : "Ekstern oppkoblingsfeil",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "Klarte ikke å hente listen over oppkoblingspunkter for Windows nettverk-disker: tomt svar fra serveren",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Noen av de konfigurerte eksterne oppkoblingspunktene er ikke tilkoblet. Klikk på de røde raden(e) for mer informasjon.",
+ "Username" : "Brukernavn",
+ "Password" : "Passord",
"Access key" : "Tilgangsnøkkel",
"Secret key" : "Hemmelig nøkkel",
"Builtin" : "Innebygget",
@@ -52,8 +56,6 @@
"Client ID" : "Client ID",
"Client secret" : "Client secret",
"OpenStack" : "OpenStack",
- "Username" : "Brukernavn",
- "Password" : "Passord",
"Tenant name" : "Prosjektnavn",
"Identity endpoint URL" : "URL for identitets-endepunkt",
"Rackspace" : "Rackspace",
diff --git a/apps/files_external/l10n/nds.js b/apps/files_external/l10n/nds.js
index b4649fe681a..f86bc638795 100644
--- a/apps/files_external/l10n/nds.js
+++ b/apps/files_external/l10n/nds.js
@@ -32,6 +32,9 @@ OC.L10N.register(
"All users. Type to select user or group." : "Alle Benutzer. Tippe, um eine Benutzergruppe auszuwählen.",
"(group)" : "(Gruppe)",
"Saved" : "Gespeichert",
+ "Saving..." : "Speichern...",
+ "Username" : "Benutzername",
+ "Password" : "Passwort",
"Access key" : "Schlüssel für Zugriff",
"Secret key" : "Geheimer Schlüssel",
"Builtin" : "Eingebaut",
@@ -43,8 +46,6 @@ OC.L10N.register(
"Client ID" : "Client ID",
"Client secret" : "Client Geheimnis",
"OpenStack" : "OpenStack",
- "Username" : "Benutzername",
- "Password" : "Passwort",
"API key" : "API Schlüssel",
"Username and password" : "Benutzername und Passwort",
"RSA public key" : "Öffentlicher RSA Schlüssel",
diff --git a/apps/files_external/l10n/nds.json b/apps/files_external/l10n/nds.json
index 75e36016384..c22b072cdf5 100644
--- a/apps/files_external/l10n/nds.json
+++ b/apps/files_external/l10n/nds.json
@@ -30,6 +30,9 @@
"All users. Type to select user or group." : "Alle Benutzer. Tippe, um eine Benutzergruppe auszuwählen.",
"(group)" : "(Gruppe)",
"Saved" : "Gespeichert",
+ "Saving..." : "Speichern...",
+ "Username" : "Benutzername",
+ "Password" : "Passwort",
"Access key" : "Schlüssel für Zugriff",
"Secret key" : "Geheimer Schlüssel",
"Builtin" : "Eingebaut",
@@ -41,8 +44,6 @@
"Client ID" : "Client ID",
"Client secret" : "Client Geheimnis",
"OpenStack" : "OpenStack",
- "Username" : "Benutzername",
- "Password" : "Passwort",
"API key" : "API Schlüssel",
"Username and password" : "Benutzername und Passwort",
"RSA public key" : "Öffentlicher RSA Schlüssel",
diff --git a/apps/files_external/l10n/nl.js b/apps/files_external/l10n/nl.js
index a3f3ca9a566..72abc65499a 100644
--- a/apps/files_external/l10n/nl.js
+++ b/apps/files_external/l10n/nl.js
@@ -36,6 +36,8 @@ OC.L10N.register(
"(group)" : "(groep)",
"Admin defined" : "Beheerder gedefinieerd",
"Saved" : "Bewaard",
+ "Saving..." : "Opslaan",
+ "Save" : "Bewaren",
"Empty response from the server" : "Lege reactie van de server",
"Couldn't access. Please logout and login to activate this mount point" : "Geen toegang. Log uit en opnieuw in om dit koppelpunt te activeren",
"Couldn't get the information from the ownCloud server: {code} {type}" : "Kon geen informatie van de ownCloud server krijgen: {code} {type}",
@@ -44,6 +46,8 @@ OC.L10N.register(
"External mount error" : "Extern koppelpunt fout",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "Kon geen overzicht met Windows netwerk koppelpunten krijgen: lege reactie van de server",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Sommige van de geconfigureerde koppelpunten zijn niet verbonden. Klok op de rode rij(en) voor meer informatie",
+ "Username" : "Gebruikersnaam",
+ "Password" : "Wachtwoord",
"Access key" : "Access Key",
"Secret key" : "Geheime sleutel",
"Builtin" : "Ingebouwd",
@@ -55,8 +59,6 @@ OC.L10N.register(
"Client ID" : "Client ID",
"Client secret" : "Client secret",
"OpenStack" : "OpenStack",
- "Username" : "Gebruikersnaam",
- "Password" : "Wachtwoord",
"Tenant name" : "Naam tenant",
"Identity endpoint URL" : "Identiteiten endpoint URL",
"Rackspace" : "Rackspace",
diff --git a/apps/files_external/l10n/nl.json b/apps/files_external/l10n/nl.json
index 8654cdc662d..ebe92e038c9 100644
--- a/apps/files_external/l10n/nl.json
+++ b/apps/files_external/l10n/nl.json
@@ -34,6 +34,8 @@
"(group)" : "(groep)",
"Admin defined" : "Beheerder gedefinieerd",
"Saved" : "Bewaard",
+ "Saving..." : "Opslaan",
+ "Save" : "Bewaren",
"Empty response from the server" : "Lege reactie van de server",
"Couldn't access. Please logout and login to activate this mount point" : "Geen toegang. Log uit en opnieuw in om dit koppelpunt te activeren",
"Couldn't get the information from the ownCloud server: {code} {type}" : "Kon geen informatie van de ownCloud server krijgen: {code} {type}",
@@ -42,6 +44,8 @@
"External mount error" : "Extern koppelpunt fout",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "Kon geen overzicht met Windows netwerk koppelpunten krijgen: lege reactie van de server",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Sommige van de geconfigureerde koppelpunten zijn niet verbonden. Klok op de rode rij(en) voor meer informatie",
+ "Username" : "Gebruikersnaam",
+ "Password" : "Wachtwoord",
"Access key" : "Access Key",
"Secret key" : "Geheime sleutel",
"Builtin" : "Ingebouwd",
@@ -53,8 +57,6 @@
"Client ID" : "Client ID",
"Client secret" : "Client secret",
"OpenStack" : "OpenStack",
- "Username" : "Gebruikersnaam",
- "Password" : "Wachtwoord",
"Tenant name" : "Naam tenant",
"Identity endpoint URL" : "Identiteiten endpoint URL",
"Rackspace" : "Rackspace",
diff --git a/apps/files_external/l10n/nn_NO.js b/apps/files_external/l10n/nn_NO.js
index 325a8a57528..7d07e956688 100644
--- a/apps/files_external/l10n/nn_NO.js
+++ b/apps/files_external/l10n/nn_NO.js
@@ -2,6 +2,8 @@ OC.L10N.register(
"files_external",
{
"Personal" : "Personleg",
+ "Saving..." : "Lagrar …",
+ "Save" : "Lagra",
"Username" : "Brukarnamn",
"Password" : "Passord",
"Region" : "Region/fylke",
diff --git a/apps/files_external/l10n/nn_NO.json b/apps/files_external/l10n/nn_NO.json
index 26e6c02d806..46c27c8197f 100644
--- a/apps/files_external/l10n/nn_NO.json
+++ b/apps/files_external/l10n/nn_NO.json
@@ -1,5 +1,7 @@
{ "translations": {
"Personal" : "Personleg",
+ "Saving..." : "Lagrar …",
+ "Save" : "Lagra",
"Username" : "Brukarnamn",
"Password" : "Passord",
"Region" : "Region/fylke",
diff --git a/apps/files_external/l10n/oc.js b/apps/files_external/l10n/oc.js
index 716326f1cae..a11b664fe5e 100644
--- a/apps/files_external/l10n/oc.js
+++ b/apps/files_external/l10n/oc.js
@@ -33,6 +33,10 @@ OC.L10N.register(
"All users. Type to select user or group." : "Totes los utilizaires. Clicatz aicí per restrénher.",
"(group)" : "(grop)",
"Saved" : "Enregistrat",
+ "Saving..." : "Enregistrament...",
+ "Save" : "Enregistrar",
+ "Username" : "Nom d'utilizaire",
+ "Password" : "Senhal",
"Access key" : "Clau d'accès",
"Secret key" : "Clau secreta",
"Builtin" : "Integrat",
@@ -44,8 +48,6 @@ OC.L10N.register(
"Client ID" : "ID Client",
"Client secret" : "Secret client",
"OpenStack" : "OpenStack",
- "Username" : "Nom d'utilizaire",
- "Password" : "Senhal",
"Tenant name" : "Tenant name",
"Identity endpoint URL" : "Identity endpoint URL",
"Rackspace" : "Rackspace",
diff --git a/apps/files_external/l10n/oc.json b/apps/files_external/l10n/oc.json
index bc882de1456..09c99f60adb 100644
--- a/apps/files_external/l10n/oc.json
+++ b/apps/files_external/l10n/oc.json
@@ -31,6 +31,10 @@
"All users. Type to select user or group." : "Totes los utilizaires. Clicatz aicí per restrénher.",
"(group)" : "(grop)",
"Saved" : "Enregistrat",
+ "Saving..." : "Enregistrament...",
+ "Save" : "Enregistrar",
+ "Username" : "Nom d'utilizaire",
+ "Password" : "Senhal",
"Access key" : "Clau d'accès",
"Secret key" : "Clau secreta",
"Builtin" : "Integrat",
@@ -42,8 +46,6 @@
"Client ID" : "ID Client",
"Client secret" : "Secret client",
"OpenStack" : "OpenStack",
- "Username" : "Nom d'utilizaire",
- "Password" : "Senhal",
"Tenant name" : "Tenant name",
"Identity endpoint URL" : "Identity endpoint URL",
"Rackspace" : "Rackspace",
diff --git a/apps/files_external/l10n/pa.js b/apps/files_external/l10n/pa.js
index ff376198ae4..5a2de008d1e 100644
--- a/apps/files_external/l10n/pa.js
+++ b/apps/files_external/l10n/pa.js
@@ -1,6 +1,7 @@
OC.L10N.register(
"files_external",
{
+ "Saving..." : "...ਸੰਭਾਲਿਆ ਜਾ ਰਿਹਾ ਹੈ",
"Username" : "ਯੂਜ਼ਰ-ਨਾਂ",
"Password" : "ਪਾਸਵਰ",
"ownCloud" : "ਓਵਨਕਲਾਉਡ",
diff --git a/apps/files_external/l10n/pa.json b/apps/files_external/l10n/pa.json
index a2ba80af130..4814737ab5a 100644
--- a/apps/files_external/l10n/pa.json
+++ b/apps/files_external/l10n/pa.json
@@ -1,4 +1,5 @@
{ "translations": {
+ "Saving..." : "...ਸੰਭਾਲਿਆ ਜਾ ਰਿਹਾ ਹੈ",
"Username" : "ਯੂਜ਼ਰ-ਨਾਂ",
"Password" : "ਪਾਸਵਰ",
"ownCloud" : "ਓਵਨਕਲਾਉਡ",
diff --git a/apps/files_external/l10n/pl.js b/apps/files_external/l10n/pl.js
index 523a913d1f2..bf1bf642be2 100644
--- a/apps/files_external/l10n/pl.js
+++ b/apps/files_external/l10n/pl.js
@@ -21,13 +21,15 @@ OC.L10N.register(
"All users. Type to select user or group." : "Wszyscy użytkownicy. Zacznij pisać, aby wybrać użytkownika lub grupę.",
"(group)" : "(grupa)",
"Saved" : "Zapisano",
+ "Saving..." : "Zapisywanie...",
+ "Save" : "Zapisz",
+ "Username" : "Nazwa użytkownika",
+ "Password" : "Hasło",
"None" : "Nic",
"App key" : "Klucz aplikacji",
"App secret" : "Hasło aplikacji",
"Client ID" : "ID klienta",
"Client secret" : "Hasło klienta",
- "Username" : "Nazwa użytkownika",
- "Password" : "Hasło",
"API key" : "Klucz API",
"Public key" : "Klucz publiczny",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/pl.json b/apps/files_external/l10n/pl.json
index 25d379cc730..2d77bdca9ee 100644
--- a/apps/files_external/l10n/pl.json
+++ b/apps/files_external/l10n/pl.json
@@ -19,13 +19,15 @@
"All users. Type to select user or group." : "Wszyscy użytkownicy. Zacznij pisać, aby wybrać użytkownika lub grupę.",
"(group)" : "(grupa)",
"Saved" : "Zapisano",
+ "Saving..." : "Zapisywanie...",
+ "Save" : "Zapisz",
+ "Username" : "Nazwa użytkownika",
+ "Password" : "Hasło",
"None" : "Nic",
"App key" : "Klucz aplikacji",
"App secret" : "Hasło aplikacji",
"Client ID" : "ID klienta",
"Client secret" : "Hasło klienta",
- "Username" : "Nazwa użytkownika",
- "Password" : "Hasło",
"API key" : "Klucz API",
"Public key" : "Klucz publiczny",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/pt_BR.js b/apps/files_external/l10n/pt_BR.js
index 283b9478577..8706a554d1e 100644
--- a/apps/files_external/l10n/pt_BR.js
+++ b/apps/files_external/l10n/pt_BR.js
@@ -29,6 +29,7 @@ OC.L10N.register(
"Error generating key pair" : "Erro ao gerar um par de chaves",
"Enable encryption" : "Ativar criptografia",
"Enable previews" : "Habilitar visualizações prévias",
+ "Enable sharing" : "Habilitar compartilhamento",
"Check for changes" : "Verifique se há alterações",
"Never" : "Nunca",
"Once every direct access" : "Uma vez a cada acesso direto",
@@ -36,6 +37,8 @@ OC.L10N.register(
"(group)" : "(grupo)",
"Admin defined" : "Definido pelo administrador",
"Saved" : "Salvo",
+ "Saving..." : "Salvando...",
+ "Save" : "Salvar",
"Empty response from the server" : "Resposta vazia a partir do servidor",
"Couldn't access. Please logout and login to activate this mount point" : "Não foi possível acessar. Por favor, desconectar e conectar novamente para ativar este ponto de montagem",
"Couldn't get the information from the ownCloud server: {code} {type}" : "Não foi possível obter as informações do servidor ownCloud: {code} {type}",
@@ -44,6 +47,8 @@ OC.L10N.register(
"External mount error" : "Erro de montagem externa",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "Não foi possível obter a lista unidades de pontos de montagem da rede do Windows: resposta vazia a partir do servidor",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Alguns dos pontos de montagem externos configurados não estão conectados. Por favor clique na linha vermelha(s) para mais informações",
+ "Username" : "Nome de Usuário",
+ "Password" : "Senha",
"Access key" : "Chave da acesso",
"Secret key" : "Chave secreta",
"Builtin" : "Construídas em",
@@ -55,13 +60,15 @@ OC.L10N.register(
"Client ID" : "ID do Cliente",
"Client secret" : "Segredo do cliente",
"OpenStack" : "OpenStack",
- "Username" : "Nome de Usuário",
- "Password" : "Senha",
"Tenant name" : "Nome do inquilino",
"Identity endpoint URL" : "Identidade pontofinal URL",
"Rackspace" : "Espaço em rack",
"API key" : "Chave API",
+ "Global Credentails" : "Credenciais Globais",
+ "Log-in credentials, save in database" : "Credenciais de login, salvos no banco de dados",
"Username and password" : "Nome de Usuário e senha",
+ "Log-in credentials, save in session" : "Credenciais de login, guardados em sessão",
+ "User entered, store in database" : "Usuário digitou, armazenar em banco de dados",
"RSA public key" : "Chave pública RSA",
"Public key" : "Chave pública",
"Amazon S3" : "Amazon S3",
@@ -104,6 +111,7 @@ OC.L10N.register(
"Storage type" : "Tipo de armazenamento",
"Scope" : "Escopo",
"External Storage" : "Armazenamento Externo",
+ "Global Credentials" : "Credenciais Globais",
"Folder name" : "Nome da pasta",
"Authentication" : "Autenticação",
"Configuration" : "Configuração",
diff --git a/apps/files_external/l10n/pt_BR.json b/apps/files_external/l10n/pt_BR.json
index f1d97e6cf4a..9cdbf5d7a11 100644
--- a/apps/files_external/l10n/pt_BR.json
+++ b/apps/files_external/l10n/pt_BR.json
@@ -27,6 +27,7 @@
"Error generating key pair" : "Erro ao gerar um par de chaves",
"Enable encryption" : "Ativar criptografia",
"Enable previews" : "Habilitar visualizações prévias",
+ "Enable sharing" : "Habilitar compartilhamento",
"Check for changes" : "Verifique se há alterações",
"Never" : "Nunca",
"Once every direct access" : "Uma vez a cada acesso direto",
@@ -34,6 +35,8 @@
"(group)" : "(grupo)",
"Admin defined" : "Definido pelo administrador",
"Saved" : "Salvo",
+ "Saving..." : "Salvando...",
+ "Save" : "Salvar",
"Empty response from the server" : "Resposta vazia a partir do servidor",
"Couldn't access. Please logout and login to activate this mount point" : "Não foi possível acessar. Por favor, desconectar e conectar novamente para ativar este ponto de montagem",
"Couldn't get the information from the ownCloud server: {code} {type}" : "Não foi possível obter as informações do servidor ownCloud: {code} {type}",
@@ -42,6 +45,8 @@
"External mount error" : "Erro de montagem externa",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "Não foi possível obter a lista unidades de pontos de montagem da rede do Windows: resposta vazia a partir do servidor",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Alguns dos pontos de montagem externos configurados não estão conectados. Por favor clique na linha vermelha(s) para mais informações",
+ "Username" : "Nome de Usuário",
+ "Password" : "Senha",
"Access key" : "Chave da acesso",
"Secret key" : "Chave secreta",
"Builtin" : "Construídas em",
@@ -53,13 +58,15 @@
"Client ID" : "ID do Cliente",
"Client secret" : "Segredo do cliente",
"OpenStack" : "OpenStack",
- "Username" : "Nome de Usuário",
- "Password" : "Senha",
"Tenant name" : "Nome do inquilino",
"Identity endpoint URL" : "Identidade pontofinal URL",
"Rackspace" : "Espaço em rack",
"API key" : "Chave API",
+ "Global Credentails" : "Credenciais Globais",
+ "Log-in credentials, save in database" : "Credenciais de login, salvos no banco de dados",
"Username and password" : "Nome de Usuário e senha",
+ "Log-in credentials, save in session" : "Credenciais de login, guardados em sessão",
+ "User entered, store in database" : "Usuário digitou, armazenar em banco de dados",
"RSA public key" : "Chave pública RSA",
"Public key" : "Chave pública",
"Amazon S3" : "Amazon S3",
@@ -102,6 +109,7 @@
"Storage type" : "Tipo de armazenamento",
"Scope" : "Escopo",
"External Storage" : "Armazenamento Externo",
+ "Global Credentials" : "Credenciais Globais",
"Folder name" : "Nome da pasta",
"Authentication" : "Autenticação",
"Configuration" : "Configuração",
diff --git a/apps/files_external/l10n/pt_PT.js b/apps/files_external/l10n/pt_PT.js
index b84c399e34d..2286df56c9f 100644
--- a/apps/files_external/l10n/pt_PT.js
+++ b/apps/files_external/l10n/pt_PT.js
@@ -29,6 +29,7 @@ OC.L10N.register(
"Error generating key pair" : "Erro ao gerar chave par",
"Enable encryption" : "Ative a encriptação",
"Enable previews" : "Ative as pré-visualizações",
+ "Enable sharing" : "Ativar partilha",
"Check for changes" : "Verifique as suas alterações",
"Never" : "Nunca",
"Once every direct access" : "Uma vez em cada acesso direto",
@@ -36,6 +37,8 @@ OC.L10N.register(
"(group)" : "(grupo)",
"Admin defined" : "Administrador definido",
"Saved" : "Guardado",
+ "Saving..." : "A guardar...",
+ "Save" : "Guardar",
"Empty response from the server" : "Resposta vazia a partir do servidor",
"Couldn't access. Please logout and login to activate this mount point" : "Não foi possível aceder. Por favor, faça logout e login para ativar este ponto de montagem",
"Couldn't get the information from the ownCloud server: {code} {type}" : "Não foi possível recolher a informação do servidor ownCloud: {code} {type}",
@@ -44,6 +47,8 @@ OC.L10N.register(
"External mount error" : "Erro de montagem externa",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "Não foi possível conseguir a lista de pontos de montagem Windows na rede: resposta vazia do servidor",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Alguns dos pontos de montagem externos configurados não estão conectados. Por favor, clique na fila vermelha para mais informação",
+ "Username" : "Nome de utilizador",
+ "Password" : "Palavra-passe",
"Access key" : "Código de acesso",
"Secret key" : "Código secreto",
"Builtin" : "Integrado",
@@ -55,12 +60,11 @@ OC.L10N.register(
"Client ID" : "Id. do Cliente",
"Client secret" : "Segredo do cliente\\\\",
"OpenStack" : "OpenStack",
- "Username" : "Nome de utilizador",
- "Password" : "Palavra-passe",
"Tenant name" : "Nome do locatário",
"Identity endpoint URL" : "Identidade URL endpoint",
"Rackspace" : "Rackspace",
"API key" : "Chave API",
+ "Global Credentails" : "Credenciais Gerais",
"Log-in credentials, save in database" : "Credenciais de login, guardar na base de dados",
"Username and password" : "Nome de utilizador e palavra-passe",
"Log-in credentials, save in session" : "Credenciais de login, guardar na sessão",
@@ -107,6 +111,7 @@ OC.L10N.register(
"Storage type" : "Tipo de Armazenamento",
"Scope" : "Âmbito",
"External Storage" : "Armazenamento Externo",
+ "Global Credentials" : "Credenciais Gerais",
"Folder name" : "Nome da pasta",
"Authentication" : "Autenticação",
"Configuration" : "Configuração",
diff --git a/apps/files_external/l10n/pt_PT.json b/apps/files_external/l10n/pt_PT.json
index ac65ca7744f..84e92ef4271 100644
--- a/apps/files_external/l10n/pt_PT.json
+++ b/apps/files_external/l10n/pt_PT.json
@@ -27,6 +27,7 @@
"Error generating key pair" : "Erro ao gerar chave par",
"Enable encryption" : "Ative a encriptação",
"Enable previews" : "Ative as pré-visualizações",
+ "Enable sharing" : "Ativar partilha",
"Check for changes" : "Verifique as suas alterações",
"Never" : "Nunca",
"Once every direct access" : "Uma vez em cada acesso direto",
@@ -34,6 +35,8 @@
"(group)" : "(grupo)",
"Admin defined" : "Administrador definido",
"Saved" : "Guardado",
+ "Saving..." : "A guardar...",
+ "Save" : "Guardar",
"Empty response from the server" : "Resposta vazia a partir do servidor",
"Couldn't access. Please logout and login to activate this mount point" : "Não foi possível aceder. Por favor, faça logout e login para ativar este ponto de montagem",
"Couldn't get the information from the ownCloud server: {code} {type}" : "Não foi possível recolher a informação do servidor ownCloud: {code} {type}",
@@ -42,6 +45,8 @@
"External mount error" : "Erro de montagem externa",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "Não foi possível conseguir a lista de pontos de montagem Windows na rede: resposta vazia do servidor",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Alguns dos pontos de montagem externos configurados não estão conectados. Por favor, clique na fila vermelha para mais informação",
+ "Username" : "Nome de utilizador",
+ "Password" : "Palavra-passe",
"Access key" : "Código de acesso",
"Secret key" : "Código secreto",
"Builtin" : "Integrado",
@@ -53,12 +58,11 @@
"Client ID" : "Id. do Cliente",
"Client secret" : "Segredo do cliente\\\\",
"OpenStack" : "OpenStack",
- "Username" : "Nome de utilizador",
- "Password" : "Palavra-passe",
"Tenant name" : "Nome do locatário",
"Identity endpoint URL" : "Identidade URL endpoint",
"Rackspace" : "Rackspace",
"API key" : "Chave API",
+ "Global Credentails" : "Credenciais Gerais",
"Log-in credentials, save in database" : "Credenciais de login, guardar na base de dados",
"Username and password" : "Nome de utilizador e palavra-passe",
"Log-in credentials, save in session" : "Credenciais de login, guardar na sessão",
@@ -105,6 +109,7 @@
"Storage type" : "Tipo de Armazenamento",
"Scope" : "Âmbito",
"External Storage" : "Armazenamento Externo",
+ "Global Credentials" : "Credenciais Gerais",
"Folder name" : "Nome da pasta",
"Authentication" : "Autenticação",
"Configuration" : "Configuração",
diff --git a/apps/files_external/l10n/ro.js b/apps/files_external/l10n/ro.js
index cc3a065a21d..636ba958cb5 100644
--- a/apps/files_external/l10n/ro.js
+++ b/apps/files_external/l10n/ro.js
@@ -6,9 +6,11 @@ OC.L10N.register(
"Grant access" : "Permite accesul",
"Access granted" : "Acces permis",
"Saved" : "Salvat",
- "None" : "Niciuna",
+ "Saving..." : "Se salvează...",
+ "Save" : "Salvează",
"Username" : "Nume utilizator",
"Password" : "Parolă",
+ "None" : "Niciuna",
"API key" : "Cheie API",
"Public key" : "Cheie publică",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/ro.json b/apps/files_external/l10n/ro.json
index 2f1f8e32883..7cff0ef5521 100644
--- a/apps/files_external/l10n/ro.json
+++ b/apps/files_external/l10n/ro.json
@@ -4,9 +4,11 @@
"Grant access" : "Permite accesul",
"Access granted" : "Acces permis",
"Saved" : "Salvat",
- "None" : "Niciuna",
+ "Saving..." : "Se salvează...",
+ "Save" : "Salvează",
"Username" : "Nume utilizator",
"Password" : "Parolă",
+ "None" : "Niciuna",
"API key" : "Cheie API",
"Public key" : "Cheie publică",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/ru.js b/apps/files_external/l10n/ru.js
index ceae42c7942..e0f55115d97 100644
--- a/apps/files_external/l10n/ru.js
+++ b/apps/files_external/l10n/ru.js
@@ -29,6 +29,7 @@ OC.L10N.register(
"Error generating key pair" : "Ошибка создания ключевой пары",
"Enable encryption" : "Включить шифрование",
"Enable previews" : "Включить предпросмотр",
+ "Enable sharing" : "Включить общий доступ",
"Check for changes" : "Проверять изменения",
"Never" : "Никогда",
"Once every direct access" : "Один раз при прямом доступе",
@@ -36,6 +37,8 @@ OC.L10N.register(
"(group)" : "(группа)",
"Admin defined" : "Админ определен",
"Saved" : "Сохранено",
+ "Saving..." : "Сохранение...",
+ "Save" : "Сохранить",
"Empty response from the server" : "Пустой ответ от сервера",
"Couldn't access. Please logout and login to activate this mount point" : "Не удалось получить доступ. Пожалуйста, выйти и войдите чтобы активировать эту точку монтирования",
"Couldn't get the information from the ownCloud server: {code} {type}" : "Не удалось получить информацию от сервера OwnCloud: {code} {type}",
@@ -44,6 +47,8 @@ OC.L10N.register(
"External mount error" : "Ошибка внешнего монтажа",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "Не удалось получить список окон сетевого диска точки монтирования: пустой ответ от сервера",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Некоторые из настроенных внешних точек монтирования не подключены. Для получения дополнительной информации, пожалуйста нажмите на красную строку (ы)",
+ "Username" : "Имя пользователя",
+ "Password" : "Пароль",
"Access key" : "Ключ доступа",
"Secret key" : "Секретный ключ",
"Builtin" : "Встроенный",
@@ -55,8 +60,6 @@ OC.L10N.register(
"Client ID" : "Идентификатор клиента",
"Client secret" : "Клиентский ключ ",
"OpenStack" : "OpenStack",
- "Username" : "Имя пользователя",
- "Password" : "Пароль",
"Tenant name" : "Имя арендатора",
"Identity endpoint URL" : "Удостоверение конечной точки URL",
"Rackspace" : "Rackspace",
diff --git a/apps/files_external/l10n/ru.json b/apps/files_external/l10n/ru.json
index d0dab706ea9..eda8da90aca 100644
--- a/apps/files_external/l10n/ru.json
+++ b/apps/files_external/l10n/ru.json
@@ -27,6 +27,7 @@
"Error generating key pair" : "Ошибка создания ключевой пары",
"Enable encryption" : "Включить шифрование",
"Enable previews" : "Включить предпросмотр",
+ "Enable sharing" : "Включить общий доступ",
"Check for changes" : "Проверять изменения",
"Never" : "Никогда",
"Once every direct access" : "Один раз при прямом доступе",
@@ -34,6 +35,8 @@
"(group)" : "(группа)",
"Admin defined" : "Админ определен",
"Saved" : "Сохранено",
+ "Saving..." : "Сохранение...",
+ "Save" : "Сохранить",
"Empty response from the server" : "Пустой ответ от сервера",
"Couldn't access. Please logout and login to activate this mount point" : "Не удалось получить доступ. Пожалуйста, выйти и войдите чтобы активировать эту точку монтирования",
"Couldn't get the information from the ownCloud server: {code} {type}" : "Не удалось получить информацию от сервера OwnCloud: {code} {type}",
@@ -42,6 +45,8 @@
"External mount error" : "Ошибка внешнего монтажа",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "Не удалось получить список окон сетевого диска точки монтирования: пустой ответ от сервера",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Некоторые из настроенных внешних точек монтирования не подключены. Для получения дополнительной информации, пожалуйста нажмите на красную строку (ы)",
+ "Username" : "Имя пользователя",
+ "Password" : "Пароль",
"Access key" : "Ключ доступа",
"Secret key" : "Секретный ключ",
"Builtin" : "Встроенный",
@@ -53,8 +58,6 @@
"Client ID" : "Идентификатор клиента",
"Client secret" : "Клиентский ключ ",
"OpenStack" : "OpenStack",
- "Username" : "Имя пользователя",
- "Password" : "Пароль",
"Tenant name" : "Имя арендатора",
"Identity endpoint URL" : "Удостоверение конечной точки URL",
"Rackspace" : "Rackspace",
diff --git a/apps/files_external/l10n/si_LK.js b/apps/files_external/l10n/si_LK.js
index 82b68af82eb..0cfb795d78c 100644
--- a/apps/files_external/l10n/si_LK.js
+++ b/apps/files_external/l10n/si_LK.js
@@ -4,9 +4,11 @@ OC.L10N.register(
"Personal" : "පෞද්ගලික",
"Grant access" : "පිවිසුම ලබාදෙන්න",
"Access granted" : "පිවිසීමට හැක",
- "None" : "කිසිවක් නැත",
+ "Saving..." : "සුරැකෙමින් පවතී...",
+ "Save" : "සුරකින්න",
"Username" : "පරිශීලක නම",
"Password" : "මුර පදය",
+ "None" : "කිසිවක් නැත",
"Port" : "තොට",
"Region" : "කළාපය",
"URL" : "URL",
diff --git a/apps/files_external/l10n/si_LK.json b/apps/files_external/l10n/si_LK.json
index 2150ac0f9b2..d93df685e77 100644
--- a/apps/files_external/l10n/si_LK.json
+++ b/apps/files_external/l10n/si_LK.json
@@ -2,9 +2,11 @@
"Personal" : "පෞද්ගලික",
"Grant access" : "පිවිසුම ලබාදෙන්න",
"Access granted" : "පිවිසීමට හැක",
- "None" : "කිසිවක් නැත",
+ "Saving..." : "සුරැකෙමින් පවතී...",
+ "Save" : "සුරකින්න",
"Username" : "පරිශීලක නම",
"Password" : "මුර පදය",
+ "None" : "කිසිවක් නැත",
"Port" : "තොට",
"Region" : "කළාපය",
"URL" : "URL",
diff --git a/apps/files_external/l10n/sk_SK.js b/apps/files_external/l10n/sk_SK.js
index 72fb57a1e0b..af390cf579f 100644
--- a/apps/files_external/l10n/sk_SK.js
+++ b/apps/files_external/l10n/sk_SK.js
@@ -32,6 +32,10 @@ OC.L10N.register(
"All users. Type to select user or group." : "Všetci používatelia. Začnite písať pre výber používateľa alebo skupinu.",
"(group)" : "(skupina)",
"Saved" : "Uložené",
+ "Saving..." : "Ukladám...",
+ "Save" : "Uložiť",
+ "Username" : "Používateľské meno",
+ "Password" : "Heslo",
"Access key" : "Prístupový kľúč",
"Secret key" : "Tajný kľúč",
"Builtin" : "Vstavaný",
@@ -43,8 +47,6 @@ OC.L10N.register(
"Client ID" : "Client ID",
"Client secret" : "Heslo klienta",
"OpenStack" : "OpenStack",
- "Username" : "Používateľské meno",
- "Password" : "Heslo",
"Tenant name" : "Meno nájomcu",
"Identity endpoint URL" : "Endpoint URL identita",
"Rackspace" : "Rackspace",
diff --git a/apps/files_external/l10n/sk_SK.json b/apps/files_external/l10n/sk_SK.json
index 267eb5b48b9..ff677233a9f 100644
--- a/apps/files_external/l10n/sk_SK.json
+++ b/apps/files_external/l10n/sk_SK.json
@@ -30,6 +30,10 @@
"All users. Type to select user or group." : "Všetci používatelia. Začnite písať pre výber používateľa alebo skupinu.",
"(group)" : "(skupina)",
"Saved" : "Uložené",
+ "Saving..." : "Ukladám...",
+ "Save" : "Uložiť",
+ "Username" : "Používateľské meno",
+ "Password" : "Heslo",
"Access key" : "Prístupový kľúč",
"Secret key" : "Tajný kľúč",
"Builtin" : "Vstavaný",
@@ -41,8 +45,6 @@
"Client ID" : "Client ID",
"Client secret" : "Heslo klienta",
"OpenStack" : "OpenStack",
- "Username" : "Používateľské meno",
- "Password" : "Heslo",
"Tenant name" : "Meno nájomcu",
"Identity endpoint URL" : "Endpoint URL identita",
"Rackspace" : "Rackspace",
diff --git a/apps/files_external/l10n/sl.js b/apps/files_external/l10n/sl.js
index 62b35ffab5e..807c6c82693 100644
--- a/apps/files_external/l10n/sl.js
+++ b/apps/files_external/l10n/sl.js
@@ -25,7 +25,11 @@ OC.L10N.register(
"All users. Type to select user or group." : "Vsi uporabniki. Skupino ali uporabnika je mogoče tudi izbrati.",
"(group)" : "(skupina)",
"Saved" : "Shranjeno",
+ "Saving..." : "Poteka shranjevanje ...",
+ "Save" : "Shrani",
"External mount error" : "Notranja napaka priklopa",
+ "Username" : "Uporabniško ime",
+ "Password" : "Geslo",
"Access key" : "Ključ za dostop",
"Secret key" : "Skriti ključ",
"Builtin" : "Vgrajeno",
@@ -37,8 +41,6 @@ OC.L10N.register(
"Client ID" : "ID odjemalca",
"Client secret" : "Skrivni ključ odjemalca",
"OpenStack" : "OpenStack",
- "Username" : "Uporabniško ime",
- "Password" : "Geslo",
"Tenant name" : "Ime uporabnika",
"API key" : "Ključ API",
"Username and password" : "Uporabniško ime in geslo",
diff --git a/apps/files_external/l10n/sl.json b/apps/files_external/l10n/sl.json
index 3a806fbd25b..42739bc315c 100644
--- a/apps/files_external/l10n/sl.json
+++ b/apps/files_external/l10n/sl.json
@@ -23,7 +23,11 @@
"All users. Type to select user or group." : "Vsi uporabniki. Skupino ali uporabnika je mogoče tudi izbrati.",
"(group)" : "(skupina)",
"Saved" : "Shranjeno",
+ "Saving..." : "Poteka shranjevanje ...",
+ "Save" : "Shrani",
"External mount error" : "Notranja napaka priklopa",
+ "Username" : "Uporabniško ime",
+ "Password" : "Geslo",
"Access key" : "Ključ za dostop",
"Secret key" : "Skriti ključ",
"Builtin" : "Vgrajeno",
@@ -35,8 +39,6 @@
"Client ID" : "ID odjemalca",
"Client secret" : "Skrivni ključ odjemalca",
"OpenStack" : "OpenStack",
- "Username" : "Uporabniško ime",
- "Password" : "Geslo",
"Tenant name" : "Ime uporabnika",
"API key" : "Ključ API",
"Username and password" : "Uporabniško ime in geslo",
diff --git a/apps/files_external/l10n/sq.js b/apps/files_external/l10n/sq.js
index 5549657c448..68de47456cb 100644
--- a/apps/files_external/l10n/sq.js
+++ b/apps/files_external/l10n/sq.js
@@ -29,6 +29,7 @@ OC.L10N.register(
"Error generating key pair" : "Gabim gjatë prodhimit të çiftit të kyçeve",
"Enable encryption" : "Aktivizoni fshehtëzim",
"Enable previews" : "Aktivizoni paraparje",
+ "Enable sharing" : "Aktivizo ndarjet",
"Check for changes" : "Kontrollo për ndryshime",
"Never" : "Kurrë",
"Once every direct access" : "Çdo herë pas hyrjesh të drejtpërdrejta",
@@ -36,6 +37,8 @@ OC.L10N.register(
"(group)" : "(grup)",
"Admin defined" : "Përcaktuar nga përgjegjësi",
"Saved" : "U ruajt",
+ "Saving..." : "Po ruhet …",
+ "Save" : "Ruaje",
"Empty response from the server" : "Përgjigje e zbrazët prej shërbyesit",
"Couldn't access. Please logout and login to activate this mount point" : "S’fut dot. Ju lutemi, dilni dhe hyni që të aktivizohet kjo pikë montimi",
"Couldn't get the information from the ownCloud server: {code} {type}" : "S’u morën dot të dhëna nga shërbyesi ownCloud: {code} {type}",
@@ -44,6 +47,8 @@ OC.L10N.register(
"External mount error" : "Gabim i jashtëm montimi",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "S’u mor dot lista e pikave të montimit Windows network drive: përgjigje e zbrazët nga shërbyesi",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Disa nga pikat e jashtme të formësuara të montimit s’janë të lidhura. Ju lutemi, klikoni në shigjetën(at) e kuqe për më tepër të dhëna",
+ "Username" : "Emër përdoruesi",
+ "Password" : "Fjalëkalim",
"Access key" : "Kyç hyrjesh",
"Secret key" : "Kyç i fshehtë",
"Builtin" : "I brendshëm",
@@ -55,12 +60,14 @@ OC.L10N.register(
"Client ID" : "ID klienti",
"Client secret" : "E fshehtë klienti",
"OpenStack" : "OpenStack",
- "Username" : "Emër përdoruesi",
- "Password" : "Fjalëkalim",
"Tenant name" : "Emër qiraxhiu",
"Rackspace" : "Rackspace",
"API key" : "Kyç API",
+ "Global Credentails" : "Kredenciale Globale",
+ "Log-in credentials, save in database" : "Kredenciale hyrjesh, ruaje në bazën e të dhënave",
"Username and password" : "Emër përdoruesi dhe fjalëkalim",
+ "Log-in credentials, save in session" : "Kredenciale hyrjesh, ruaje në sesion",
+ "User entered, store in database" : "Përdoruesi u dha, ruajeni në bazën e të dhënave",
"RSA public key" : "Kyç publik RSA ",
"Public key" : "Kyç publik",
"Amazon S3" : "Amazon S3",
@@ -103,6 +110,7 @@ OC.L10N.register(
"Storage type" : "Lloj depozite",
"Scope" : "Shtrirje",
"External Storage" : "Depozitë e Jashtme",
+ "Global Credentials" : "Kredenciale Globale",
"Folder name" : "Emër dosjeje",
"Authentication" : "Mirëfilltësim",
"Configuration" : "Formësim",
diff --git a/apps/files_external/l10n/sq.json b/apps/files_external/l10n/sq.json
index 5176c5ded27..9ee9e8bb743 100644
--- a/apps/files_external/l10n/sq.json
+++ b/apps/files_external/l10n/sq.json
@@ -27,6 +27,7 @@
"Error generating key pair" : "Gabim gjatë prodhimit të çiftit të kyçeve",
"Enable encryption" : "Aktivizoni fshehtëzim",
"Enable previews" : "Aktivizoni paraparje",
+ "Enable sharing" : "Aktivizo ndarjet",
"Check for changes" : "Kontrollo për ndryshime",
"Never" : "Kurrë",
"Once every direct access" : "Çdo herë pas hyrjesh të drejtpërdrejta",
@@ -34,6 +35,8 @@
"(group)" : "(grup)",
"Admin defined" : "Përcaktuar nga përgjegjësi",
"Saved" : "U ruajt",
+ "Saving..." : "Po ruhet …",
+ "Save" : "Ruaje",
"Empty response from the server" : "Përgjigje e zbrazët prej shërbyesit",
"Couldn't access. Please logout and login to activate this mount point" : "S’fut dot. Ju lutemi, dilni dhe hyni që të aktivizohet kjo pikë montimi",
"Couldn't get the information from the ownCloud server: {code} {type}" : "S’u morën dot të dhëna nga shërbyesi ownCloud: {code} {type}",
@@ -42,6 +45,8 @@
"External mount error" : "Gabim i jashtëm montimi",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "S’u mor dot lista e pikave të montimit Windows network drive: përgjigje e zbrazët nga shërbyesi",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Disa nga pikat e jashtme të formësuara të montimit s’janë të lidhura. Ju lutemi, klikoni në shigjetën(at) e kuqe për më tepër të dhëna",
+ "Username" : "Emër përdoruesi",
+ "Password" : "Fjalëkalim",
"Access key" : "Kyç hyrjesh",
"Secret key" : "Kyç i fshehtë",
"Builtin" : "I brendshëm",
@@ -53,12 +58,14 @@
"Client ID" : "ID klienti",
"Client secret" : "E fshehtë klienti",
"OpenStack" : "OpenStack",
- "Username" : "Emër përdoruesi",
- "Password" : "Fjalëkalim",
"Tenant name" : "Emër qiraxhiu",
"Rackspace" : "Rackspace",
"API key" : "Kyç API",
+ "Global Credentails" : "Kredenciale Globale",
+ "Log-in credentials, save in database" : "Kredenciale hyrjesh, ruaje në bazën e të dhënave",
"Username and password" : "Emër përdoruesi dhe fjalëkalim",
+ "Log-in credentials, save in session" : "Kredenciale hyrjesh, ruaje në sesion",
+ "User entered, store in database" : "Përdoruesi u dha, ruajeni në bazën e të dhënave",
"RSA public key" : "Kyç publik RSA ",
"Public key" : "Kyç publik",
"Amazon S3" : "Amazon S3",
@@ -101,6 +108,7 @@
"Storage type" : "Lloj depozite",
"Scope" : "Shtrirje",
"External Storage" : "Depozitë e Jashtme",
+ "Global Credentials" : "Kredenciale Globale",
"Folder name" : "Emër dosjeje",
"Authentication" : "Mirëfilltësim",
"Configuration" : "Formësim",
diff --git a/apps/files_external/l10n/sr.js b/apps/files_external/l10n/sr.js
index a90d36b586f..0600f747509 100644
--- a/apps/files_external/l10n/sr.js
+++ b/apps/files_external/l10n/sr.js
@@ -21,13 +21,15 @@ OC.L10N.register(
"All users. Type to select user or group." : "Сви корисници. Куцајте за избор корисника или групе.",
"(group)" : "(група)",
"Saved" : "Сачувано",
+ "Saving..." : "Уписујем...",
+ "Save" : "Сачувај",
+ "Username" : "Корисничко име",
+ "Password" : "Лозинка",
"None" : "Ништа",
"App key" : "Кључ апликације",
"App secret" : "Тајна апликације",
"Client ID" : "ИД клијента",
"Client secret" : "Тајна клијента",
- "Username" : "Корисничко име",
- "Password" : "Лозинка",
"API key" : "API кључ",
"Public key" : "Јавни кључ",
"Amazon S3" : "Амазон С3",
diff --git a/apps/files_external/l10n/sr.json b/apps/files_external/l10n/sr.json
index 6c938e8a14c..aa8471447df 100644
--- a/apps/files_external/l10n/sr.json
+++ b/apps/files_external/l10n/sr.json
@@ -19,13 +19,15 @@
"All users. Type to select user or group." : "Сви корисници. Куцајте за избор корисника или групе.",
"(group)" : "(група)",
"Saved" : "Сачувано",
+ "Saving..." : "Уписујем...",
+ "Save" : "Сачувај",
+ "Username" : "Корисничко име",
+ "Password" : "Лозинка",
"None" : "Ништа",
"App key" : "Кључ апликације",
"App secret" : "Тајна апликације",
"Client ID" : "ИД клијента",
"Client secret" : "Тајна клијента",
- "Username" : "Корисничко име",
- "Password" : "Лозинка",
"API key" : "API кључ",
"Public key" : "Јавни кључ",
"Amazon S3" : "Амазон С3",
diff --git a/apps/files_external/l10n/sr@latin.js b/apps/files_external/l10n/sr@latin.js
index 0420189571c..3f73fd420ed 100644
--- a/apps/files_external/l10n/sr@latin.js
+++ b/apps/files_external/l10n/sr@latin.js
@@ -11,12 +11,14 @@ OC.L10N.register(
"All users. Type to select user or group." : "Svi korisnici. Kucajte da biste izabrali korisnika ili grupu.",
"(group)" : "(grupa)",
"Saved" : "Sačuvano",
+ "Saving..." : "Upisujem...",
+ "Save" : "Sačuvaj",
+ "Username" : "Korisničko ime",
+ "Password" : "Lozinka",
"App key" : "Ključ Aplikacije",
"App secret" : "Tajna lozinka Aplikacije",
"Client ID" : "Identifikator klijenta",
"Client secret" : "Tajna lozinka klijenta",
- "Username" : "Korisničko ime",
- "Password" : "Lozinka",
"Amazon S3" : "Amazon S3",
"Bucket" : "Korpa",
"Hostname" : "Ime računara",
diff --git a/apps/files_external/l10n/sr@latin.json b/apps/files_external/l10n/sr@latin.json
index 3320ab2c863..92df9c7146b 100644
--- a/apps/files_external/l10n/sr@latin.json
+++ b/apps/files_external/l10n/sr@latin.json
@@ -9,12 +9,14 @@
"All users. Type to select user or group." : "Svi korisnici. Kucajte da biste izabrali korisnika ili grupu.",
"(group)" : "(grupa)",
"Saved" : "Sačuvano",
+ "Saving..." : "Upisujem...",
+ "Save" : "Sačuvaj",
+ "Username" : "Korisničko ime",
+ "Password" : "Lozinka",
"App key" : "Ključ Aplikacije",
"App secret" : "Tajna lozinka Aplikacije",
"Client ID" : "Identifikator klijenta",
"Client secret" : "Tajna lozinka klijenta",
- "Username" : "Korisničko ime",
- "Password" : "Lozinka",
"Amazon S3" : "Amazon S3",
"Bucket" : "Korpa",
"Hostname" : "Ime računara",
diff --git a/apps/files_external/l10n/sv.js b/apps/files_external/l10n/sv.js
index f20b96caed8..76da77967db 100644
--- a/apps/files_external/l10n/sv.js
+++ b/apps/files_external/l10n/sv.js
@@ -11,13 +11,15 @@ OC.L10N.register(
"All users. Type to select user or group." : "Alla användare. Skriv för att välja användare eller grupp.",
"(group)" : "(grupp)",
"Saved" : "Sparad",
+ "Saving..." : "Sparar...",
+ "Save" : "Spara",
+ "Username" : "Användarnamn",
+ "Password" : "Lösenord",
"None" : "Ingen",
"App key" : "App-nyckel",
"App secret" : "App-hemlighet",
"Client ID" : "Klient ID",
"Client secret" : "klient secret",
- "Username" : "Användarnamn",
- "Password" : "Lösenord",
"API key" : "API-nyckel",
"Public key" : "Publik nyckel",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/sv.json b/apps/files_external/l10n/sv.json
index cd3dc13296d..6f5d4dfe3aa 100644
--- a/apps/files_external/l10n/sv.json
+++ b/apps/files_external/l10n/sv.json
@@ -9,13 +9,15 @@
"All users. Type to select user or group." : "Alla användare. Skriv för att välja användare eller grupp.",
"(group)" : "(grupp)",
"Saved" : "Sparad",
+ "Saving..." : "Sparar...",
+ "Save" : "Spara",
+ "Username" : "Användarnamn",
+ "Password" : "Lösenord",
"None" : "Ingen",
"App key" : "App-nyckel",
"App secret" : "App-hemlighet",
"Client ID" : "Klient ID",
"Client secret" : "klient secret",
- "Username" : "Användarnamn",
- "Password" : "Lösenord",
"API key" : "API-nyckel",
"Public key" : "Publik nyckel",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/ta_LK.js b/apps/files_external/l10n/ta_LK.js
index 8ab0f6d513c..87f2dabd7ce 100644
--- a/apps/files_external/l10n/ta_LK.js
+++ b/apps/files_external/l10n/ta_LK.js
@@ -4,9 +4,11 @@ OC.L10N.register(
"Personal" : "தனிப்பட்ட",
"Grant access" : "அனுமதியை வழங்கல்",
"Access granted" : "அனுமதி வழங்கப்பட்டது",
- "None" : "ஒன்றுமில்லை",
+ "Saving..." : "சேமிக்கப்படுகிறது...",
+ "Save" : "சேமிக்க ",
"Username" : "பயனாளர் பெயர்",
"Password" : "கடவுச்சொல்",
+ "None" : "ஒன்றுமில்லை",
"Port" : "துறை ",
"Region" : "பிரதேசம்",
"URL" : "URL",
diff --git a/apps/files_external/l10n/ta_LK.json b/apps/files_external/l10n/ta_LK.json
index dd1c1003728..00959a601b1 100644
--- a/apps/files_external/l10n/ta_LK.json
+++ b/apps/files_external/l10n/ta_LK.json
@@ -2,9 +2,11 @@
"Personal" : "தனிப்பட்ட",
"Grant access" : "அனுமதியை வழங்கல்",
"Access granted" : "அனுமதி வழங்கப்பட்டது",
- "None" : "ஒன்றுமில்லை",
+ "Saving..." : "சேமிக்கப்படுகிறது...",
+ "Save" : "சேமிக்க ",
"Username" : "பயனாளர் பெயர்",
"Password" : "கடவுச்சொல்",
+ "None" : "ஒன்றுமில்லை",
"Port" : "துறை ",
"Region" : "பிரதேசம்",
"URL" : "URL",
diff --git a/apps/files_external/l10n/te.js b/apps/files_external/l10n/te.js
index 155676d9a8f..4c05e915da4 100644
--- a/apps/files_external/l10n/te.js
+++ b/apps/files_external/l10n/te.js
@@ -2,6 +2,7 @@ OC.L10N.register(
"files_external",
{
"Personal" : "వ్యక్తిగతం",
+ "Save" : "భద్రపరచు",
"Username" : "వాడుకరి పేరు",
"Password" : "సంకేతపదం",
"Name" : "పేరు",
diff --git a/apps/files_external/l10n/te.json b/apps/files_external/l10n/te.json
index 5a55f60376a..493efe033f7 100644
--- a/apps/files_external/l10n/te.json
+++ b/apps/files_external/l10n/te.json
@@ -1,5 +1,6 @@
{ "translations": {
"Personal" : "వ్యక్తిగతం",
+ "Save" : "భద్రపరచు",
"Username" : "వాడుకరి పేరు",
"Password" : "సంకేతపదం",
"Name" : "పేరు",
diff --git a/apps/files_external/l10n/th_TH.js b/apps/files_external/l10n/th_TH.js
index 31993619cae..e8f3aa3aaec 100644
--- a/apps/files_external/l10n/th_TH.js
+++ b/apps/files_external/l10n/th_TH.js
@@ -18,6 +18,7 @@ OC.L10N.register(
"Unsatisfied authentication mechanism parameters" : "การรับรองความถูกต้องไม่เพียงพอ",
"Insufficient data: %s" : "ข้อมูลไม่เพียงพอ: %s",
"%s" : "%s",
+ "Storage with id \"%i\" is not user editable" : "พื้นที่เก็บข้อมูล รหัส \"%i\" ไม่อนุญาตให้ผู้ใช้แก้ไขข้อมูลได้",
"Personal" : "ส่วนตัว",
"System" : "ระบบ",
"Grant access" : "อนุญาตให้เข้าถึงได้",
@@ -28,6 +29,7 @@ OC.L10N.register(
"Error generating key pair" : "ข้อผิดพลาดในการสร้างคีย์แบบเป็นคู่",
"Enable encryption" : "เปิดใช้งานการเข้ารหัส",
"Enable previews" : "เปิดใช้งานการแสดงตัวอย่าง",
+ "Enable sharing" : "เปิดให้สามารถแชร์ได้",
"Check for changes" : "ตรวจสอบการเปลี่ยนแปลง",
"Never" : "ไม่เคย",
"Once every direct access" : "เมื่อทุกคนเข้าถึงโดยตรง",
@@ -35,6 +37,8 @@ OC.L10N.register(
"(group)" : "(กลุ่ม)",
"Admin defined" : "ถูกกำหนดโดยผู้ดูแลระบบ",
"Saved" : "บันทึกแล้ว",
+ "Saving..." : "กำลังบันทึกข้อมูล...",
+ "Save" : "บันทึก",
"Empty response from the server" : "ไม่มีการตอบสนองจากเซิร์ฟเวอร์",
"Couldn't access. Please logout and login to activate this mount point" : "ไม่สามารถเข้าถึง กรุณออกจากระบบและาเข้าสู่ระบบใหม่เพื่อเปิดใช้งานจุดเชื่อมต่อนี้",
"Couldn't get the information from the ownCloud server: {code} {type}" : "ไม่สามารถรับข้อมูลจากเซิร์ฟเวอร์ ownCloud: {code} {type}",
@@ -43,6 +47,8 @@ OC.L10N.register(
"External mount error" : "การติดจากตั้งภายนอกเกิดข้อผิดพลาด",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "ไม่สามารถรับรายชื่อไดรฟ์เครือข่ายของวินโดว์ส จุดที่ติดตั้ง: ไม่มีการตอบสนองจากเซิร์ฟเวอร์",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "การกำหนดค่าบางส่วนของจุดเชื่อมต่อภายนอกไม่ถูกเชื่อมต่อ กรุณาคลิกที่ตรงสีแดงสำหรับข้อมูลเพิ่มเติม",
+ "Username" : "ชื่อผู้ใช้งาน",
+ "Password" : "รหัสผ่าน",
"Access key" : "คีย์การเข้าถึง",
"Secret key" : "คีย์ลับ",
"Builtin" : "ในตัว",
@@ -54,13 +60,14 @@ OC.L10N.register(
"Client ID" : "Client ID",
"Client secret" : "Client secret",
"OpenStack" : "OpenStack",
- "Username" : "ชื่อผู้ใช้งาน",
- "Password" : "รหัสผ่าน",
"Tenant name" : "ชื่อผู้เช่า",
"Identity endpoint URL" : "ตัวตนของ URL ปลายทาง",
"Rackspace" : "Rackspace",
"API key" : "รหัส API",
+ "Log-in credentials, save in database" : "ข้อมูลประจำตัวสำหรับเข้าสู่ระบบ, บันทึกลงในฐานข้อมูล",
"Username and password" : "ชื่อผู้ใช้และรหัสผ่าน",
+ "Log-in credentials, save in session" : "ข้อมูลประจำตัวสำหรับเข้าสู่ระบบ, บันทึกลงในช่วงเวลาเข้าใช้งาน",
+ "User entered, store in database" : "เมื่อผู้ใช้กรอก, เก็บข้อมูลไว้ในฐานข้อมูล",
"RSA public key" : "RSA คีย์สาธารณะ",
"Public key" : "คีย์สาธารณะ",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/th_TH.json b/apps/files_external/l10n/th_TH.json
index 07424cc1d23..5cdfd95411f 100644
--- a/apps/files_external/l10n/th_TH.json
+++ b/apps/files_external/l10n/th_TH.json
@@ -16,6 +16,7 @@
"Unsatisfied authentication mechanism parameters" : "การรับรองความถูกต้องไม่เพียงพอ",
"Insufficient data: %s" : "ข้อมูลไม่เพียงพอ: %s",
"%s" : "%s",
+ "Storage with id \"%i\" is not user editable" : "พื้นที่เก็บข้อมูล รหัส \"%i\" ไม่อนุญาตให้ผู้ใช้แก้ไขข้อมูลได้",
"Personal" : "ส่วนตัว",
"System" : "ระบบ",
"Grant access" : "อนุญาตให้เข้าถึงได้",
@@ -26,6 +27,7 @@
"Error generating key pair" : "ข้อผิดพลาดในการสร้างคีย์แบบเป็นคู่",
"Enable encryption" : "เปิดใช้งานการเข้ารหัส",
"Enable previews" : "เปิดใช้งานการแสดงตัวอย่าง",
+ "Enable sharing" : "เปิดให้สามารถแชร์ได้",
"Check for changes" : "ตรวจสอบการเปลี่ยนแปลง",
"Never" : "ไม่เคย",
"Once every direct access" : "เมื่อทุกคนเข้าถึงโดยตรง",
@@ -33,6 +35,8 @@
"(group)" : "(กลุ่ม)",
"Admin defined" : "ถูกกำหนดโดยผู้ดูแลระบบ",
"Saved" : "บันทึกแล้ว",
+ "Saving..." : "กำลังบันทึกข้อมูล...",
+ "Save" : "บันทึก",
"Empty response from the server" : "ไม่มีการตอบสนองจากเซิร์ฟเวอร์",
"Couldn't access. Please logout and login to activate this mount point" : "ไม่สามารถเข้าถึง กรุณออกจากระบบและาเข้าสู่ระบบใหม่เพื่อเปิดใช้งานจุดเชื่อมต่อนี้",
"Couldn't get the information from the ownCloud server: {code} {type}" : "ไม่สามารถรับข้อมูลจากเซิร์ฟเวอร์ ownCloud: {code} {type}",
@@ -41,6 +45,8 @@
"External mount error" : "การติดจากตั้งภายนอกเกิดข้อผิดพลาด",
"Couldn't get the list of Windows network drive mount points: empty response from the server" : "ไม่สามารถรับรายชื่อไดรฟ์เครือข่ายของวินโดว์ส จุดที่ติดตั้ง: ไม่มีการตอบสนองจากเซิร์ฟเวอร์",
"Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "การกำหนดค่าบางส่วนของจุดเชื่อมต่อภายนอกไม่ถูกเชื่อมต่อ กรุณาคลิกที่ตรงสีแดงสำหรับข้อมูลเพิ่มเติม",
+ "Username" : "ชื่อผู้ใช้งาน",
+ "Password" : "รหัสผ่าน",
"Access key" : "คีย์การเข้าถึง",
"Secret key" : "คีย์ลับ",
"Builtin" : "ในตัว",
@@ -52,13 +58,14 @@
"Client ID" : "Client ID",
"Client secret" : "Client secret",
"OpenStack" : "OpenStack",
- "Username" : "ชื่อผู้ใช้งาน",
- "Password" : "รหัสผ่าน",
"Tenant name" : "ชื่อผู้เช่า",
"Identity endpoint URL" : "ตัวตนของ URL ปลายทาง",
"Rackspace" : "Rackspace",
"API key" : "รหัส API",
+ "Log-in credentials, save in database" : "ข้อมูลประจำตัวสำหรับเข้าสู่ระบบ, บันทึกลงในฐานข้อมูล",
"Username and password" : "ชื่อผู้ใช้และรหัสผ่าน",
+ "Log-in credentials, save in session" : "ข้อมูลประจำตัวสำหรับเข้าสู่ระบบ, บันทึกลงในช่วงเวลาเข้าใช้งาน",
+ "User entered, store in database" : "เมื่อผู้ใช้กรอก, เก็บข้อมูลไว้ในฐานข้อมูล",
"RSA public key" : "RSA คีย์สาธารณะ",
"Public key" : "คีย์สาธารณะ",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/tr.js b/apps/files_external/l10n/tr.js
index cb506b24c1f..0473544da04 100644
--- a/apps/files_external/l10n/tr.js
+++ b/apps/files_external/l10n/tr.js
@@ -33,6 +33,10 @@ OC.L10N.register(
"All users. Type to select user or group." : "Tüm kullanıcılar. Kullanıcı veya grup seçmek için yazın.",
"(group)" : "(grup)",
"Saved" : "Kaydedildi",
+ "Saving..." : "Kaydediliyor...",
+ "Save" : "Kaydet",
+ "Username" : "Kullanıcı Adı",
+ "Password" : "Parola",
"Access key" : "Erişim anahtarı",
"Secret key" : "Gizli anahtar",
"Builtin" : "Yerleşik",
@@ -44,8 +48,6 @@ OC.L10N.register(
"Client ID" : "İstemci kimliği",
"Client secret" : "İstemci parolası",
"OpenStack" : "OpenStack",
- "Username" : "Kullanıcı Adı",
- "Password" : "Parola",
"Tenant name" : "Kiracı adı",
"Identity endpoint URL" : "Kimlik uç nokta URL'si",
"Rackspace" : "Rackspace",
diff --git a/apps/files_external/l10n/tr.json b/apps/files_external/l10n/tr.json
index 1eeaafa433c..384bf0afe2f 100644
--- a/apps/files_external/l10n/tr.json
+++ b/apps/files_external/l10n/tr.json
@@ -31,6 +31,10 @@
"All users. Type to select user or group." : "Tüm kullanıcılar. Kullanıcı veya grup seçmek için yazın.",
"(group)" : "(grup)",
"Saved" : "Kaydedildi",
+ "Saving..." : "Kaydediliyor...",
+ "Save" : "Kaydet",
+ "Username" : "Kullanıcı Adı",
+ "Password" : "Parola",
"Access key" : "Erişim anahtarı",
"Secret key" : "Gizli anahtar",
"Builtin" : "Yerleşik",
@@ -42,8 +46,6 @@
"Client ID" : "İstemci kimliği",
"Client secret" : "İstemci parolası",
"OpenStack" : "OpenStack",
- "Username" : "Kullanıcı Adı",
- "Password" : "Parola",
"Tenant name" : "Kiracı adı",
"Identity endpoint URL" : "Kimlik uç nokta URL'si",
"Rackspace" : "Rackspace",
diff --git a/apps/files_external/l10n/ug.js b/apps/files_external/l10n/ug.js
index 37adb851973..a10cc344c4a 100644
--- a/apps/files_external/l10n/ug.js
+++ b/apps/files_external/l10n/ug.js
@@ -3,9 +3,11 @@ OC.L10N.register(
{
"External storage" : "سىرتقى ساقلىغۇچ",
"Personal" : "شەخسىي",
- "None" : "يوق",
+ "Saving..." : "ساقلاۋاتىدۇ…",
+ "Save" : "ساقلا",
"Username" : "ئىشلەتكۈچى ئاتى",
"Password" : "ئىم",
+ "None" : "يوق",
"Port" : "ئېغىز",
"WebDAV" : "WebDAV",
"URL" : "URL",
diff --git a/apps/files_external/l10n/ug.json b/apps/files_external/l10n/ug.json
index f7a072bfe38..db22e09ec11 100644
--- a/apps/files_external/l10n/ug.json
+++ b/apps/files_external/l10n/ug.json
@@ -1,9 +1,11 @@
{ "translations": {
"External storage" : "سىرتقى ساقلىغۇچ",
"Personal" : "شەخسىي",
- "None" : "يوق",
+ "Saving..." : "ساقلاۋاتىدۇ…",
+ "Save" : "ساقلا",
"Username" : "ئىشلەتكۈچى ئاتى",
"Password" : "ئىم",
+ "None" : "يوق",
"Port" : "ئېغىز",
"WebDAV" : "WebDAV",
"URL" : "URL",
diff --git a/apps/files_external/l10n/uk.js b/apps/files_external/l10n/uk.js
index 702b3e328ce..0333998c9df 100644
--- a/apps/files_external/l10n/uk.js
+++ b/apps/files_external/l10n/uk.js
@@ -17,13 +17,15 @@ OC.L10N.register(
"All users. Type to select user or group." : "Всі користувачі. Введіть ім'я користувача або групи.",
"(group)" : "(група)",
"Saved" : "Збережено",
+ "Saving..." : "Збереження...",
+ "Save" : "Зберегти",
+ "Username" : "Ім'я користувача",
+ "Password" : "Пароль",
"None" : "Жоден",
"App key" : "Ключ додатку",
"App secret" : "Секретний ключ додатку",
"Client ID" : "Ідентифікатор клієнта",
"Client secret" : "Ключ клієнта",
- "Username" : "Ім'я користувача",
- "Password" : "Пароль",
"API key" : "ключ API",
"Public key" : "Відкритий ключ",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/uk.json b/apps/files_external/l10n/uk.json
index cddda62118f..f45274195ae 100644
--- a/apps/files_external/l10n/uk.json
+++ b/apps/files_external/l10n/uk.json
@@ -15,13 +15,15 @@
"All users. Type to select user or group." : "Всі користувачі. Введіть ім'я користувача або групи.",
"(group)" : "(група)",
"Saved" : "Збережено",
+ "Saving..." : "Збереження...",
+ "Save" : "Зберегти",
+ "Username" : "Ім'я користувача",
+ "Password" : "Пароль",
"None" : "Жоден",
"App key" : "Ключ додатку",
"App secret" : "Секретний ключ додатку",
"Client ID" : "Ідентифікатор клієнта",
"Client secret" : "Ключ клієнта",
- "Username" : "Ім'я користувача",
- "Password" : "Пароль",
"API key" : "ключ API",
"Public key" : "Відкритий ключ",
"Amazon S3" : "Amazon S3",
diff --git a/apps/files_external/l10n/ur_PK.js b/apps/files_external/l10n/ur_PK.js
index 55c8ee1f1bc..0a41084c07b 100644
--- a/apps/files_external/l10n/ur_PK.js
+++ b/apps/files_external/l10n/ur_PK.js
@@ -2,6 +2,8 @@ OC.L10N.register(
"files_external",
{
"Personal" : "شخصی",
+ "Saving..." : "محفوظ ھو رہا ہے ...",
+ "Save" : "حفظ",
"Username" : "یوزر نیم",
"Password" : "پاسورڈ",
"URL" : "یو ار ایل",
diff --git a/apps/files_external/l10n/ur_PK.json b/apps/files_external/l10n/ur_PK.json
index e8b9c79e1f1..175d2e32414 100644
--- a/apps/files_external/l10n/ur_PK.json
+++ b/apps/files_external/l10n/ur_PK.json
@@ -1,5 +1,7 @@
{ "translations": {
"Personal" : "شخصی",
+ "Saving..." : "محفوظ ھو رہا ہے ...",
+ "Save" : "حفظ",
"Username" : "یوزر نیم",
"Password" : "پاسورڈ",
"URL" : "یو ار ایل",
diff --git a/apps/files_external/l10n/vi.js b/apps/files_external/l10n/vi.js
index 65b3d492429..642299b8941 100644
--- a/apps/files_external/l10n/vi.js
+++ b/apps/files_external/l10n/vi.js
@@ -6,9 +6,11 @@ OC.L10N.register(
"Grant access" : "Cấp quyền truy cập",
"Access granted" : "Đã cấp quyền truy cập",
"Saved" : "Đã lưu",
- "None" : "Không gì cả",
+ "Saving..." : "Đang lưu...",
+ "Save" : "Lưu",
"Username" : "Tên đăng nhập",
"Password" : "Mật khẩu",
+ "None" : "Không gì cả",
"Port" : "Cổng",
"Region" : "Vùng/miền",
"WebDAV" : "WebDAV",
diff --git a/apps/files_external/l10n/vi.json b/apps/files_external/l10n/vi.json
index 031dddee8e3..95cf65233d7 100644
--- a/apps/files_external/l10n/vi.json
+++ b/apps/files_external/l10n/vi.json
@@ -4,9 +4,11 @@
"Grant access" : "Cấp quyền truy cập",
"Access granted" : "Đã cấp quyền truy cập",
"Saved" : "Đã lưu",
- "None" : "Không gì cả",
+ "Saving..." : "Đang lưu...",
+ "Save" : "Lưu",
"Username" : "Tên đăng nhập",
"Password" : "Mật khẩu",
+ "None" : "Không gì cả",
"Port" : "Cổng",
"Region" : "Vùng/miền",
"WebDAV" : "WebDAV",
diff --git a/apps/files_external/l10n/zh_CN.js b/apps/files_external/l10n/zh_CN.js
index ca35a97bb53..989c31e915a 100644
--- a/apps/files_external/l10n/zh_CN.js
+++ b/apps/files_external/l10n/zh_CN.js
@@ -10,9 +10,11 @@ OC.L10N.register(
"Access granted" : "权限已授予。",
"Enable encryption" : "启用加密",
"Saved" : "已保存",
- "None" : "无",
+ "Saving..." : "保存中...",
+ "Save" : "保存",
"Username" : "用户名",
"Password" : "密码",
+ "None" : "无",
"API key" : "API密匙",
"Amazon S3" : "Amazon S3",
"Port" : "端口",
diff --git a/apps/files_external/l10n/zh_CN.json b/apps/files_external/l10n/zh_CN.json
index 53c1df78899..dfc01a86c7b 100644
--- a/apps/files_external/l10n/zh_CN.json
+++ b/apps/files_external/l10n/zh_CN.json
@@ -8,9 +8,11 @@
"Access granted" : "权限已授予。",
"Enable encryption" : "启用加密",
"Saved" : "已保存",
- "None" : "无",
+ "Saving..." : "保存中...",
+ "Save" : "保存",
"Username" : "用户名",
"Password" : "密码",
+ "None" : "无",
"API key" : "API密匙",
"Amazon S3" : "Amazon S3",
"Port" : "端口",
diff --git a/apps/files_external/l10n/zh_HK.js b/apps/files_external/l10n/zh_HK.js
index 7a38dd7ffed..8a9eafeb906 100644
--- a/apps/files_external/l10n/zh_HK.js
+++ b/apps/files_external/l10n/zh_HK.js
@@ -3,9 +3,11 @@ OC.L10N.register(
{
"Personal" : "個人",
"Saved" : "已儲存",
- "None" : "空",
+ "Saving..." : "儲存中...",
+ "Save" : "儲存",
"Username" : "用戶名稱",
"Password" : "密碼",
+ "None" : "空",
"Port" : "連接埠",
"WebDAV" : "WebDAV",
"URL" : "網址",
diff --git a/apps/files_external/l10n/zh_HK.json b/apps/files_external/l10n/zh_HK.json
index befeede4bbe..d6dbd19c486 100644
--- a/apps/files_external/l10n/zh_HK.json
+++ b/apps/files_external/l10n/zh_HK.json
@@ -1,9 +1,11 @@
{ "translations": {
"Personal" : "個人",
"Saved" : "已儲存",
- "None" : "空",
+ "Saving..." : "儲存中...",
+ "Save" : "儲存",
"Username" : "用戶名稱",
"Password" : "密碼",
+ "None" : "空",
"Port" : "連接埠",
"WebDAV" : "WebDAV",
"URL" : "網址",
diff --git a/apps/files_external/l10n/zh_TW.js b/apps/files_external/l10n/zh_TW.js
index ff0857709e8..1d12fc25384 100644
--- a/apps/files_external/l10n/zh_TW.js
+++ b/apps/files_external/l10n/zh_TW.js
@@ -33,10 +33,14 @@ OC.L10N.register(
"All users. Type to select user or group." : "所有人都可以使用,或者選擇特定使用者、群組",
"(group)" : "(群組)",
"Saved" : "已儲存",
+ "Saving..." : "儲存中...",
+ "Save" : "儲存",
"Couldn't access. Please logout and login to activate this mount point" : "無法存取。請重新登出再登入啟動此掛載點。",
"Couldn't get the information from the ownCloud server: {code} {type}" : "無法從ownCloud伺服器得到資訊: {code} {type}",
"Couldn't get the list of external mount points: {type}" : "無法得到外部掛載點的列表: {type}",
"External mount error" : "外部掛載錯誤",
+ "Username" : "使用者名稱",
+ "Password" : "密碼",
"Access key" : "存取金鑰",
"Secret key" : "私密金鑰",
"None" : "無",
@@ -45,8 +49,6 @@ OC.L10N.register(
"Client ID" : "客戶端ID",
"Client secret" : "客戶端密碼",
"OpenStack" : "OpenStack",
- "Username" : "使用者名稱",
- "Password" : "密碼",
"Tenant name" : "租戶/專案名稱",
"Identity endpoint URL" : "身份識別終端點 URL",
"Rackspace" : "Rackspace",
diff --git a/apps/files_external/l10n/zh_TW.json b/apps/files_external/l10n/zh_TW.json
index 4fd9424bc6f..4363e8ea347 100644
--- a/apps/files_external/l10n/zh_TW.json
+++ b/apps/files_external/l10n/zh_TW.json
@@ -31,10 +31,14 @@
"All users. Type to select user or group." : "所有人都可以使用,或者選擇特定使用者、群組",
"(group)" : "(群組)",
"Saved" : "已儲存",
+ "Saving..." : "儲存中...",
+ "Save" : "儲存",
"Couldn't access. Please logout and login to activate this mount point" : "無法存取。請重新登出再登入啟動此掛載點。",
"Couldn't get the information from the ownCloud server: {code} {type}" : "無法從ownCloud伺服器得到資訊: {code} {type}",
"Couldn't get the list of external mount points: {type}" : "無法得到外部掛載點的列表: {type}",
"External mount error" : "外部掛載錯誤",
+ "Username" : "使用者名稱",
+ "Password" : "密碼",
"Access key" : "存取金鑰",
"Secret key" : "私密金鑰",
"None" : "無",
@@ -43,8 +47,6 @@
"Client ID" : "客戶端ID",
"Client secret" : "客戶端密碼",
"OpenStack" : "OpenStack",
- "Username" : "使用者名稱",
- "Password" : "密碼",
"Tenant name" : "租戶/專案名稱",
"Identity endpoint URL" : "身份識別終端點 URL",
"Rackspace" : "Rackspace",
diff --git a/apps/files_external/lib/auth/password/globalauth.php b/apps/files_external/lib/auth/password/globalauth.php
new file mode 100644
index 00000000000..b1e52fb53ab
--- /dev/null
+++ b/apps/files_external/lib/auth/password/globalauth.php
@@ -0,0 +1,88 @@
+<?php
+/**
+ * @author Robin Appelman <icewind@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\Files_External\Lib\Auth\Password;
+
+use OCA\Files_External\Lib\Auth\IUserProvided;
+use OCA\Files_External\Lib\DefinitionParameter;
+use OCA\Files_External\Service\BackendService;
+use OCP\IL10N;
+use OCP\IUser;
+use OCA\Files_External\Lib\Auth\AuthMechanism;
+use OCA\Files_External\Lib\StorageConfig;
+use OCP\Security\ICredentialsManager;
+use OCP\Files\Storage;
+use OCA\Files_External\Lib\InsufficientDataForMeaningfulAnswerException;
+
+/**
+ * Global Username and Password
+ */
+class GlobalAuth extends AuthMechanism {
+
+ const CREDENTIALS_IDENTIFIER = 'password::global';
+
+ /** @var ICredentialsManager */
+ protected $credentialsManager;
+
+ public function __construct(IL10N $l, ICredentialsManager $credentialsManager) {
+ $this->credentialsManager = $credentialsManager;
+
+ $this
+ ->setIdentifier('password::global')
+ ->setVisibility(BackendService::VISIBILITY_DEFAULT)
+ ->setScheme(self::SCHEME_PASSWORD)
+ ->setText($l->t('Global Credentails'));
+ }
+
+ public function getAuth($uid) {
+ $auth = $this->credentialsManager->retrieve($uid, self::CREDENTIALS_IDENTIFIER);
+ if (!is_array($auth)) {
+ return [
+ 'user' => '',
+ 'password' => ''
+ ];
+ } else {
+ return $auth;
+ }
+ }
+
+ public function saveAuth($uid, $user, $password) {
+ $this->credentialsManager->store($uid, self::CREDENTIALS_IDENTIFIER, [
+ 'user' => $user,
+ 'password' => $password
+ ]);
+ }
+
+ public function manipulateStorageConfig(StorageConfig &$storage, IUser $user = null) {
+ if ($storage->getType() === StorageConfig::MOUNT_TYPE_ADMIN) {
+ $uid = '';
+ } else {
+ $uid = $user->getUID();
+ }
+ $credentials = $this->credentialsManager->retrieve($uid, self::CREDENTIALS_IDENTIFIER);
+
+ if (is_array($credentials)) {
+ $storage->setBackendOption('user', $credentials['user']);
+ $storage->setBackendOption('password', $credentials['password']);
+ }
+ }
+
+}
diff --git a/apps/files_external/lib/config/configadapter.php b/apps/files_external/lib/config/configadapter.php
index 2bf39bcaa4f..51c2debd726 100644
--- a/apps/files_external/lib/config/configadapter.php
+++ b/apps/files_external/lib/config/configadapter.php
@@ -130,6 +130,16 @@ class ConfigAdapter implements IMountProvider {
$impl = new FailedStorage(['exception' => $e]);
}
+ try {
+ $availability = $impl->getAvailability();
+ if (!$availability['available']) {
+ $impl = new FailedStorage(['exception' => null]);
+ }
+ } catch (\Exception $e) {
+ // propagate exception into filesystem
+ $impl = new FailedStorage(['exception' => $e]);
+ }
+
$mount = new MountPoint(
$impl,
'/' . $user->getUID() . '/files' . $storage->getMountPoint(),
diff --git a/apps/files_external/lib/failedcache.php b/apps/files_external/lib/failedcache.php
index 9e24c12f4b5..0f59495e595 100644
--- a/apps/files_external/lib/failedcache.php
+++ b/apps/files_external/lib/failedcache.php
@@ -22,6 +22,7 @@
namespace OCA\Files_External\Lib;
use OC\Files\Cache\CacheEntry;
+use OCP\Constants;
use OCP\Files\Cache\ICache;
/**
@@ -40,7 +41,7 @@ class FailedCache implements ICache {
'size' => 0,
'mimetype' => 'httpd/unix-directory',
'mimepart' => 'httpd',
- 'permissions' => 0,
+ 'permissions' => Constants::PERMISSION_READ,
'mtime' => time()
]);
} else {
@@ -60,6 +61,10 @@ class FailedCache implements ICache {
return;
}
+ public function insert($file, array $data) {
+ return;
+ }
+
public function update($id, array $data) {
return;
}
diff --git a/apps/files_external/lib/insufficientdataformeaningfulanswerexception.php b/apps/files_external/lib/insufficientdataformeaningfulanswerexception.php
index 871301b9b51..22d83ef56f4 100644
--- a/apps/files_external/lib/insufficientdataformeaningfulanswerexception.php
+++ b/apps/files_external/lib/insufficientdataformeaningfulanswerexception.php
@@ -27,4 +27,15 @@ use \OCP\Files\StorageNotAvailableException;
* Authentication mechanism or backend has insufficient data
*/
class InsufficientDataForMeaningfulAnswerException extends StorageNotAvailableException {
+ /**
+ * StorageNotAvailableException constructor.
+ *
+ * @param string $message
+ * @param int $code
+ * @param \Exception $previous
+ * @since 6.0.0
+ */
+ public function __construct($message = '', $code = self::STATUS_INDETERMINATE, \Exception $previous = null) {
+ parent::__construct($message, $code, $previous);
+ }
}
diff --git a/apps/files_external/lib/smb.php b/apps/files_external/lib/smb.php
index 9da21dc88e6..50bd56f28ad 100644
--- a/apps/files_external/lib/smb.php
+++ b/apps/files_external/lib/smb.php
@@ -314,4 +314,17 @@ class SMB extends Common {
|| Server::NativeAvailable()
) ? true : ['smbclient'];
}
+
+ /**
+ * Test a storage for availability
+ *
+ * @return bool
+ */
+ public function test() {
+ try {
+ return parent::test();
+ } catch (Exception $e) {
+ return false;
+ }
+ }
}
diff --git a/apps/files_external/lib/storageconfig.php b/apps/files_external/lib/storageconfig.php
index 7f716893842..6f44b25a2e6 100644
--- a/apps/files_external/lib/storageconfig.php
+++ b/apps/files_external/lib/storageconfig.php
@@ -24,6 +24,7 @@
namespace OCA\Files_external\Lib;
+use OCA\Files_External\Lib\Auth\IUserProvided;
use \OCA\Files_External\Lib\Backend\Backend;
use \OCA\Files_External\Lib\Auth\AuthMechanism;
@@ -406,6 +407,7 @@ class StorageConfig implements \JsonSerializable {
if (!is_null($this->statusMessage)) {
$result['statusMessage'] = $this->statusMessage;
}
+ $result['userProvided'] = $this->authMechanism instanceof IUserProvided;
$result['type'] = ($this->getType() === self::MOUNT_TYPE_PERSONAl) ? 'personal': 'system';
return $result;
}
diff --git a/apps/files_external/personal.php b/apps/files_external/personal.php
index 4d8f480ecc0..f180b7e8f5c 100644
--- a/apps/files_external/personal.php
+++ b/apps/files_external/personal.php
@@ -30,6 +30,7 @@ use \OCA\Files_External\Service\BackendService;
$appContainer = \OC_Mount_Config::$app->getContainer();
$backendService = $appContainer->query('OCA\Files_External\Service\BackendService');
$userStoragesService = $appContainer->query('OCA\Files_external\Service\UserStoragesService');
+$globalAuth = $appContainer->query('OCA\Files_External\Lib\Auth\Password\GlobalAuth');
$tmpl = new OCP\Template('files_external', 'settings');
$tmpl->assign('encryptionEnabled', \OC::$server->getEncryptionManager()->isEnabled());
@@ -38,4 +39,7 @@ $tmpl->assign('storages', $userStoragesService->getStorages());
$tmpl->assign('dependencies', OC_Mount_Config::dependencyMessage($backendService->getBackends()));
$tmpl->assign('backends', $backendService->getAvailableBackends());
$tmpl->assign('authMechanisms', $backendService->getAuthMechanisms());
+$uid = \OC::$server->getUserSession()->getUser()->getUID();
+$tmpl->assign('globalCredentials', $globalAuth->getAuth($uid));
+$tmpl->assign('globalCredentialsUid', $uid);
return $tmpl->fetchPage();
diff --git a/apps/files_external/settings.php b/apps/files_external/settings.php
index 0d83d26ff97..a5265c500d9 100644
--- a/apps/files_external/settings.php
+++ b/apps/files_external/settings.php
@@ -32,6 +32,7 @@ use \OCA\Files_External\Service\BackendService;
$appContainer = \OC_Mount_Config::$app->getContainer();
$backendService = $appContainer->query('OCA\Files_External\Service\BackendService');
$globalStoragesService = $appContainer->query('OCA\Files_external\Service\GlobalStoragesService');
+$globalAuth = $appContainer->query('OCA\Files_External\Lib\Auth\Password\GlobalAuth');
\OC_Util::addVendorScript('select2/select2');
\OC_Util::addVendorStyle('select2/select2');
@@ -44,4 +45,7 @@ $tmpl->assign('backends', $backendService->getAvailableBackends());
$tmpl->assign('authMechanisms', $backendService->getAuthMechanisms());
$tmpl->assign('dependencies', OC_Mount_Config::dependencyMessage($backendService->getBackends()));
$tmpl->assign('allowUserMounting', $backendService->isUserMountingAllowed());
+$tmpl->assign('allowUserMounting', $backendService->isUserMountingAllowed());
+$tmpl->assign('globalCredentials', $globalAuth->getAuth(''));
+$tmpl->assign('globalCredentialsUid', '');
return $tmpl->fetchPage();
diff --git a/apps/files_external/templates/settings.php b/apps/files_external/templates/settings.php
index f7caf3d2caa..8b453fe77c3 100644
--- a/apps/files_external/templates/settings.php
+++ b/apps/files_external/templates/settings.php
@@ -68,8 +68,23 @@
}
}
?>
-<form id="files_external" class="section" data-encryption-enabled="<?php echo $_['encryptionEnabled']?'true': 'false'; ?>">
+<form autocomplete="false" class="section" action="#"
+ id="global_credentials">
<h2><?php p($l->t('External Storage')); ?></h2>
+ <p><?php p($l->t('Global Credentials')); ?></p>
+ <input type="text" name="username"
+ autocomplete="false"
+ value="<?php p($_['globalCredentials']['user']); ?>"
+ placeholder="<?php p($l->t('Username')) ?>"/>
+ <input type="password" name="password"
+ autocomplete="false"
+ value="<?php p($_['globalCredentials']['password']); ?>"
+ placeholder="<?php p($l->t('Password')) ?>"/>
+ <input type="hidden" name="uid"
+ value="<?php p($_['globalCredentialsUid']); ?>"/>
+ <input type="submit" value="<?php p($l->t('Save')) ?>"/>
+</form>
+<form id="files_external" class="section" data-encryption-enabled="<?php echo $_['encryptionEnabled']?'true': 'false'; ?>">
<?php if (isset($_['dependencies']) and ($_['dependencies']<>'')) print_unescaped(''.$_['dependencies'].''); ?>
<table id="externalStorage" class="grid" data-admin='<?php print_unescaped(json_encode($_['visibilityType'] === BackendService::VISIBILITY_ADMIN)); ?>'>
<thead>
diff --git a/apps/files_sharing/api/share20ocs.php b/apps/files_sharing/api/share20ocs.php
index 8fe8991f9c9..d7c5d004d9c 100644
--- a/apps/files_sharing/api/share20ocs.php
+++ b/apps/files_sharing/api/share20ocs.php
@@ -26,32 +26,41 @@ use OCP\IRequest;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\Files\IRootFolder;
+use OCP\Share\IManager;
+
+use OCP\Share\Exceptions\ShareNotFound;
+use OCP\Share\Exceptions\GenericShareException;
class Share20OCS {
- /** @var \OC\Share20\Manager */
+ /** @var IManager */
private $shareManager;
-
/** @var IGroupManager */
private $groupManager;
-
/** @var IUserManager */
private $userManager;
-
/** @var IRequest */
private $request;
-
/** @var IRootFolder */
private $rootFolder;
-
/** @var IUrlGenerator */
private $urlGenerator;
-
/** @var IUser */
private $currentUser;
+ /**
+ * Share20OCS constructor.
+ *
+ * @param IManager $shareManager
+ * @param IGroupManager $groupManager
+ * @param IUserManager $userManager
+ * @param IRequest $request
+ * @param IRootFolder $rootFolder
+ * @param IURLGenerator $urlGenerator
+ * @param IUser $currentUser
+ */
public function __construct(
- \OC\Share20\Manager $shareManager,
+ IManager $shareManager,
IGroupManager $groupManager,
IUserManager $userManager,
IRequest $request,
@@ -75,22 +84,24 @@ class Share20OCS {
* @return array
*/
protected function formatShare(\OCP\Share\IShare $share) {
+ $sharedBy = $this->userManager->get($share->getSharedBy());
+ $shareOwner = $this->userManager->get($share->getShareOwner());
$result = [
'id' => $share->getId(),
'share_type' => $share->getShareType(),
- 'uid_owner' => $share->getSharedBy()->getUID(),
- 'displayname_owner' => $share->getSharedBy()->getDisplayName(),
+ 'uid_owner' => $share->getSharedBy(),
+ 'displayname_owner' => $sharedBy->getDisplayName(),
'permissions' => $share->getPermissions(),
'stime' => $share->getShareTime()->getTimestamp(),
'parent' => null,
'expiration' => null,
'token' => null,
- 'uid_file_owner' => $share->getShareOwner()->getUID(),
- 'displayname_file_owner' => $share->getShareOwner()->getDisplayName(),
+ 'uid_file_owner' => $share->getShareOwner(),
+ 'displayname_file_owner' => $shareOwner->getDisplayName(),
];
$node = $share->getNode();
- $result['path'] = $this->rootFolder->getUserFolder($share->getShareOwner()->getUID())->getRelativePath($node->getPath());
+ $result['path'] = $this->rootFolder->getUserFolder($share->getShareOwner())->getRelativePath($node->getPath());
if ($node instanceOf \OCP\Files\Folder) {
$result['item_type'] = 'folder';
} else {
@@ -104,13 +115,12 @@ class Share20OCS {
$result['file_target'] = $share->getTarget();
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
- $sharedWith = $share->getSharedWith();
+ $sharedWith = $this->userManager->get($share->getSharedWith());
$result['share_with'] = $sharedWith->getUID();
$result['share_with_displayname'] = $sharedWith->getDisplayName();
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
- $sharedWith = $share->getSharedWith();
- $result['share_with'] = $sharedWith->getGID();
- $result['share_with_displayname'] = $sharedWith->getGID();
+ $result['share_with'] = $share->getSharedWith();
+ $result['share_with_displayname'] = $share->getSharedWith();
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
$result['share_with'] = $share->getPassword();
@@ -148,7 +158,7 @@ class Share20OCS {
// First check if it is an internal share.
try {
$share = $this->shareManager->getShareById('ocinternal:'.$id);
- } catch (\OC\Share20\Exception\ShareNotFound $e) {
+ } catch (ShareNotFound $e) {
// Ignore for now
//return new \OC_OCS_Result(null, 404, 'wrong share ID, share doesn\'t exist.');
}
@@ -178,7 +188,7 @@ class Share20OCS {
try {
$share = $this->shareManager->getShareById('ocinternal:' . $id);
- } catch (\OC\Share20\Exception\ShareNotFound $e) {
+ } catch (ShareNotFound $e) {
//Ignore for now
//return new \OC_OCS_Result(null, 404, 'wrong share ID, share doesn\'t exist.');
}
@@ -192,11 +202,7 @@ class Share20OCS {
return new \OC_OCS_Result(null, 404, 'could not delete share');
}
- try {
- $this->shareManager->deleteShare($share);
- } catch (\OC\Share20\Exception\BackendError $e) {
- return new \OC_OCS_Result(null, 404, 'could not delete share');
- }
+ $this->shareManager->deleteShare($share);
return new \OC_OCS_Result();
}
@@ -251,14 +257,14 @@ class Share20OCS {
if ($shareWith === null || !$this->userManager->userExists($shareWith)) {
return new \OC_OCS_Result(null, 404, 'please specify a valid user');
}
- $share->setSharedWith($this->userManager->get($shareWith));
+ $share->setSharedWith($shareWith);
$share->setPermissions($permissions);
} else if ($shareType === \OCP\Share::SHARE_TYPE_GROUP) {
// Valid group is required to share
if ($shareWith === null || !$this->groupManager->groupExists($shareWith)) {
return new \OC_OCS_Result(null, 404, 'please specify a valid group');
}
- $share->setSharedWith($this->groupManager->get($shareWith));
+ $share->setSharedWith($shareWith);
$share->setPermissions($permissions);
} else if ($shareType === \OCP\Share::SHARE_TYPE_LINK) {
//Can we even share links?
@@ -314,11 +320,11 @@ class Share20OCS {
}
$share->setShareType($shareType);
- $share->setSharedBy($this->currentUser);
+ $share->setSharedBy($this->currentUser->getUID());
try {
$share = $this->shareManager->createShare($share);
- } catch (\OC\HintException $e) {
+ } catch (GenericShareException $e) {
$code = $e->getCode() === 0 ? 403 : $e->getCode();
return new \OC_OCS_Result(null, $code, $e->getHint());
}catch (\Exception $e) {
@@ -334,8 +340,8 @@ class Share20OCS {
* @return \OC_OCS_Result
*/
private function getSharedWithMe($node = null) {
- $userShares = $this->shareManager->getSharedWith($this->currentUser, \OCP\Share::SHARE_TYPE_USER, $node, -1, 0);
- $groupShares = $this->shareManager->getSharedWith($this->currentUser, \OCP\Share::SHARE_TYPE_GROUP, $node, -1, 0);
+ $userShares = $this->shareManager->getSharedWith($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_USER, $node, -1, 0);
+ $groupShares = $this->shareManager->getSharedWith($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $node, -1, 0);
$shares = array_merge($userShares, $groupShares);
@@ -362,9 +368,9 @@ class Share20OCS {
/** @var \OCP\Share\IShare[] $shares */
$shares = [];
foreach ($nodes as $node) {
- $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_USER, $node, false, -1, 0));
- $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_GROUP, $node, false, -1, 0));
- $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_LINK, $node, false, -1, 0));
+ $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_USER, $node, false, -1, 0));
+ $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $node, false, -1, 0));
+ $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_LINK, $node, false, -1, 0));
//TODO: Add federated shares
}
@@ -418,9 +424,9 @@ class Share20OCS {
}
// Get all shares
- $userShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_USER, $path, $reshares, -1, 0);
- $groupShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_GROUP, $path, $reshares, -1, 0);
- $linkShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_LINK, $path, $reshares, -1, 0);
+ $userShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_USER, $path, $reshares, -1, 0);
+ $groupShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $path, $reshares, -1, 0);
+ $linkShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_LINK, $path, $reshares, -1, 0);
//TODO: Add federated shares
$shares = array_merge($userShares, $groupShares, $linkShares);
@@ -443,7 +449,7 @@ class Share20OCS {
try {
$share = $this->shareManager->getShareById('ocinternal:' . $id);
- } catch (\OC\Share20\Exception\ShareNotFound $e) {
+ } catch (ShareNotFound $e) {
//Ignore for now
//return new \OC_OCS_Result(null, 404, 'wrong share ID, share doesn\'t exist.');
}
@@ -539,14 +545,6 @@ class Share20OCS {
return new \OC_OCS_Result($this->formatShare($share));
}
- public function validatePermissions($permissions) {
- if ($permissions < 0 || $permissions > \OCP\Constants::PERMISSION_ALL) {
- return false;
- }
-
-
- }
-
/**
* @param \OCP\Share\IShare $share
* @return bool
@@ -558,21 +556,23 @@ class Share20OCS {
}
// Owner of the file and the sharer of the file can always get share
- if ($share->getShareOwner() === $this->currentUser ||
- $share->getSharedBy() === $this->currentUser
+ if ($share->getShareOwner() === $this->currentUser->getUID() ||
+ $share->getSharedBy() === $this->currentUser->getUID()
) {
return true;
}
// If the share is shared with you (or a group you are a member of)
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
- $share->getSharedWith() === $this->currentUser) {
+ $share->getSharedWith() === $this->currentUser->getUID()) {
return true;
}
- if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP &&
- $share->getSharedWith()->inGroup($this->currentUser)) {
- return true;
+ if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
+ $sharedWith = $this->groupManager->get($share->getSharedWith());
+ if ($sharedWith->inGroup($this->currentUser)) {
+ return true;
+ }
}
return false;
diff --git a/apps/files_sharing/js/public.js b/apps/files_sharing/js/public.js
index f2d6355d76a..bc609f04f79 100644
--- a/apps/files_sharing/js/public.js
+++ b/apps/files_sharing/js/public.js
@@ -155,11 +155,7 @@ OCA.Sharing.PublicApp = {
this.fileList.getDownloadUrl = function (filename, dir, isDir) {
var path = dir || this.getCurrentDirectory();
if (filename && !_.isArray(filename) && !isDir) {
- var portPart = '';
- if (OC.getPort()) {
- portPart = ':' + OC.getPort();
- }
- return OC.getProtocol() + '://' + token + '@' + OC.getHost() + portPart + OC.getRootPath() + '/public.php/webdav' + OC.joinPaths(path, filename);
+ return OC.getProtocol() + '://' + token + '@' + OC.getHost() + OC.getRootPath() + '/public.php/webdav' + OC.joinPaths(path, filename);
}
if (_.isArray(filename)) {
filename = JSON.stringify(filename);
diff --git a/apps/files_sharing/lib/controllers/sharecontroller.php b/apps/files_sharing/lib/controllers/sharecontroller.php
index 9fec57edbdd..bbe68096b52 100644
--- a/apps/files_sharing/lib/controllers/sharecontroller.php
+++ b/apps/files_sharing/lib/controllers/sharecontroller.php
@@ -52,6 +52,7 @@ use OCP\Util;
use OCA\Files_Sharing\Activity;
use \OCP\Files\NotFoundException;
use OCP\Files\IRootFolder;
+use OCP\Share\Exceptions\ShareNotFound;
/**
* Class ShareController
@@ -147,7 +148,7 @@ class ShareController extends Controller {
// Check whether share exists
try {
$share = $this->shareManager->getShareByToken($token);
- } catch (\OC\Share20\Exception\ShareNotFound $e) {
+ } catch (ShareNotFound $e) {
return new NotFoundResponse();
}
@@ -203,7 +204,7 @@ class ShareController extends Controller {
// Check whether share exists
try {
$share = $this->shareManager->getShareByToken($token);
- } catch (\OC\Share20\Exception\ShareNotFound $e) {
+ } catch (ShareNotFound $e) {
return new NotFoundResponse();
}
@@ -231,8 +232,8 @@ class ShareController extends Controller {
}
$shareTmpl = [];
- $shareTmpl['displayName'] = $share->getShareOwner()->getDisplayName();
- $shareTmpl['owner'] = $share->getShareOwner()->getUID();
+ $shareTmpl['displayName'] = $this->userManager->get($share->getShareOwner())->getDisplayName();
+ $shareTmpl['owner'] = $share->getShareOwner();
$shareTmpl['filename'] = $share->getNode()->getName();
$shareTmpl['directory_path'] = $share->getTarget();
$shareTmpl['mimetype'] = $share->getNode()->getMimetype();
@@ -319,7 +320,7 @@ class ShareController extends Controller {
}
}
- $userFolder = $this->rootFolder->getUserFolder($share->getShareOwner()->getUID());
+ $userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
$originalSharePath = $userFolder->getRelativePath($share->getNode()->getPath());
// Single file share
@@ -329,7 +330,7 @@ class ShareController extends Controller {
$event->setApp('files_sharing')
->setType(Activity::TYPE_PUBLIC_LINKS)
->setSubject(Activity::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED, [$userFolder->getRelativePath($share->getNode()->getPath())])
- ->setAffectedUser($share->getShareOwner()->getUID())
+ ->setAffectedUser($share->getShareOwner())
->setObject('files', $share->getNode()->getId(), $userFolder->getRelativePath($share->getNode()->getPath()));
$this->activityManager->publish($event);
}
@@ -355,7 +356,7 @@ class ShareController extends Controller {
$event->setApp('files_sharing')
->setType(Activity::TYPE_PUBLIC_LINKS)
->setSubject(Activity::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED, [$userFolder->getRelativePath($node->getPath())])
- ->setAffectedUser($share->getShareOwner()->getUID())
+ ->setAffectedUser($share->getShareOwner())
->setObject('files', $node->getId(), $userFolder->getRelativePath($node->getPath()));
$this->activityManager->publish($event);
} else if (!empty($files_list)) {
@@ -368,7 +369,7 @@ class ShareController extends Controller {
$event = $this->activityManager->generateEvent();
$event->setApp('files_sharing')
->setType(Activity::TYPE_PUBLIC_LINKS)
- ->setAffectedUser($share->getShareOwner()->getUID())
+ ->setAffectedUser($share->getShareOwner())
->setObject('files', $subNode->getId(), $userFolder->getRelativePath($subNode->getPath()));
if ($subNode instanceof \OCP\Files\File) {
@@ -385,7 +386,7 @@ class ShareController extends Controller {
$event->setApp('files_sharing')
->setType(Activity::TYPE_PUBLIC_LINKS)
->setSubject(Activity::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED, [$userFolder->getRelativePath($node->getPath())])
- ->setAffectedUser($share->getShareOwner()->getUID())
+ ->setAffectedUser($share->getShareOwner())
->setObject('files', $node->getId(), $userFolder->getRelativePath($node->getPath()));
$this->activityManager->publish($event);
}
@@ -393,7 +394,7 @@ class ShareController extends Controller {
/* FIXME: We should do this all nicely in OCP */
OC_Util::tearDownFS();
- OC_Util::setupFS($share->getShareOwner()->getUID());
+ OC_Util::setupFS($share->getShareOwner());
/**
* this sets a cookie to be able to recognize the start of the download
diff --git a/apps/files_sharing/lib/updater.php b/apps/files_sharing/lib/updater.php
index 9a1e554046b..10da2462807 100644
--- a/apps/files_sharing/lib/updater.php
+++ b/apps/files_sharing/lib/updater.php
@@ -73,6 +73,12 @@ class Shared_Updater {
*/
static private function moveShareToShare($path) {
$userFolder = \OC::$server->getUserFolder();
+
+ // If the user folder can't be constructed (e.g. link share) just return.
+ if ($userFolder === null) {
+ return;
+ }
+
$src = $userFolder->get($path);
$type = $src instanceof \OCP\Files\File ? 'file' : 'folder';
diff --git a/apps/files_sharing/templates/settings-personal.php b/apps/files_sharing/templates/settings-personal.php
index 1b93084e547..c318943712f 100644
--- a/apps/files_sharing/templates/settings-personal.php
+++ b/apps/files_sharing/templates/settings-personal.php
@@ -31,7 +31,7 @@ if ($_['showShareIT']) {
</button>
</div>
<button class="social-diaspora pop-up"
- data-url='http://sharetodiaspora.github.io/?title=<?php p($_['message_without_URL']); ?>&url=<?php p(urlencode($_['reference'])); ?>'>
+ data-url='https://sharetodiaspora.github.io/?title=<?php p($_['message_without_URL']); ?>&url=<?php p(urlencode($_['reference'])); ?>'>
Diaspora
</button>
<button class="social-twitter pop-up"
diff --git a/apps/files_sharing/tests/api/share20ocstest.php b/apps/files_sharing/tests/api/share20ocstest.php
index 111fad0236f..a93cd5f58ce 100644
--- a/apps/files_sharing/tests/api/share20ocstest.php
+++ b/apps/files_sharing/tests/api/share20ocstest.php
@@ -55,7 +55,7 @@ class Share20OCSTest extends \Test\TestCase {
private $ocs;
protected function setUp() {
- $this->shareManager = $this->getMockBuilder('OC\Share20\Manager')
+ $this->shareManager = $this->getMockBuilder('OCP\Share\IManager')
->disableOriginalConstructor()
->getMock();
$this->groupManager = $this->getMock('OCP\IGroupManager');
@@ -91,39 +91,24 @@ class Share20OCSTest extends \Test\TestCase {
->getMock();
}
- public function testDeleteShareShareNotFound() {
- $this->shareManager
- ->expects($this->once())
- ->method('getShareById')
- ->with('ocinternal:42')
- ->will($this->throwException(new \OC\Share20\Exception\ShareNotFound()));
-
- $expected = new \OC_OCS_Result(null, 404, 'wrong share ID, share doesn\'t exist.');
- $this->assertEquals($expected, $this->ocs->deleteShare(42));
+ private function newShare() {
+ return \OC::$server->getShareManager()->newShare();
}
- public function testDeleteShareCouldNotDelete() {
- $share = $this->getMock('OCP\Share\IShare');
- $share->method('getShareOwner')->willReturn($this->currentUser);
+ public function testDeleteShareShareNotFound() {
$this->shareManager
->expects($this->once())
->method('getShareById')
->with('ocinternal:42')
- ->willReturn($share);
- $this->shareManager
- ->expects($this->once())
- ->method('deleteShare')
- ->with($share)
- ->will($this->throwException(new \OC\Share20\Exception\BackendError()));
+ ->will($this->throwException(new \OCP\Share\Exceptions\ShareNotFound()));
-
- $expected = new \OC_OCS_Result(null, 404, 'could not delete share');
+ $expected = new \OC_OCS_Result(null, 404, 'wrong share ID, share doesn\'t exist.');
$this->assertEquals($expected, $this->ocs->deleteShare(42));
}
public function testDeleteShare() {
- $share = $this->getMock('OCP\Share\IShare');
- $share->method('getSharedBy')->willReturn($this->currentUser);
+ $share = $this->newShare();
+ $share->setSharedBy($this->currentUser->getUID());
$this->shareManager
->expects($this->once())
->method('getShareById')
@@ -156,7 +141,7 @@ class Share20OCSTest extends \Test\TestCase {
public function createShare($id, $shareType, $sharedWith, $sharedBy, $shareOwner, $path, $permissions,
$shareTime, $expiration, $parent, $target, $mail_send, $token=null,
$password=null) {
- $share = $this->getMock('OCP\Share\IShare');
+ $share = $this->getMock('\OCP\Share\IShare');
$share->method('getId')->willReturn($id);
$share->method('getShareType')->willReturn($shareType);
$share->method('getSharedWith')->willReturn($sharedWith);
@@ -185,21 +170,6 @@ class Share20OCSTest extends \Test\TestCase {
public function dataGetShare() {
$data = [];
- $initiator = $this->getMock('OCP\IUser');
- $initiator->method('getUID')->willReturn('initiatorId');
- $initiator->method('getDisplayName')->willReturn('initiatorDisplay');
-
- $owner = $this->getMock('OCP\IUser');
- $owner->method('getUID')->willReturn('ownerId');
- $owner->method('getDisplayName')->willReturn('ownerDisplay');
-
- $user = $this->getMock('OCP\IUser');
- $user->method('getUID')->willReturn('userId');
- $user->method('getDisplayName')->willReturn('userDisplay');
-
- $group = $this->getMock('OCP\IGroup');
- $group->method('getGID')->willReturn('groupId');
-
$cache = $this->getMockBuilder('OC\Files\Cache\Cache')
->disableOriginalConstructor()
->getMock();
@@ -230,9 +200,9 @@ class Share20OCSTest extends \Test\TestCase {
$share = $this->createShare(
100,
\OCP\Share::SHARE_TYPE_USER,
- $user,
- $initiator,
- $owner,
+ 'userId',
+ 'initiatorId',
+ 'ownerId',
$file,
4,
5,
@@ -271,9 +241,9 @@ class Share20OCSTest extends \Test\TestCase {
$share = $this->createShare(
101,
\OCP\Share::SHARE_TYPE_GROUP,
- $group,
- $initiator,
- $owner,
+ 'groupId',
+ 'initiatorId',
+ 'ownerId',
$folder,
4,
5,
@@ -314,8 +284,8 @@ class Share20OCSTest extends \Test\TestCase {
101,
\OCP\Share::SHARE_TYPE_LINK,
null,
- $initiator,
- $owner,
+ 'initiatorId',
+ 'ownerId',
$folder,
4,
5,
@@ -386,29 +356,53 @@ class Share20OCSTest extends \Test\TestCase {
->will($this->returnArgument(0));
$this->rootFolder->method('getUserFolder')
- ->with($share->getShareOwner()->getUID())
+ ->with($share->getShareOwner())
->willReturn($userFolder);
$this->urlGenerator
->method('linkToRouteAbsolute')
->willReturn('url');
+ $initiator = $this->getMock('OCP\IUser');
+ $initiator->method('getUID')->willReturn('initiatorId');
+ $initiator->method('getDisplayName')->willReturn('initiatorDisplay');
+
+ $owner = $this->getMock('OCP\IUser');
+ $owner->method('getUID')->willReturn('ownerId');
+ $owner->method('getDisplayName')->willReturn('ownerDisplay');
+
+ $user = $this->getMock('OCP\IUser');
+ $user->method('getUID')->willReturn('userId');
+ $user->method('getDisplayName')->willReturn('userDisplay');
+
+ $group = $this->getMock('OCP\IGroup');
+ $group->method('getGID')->willReturn('groupId');
+
+ $this->userManager->method('get')->will($this->returnValueMap([
+ ['userId', $user],
+ ['initiatorId', $initiator],
+ ['ownerId', $owner],
+ ]));
+ $this->groupManager->method('get')->will($this->returnValueMap([
+ ['group', $group],
+ ]));
+
$expected = new \OC_OCS_Result($result);
$this->assertEquals($expected->getData(), $ocs->getShare($share->getId())->getData());
}
public function testCanAccessShare() {
$share = $this->getMock('OCP\Share\IShare');
- $share->method('getShareOwner')->willReturn($this->currentUser);
+ $share->method('getShareOwner')->willReturn($this->currentUser->getUID());
$this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
$share = $this->getMock('OCP\Share\IShare');
- $share->method('getSharedBy')->willReturn($this->currentUser);
+ $share->method('getSharedBy')->willReturn($this->currentUser->getUID());
$this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
$share = $this->getMock('OCP\Share\IShare');
$share->method('getShareType')->willReturn(\OCP\Share::SHARE_TYPE_USER);
- $share->method('getSharedWith')->willReturn($this->currentUser);
+ $share->method('getSharedWith')->willReturn($this->currentUser->getUID());
$this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
$share = $this->getMock('OCP\Share\IShare');
@@ -418,16 +412,25 @@ class Share20OCSTest extends \Test\TestCase {
$share = $this->getMock('OCP\Share\IShare');
$share->method('getShareType')->willReturn(\OCP\Share::SHARE_TYPE_GROUP);
+ $share->method('getSharedWith')->willReturn('group');
+
$group = $this->getMock('OCP\IGroup');
$group->method('inGroup')->with($this->currentUser)->willReturn(true);
- $share->method('getSharedWith')->willReturn($group);
+ $group2 = $this->getMock('OCP\IGroup');
+ $group2->method('inGroup')->with($this->currentUser)->willReturn(false);
+
+
+ $this->groupManager->method('get')->will($this->returnValueMap([
+ ['group', $group],
+ ['group2', $group2],
+ ]));
$this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
$share = $this->getMock('OCP\Share\IShare');
$share->method('getShareType')->willReturn(\OCP\Share::SHARE_TYPE_GROUP);
- $group = $this->getMock('OCP\IGroup');
- $group->method('inGroup')->with($this->currentUser)->willReturn(false);
- $share->method('getSharedWith')->willReturn($group);
+ $share->method('getSharedWith')->willReturn('group2');
+
+ $this->groupManager->method('get')->with('group2')->willReturn($group);
$this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
$share = $this->getMock('OCP\Share\IShare');
@@ -606,7 +609,6 @@ class Share20OCSTest extends \Test\TestCase {
$user = $this->getMock('\OCP\IUser');
$this->userManager->method('userExists')->with('validUser')->willReturn(true);
- $this->userManager->method('get')->with('validUser')->willReturn($user);
$share->method('setPath')->with($path);
$share->method('setPermissions')
@@ -615,8 +617,8 @@ class Share20OCSTest extends \Test\TestCase {
~\OCP\Constants::PERMISSION_DELETE &
~\OCP\Constants::PERMISSION_CREATE);
$share->method('setShareType')->with(\OCP\Share::SHARE_TYPE_USER);
- $share->method('setSharedWith')->with($user);
- $share->method('setSharedBy')->with($this->currentUser);
+ $share->method('setSharedWith')->with('validUser');
+ $share->method('setSharedBy')->with('currentUser');
$expected = new \OC_OCS_Result();
$result = $ocs->createShare();
@@ -699,13 +701,12 @@ class Share20OCSTest extends \Test\TestCase {
$group = $this->getMock('\OCP\IGroup');
$this->groupManager->method('groupExists')->with('validGroup')->willReturn(true);
- $this->groupManager->method('get')->with('validGroup')->willReturn($group);
$share->method('setPath')->with($path);
$share->method('setPermissions')->with(\OCP\Constants::PERMISSION_ALL);
$share->method('setShareType')->with(\OCP\Share::SHARE_TYPE_GROUP);
- $share->method('setSharedWith')->with($group);
- $share->method('setSharedBy')->with($this->currentUser);
+ $share->method('setSharedWith')->with('validGroup');
+ $share->method('setSharedBy')->with('currentUser');
$expected = new \OC_OCS_Result();
$result = $ocs->createShare();
@@ -803,14 +804,12 @@ class Share20OCSTest extends \Test\TestCase {
$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
- $currentUser = $this->currentUser;
-
$this->shareManager->expects($this->once())->method('createShare')->with(
- $this->callback(function (\OCP\Share\IShare $share) use ($path, $currentUser) {
+ $this->callback(function (\OCP\Share\IShare $share) use ($path) {
return $share->getNode() === $path &&
$share->getShareType() === \OCP\Share::SHARE_TYPE_LINK &&
$share->getPermissions() === \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE &&
- $share->getSharedBy() === $currentUser &&
+ $share->getSharedBy() === 'currentUser' &&
$share->getPassword() === null &&
$share->getExpirationDate() === null;
})
@@ -844,14 +843,12 @@ class Share20OCSTest extends \Test\TestCase {
$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
- $currentUser = $this->currentUser;
-
$this->shareManager->expects($this->once())->method('createShare')->with(
- $this->callback(function (\OCP\Share\IShare $share) use ($path, $currentUser) {
+ $this->callback(function (\OCP\Share\IShare $share) use ($path) {
return $share->getNode() === $path &&
$share->getShareType() === \OCP\Share::SHARE_TYPE_LINK &&
$share->getPermissions() === \OCP\Constants::PERMISSION_READ &&
- $share->getSharedBy() === $currentUser &&
+ $share->getSharedBy() === 'currentUser' &&
$share->getPassword() === 'password' &&
$share->getExpirationDate() === null;
})
@@ -885,17 +882,15 @@ class Share20OCSTest extends \Test\TestCase {
$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
- $currentUser = $this->currentUser;
-
$this->shareManager->expects($this->once())->method('createShare')->with(
- $this->callback(function (\OCP\Share\IShare $share) use ($path, $currentUser) {
+ $this->callback(function (\OCP\Share\IShare $share) use ($path) {
$date = new \DateTime('2000-01-01');
$date->setTime(0,0,0);
return $share->getNode() === $path &&
$share->getShareType() === \OCP\Share::SHARE_TYPE_LINK &&
$share->getPermissions() === \OCP\Constants::PERMISSION_READ &&
- $share->getSharedBy() === $currentUser &&
+ $share->getSharedBy() === 'currentUser' &&
$share->getPassword() === null &&
$share->getExpirationDate() == $date;
})
@@ -951,7 +946,7 @@ class Share20OCSTest extends \Test\TestCase {
public function testUpdateNoParametersLink() {
$share = \OC::$server->getShareManager()->newShare();
$share->setPermissions(\OCP\Constants::PERMISSION_ALL)
- ->setSharedBy($this->currentUser)
+ ->setSharedBy($this->currentUser->getUID())
->setShareType(\OCP\Share::SHARE_TYPE_LINK);
$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
@@ -966,7 +961,7 @@ class Share20OCSTest extends \Test\TestCase {
public function testUpdateNoParametersOther() {
$share = \OC::$server->getShareManager()->newShare();
$share->setPermissions(\OCP\Constants::PERMISSION_ALL)
- ->setSharedBy($this->currentUser)
+ ->setSharedBy($this->currentUser->getUID())
->setShareType(\OCP\Share::SHARE_TYPE_GROUP);
$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
@@ -983,7 +978,7 @@ class Share20OCSTest extends \Test\TestCase {
$share = \OC::$server->getShareManager()->newShare();
$share->setPermissions(\OCP\Constants::PERMISSION_ALL)
- ->setSharedBy($this->currentUser)
+ ->setSharedBy($this->currentUser->getUID())
->setShareType(\OCP\Share::SHARE_TYPE_LINK)
->setPassword('password')
->setExpirationDate(new \DateTime())
@@ -1021,7 +1016,7 @@ class Share20OCSTest extends \Test\TestCase {
$share = \OC::$server->getShareManager()->newShare();
$share->setPermissions(\OCP\Constants::PERMISSION_ALL)
- ->setSharedBy($this->currentUser)
+ ->setSharedBy($this->currentUser->getUID())
->setShareType(\OCP\Share::SHARE_TYPE_LINK)
->setNode($folder);
@@ -1061,7 +1056,7 @@ class Share20OCSTest extends \Test\TestCase {
$share = \OC::$server->getShareManager()->newShare();
$share->setPermissions(\OCP\Constants::PERMISSION_ALL)
- ->setSharedBy($this->currentUser)
+ ->setSharedBy($this->currentUser->getUID())
->setShareType(\OCP\Share::SHARE_TYPE_LINK)
->setNode($folder);
@@ -1090,7 +1085,7 @@ class Share20OCSTest extends \Test\TestCase {
$share = \OC::$server->getShareManager()->newShare();
$share->setPermissions(\OCP\Constants::PERMISSION_ALL)
- ->setSharedBy($this->currentUser)
+ ->setSharedBy($this->currentUser->getUID())
->setShareType(\OCP\Share::SHARE_TYPE_LINK)
->setNode($folder);
@@ -1119,7 +1114,7 @@ class Share20OCSTest extends \Test\TestCase {
$share = \OC::$server->getShareManager()->newShare();
$share->setPermissions(\OCP\Constants::PERMISSION_ALL)
- ->setSharedBy($this->currentUser)
+ ->setSharedBy($this->currentUser->getUID())
->setShareType(\OCP\Share::SHARE_TYPE_LINK)
->setNode($file);
@@ -1149,7 +1144,7 @@ class Share20OCSTest extends \Test\TestCase {
$share = \OC::$server->getShareManager()->newShare();
$share->setPermissions(\OCP\Constants::PERMISSION_ALL)
- ->setSharedBy($this->currentUser)
+ ->setSharedBy($this->currentUser->getUID())
->setShareType(\OCP\Share::SHARE_TYPE_LINK)
->setPassword('password')
->setExpirationDate($date)
@@ -1183,7 +1178,7 @@ class Share20OCSTest extends \Test\TestCase {
$share = \OC::$server->getShareManager()->newShare();
$share->setPermissions(\OCP\Constants::PERMISSION_ALL)
- ->setSharedBy($this->currentUser)
+ ->setSharedBy($this->currentUser->getUID())
->setShareType(\OCP\Share::SHARE_TYPE_LINK)
->setPassword('password')
->setExpirationDate(new \DateTime())
@@ -1224,7 +1219,7 @@ class Share20OCSTest extends \Test\TestCase {
$share = \OC::$server->getShareManager()->newShare();
$share->setPermissions(\OCP\Constants::PERMISSION_ALL)
- ->setSharedBy($this->currentUser)
+ ->setSharedBy($this->currentUser->getUID())
->setShareType(\OCP\Share::SHARE_TYPE_LINK)
->setPassword('password')
->setExpirationDate($date)
@@ -1264,7 +1259,7 @@ class Share20OCSTest extends \Test\TestCase {
$share = \OC::$server->getShareManager()->newShare();
$share->setPermissions(\OCP\Constants::PERMISSION_ALL)
- ->setSharedBy($this->currentUser)
+ ->setSharedBy($this->currentUser->getUID())
->setShareType(\OCP\Share::SHARE_TYPE_LINK)
->setPassword('password')
->setExpirationDate($date)
@@ -1304,7 +1299,7 @@ class Share20OCSTest extends \Test\TestCase {
$share = \OC::$server->getShareManager()->newShare();
$share->setPermissions(\OCP\Constants::PERMISSION_ALL)
- ->setSharedBy($this->currentUser)
+ ->setSharedBy($this->currentUser->getUID())
->setShareType(\OCP\Share::SHARE_TYPE_LINK)
->setPassword('password')
->setExpirationDate($date)
@@ -1334,7 +1329,7 @@ class Share20OCSTest extends \Test\TestCase {
$share = \OC::$server->getShareManager()->newShare();
$share->setPermissions(\OCP\Constants::PERMISSION_ALL)
- ->setSharedBy($this->currentUser)
+ ->setSharedBy($this->currentUser->getUID())
->setShareType(\OCP\Share::SHARE_TYPE_USER)
->setNode($file);
diff --git a/apps/files_sharing/tests/controller/sharecontroller.php b/apps/files_sharing/tests/controller/sharecontroller.php
index 9f1d38f9f23..22e15972cd6 100644
--- a/apps/files_sharing/tests/controller/sharecontroller.php
+++ b/apps/files_sharing/tests/controller/sharecontroller.php
@@ -30,11 +30,12 @@
namespace OCA\Files_Sharing\Controllers;
use OC\Files\Filesystem;
-use OC\Share20\Exception\ShareNotFound;
+use OCP\Share\Exceptions\ShareNotFound;
use OCP\AppFramework\Http\NotFoundResponse;
use OCP\AppFramework\Http\RedirectResponse;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\ISession;
+use OCP\IUserManager;
use OCP\Security\ISecureRandom;
use OCP\IURLGenerator;
@@ -64,6 +65,8 @@ class ShareControllerTest extends \Test\TestCase {
private $config;
/** @var \OC\Share20\Manager | \PHPUnit_Framework_MockObject_MockObject */
private $shareManager;
+ /** @var IUserManager | \PHPUnit_Framework_MockObject_MockObject */
+ private $userManager;
protected function setUp() {
$this->appName = 'files_sharing';
@@ -73,13 +76,14 @@ class ShareControllerTest extends \Test\TestCase {
$this->session = $this->getMock('\OCP\ISession');
$this->previewManager = $this->getMock('\OCP\IPreview');
$this->config = $this->getMock('\OCP\IConfig');
+ $this->userManager = $this->getMock('\OCP\IUserManager');
$this->shareController = new \OCA\Files_Sharing\Controllers\ShareController(
$this->appName,
$this->getMock('\OCP\IRequest'),
$this->config,
$this->urlGenerator,
- $this->getMock('\OCP\IUserManager'),
+ $this->userManager,
$this->getMock('\OCP\ILogger'),
$this->getMock('\OCP\Activity\IManager'),
$this->shareManager,
@@ -116,7 +120,7 @@ class ShareControllerTest extends \Test\TestCase {
}
public function testShowAuthenticateNotAuthenticated() {
- $share = $this->getMock('\OCP\Share\IShare');
+ $share = \OC::$server->getShareManager()->newShare();
$this->shareManager
->expects($this->once())
@@ -130,8 +134,8 @@ class ShareControllerTest extends \Test\TestCase {
}
public function testShowAuthenticateAuthenticatedForDifferentShare() {
- $share = $this->getMock('\OCP\Share\IShare');
- $share->method('getId')->willReturn(1);
+ $share = \OC::$server->getShareManager()->newShare();
+ $share->setId(1);
$this->shareManager
->expects($this->once())
@@ -148,8 +152,8 @@ class ShareControllerTest extends \Test\TestCase {
}
public function testShowAuthenticateCorrectShare() {
- $share = $this->getMock('\OCP\Share\IShare');
- $share->method('getId')->willReturn(1);
+ $share = \OC::$server->getShareManager()->newShare();
+ $share->setId(1);
$this->shareManager
->expects($this->once())
@@ -175,7 +179,7 @@ class ShareControllerTest extends \Test\TestCase {
->expects($this->once())
->method('getShareByToken')
->with('token')
- ->will($this->throwException(new \OC\Share20\Exception\ShareNotFound()));
+ ->will($this->throwException(new \OCP\Share\Exceptions\ShareNotFound()));
$response = $this->shareController->authenticate('token');
$expectedResponse = new NotFoundResponse();
@@ -183,8 +187,8 @@ class ShareControllerTest extends \Test\TestCase {
}
public function testAuthenticateValidPassword() {
- $share = $this->getMock('\OCP\Share\IShare');
- $share->method('getId')->willReturn(42);
+ $share = \OC::$server->getShareManager()->newShare();
+ $share->setId(42);
$this->shareManager
->expects($this->once())
@@ -214,8 +218,8 @@ class ShareControllerTest extends \Test\TestCase {
}
public function testAuthenticateInvalidPassword() {
- $share = $this->getMock('\OCP\Share\IShare');
- $share->method('getId')->willReturn(42);
+ $share = \OC::$server->getShareManager()->newShare();
+ $share->setId(42);
$this->shareManager
->expects($this->once())
@@ -252,8 +256,8 @@ class ShareControllerTest extends \Test\TestCase {
}
public function testShowShareNotAuthenticated() {
- $share = $this->getMock('\OCP\Share\IShare');
- $share->method('getPassword')->willReturn('password');
+ $share = \OC::$server->getShareManager()->newShare();
+ $share->setPassword('password');
$this->shareManager
->expects($this->once())
@@ -283,12 +287,12 @@ class ShareControllerTest extends \Test\TestCase {
$file->method('getMimetype')->willReturn('text/plain');
$file->method('getSize')->willReturn(33);
- $share = $this->getMock('\OCP\Share\IShare');
- $share->method('getId')->willReturn('42');
- $share->method('getPassword')->willReturn('password');
- $share->method('getShareOwner')->willReturn($owner);
- $share->method('getNode')->willReturn($file);
- $share->method('getTarget')->willReturn('/file1.txt');
+ $share = \OC::$server->getShareManager()->newShare();
+ $share->setId(42);
+ $share->setPassword('password')
+ ->setShareOwner('ownerUID')
+ ->setNode($file)
+ ->setTarget('/file1.txt');
$this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
$this->session->method('get')->with('public_link_authenticated')->willReturn('42');
@@ -311,6 +315,8 @@ class ShareControllerTest extends \Test\TestCase {
->with('token')
->willReturn($share);
+ $this->userManager->method('get')->with('ownerUID')->willReturn($owner);
+
$response = $this->shareController->showShare('token');
$sharedTmplParams = array(
'displayName' => 'ownerDisplay',
diff --git a/apps/files_sharing/tests/js/publicAppSpec.js b/apps/files_sharing/tests/js/publicAppSpec.js
index 17b7ffc9798..8561836d77c 100644
--- a/apps/files_sharing/tests/js/publicAppSpec.js
+++ b/apps/files_sharing/tests/js/publicAppSpec.js
@@ -21,13 +21,12 @@
describe('OCA.Sharing.PublicApp tests', function() {
var App = OCA.Sharing.PublicApp;
- var hostStub, portStub, protocolStub, webrootStub;
+ var hostStub, protocolStub, webrootStub;
var $preview;
beforeEach(function() {
protocolStub = sinon.stub(OC, 'getProtocol').returns('https');
- hostStub = sinon.stub(OC, 'getHost').returns('example.com');
- portStub = sinon.stub(OC, 'getPort').returns(9876);
+ hostStub = sinon.stub(OC, 'getHost').returns('example.com:9876');
webrootStub = sinon.stub(OC, 'getRootPath').returns('/owncloud');
$preview = $('<div id="preview"></div>');
$('#testArea').append($preview);
@@ -41,7 +40,6 @@ describe('OCA.Sharing.PublicApp tests', function() {
afterEach(function() {
protocolStub.restore();
hostStub.restore();
- portStub.restore();
webrootStub.restore();
});
@@ -91,7 +89,7 @@ describe('OCA.Sharing.PublicApp tests', function() {
it('Uses public webdav endpoint', function() {
expect(fakeServer.requests.length).toEqual(1);
expect(fakeServer.requests[0].method).toEqual('PROPFIND');
- expect(fakeServer.requests[0].url).toEqual('https://example.com/owncloud/public.php/webdav/subdir');
+ expect(fakeServer.requests[0].url).toEqual('https://example.com:9876/owncloud/public.php/webdav/subdir');
expect(fakeServer.requests[0].requestHeaders.Authorization).toEqual('Basic c2g0dG9rOm51bGw=');
});
diff --git a/apps/systemtags/appinfo/info.xml b/apps/systemtags/appinfo/info.xml
index 5da945db703..d0b4c1fce00 100644
--- a/apps/systemtags/appinfo/info.xml
+++ b/apps/systemtags/appinfo/info.xml
@@ -10,9 +10,6 @@
<dependencies>
<owncloud min-version="9.0" max-version="9.0" />
</dependencies>
- <documentation>
- <user>user-systemtags</user>
- </documentation>
<types>
<logging/>
</types>
diff --git a/apps/user_ldap/group_ldap.php b/apps/user_ldap/group_ldap.php
index 76152e1780a..05ab9ddfaae 100644
--- a/apps/user_ldap/group_ldap.php
+++ b/apps/user_ldap/group_ldap.php
@@ -12,6 +12,7 @@
* @author Robin McCorkell <robin@mccorkell.me.uk>
* @author Thomas Müller <thomas.mueller@tmit.eu>
* @author Vincent Petry <pvince81@owncloud.com>
+ * @author Richard Bentley <rbentley@e2advance.com>
*
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @license AGPL-3.0
@@ -148,6 +149,46 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
/**
* @param string $dnGroup
+ * @return array
+ *
+ * For a group that has user membership defined by an LDAP search url attribute returns the users
+ * that match the search url otherwise returns an empty array.
+ */
+ public function getDynamicGroupMembers($dnGroup) {
+ $dynamicGroupMemberURL = strtolower($this->access->connection->ldapDynamicGroupMemberURL);
+
+ if (empty($dynamicGroupMemberURL)) {
+ return array();
+ }
+
+ $dynamicMembers = array();
+ $memberURLs = $this->access->readAttribute(
+ $dnGroup,
+ $dynamicGroupMemberURL,
+ $this->access->connection->ldapGroupFilter
+ );
+ if ($memberURLs !== false) {
+ // this group has the 'memberURL' attribute so this is a dynamic group
+ // example 1: ldap:///cn=users,cn=accounts,dc=dcsubbase,dc=dcbase??one?(o=HeadOffice)
+ // example 2: ldap:///cn=users,cn=accounts,dc=dcsubbase,dc=dcbase??one?(&(o=HeadOffice)(uidNumber>=500))
+ $pos = strpos($memberURLs[0], '(');
+ if ($pos !== false) {
+ $memberUrlFilter = substr($memberURLs[0], $pos);
+ $foundMembers = $this->access->searchUsers($memberUrlFilter,'dn');
+ $dynamicMembers = array();
+ foreach($foundMembers as $value) {
+ $dynamicMembers[$value['dn'][0]] = 1;
+ }
+ } else {
+ \OCP\Util::writeLog('user_ldap', 'No search filter found on member url '.
+ 'of group ' . $dnGroup, \OCP\Util::DEBUG);
+ }
+ }
+ return $dynamicMembers;
+ }
+
+ /**
+ * @param string $dnGroup
* @param array|null &$seen
* @return array|mixed|null
*/
@@ -180,6 +221,9 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
}
}
}
+
+ $allMembers = array_merge($allMembers, $this->getDynamicGroupMembers($dnGroup));
+
$this->access->connection->writeToCache($cacheKey, $allMembers);
return $allMembers;
}
@@ -387,6 +431,8 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
*
* This function fetches all groups a user belongs to. It does not check
* if the user exists at all.
+ *
+ * This function includes groups based on dynamic group membership.
*/
public function getUserGroups($uid) {
if(!$this->enabled) {
@@ -405,6 +451,41 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
$groups = [];
$primaryGroup = $this->getUserPrimaryGroup($userDN);
+ $dynamicGroupMemberURL = strtolower($this->access->connection->ldapDynamicGroupMemberURL);
+
+ if (!empty($dynamicGroupMemberURL)) {
+ // look through dynamic groups to add them to the result array if needed
+ $groupsToMatch = $this->access->fetchListOfGroups(
+ $this->access->connection->ldapGroupFilter,array('dn',$dynamicGroupMemberURL));
+ foreach($groupsToMatch as $dynamicGroup) {
+ if (!array_key_exists($dynamicGroupMemberURL, $dynamicGroup)) {
+ continue;
+ }
+ $pos = strpos($dynamicGroup[$dynamicGroupMemberURL][0], '(');
+ if ($pos !== false) {
+ $memberUrlFilter = substr($dynamicGroup[$dynamicGroupMemberURL][0],$pos);
+ // apply filter via ldap search to see if this user is in this
+ // dynamic group
+ $userMatch = $this->access->readAttribute(
+ $uid,
+ $this->access->connection->ldapUserDisplayName,
+ $memberUrlFilter
+ );
+ if ($userMatch !== false) {
+ // match found so this user is in this group
+ $pos = strpos($dynamicGroup['dn'][0], ',');
+ if ($pos !== false) {
+ $membershipGroup = substr($dynamicGroup['dn'][0],3,$pos-3);
+ $groups[] = $membershipGroup;
+ }
+ }
+ } else {
+ \OCP\Util::writeLog('user_ldap', 'No search filter found on member url '.
+ 'of group ' . print_r($dynamicGroup, true), \OCP\Util::DEBUG);
+ }
+ }
+ }
+
// if possible, read out membership via memberOf. It's far faster than
// performing a search, which still is a fallback later.
if(intval($this->access->connection->hasMemberOfFilterSupport) === 1
diff --git a/apps/user_ldap/js/wizard/wizardTabAdvanced.js b/apps/user_ldap/js/wizard/wizardTabAdvanced.js
index d85dde0ccdf..d1e5002d40a 100644
--- a/apps/user_ldap/js/wizard/wizardTabAdvanced.js
+++ b/apps/user_ldap/js/wizard/wizardTabAdvanced.js
@@ -83,6 +83,10 @@ OCA = OCA || {};
$element: $('#ldap_group_member_assoc_attribute'),
setMethod: 'setGroupMemberAssociationAttribute'
},
+ ldap_dynamic_group_member_url: {
+ $element: $('#ldap_dynamic_group_member_url'),
+ setMethod: 'setDynamicGroupMemberURL'
+ },
ldap_nested_groups: {
$element: $('#ldap_nested_groups'),
setMethod: 'setUseNestedGroups'
@@ -258,6 +262,15 @@ OCA = OCA || {};
},
/**
+ * sets the dynamic group member url attribute
+ *
+ * @param {string} attribute
+ */
+ setDynamicGroupMemberURL: function(attribute) {
+ this.setElementValue(this.managedItems.ldap_dynamic_group_member_url.$element, attribute);
+ },
+
+ /**
* enabled or disables the use of nested groups (groups in groups in
* groups…)
*
diff --git a/apps/user_ldap/l10n/he.js b/apps/user_ldap/l10n/he.js
index 56be7447e72..0e4b78f0373 100644
--- a/apps/user_ldap/l10n/he.js
+++ b/apps/user_ldap/l10n/he.js
@@ -113,7 +113,16 @@ OC.L10N.register(
"Turn off SSL certificate validation." : "כיבוי אימות אישורי אבטחה SSL.",
"in seconds. A change empties the cache." : "בשניות. שינוי מרוקן את המטמון.",
"Directory Settings" : "הגדרות תיקייה",
+ "User Display Name Field" : "שדה שם תצוגה למשתמש",
"Base User Tree" : "עץ משתמש בסיסי",
- "in bytes" : "בבתים"
+ "Base Group Tree" : "עץ קבוצה בסיסי",
+ "Group Search Attributes" : "מאפייני חיפוש קבוצה",
+ "Special Attributes" : "מאפיינים מיוחדים",
+ "Quota Field" : "שדה מכסה",
+ "Quota Default" : "ברירת מחדל מכסה",
+ "in bytes" : "בבתים",
+ "Email Field" : "שדה דואר אלקטרוני",
+ "Internal Username" : "שם משתמש פנימי",
+ "Internal Username Attribute:" : "מאפיין שם משתמש פנימי:"
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/user_ldap/l10n/he.json b/apps/user_ldap/l10n/he.json
index ca2ba2f91a6..21b0cbb70a4 100644
--- a/apps/user_ldap/l10n/he.json
+++ b/apps/user_ldap/l10n/he.json
@@ -111,7 +111,16 @@
"Turn off SSL certificate validation." : "כיבוי אימות אישורי אבטחה SSL.",
"in seconds. A change empties the cache." : "בשניות. שינוי מרוקן את המטמון.",
"Directory Settings" : "הגדרות תיקייה",
+ "User Display Name Field" : "שדה שם תצוגה למשתמש",
"Base User Tree" : "עץ משתמש בסיסי",
- "in bytes" : "בבתים"
+ "Base Group Tree" : "עץ קבוצה בסיסי",
+ "Group Search Attributes" : "מאפייני חיפוש קבוצה",
+ "Special Attributes" : "מאפיינים מיוחדים",
+ "Quota Field" : "שדה מכסה",
+ "Quota Default" : "ברירת מחדל מכסה",
+ "in bytes" : "בבתים",
+ "Email Field" : "שדה דואר אלקטרוני",
+ "Internal Username" : "שם משתמש פנימי",
+ "Internal Username Attribute:" : "מאפיין שם משתמש פנימי:"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/user_ldap/l10n/it.js b/apps/user_ldap/l10n/it.js
index 8bb42e1a72a..8f51e607ab7 100644
--- a/apps/user_ldap/l10n/it.js
+++ b/apps/user_ldap/l10n/it.js
@@ -132,6 +132,8 @@ OC.L10N.register(
"One Group Base DN per line" : "Un DN base gruppo per riga",
"Group Search Attributes" : "Attributi di ricerca gruppo",
"Group-Member association" : "Associazione gruppo-utente ",
+ "Dynamic Group Member URL" : "URL membro di gruppo dinamico",
+ "The LDAP attribute that on group objects contains an LDAP search URL that determines what objects belong to the group. (An empty setting disables dynamic group membership functionality.)" : "L'attributo LDAP che sugli oggetti di gruppo contiene un URL di ricerca LDAP che determina quali oggetti appartengono al gruppo. (Un valore vuoto disabilità la funzionalità di appartenenza ai gruppi dinamica)",
"Nested Groups" : "Gruppi nidificati",
"When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" : "Quando è attivato, i gruppi che contengono altri gruppi sono supportati. (Funziona solo se l'attributo del gruppo membro contiene DN.)",
"Paging chunksize" : "Dimensione del blocco di paginazione",
diff --git a/apps/user_ldap/l10n/it.json b/apps/user_ldap/l10n/it.json
index 73234261016..575ac66c5b5 100644
--- a/apps/user_ldap/l10n/it.json
+++ b/apps/user_ldap/l10n/it.json
@@ -130,6 +130,8 @@
"One Group Base DN per line" : "Un DN base gruppo per riga",
"Group Search Attributes" : "Attributi di ricerca gruppo",
"Group-Member association" : "Associazione gruppo-utente ",
+ "Dynamic Group Member URL" : "URL membro di gruppo dinamico",
+ "The LDAP attribute that on group objects contains an LDAP search URL that determines what objects belong to the group. (An empty setting disables dynamic group membership functionality.)" : "L'attributo LDAP che sugli oggetti di gruppo contiene un URL di ricerca LDAP che determina quali oggetti appartengono al gruppo. (Un valore vuoto disabilità la funzionalità di appartenenza ai gruppi dinamica)",
"Nested Groups" : "Gruppi nidificati",
"When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" : "Quando è attivato, i gruppi che contengono altri gruppi sono supportati. (Funziona solo se l'attributo del gruppo membro contiene DN.)",
"Paging chunksize" : "Dimensione del blocco di paginazione",
diff --git a/apps/user_ldap/l10n/pt_BR.js b/apps/user_ldap/l10n/pt_BR.js
index e027c930ceb..8e52b17dce6 100644
--- a/apps/user_ldap/l10n/pt_BR.js
+++ b/apps/user_ldap/l10n/pt_BR.js
@@ -132,6 +132,8 @@ OC.L10N.register(
"One Group Base DN per line" : "Um grupo-base DN por linha",
"Group Search Attributes" : "Atributos de Busca de Grupo",
"Group-Member association" : "Associação Grupo-Membro",
+ "Dynamic Group Member URL" : "Membro do Grupo Dinâmico URL",
+ "The LDAP attribute that on group objects contains an LDAP search URL that determines what objects belong to the group. (An empty setting disables dynamic group membership functionality.)" : "O atributo LDAP que em objetos do grupo contém uma pesquisa URL LDAP que determina quais objetos pertencem ao grupo. (Um cenário vazio desativa a funcionalidade de membros de grupo dinâmico.)",
"Nested Groups" : "Grupos Aninhados",
"When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" : "Quando habilitado, os grupos que contêm os grupos são suportados. (Só funciona se o atributo de membro de grupo contém DNs.)",
"Paging chunksize" : "Bloco de paginação",
diff --git a/apps/user_ldap/l10n/pt_BR.json b/apps/user_ldap/l10n/pt_BR.json
index 8251fa082a6..4ca70230a19 100644
--- a/apps/user_ldap/l10n/pt_BR.json
+++ b/apps/user_ldap/l10n/pt_BR.json
@@ -130,6 +130,8 @@
"One Group Base DN per line" : "Um grupo-base DN por linha",
"Group Search Attributes" : "Atributos de Busca de Grupo",
"Group-Member association" : "Associação Grupo-Membro",
+ "Dynamic Group Member URL" : "Membro do Grupo Dinâmico URL",
+ "The LDAP attribute that on group objects contains an LDAP search URL that determines what objects belong to the group. (An empty setting disables dynamic group membership functionality.)" : "O atributo LDAP que em objetos do grupo contém uma pesquisa URL LDAP que determina quais objetos pertencem ao grupo. (Um cenário vazio desativa a funcionalidade de membros de grupo dinâmico.)",
"Nested Groups" : "Grupos Aninhados",
"When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" : "Quando habilitado, os grupos que contêm os grupos são suportados. (Só funciona se o atributo de membro de grupo contém DNs.)",
"Paging chunksize" : "Bloco de paginação",
diff --git a/apps/user_ldap/l10n/pt_PT.js b/apps/user_ldap/l10n/pt_PT.js
index d6bd1d9d515..7845d4427a0 100644
--- a/apps/user_ldap/l10n/pt_PT.js
+++ b/apps/user_ldap/l10n/pt_PT.js
@@ -132,6 +132,8 @@ OC.L10N.register(
"One Group Base DN per line" : "Uma base de grupo DN por linha",
"Group Search Attributes" : "Atributos de pesquisa de grupo",
"Group-Member association" : "Associar utilizador ao grupo.",
+ "Dynamic Group Member URL" : "URL Dinâmica de Membro do Grupo",
+ "The LDAP attribute that on group objects contains an LDAP search URL that determines what objects belong to the group. (An empty setting disables dynamic group membership functionality.)" : "O atributo LDAP que em objetos de grupo contém um URL de pesquisa LDAP que determina que objetos pertencem ao grupo. (Uma definição vazia desativa a funcionalidade de membros de grupo dinâmico.)",
"Nested Groups" : "Grupos agrupados",
"When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" : "Quando habilitado os grupos, os grupos são suportados. (Só funciona se o atributo de membro de grupo contém DNs.)",
"Paging chunksize" : "Bloco de paginação",
diff --git a/apps/user_ldap/l10n/pt_PT.json b/apps/user_ldap/l10n/pt_PT.json
index 8073db3efa6..b0538292937 100644
--- a/apps/user_ldap/l10n/pt_PT.json
+++ b/apps/user_ldap/l10n/pt_PT.json
@@ -130,6 +130,8 @@
"One Group Base DN per line" : "Uma base de grupo DN por linha",
"Group Search Attributes" : "Atributos de pesquisa de grupo",
"Group-Member association" : "Associar utilizador ao grupo.",
+ "Dynamic Group Member URL" : "URL Dinâmica de Membro do Grupo",
+ "The LDAP attribute that on group objects contains an LDAP search URL that determines what objects belong to the group. (An empty setting disables dynamic group membership functionality.)" : "O atributo LDAP que em objetos de grupo contém um URL de pesquisa LDAP que determina que objetos pertencem ao grupo. (Uma definição vazia desativa a funcionalidade de membros de grupo dinâmico.)",
"Nested Groups" : "Grupos agrupados",
"When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" : "Quando habilitado os grupos, os grupos são suportados. (Só funciona se o atributo de membro de grupo contém DNs.)",
"Paging chunksize" : "Bloco de paginação",
diff --git a/apps/user_ldap/l10n/sq.js b/apps/user_ldap/l10n/sq.js
index aaebf07862d..e2db8bfe618 100644
--- a/apps/user_ldap/l10n/sq.js
+++ b/apps/user_ldap/l10n/sq.js
@@ -132,8 +132,12 @@ OC.L10N.register(
"One Group Base DN per line" : "Një DN Bazë Grupi për rresht",
"Group Search Attributes" : "Atribute Kërkimi Grupi",
"Group-Member association" : "Përshoqërim Grup-Përdorues",
+ "Dynamic Group Member URL" : "URL Anëtari Grupi Dinamik",
+ "The LDAP attribute that on group objects contains an LDAP search URL that determines what objects belong to the group. (An empty setting disables dynamic group membership functionality.)" : "Atributi LDAP që në objekte grupi përmban një URL kërkimi LDAP që përcakton se cilat objekte i përkasin grupit. (Nëse rregullimi lihet i zbrazët, funksioni i anëtarësisë në grup dinamik.)",
"Nested Groups" : "Grupe Brenda Njëri-Tjetrit",
"When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" : "Kur aktivizohet, grupet që përmbajnë grupe mbulohen. (Funksionon vetëm nëse atributi për anëtar grupi përmban DN-ra.)",
+ "Paging chunksize" : "Madhësi copash faqosjeje",
+ "Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)" : "Madhësi copash të përdorura për kërkime LDAP të sistemuara në faqe, kërkime që japin përfundime të papërpunuara, të tilla si numër përdoruesish ose grupesh. (Caktimi si 0 i çaktivizon kërkimet e faqosura LDAP për këto raste.)",
"Special Attributes" : "Atribute Speciale",
"Quota Field" : "Fushë Kuotash",
"Quota Default" : "Parazgjedhje Kuotash",
diff --git a/apps/user_ldap/l10n/sq.json b/apps/user_ldap/l10n/sq.json
index 335a42630b5..93ae9c7b818 100644
--- a/apps/user_ldap/l10n/sq.json
+++ b/apps/user_ldap/l10n/sq.json
@@ -130,8 +130,12 @@
"One Group Base DN per line" : "Një DN Bazë Grupi për rresht",
"Group Search Attributes" : "Atribute Kërkimi Grupi",
"Group-Member association" : "Përshoqërim Grup-Përdorues",
+ "Dynamic Group Member URL" : "URL Anëtari Grupi Dinamik",
+ "The LDAP attribute that on group objects contains an LDAP search URL that determines what objects belong to the group. (An empty setting disables dynamic group membership functionality.)" : "Atributi LDAP që në objekte grupi përmban një URL kërkimi LDAP që përcakton se cilat objekte i përkasin grupit. (Nëse rregullimi lihet i zbrazët, funksioni i anëtarësisë në grup dinamik.)",
"Nested Groups" : "Grupe Brenda Njëri-Tjetrit",
"When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" : "Kur aktivizohet, grupet që përmbajnë grupe mbulohen. (Funksionon vetëm nëse atributi për anëtar grupi përmban DN-ra.)",
+ "Paging chunksize" : "Madhësi copash faqosjeje",
+ "Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)" : "Madhësi copash të përdorura për kërkime LDAP të sistemuara në faqe, kërkime që japin përfundime të papërpunuara, të tilla si numër përdoruesish ose grupesh. (Caktimi si 0 i çaktivizon kërkimet e faqosura LDAP për këto raste.)",
"Special Attributes" : "Atribute Speciale",
"Quota Field" : "Fushë Kuotash",
"Quota Default" : "Parazgjedhje Kuotash",
diff --git a/apps/user_ldap/lib/configuration.php b/apps/user_ldap/lib/configuration.php
index 752f3e81a3e..f829160b62a 100644
--- a/apps/user_ldap/lib/configuration.php
+++ b/apps/user_ldap/lib/configuration.php
@@ -7,6 +7,7 @@
* @author Lukas Reschke <lukas@owncloud.com>
* @author Morris Jobke <hey@morrisjobke.de>
* @author Robin McCorkell <robin@mccorkell.me.uk>
+ * @author Richard Bentley <rbentley@e2advance.com>
*
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @license AGPL-3.0
@@ -84,6 +85,7 @@ class Configuration {
'lastJpegPhotoLookup' => null,
'ldapNestedGroups' => false,
'ldapPagingSize' => null,
+ 'ldapDynamicGroupMemberURL' => null,
);
/**
@@ -442,6 +444,7 @@ class Configuration {
'ldap_nested_groups' => 0,
'ldap_paging_size' => 500,
'ldap_experienced_admin' => 0,
+ 'ldap_dynamic_group_member_url' => '',
);
}
@@ -496,7 +499,8 @@ class Configuration {
'last_jpegPhoto_lookup' => 'lastJpegPhotoLookup',
'ldap_nested_groups' => 'ldapNestedGroups',
'ldap_paging_size' => 'ldapPagingSize',
- 'ldap_experienced_admin' => 'ldapExperiencedAdmin'
+ 'ldap_experienced_admin' => 'ldapExperiencedAdmin',
+ 'ldap_dynamic_group_member_url' => 'ldapDynamicGroupMemberURL',
);
return $array;
}
diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php
index 3ba106bec9f..23e6d5591a9 100644
--- a/apps/user_ldap/templates/settings.php
+++ b/apps/user_ldap/templates/settings.php
@@ -91,6 +91,7 @@ style('user_ldap', 'settings');
<p><label for="ldap_base_groups"><?php p($l->t('Base Group Tree'));?></label><textarea id="ldap_base_groups" name="ldap_base_groups" placeholder="<?php p($l->t('One Group Base DN per line'));?>" data-default="<?php p($_['ldap_base_groups_default']); ?>" title="<?php p($l->t('Base Group Tree'));?>"></textarea></p>
<p><label for="ldap_attributes_for_group_search"><?php p($l->t('Group Search Attributes'));?></label><textarea id="ldap_attributes_for_group_search" name="ldap_attributes_for_group_search" placeholder="<?php p($l->t('Optional; one attribute per line'));?>" data-default="<?php p($_['ldap_attributes_for_group_search_default']); ?>" title="<?php p($l->t('Group Search Attributes'));?>"></textarea></p>
<p><label for="ldap_group_member_assoc_attribute"><?php p($l->t('Group-Member association'));?></label><select id="ldap_group_member_assoc_attribute" name="ldap_group_member_assoc_attribute" data-default="<?php p($_['ldap_group_member_assoc_attribute_default']); ?>" ><option value="uniqueMember"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'uniqueMember')) p(' selected'); ?>>uniqueMember</option><option value="memberUid"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'memberUid')) p(' selected'); ?>>memberUid</option><option value="member"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'member')) p(' selected'); ?>>member (AD)</option></select></p>
+ <p><label for="ldap_dynamic_group_member_url"><?php p($l->t('Dynamic Group Member URL'));?></label><input type="text" id="ldap_dynamic_group_member_url" name="ldap_dynamic_group_member_url" title="<?php p($l->t('The LDAP attribute that on group objects contains an LDAP search URL that determines what objects belong to the group. (An empty setting disables dynamic group membership functionality.)'));?>" data-default="<?php p($_['ldap_dynamic_group_member_url_default']); ?>" /></p>
<p><label for="ldap_nested_groups"><?php p($l->t('Nested Groups'));?></label><input type="checkbox" id="ldap_nested_groups" name="ldap_nested_groups" value="1" data-default="<?php p($_['ldap_nested_groups_default']); ?>" title="<?php p($l->t('When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)'));?>" /></p>
<p><label for="ldap_paging_size"><?php p($l->t('Paging chunksize'));?></label><input type="number" id="ldap_paging_size" name="ldap_paging_size" title="<?php p($l->t('Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)'));?>" data-default="<?php p($_['ldap_paging_size_default']); ?>" /></p>
</div>
diff --git a/apps/user_ldap/tests/group_ldap.php b/apps/user_ldap/tests/group_ldap.php
index 5f9ded878ca..667a1c3acb2 100644
--- a/apps/user_ldap/tests/group_ldap.php
+++ b/apps/user_ldap/tests/group_ldap.php
@@ -67,10 +67,13 @@ class Test_Group_Ldap extends \Test\TestCase {
private function enableGroups($access) {
$access->connection->expects($this->any())
- ->method('__get')
- ->will($this->returnCallback(function() {
- return 1;
- }));
+ ->method('__get')
+ ->will($this->returnCallback(function($name) {
+ if($name === 'ldapDynamicGroupMemberURL') {
+ return '';
+ }
+ return 1;
+ }));
}
public function testCountEmptySearchString() {
@@ -430,6 +433,8 @@ class Test_Group_Ldap extends \Test\TestCase {
->will($this->returnCallback(function($name) {
if($name === 'useMemberOfToDetectMembership') {
return 0;
+ } else if($name === 'ldapDynamicGroupMemberURL') {
+ return '';
}
return 1;
}));
diff --git a/build/integration/features/sharing-v1.feature b/build/integration/features/sharing-v1.feature
index bdc1a4224d8..1a1a5c1981a 100644
--- a/build/integration/features/sharing-v1.feature
+++ b/build/integration/features/sharing-v1.feature
@@ -480,13 +480,18 @@ Feature: sharing
Then the OCS status code should be "100"
And the HTTP status code should be "200"
-
-
-
-
-
-
-
-
-
-
+ Scenario: Keep usergroup shares (#22143)
+ Given As an "admin"
+ And user "user0" exists
+ And user "user1" exists
+ And user "user2" exists
+ And group "group" exists
+ And user "user1" belongs to group "group"
+ And user "user2" belongs to group "group"
+ And user "user0" created a folder "/TMP"
+ And file "TMP" of user "user0" is shared with group "group"
+ And user "user1" created a folder "/myFOLDER"
+ And User "user1" moves file "/TMP" to "/myFOLDER/myTMP"
+ And user "user2" does not exist
+ And user "user1" should see following elements
+ | /myFOLDER/myTMP/ |
diff --git a/config/config.sample.php b/config/config.sample.php
index bdbf3f42046..81a02efb3f7 100644
--- a/config/config.sample.php
+++ b/config/config.sample.php
@@ -1196,15 +1196,6 @@ $CONFIG = array(
'debug' => false,
/**
- * Skips the migration test during upgrades
- *
- * If this is set to true the migration test are deactivated during upgrade.
- * This is only recommended in installations where upgrade tests are run in
- * advance with the same data on a test system.
- */
-'update.skip-migration-test' => false,
-
-/**
* This entry is just here to show a warning in case somebody copied the sample
* configuration. DO NOT ADD THIS SWITCH TO YOUR CONFIGURATION!
*
diff --git a/console.php b/console.php
index 2073654fa8d..d08d400c051 100644
--- a/console.php
+++ b/console.php
@@ -80,7 +80,7 @@ try {
echo "The process control (PCNTL) extensions are required in case you want to interrupt long running commands - see http://php.net/manual/en/book.pcntl.php" . PHP_EOL;
}
- $application = new Application(\OC::$server->getConfig());
+ $application = new Application(\OC::$server->getConfig(), \OC::$server->getEventDispatcher(), \OC::$server->getRequest());
$application->loadCommands(new ConsoleOutput());
$application->run();
} catch (Exception $ex) {
diff --git a/core/ajax/update.php b/core/ajax/update.php
index 15daff4e1de..4d8fe19f168 100644
--- a/core/ajax/update.php
+++ b/core/ajax/update.php
@@ -50,12 +50,6 @@ if (OC::checkUpgrade(false)) {
\OC::$server->getIntegrityCodeChecker(),
$logger
);
-
- if ($config->getSystemValue('update.skip-migration-test', false)) {
- $eventSource->send('success', (string)$l->t('Migration tests are skipped - "update.skip-migration-test" is activated in config.php'));
- $updater->setSimulateStepEnabled(false);
- }
-
$incompatibleApps = [];
$disabledThirdPartyApps = [];
diff --git a/core/command/integrity/signcore.php b/core/command/integrity/signcore.php
index 531a4d33aa3..e5c2de73e00 100644
--- a/core/command/integrity/signcore.php
+++ b/core/command/integrity/signcore.php
@@ -59,7 +59,8 @@ class SignCore extends Command {
->setName('integrity:sign-core')
->setDescription('Sign core using a private key.')
->addOption('privateKey', null, InputOption::VALUE_REQUIRED, 'Path to private key to use for signing')
- ->addOption('certificate', null, InputOption::VALUE_REQUIRED, 'Path to certificate to use for signing');
+ ->addOption('certificate', null, InputOption::VALUE_REQUIRED, 'Path to certificate to use for signing')
+ ->addOption('path', null, InputOption::VALUE_REQUIRED, 'Path of core to sign');
}
/**
@@ -68,8 +69,9 @@ class SignCore extends Command {
protected function execute(InputInterface $input, OutputInterface $output) {
$privateKeyPath = $input->getOption('privateKey');
$keyBundlePath = $input->getOption('certificate');
- if(is_null($privateKeyPath) || is_null($keyBundlePath)) {
- $output->writeln('--privateKey and --certificate are required.');
+ $path = $input->getOption('path');
+ if(is_null($privateKeyPath) || is_null($keyBundlePath) || is_null($path)) {
+ $output->writeln('--privateKey, --certificate and --path are required.');
return null;
}
@@ -91,7 +93,7 @@ class SignCore extends Command {
$x509 = new X509();
$x509->loadX509($keyBundle);
$x509->setPrivateKey($rsa);
- $this->checker->writeCoreSignature($x509, $rsa);
+ $this->checker->writeCoreSignature($x509, $rsa, $path);
$output->writeln('Successfully signed "core"');
}
diff --git a/core/command/upgrade.php b/core/command/upgrade.php
index 2123efdfd38..c45984d7a30 100644
--- a/core/command/upgrade.php
+++ b/core/command/upgrade.php
@@ -99,12 +99,6 @@ class Upgrade extends Command {
$updateStepEnabled = true;
$skip3rdPartyAppsDisable = false;
- if ($this->config->getSystemValue('update.skip-migration-test', false)) {
- $output->writeln(
- '<info>"skip-migration-test" is activated via config.php</info>'
- );
- $simulateStepEnabled = false;
- }
if ($input->getOption('skip-migration-test')) {
$simulateStepEnabled = false;
}
diff --git a/core/css/systemtags.css b/core/css/systemtags.css
index 2a02bc05ea7..588c76e1e3f 100644
--- a/core/css/systemtags.css
+++ b/core/css/systemtags.css
@@ -76,4 +76,10 @@
.systemtags-select2-container .select2-choices .select2-search-field input {
line-height: 20px;
}
-
+.systemtags-select2-dropdown .label {
+ width:85%;
+ display:-moz-inline-box;
+ display:inline-block;
+ overflow:hidden;
+ text-overflow:ellipsis;
+}
diff --git a/core/img/actions/comment.png b/core/img/actions/comment.png
new file mode 100644
index 00000000000..7ca20eba363
--- /dev/null
+++ b/core/img/actions/comment.png
Binary files differ
diff --git a/core/img/actions/comment.svg b/core/img/actions/comment.svg
new file mode 100644
index 00000000000..a8ab95e615b
--- /dev/null
+++ b/core/img/actions/comment.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <path style="color:#000000;block-progression:tb;text-transform:none;text-indent:0" d="m2.3496 1.002c-0.1975 0.0382-0.3531 0.2333-0.3496 0.4375v13.122c0 0.23 0.2061 0.438 0.4316 0.438h11.138c0.226 0 0.432-0.208 0.432-0.438v-10.142c-0.004-0.0669-0.023-0.133-0.055-0.1915l-3.312-3.1992c-0.043-0.0164-0.089-0.0255-0.135-0.0273h-8.0684c-0.0268-0.00265-0.0552-0.00265-0.082 0zm1.6504 1.998h6v1h-6v-1zm0 3h5v1h-5v-1zm0 3h8v1h-8v-1zm0 3h4v1h-4v-1z"/>
+</svg>
diff --git a/core/img/appstore.png b/core/img/appstore.png
deleted file mode 100644
index 2b90216f797..00000000000
--- a/core/img/appstore.png
+++ /dev/null
Binary files differ
diff --git a/core/img/appstore.svg b/core/img/appstore.svg
new file mode 100644
index 00000000000..ac111e59746
--- /dev/null
+++ b/core/img/appstore.svg
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="US_UK_Download_on_the" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+ x="0px" y="0px" width="135px" height="40px" viewBox="0 0 135 40" enable-background="new 0 0 135 40" xml:space="preserve">
+<g>
+ <path fill="#A6A6A6" d="M130.197,40H4.729C2.122,40,0,37.872,0,35.267V4.726C0,2.12,2.122,0,4.729,0h125.468
+ C132.803,0,135,2.12,135,4.726v30.541C135,37.872,132.803,40,130.197,40L130.197,40z"/>
+ <path d="M134.032,35.268c0,2.116-1.714,3.83-3.834,3.83H4.729c-2.119,0-3.839-1.714-3.839-3.83V4.725
+ c0-2.115,1.72-3.835,3.839-3.835h125.468c2.121,0,3.834,1.72,3.834,3.835L134.032,35.268L134.032,35.268z"/>
+ <g>
+ <g>
+ <path fill="#FFFFFF" d="M30.128,19.784c-0.029-3.223,2.639-4.791,2.761-4.864c-1.511-2.203-3.853-2.504-4.676-2.528
+ c-1.967-0.207-3.875,1.177-4.877,1.177c-1.022,0-2.565-1.157-4.228-1.123c-2.14,0.033-4.142,1.272-5.24,3.196
+ c-2.266,3.923-0.576,9.688,1.595,12.859c1.086,1.553,2.355,3.287,4.016,3.226c1.625-0.067,2.232-1.036,4.193-1.036
+ c1.943,0,2.513,1.036,4.207,0.997c1.744-0.028,2.842-1.56,3.89-3.127c1.255-1.78,1.759-3.533,1.779-3.623
+ C33.507,24.924,30.161,23.647,30.128,19.784z"/>
+ <path fill="#FFFFFF" d="M26.928,10.306c0.874-1.093,1.472-2.58,1.306-4.089c-1.265,0.056-2.847,0.875-3.758,1.944
+ c-0.806,0.942-1.526,2.486-1.34,3.938C24.557,12.205,26.016,11.382,26.928,10.306z"/>
+ </g>
+ </g>
+ <g>
+ <path fill="#FFFFFF" d="M53.645,31.504h-2.271l-1.244-3.909h-4.324l-1.185,3.909h-2.211l4.284-13.308h2.646L53.645,31.504z
+ M49.755,25.955L48.63,22.48c-0.119-0.355-0.342-1.191-0.671-2.507h-0.04c-0.131,0.566-0.342,1.402-0.632,2.507l-1.105,3.475
+ H49.755z"/>
+ <path fill="#FFFFFF" d="M64.662,26.588c0,1.632-0.441,2.922-1.323,3.869c-0.79,0.843-1.771,1.264-2.942,1.264
+ c-1.264,0-2.172-0.454-2.725-1.362h-0.04v5.055h-2.132V25.067c0-1.026-0.027-2.079-0.079-3.159h1.875l0.119,1.521h0.04
+ c0.711-1.146,1.79-1.718,3.238-1.718c1.132,0,2.077,0.447,2.833,1.342C64.284,23.949,64.662,25.127,64.662,26.588z M62.49,26.666
+ c0-0.934-0.21-1.704-0.632-2.31c-0.461-0.632-1.08-0.948-1.856-0.948c-0.526,0-1.004,0.176-1.431,0.523
+ c-0.428,0.35-0.708,0.807-0.839,1.373c-0.066,0.264-0.099,0.48-0.099,0.65v1.6c0,0.698,0.214,1.287,0.642,1.768
+ s0.984,0.721,1.668,0.721c0.803,0,1.428-0.31,1.875-0.928C62.266,28.496,62.49,27.68,62.49,26.666z"/>
+ <path fill="#FFFFFF" d="M75.699,26.588c0,1.632-0.441,2.922-1.324,3.869c-0.789,0.843-1.77,1.264-2.941,1.264
+ c-1.264,0-2.172-0.454-2.724-1.362H68.67v5.055h-2.132V25.067c0-1.026-0.027-2.079-0.079-3.159h1.875l0.119,1.521h0.04
+ c0.71-1.146,1.789-1.718,3.238-1.718c1.131,0,2.076,0.447,2.834,1.342C75.32,23.949,75.699,25.127,75.699,26.588z M73.527,26.666
+ c0-0.934-0.211-1.704-0.633-2.31c-0.461-0.632-1.078-0.948-1.855-0.948c-0.527,0-1.004,0.176-1.432,0.523
+ c-0.428,0.35-0.707,0.807-0.838,1.373c-0.065,0.264-0.099,0.48-0.099,0.65v1.6c0,0.698,0.214,1.287,0.64,1.768
+ c0.428,0.48,0.984,0.721,1.67,0.721c0.803,0,1.428-0.31,1.875-0.928C73.303,28.496,73.527,27.68,73.527,26.666z"/>
+ <path fill="#FFFFFF" d="M88.039,27.772c0,1.132-0.393,2.053-1.182,2.764c-0.867,0.777-2.074,1.165-3.625,1.165
+ c-1.432,0-2.58-0.276-3.449-0.829l0.494-1.777c0.936,0.566,1.963,0.85,3.082,0.85c0.803,0,1.428-0.182,1.877-0.544
+ c0.447-0.362,0.67-0.848,0.67-1.454c0-0.54-0.184-0.995-0.553-1.364c-0.367-0.369-0.98-0.712-1.836-1.029
+ c-2.33-0.869-3.494-2.142-3.494-3.816c0-1.094,0.408-1.991,1.225-2.689c0.814-0.699,1.9-1.048,3.258-1.048
+ c1.211,0,2.217,0.211,3.02,0.632l-0.533,1.738c-0.75-0.408-1.598-0.612-2.547-0.612c-0.75,0-1.336,0.185-1.756,0.553
+ c-0.355,0.329-0.533,0.73-0.533,1.205c0,0.526,0.203,0.961,0.611,1.303c0.355,0.316,1,0.658,1.936,1.027
+ c1.145,0.461,1.986,1,2.527,1.618C87.77,26.081,88.039,26.852,88.039,27.772z"/>
+ <path fill="#FFFFFF" d="M95.088,23.508h-2.35v4.659c0,1.185,0.414,1.777,1.244,1.777c0.381,0,0.697-0.033,0.947-0.099l0.059,1.619
+ c-0.42,0.157-0.973,0.236-1.658,0.236c-0.842,0-1.5-0.257-1.975-0.77c-0.473-0.514-0.711-1.376-0.711-2.587v-4.837h-1.4v-1.6h1.4
+ v-1.757l2.094-0.632v2.389h2.35V23.508z"/>
+ <path fill="#FFFFFF" d="M105.691,26.627c0,1.475-0.422,2.686-1.264,3.633c-0.883,0.975-2.055,1.461-3.516,1.461
+ c-1.408,0-2.529-0.467-3.365-1.401s-1.254-2.113-1.254-3.534c0-1.487,0.43-2.705,1.293-3.652c0.861-0.948,2.023-1.422,3.484-1.422
+ c1.408,0,2.541,0.467,3.396,1.402C105.283,24.021,105.691,25.192,105.691,26.627z M103.479,26.696
+ c0-0.885-0.189-1.644-0.572-2.277c-0.447-0.766-1.086-1.148-1.914-1.148c-0.857,0-1.508,0.383-1.955,1.148
+ c-0.383,0.634-0.572,1.405-0.572,2.317c0,0.885,0.189,1.644,0.572,2.276c0.461,0.766,1.105,1.148,1.936,1.148
+ c0.814,0,1.453-0.39,1.914-1.168C103.281,28.347,103.479,27.58,103.479,26.696z"/>
+ <path fill="#FFFFFF" d="M112.621,23.783c-0.211-0.039-0.436-0.059-0.672-0.059c-0.75,0-1.33,0.283-1.738,0.85
+ c-0.355,0.5-0.533,1.132-0.533,1.895v5.035h-2.131l0.02-6.574c0-1.106-0.027-2.113-0.08-3.021h1.857l0.078,1.836h0.059
+ c0.225-0.631,0.58-1.139,1.066-1.52c0.475-0.343,0.988-0.514,1.541-0.514c0.197,0,0.375,0.014,0.533,0.039V23.783z"/>
+ <path fill="#FFFFFF" d="M122.156,26.252c0,0.382-0.025,0.704-0.078,0.967h-6.396c0.025,0.948,0.334,1.673,0.928,2.173
+ c0.539,0.447,1.236,0.671,2.092,0.671c0.947,0,1.811-0.151,2.588-0.454l0.334,1.48c-0.908,0.396-1.98,0.593-3.217,0.593
+ c-1.488,0-2.656-0.438-3.506-1.313c-0.848-0.875-1.273-2.05-1.273-3.524c0-1.447,0.395-2.652,1.186-3.613
+ c0.828-1.026,1.947-1.539,3.355-1.539c1.383,0,2.43,0.513,3.141,1.539C121.873,24.047,122.156,25.055,122.156,26.252z
+ M120.123,25.699c0.014-0.632-0.125-1.178-0.414-1.639c-0.369-0.593-0.936-0.889-1.699-0.889c-0.697,0-1.264,0.289-1.697,0.869
+ c-0.355,0.461-0.566,1.014-0.631,1.658H120.123z"/>
+ </g>
+ <g>
+ <g>
+ <path fill="#FFFFFF" d="M49.05,10.009c0,1.177-0.353,2.063-1.058,2.658c-0.653,0.549-1.581,0.824-2.783,0.824
+ c-0.596,0-1.106-0.026-1.533-0.078V6.982c0.557-0.09,1.157-0.136,1.805-0.136c1.145,0,2.008,0.249,2.59,0.747
+ C48.723,8.156,49.05,8.961,49.05,10.009z M47.945,10.038c0-0.763-0.202-1.348-0.606-1.756c-0.404-0.407-0.994-0.611-1.771-0.611
+ c-0.33,0-0.611,0.022-0.844,0.068v4.889c0.129,0.02,0.365,0.029,0.708,0.029c0.802,0,1.421-0.223,1.857-0.669
+ S47.945,10.892,47.945,10.038z"/>
+ <path fill="#FFFFFF" d="M54.909,11.037c0,0.725-0.207,1.319-0.621,1.785c-0.434,0.479-1.009,0.718-1.727,0.718
+ c-0.692,0-1.243-0.229-1.654-0.689c-0.41-0.459-0.615-1.038-0.615-1.736c0-0.73,0.211-1.329,0.635-1.794s0.994-0.698,1.712-0.698
+ c0.692,0,1.248,0.229,1.669,0.688C54.708,9.757,54.909,10.333,54.909,11.037z M53.822,11.071c0-0.435-0.094-0.808-0.281-1.119
+ c-0.22-0.376-0.533-0.564-0.94-0.564c-0.421,0-0.741,0.188-0.961,0.564c-0.188,0.311-0.281,0.69-0.281,1.138
+ c0,0.435,0.094,0.808,0.281,1.119c0.227,0.376,0.543,0.564,0.951,0.564c0.4,0,0.714-0.191,0.94-0.574
+ C53.725,11.882,53.822,11.506,53.822,11.071z"/>
+ <path fill="#FFFFFF" d="M62.765,8.719l-1.475,4.714h-0.96l-0.611-2.047c-0.155-0.511-0.281-1.019-0.379-1.523h-0.019
+ c-0.091,0.518-0.217,1.025-0.379,1.523l-0.649,2.047h-0.971l-1.387-4.714h1.077l0.533,2.241c0.129,0.53,0.235,1.035,0.32,1.513
+ h0.019c0.078-0.394,0.207-0.896,0.389-1.503l0.669-2.25h0.854l0.641,2.202c0.155,0.537,0.281,1.054,0.378,1.552h0.029
+ c0.071-0.485,0.178-1.002,0.32-1.552l0.572-2.202H62.765z"/>
+ <path fill="#FFFFFF" d="M68.198,13.433H67.15v-2.7c0-0.832-0.316-1.248-0.95-1.248c-0.311,0-0.562,0.114-0.757,0.343
+ c-0.193,0.229-0.291,0.499-0.291,0.808v2.796h-1.048v-3.366c0-0.414-0.013-0.863-0.038-1.349h0.921l0.049,0.737h0.029
+ c0.122-0.229,0.304-0.418,0.543-0.569c0.284-0.176,0.602-0.265,0.95-0.265c0.44,0,0.806,0.142,1.097,0.427
+ c0.362,0.349,0.543,0.87,0.543,1.562V13.433z"/>
+ <path fill="#FFFFFF" d="M71.088,13.433h-1.047V6.556h1.047V13.433z"/>
+ <path fill="#FFFFFF" d="M77.258,11.037c0,0.725-0.207,1.319-0.621,1.785c-0.434,0.479-1.01,0.718-1.727,0.718
+ c-0.693,0-1.244-0.229-1.654-0.689c-0.41-0.459-0.615-1.038-0.615-1.736c0-0.73,0.211-1.329,0.635-1.794s0.994-0.698,1.711-0.698
+ c0.693,0,1.248,0.229,1.67,0.688C77.057,9.757,77.258,10.333,77.258,11.037z M76.17,11.071c0-0.435-0.094-0.808-0.281-1.119
+ c-0.219-0.376-0.533-0.564-0.939-0.564c-0.422,0-0.742,0.188-0.961,0.564c-0.188,0.311-0.281,0.69-0.281,1.138
+ c0,0.435,0.094,0.808,0.281,1.119c0.227,0.376,0.543,0.564,0.951,0.564c0.4,0,0.713-0.191,0.939-0.574
+ C76.074,11.882,76.17,11.506,76.17,11.071z"/>
+ <path fill="#FFFFFF" d="M82.33,13.433h-0.941l-0.078-0.543h-0.029c-0.322,0.433-0.781,0.65-1.377,0.65
+ c-0.445,0-0.805-0.143-1.076-0.427c-0.246-0.258-0.369-0.579-0.369-0.96c0-0.576,0.24-1.015,0.723-1.319
+ c0.482-0.304,1.16-0.453,2.033-0.446V10.3c0-0.621-0.326-0.931-0.979-0.931c-0.465,0-0.875,0.117-1.229,0.349l-0.213-0.688
+ c0.438-0.271,0.979-0.407,1.617-0.407c1.232,0,1.85,0.65,1.85,1.95v1.736C82.262,12.78,82.285,13.155,82.33,13.433z
+ M81.242,11.813v-0.727c-1.156-0.02-1.734,0.297-1.734,0.95c0,0.246,0.066,0.43,0.201,0.553c0.135,0.123,0.307,0.184,0.512,0.184
+ c0.23,0,0.445-0.073,0.641-0.218c0.197-0.146,0.318-0.331,0.363-0.558C81.236,11.946,81.242,11.884,81.242,11.813z"/>
+ <path fill="#FFFFFF" d="M88.285,13.433h-0.93l-0.049-0.757h-0.029c-0.297,0.576-0.803,0.864-1.514,0.864
+ c-0.568,0-1.041-0.223-1.416-0.669s-0.562-1.025-0.562-1.736c0-0.763,0.203-1.381,0.611-1.853c0.395-0.44,0.879-0.66,1.455-0.66
+ c0.633,0,1.076,0.213,1.328,0.64h0.02V6.556h1.049v5.607C88.248,12.622,88.26,13.045,88.285,13.433z M87.199,11.445v-0.786
+ c0-0.136-0.01-0.246-0.029-0.33c-0.059-0.252-0.186-0.464-0.379-0.635c-0.195-0.171-0.43-0.257-0.701-0.257
+ c-0.391,0-0.697,0.155-0.922,0.466c-0.223,0.311-0.336,0.708-0.336,1.193c0,0.466,0.107,0.844,0.322,1.135
+ c0.227,0.31,0.533,0.465,0.916,0.465c0.344,0,0.619-0.129,0.828-0.388C87.1,12.069,87.199,11.781,87.199,11.445z"/>
+ <path fill="#FFFFFF" d="M97.248,11.037c0,0.725-0.207,1.319-0.621,1.785c-0.434,0.479-1.008,0.718-1.727,0.718
+ c-0.691,0-1.242-0.229-1.654-0.689c-0.41-0.459-0.615-1.038-0.615-1.736c0-0.73,0.211-1.329,0.635-1.794s0.994-0.698,1.713-0.698
+ c0.691,0,1.248,0.229,1.668,0.688C97.047,9.757,97.248,10.333,97.248,11.037z M96.162,11.071c0-0.435-0.094-0.808-0.281-1.119
+ c-0.221-0.376-0.533-0.564-0.941-0.564c-0.42,0-0.74,0.188-0.961,0.564c-0.188,0.311-0.281,0.69-0.281,1.138
+ c0,0.435,0.094,0.808,0.281,1.119c0.227,0.376,0.543,0.564,0.951,0.564c0.4,0,0.715-0.191,0.941-0.574
+ C96.064,11.882,96.162,11.506,96.162,11.071z"/>
+ <path fill="#FFFFFF" d="M102.883,13.433h-1.047v-2.7c0-0.832-0.316-1.248-0.951-1.248c-0.311,0-0.562,0.114-0.756,0.343
+ s-0.291,0.499-0.291,0.808v2.796h-1.049v-3.366c0-0.414-0.012-0.863-0.037-1.349h0.92l0.049,0.737h0.029
+ c0.123-0.229,0.305-0.418,0.543-0.569c0.285-0.176,0.602-0.265,0.951-0.265c0.439,0,0.805,0.142,1.096,0.427
+ c0.363,0.349,0.543,0.87,0.543,1.562V13.433z"/>
+ <path fill="#FFFFFF" d="M109.936,9.504h-1.154v2.29c0,0.582,0.205,0.873,0.611,0.873c0.188,0,0.344-0.016,0.467-0.049
+ l0.027,0.795c-0.207,0.078-0.479,0.117-0.814,0.117c-0.414,0-0.736-0.126-0.969-0.378c-0.234-0.252-0.35-0.676-0.35-1.271V9.504
+ h-0.689V8.719h0.689V7.855l1.027-0.31v1.173h1.154V9.504z"/>
+ <path fill="#FFFFFF" d="M115.484,13.433h-1.049v-2.68c0-0.845-0.316-1.268-0.949-1.268c-0.486,0-0.818,0.245-1,0.735
+ c-0.031,0.103-0.049,0.229-0.049,0.377v2.835h-1.047V6.556h1.047v2.841h0.02c0.33-0.517,0.803-0.775,1.416-0.775
+ c0.434,0,0.793,0.142,1.078,0.427c0.355,0.355,0.533,0.883,0.533,1.581V13.433z"/>
+ <path fill="#FFFFFF" d="M121.207,10.853c0,0.188-0.014,0.346-0.039,0.475h-3.143c0.014,0.466,0.164,0.821,0.455,1.067
+ c0.266,0.22,0.609,0.33,1.029,0.33c0.465,0,0.889-0.074,1.271-0.223l0.164,0.728c-0.447,0.194-0.973,0.291-1.582,0.291
+ c-0.73,0-1.305-0.215-1.721-0.645c-0.418-0.43-0.625-1.007-0.625-1.731c0-0.711,0.193-1.303,0.582-1.775
+ c0.406-0.504,0.955-0.756,1.648-0.756c0.678,0,1.193,0.252,1.541,0.756C121.068,9.77,121.207,10.265,121.207,10.853z
+ M120.207,10.582c0.008-0.311-0.061-0.579-0.203-0.805c-0.182-0.291-0.459-0.437-0.834-0.437c-0.342,0-0.621,0.142-0.834,0.427
+ c-0.174,0.227-0.277,0.498-0.311,0.815H120.207z"/>
+ </g>
+ </g>
+</g>
+</svg>
diff --git a/core/img/desktopapp.svg b/core/img/desktopapp.svg
index d63cfef0848..98f3616537d 100644
--- a/core/img/desktopapp.svg
+++ b/core/img/desktopapp.svg
@@ -1,5 +1,35 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" height="60" width="170" version="1.1" y="0px" x="0px" xmlns:cc="http://creativecommons.org/ns#" enable-background="new 0 0 792 612" viewBox="0 0 1346.4 475.2" xmlns:dc="http://purl.org/dc/elements/1.1/">
-<rect rx="50" ry="50" height="475.2" width="1346.4" y="-3.5527e-15" x="-2.8405e-15"/><path d="m150.48 126.72c-11.88 0-23.76 11.88-23.76 23.76v166.32l-47.52 23.76v11.88s0 11.88 11.88 11.88h356.4c11.88 0 11.88-11.88 11.88-11.88v-11.88l-47.52-23.76v-166.32c0-11.88-11.88-23.76-23.76-23.76zm0 23.667h237.6v142.65h-237.6z" fill="#fff"/><text style="word-spacing:0px;letter-spacing:0px" xml:space="preserve" font-size="316.8px" y="239.58" x="451.44" font-family="Sans" line-height="125%" fill="#ffffff"><tspan font-size="126.72px" font-weight="600" y="239.58" x="451.44" font-family="FreeSans" fill="#ffffff">Desktop app</tspan></text>
-<text style="word-spacing:0px;letter-spacing:0px" xml:space="preserve" font-size="316.8px" y="342.54001" x="493.01996" font-family="Sans" line-height="125%" fill="#ffffff"><tspan y="342.54001" x="493.01996" font-size="71.28px" font-family="FreeSans" fill="#ffffff">Windows, OS X, Linux</tspan></text>
+ <rect rx="50" ry="50" height="475.2" width="1346.4" y="-3.5527e-15" x="-2.8405e-15"/>
+ <path d="m150.48 126.72c-11.88 0-23.76 11.88-23.76 23.76v166.32l-47.52 23.76v11.88s0 11.88 11.88 11.88h356.4c11.88 0 11.88-11.88 11.88-11.88v-11.88l-47.52-23.76v-166.32c0-11.88-11.88-23.76-23.76-23.76zm0 23.667h237.6v142.65h-237.6z" fill="#fff"/>
+ <g id="text8" style="font-size:316.79998779px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#ffffff">
+ <path d="m 537.87938,193.48313 q 0,22.33687 -12.74625,34.21687 -12.68438,11.88 -36.69188,11.88 l -25.61625,0 0,-90.46125 28.40063,0 q 22.15125,0 34.4025,11.69438 12.25125,11.69437 12.25125,32.67 z m -19.92375,0.495 q 0,-29.14313 -25.74,-29.14313 l -10.20938,0 0,58.905 8.22938,0 q 27.72,0 27.72,-29.76187 z" />
+ <path d="m 583.79063,182.53125 q -6.00188,0 -9.405,3.83625 -3.40313,3.77438 -3.89813,10.76625 l 26.4825,0 q -0.12375,-6.99187 -3.65062,-10.76625 -3.52688,-3.83625 -9.52875,-3.83625 z m 2.66062,58.28625 q -16.70625,0 -26.11125,-9.21937 -9.405,-9.21938 -9.405,-26.11125 0,-17.38688 8.6625,-26.85375 8.72438,-9.52875 24.06938,-9.52875 14.66437,0 22.83187,8.35312 8.1675,8.35313 8.1675,23.07938 l 0,9.1575 -44.61187,0 q 0.30937,8.04375 4.76437,12.56062 4.455,4.51688 12.49875,4.51688 6.24938,0 11.81813,-1.29938 5.56875,-1.29937 11.6325,-4.14562 l 0,14.6025 q -4.95,2.475 -10.58063,3.65062 -5.63062,1.2375 -13.73625,1.2375 z" />
+ <path d="m 678.3975,219.0375 q 0,10.6425 -7.425,16.21125 -7.36312,5.56875 -22.08937,5.56875 -7.54875,0 -12.87,-1.05187 -5.32125,-0.99 -9.96188,-2.97 l 0,-15.5925 q 5.25938,2.475 11.81813,4.14562 6.62062,1.67063 11.6325,1.67063 10.27125,0 10.27125,-5.94 0,-2.2275 -1.36125,-3.58875 -1.36125,-1.42313 -4.7025,-3.15563 -3.34125,-1.79437 -8.91,-4.14562 -7.98188,-3.34125 -11.75625,-6.1875 -3.7125,-2.84625 -5.445,-6.49688 -1.67063,-3.7125 -1.67063,-9.09562 0,-9.21938 7.11563,-14.23125 7.1775,-5.07375 20.295,-5.07375 12.49875,0 24.31687,5.445 l -5.6925,13.6125 q -5.1975,-2.2275 -9.71437,-3.65063 -4.51688,-1.42312 -9.21938,-1.42312 -8.35312,0 -8.35312,4.51687 0,2.53688 2.66062,4.39313 2.7225,1.85625 11.81813,5.50687 8.10562,3.27938 11.88,6.12563 3.77437,2.84625 5.56875,6.55875 1.79437,3.7125 1.79437,8.84812 z" />
+ <path d="m 711.37688,201.96 8.22937,-10.51875 19.36688,-21.0375 21.285,0 -27.4725,30.00938 29.14312,39.16687 -21.78,0 -19.92375,-28.02937 -8.10562,6.49687 0,21.5325 -18.87188,0 0,-96.2775 18.87188,0 0,42.94125 -0.99,15.71625 0.2475,0 z" />
+ <path d="m 801.09562,225.78188 q 4.95,0 11.88,-2.16563 l 0,14.04563 q -7.05375,3.15562 -17.325,3.15562 -11.32313,0 -16.52063,-5.6925 -5.13562,-5.75437 -5.13562,-17.20125 l 0,-33.35062 -9.03375,0 0,-7.98188 10.395,-6.31125 5.445,-14.6025 12.06562,0 0,14.72625 19.36688,0 0,14.16938 -19.36688,0 0,33.35062 q 0,4.02188 2.2275,5.94 2.28938,1.91813 6.00188,1.91813 z" />
+ <path d="m 841.93312,204.86813 q 0,10.27125 3.34125,15.53062 3.40313,5.25938 11.01375,5.25938 7.54875,0 10.82813,-5.1975 3.34125,-5.25938 3.34125,-15.5925 0,-10.27125 -3.34125,-15.40688 -3.34125,-5.13562 -10.95188,-5.13562 -7.54875,0 -10.89,5.13562 -3.34125,5.07375 -3.34125,15.40688 z m 47.82938,0 q 0,16.89187 -8.91,26.42062 -8.91,9.52875 -24.81188,9.52875 -9.96187,0 -17.5725,-4.33125 -7.61062,-4.39312 -11.69437,-12.56062 -4.08375,-8.1675 -4.08375,-19.0575 0,-16.95375 8.84812,-26.35875 8.84813,-9.405 24.87375,-9.405 9.96188,0 17.5725,4.33125 7.61063,4.33125 11.69438,12.43687 4.08375,8.10563 4.08375,18.99563 z" />
+ <path d="m 943.34627,240.8175 q -12.18938,0 -19.11938,-8.84812 l -0.99,0 q 0.99,8.6625 0.99,10.02375 l 0,28.02937 -18.87187,0 0,-99.61875 15.345,0 2.66062,8.97188 0.86625,0 q 6.62063,-10.27125 19.61438,-10.27125 12.25125,0 19.18125,9.46687 6.93,9.46688 6.93,26.29688 0,11.07562 -3.27938,19.24312 -3.2175,8.1675 -9.21937,12.43688 -6.00188,4.26937 -14.1075,4.26937 z m -5.56875,-56.61562 q -6.99188,0 -10.20938,4.33125 -3.2175,4.26937 -3.34125,14.16937 l 0,2.04188 q 0,11.1375 3.27938,15.96375 3.34125,4.82625 10.51875,4.82625 12.68437,0 12.68437,-20.91375 0,-10.20938 -3.15562,-15.28313 -3.09375,-5.13562 -9.77625,-5.13562 z" />
+ <path d="m 1062.3938,239.58 -3.6507,-9.405 -0.495,0 q -4.7643,6.00188 -9.8381,8.35313 -5.0119,2.28937 -13.1175,2.28937 -9.9619,0 -15.7162,-5.6925 -5.6925,-5.6925 -5.6925,-16.21125 0,-11.01375 7.6725,-16.21125 7.7343,-5.25937 23.265,-5.81625 l 12.0037,-0.37125 0,-3.03187 q 0,-10.51875 -10.7662,-10.51875 -8.2913,0 -19.4907,5.01187 L 1020.3188,175.23 q 11.9418,-6.24937 26.4825,-6.24937 13.9218,0 21.3468,6.06375 7.425,6.06375 7.425,18.43875 l 0,46.09687 -13.1793,0 z m -5.5688,-32.05125 -7.3012,0.2475 q -8.2294,0.2475 -12.2513,2.97 -4.0219,2.7225 -4.0219,8.29125 0,7.98188 9.1575,7.98188 6.5588,0 10.4569,-3.77438 3.96,-3.77437 3.96,-10.02375 l 0,-5.6925 z" />
+ <path d="m 1132.9312,240.8175 q -12.1893,0 -19.1193,-8.84812 l -0.99,0 q 0.99,8.6625 0.99,10.02375 l 0,28.02937 -18.8719,0 0,-99.61875 15.345,0 2.6606,8.97188 0.8663,0 q 6.6206,-10.27125 19.6143,-10.27125 12.2513,0 19.1813,9.46687 6.93,9.46688 6.93,26.29688 0,11.07562 -3.2794,19.24312 -3.2175,8.1675 -9.2194,12.43688 -6.0018,4.26937 -14.1075,4.26937 z m -5.5687,-56.61562 q -6.9919,0 -10.2094,4.33125 -3.2175,4.26937 -3.3412,14.16937 l 0,2.04188 q 0,11.1375 3.2793,15.96375 3.3413,4.82625 10.5188,4.82625 12.6844,0 12.6844,-20.91375 0,-10.20938 -3.1557,-15.28313 -3.0937,-5.13562 -9.7762,-5.13562 z" />
+ <path d="m 1213.1213,240.8175 q -12.1894,0 -19.1194,-8.84812 l -0.99,0 q 0.99,8.6625 0.99,10.02375 l 0,28.02937 -18.8719,0 0,-99.61875 15.345,0 2.6607,8.97188 0.8662,0 q 6.6206,-10.27125 19.6144,-10.27125 12.2512,0 19.1812,9.46687 6.93,9.46688 6.93,26.29688 0,11.07562 -3.2793,19.24312 -3.2175,8.1675 -9.2194,12.43688 -6.0019,4.26937 -14.1075,4.26937 z m -5.5688,-56.61562 q -6.9918,0 -10.2093,4.33125 -3.2175,4.26937 -3.3413,14.16937 l 0,2.04188 q 0,11.1375 3.2794,15.96375 3.3412,4.82625 10.5187,4.82625 12.6844,0 12.6844,-20.91375 0,-10.20938 -3.1556,-15.28313 -3.0938,-5.13562 -9.7763,-5.13562 z" /></g>
+ <g id="text12" style="fill:#ffffff">
+ <path d="m 544.42648,342.54001 -5.84719,0 -10.26738,-34.07379 q -0.7309,-2.2623 -1.63582,-5.70797 -0.90492,-3.44566 -0.93973,-4.14176 -0.7657,4.59422 -2.43632,10.05856 l -9.95414,33.86496 -5.84719,0 -13.53902,-50.88445 6.26484,0 8.03988,31.42863 q 1.67063,6.61289 2.43633,11.97281 0.93973,-6.36926 2.78437,-12.46008 l 9.11883,-30.94136 6.26485,0 9.57128,31.2198 q 1.67063,5.39473 2.81918,12.18164 0.66129,-4.94226 2.50594,-12.04242 l 8.00508,-31.35902 6.26484,0 -13.60863,50.88445 z" />
+ <path d="m 570.91285,342.54001 -5.77758,0 0,-38.14594 5.77758,0 0,38.14594 z M 564.648,294.05708 q 0,-1.98387 0.97453,-2.88879 0.97454,-0.93973 2.43633,-0.93973 1.39219,0 2.40153,0.93973 1.00933,0.93973 1.00933,2.88879 0,1.94906 -1.00933,2.92359 -1.00934,0.93973 -2.40153,0.93973 -1.46179,0 -2.43633,-0.93973 -0.97453,-0.97453 -0.97453,-2.92359 z" />
+ <path d="m 609.33722,342.54001 0,-24.67652 q 0,-4.66383 -2.12309,-6.96094 -2.12308,-2.29711 -6.64769,-2.29711 -5.98641,0 -8.77078,3.23683 -2.78438,3.23684 -2.78438,10.68504 l 0,20.0127 -5.77758,0 0,-38.14594 4.69864,0 0.93972,5.2207 0.27844,0 q 1.77504,-2.81917 4.97707,-4.35058 3.20203,-1.56621 7.13496,-1.56621 6.89133,0 10.3718,3.34125 3.48047,3.30644 3.48047,10.61543 l 0,24.88535 -5.77758,0 z" />
+ <path d="m 652.91269,337.42372 -0.31324,0 q -4.00254,5.81238 -11.97281,5.81238 -7.48301,0 -11.65957,-5.11629 -4.14176,-5.11629 -4.14176,-14.54836 0,-9.43207 4.17656,-14.65277 4.17656,-5.2207 11.62477,-5.2207 7.76144,0 11.9032,5.63836 l 0.45246,0 -0.24363,-2.74957 -0.13922,-2.67996 0,-15.52289 5.77758,0 0,54.15609 -4.69864,0 -0.7657,-5.11629 z m -11.55516,0.97453 q 5.9168,0 8.56196,-3.20203 2.67996,-3.23684 2.67996,-10.4066 l 0,-1.21817 q 0,-8.10949 -2.71477,-11.55515 -2.67996,-3.48047 -8.59675,-3.48047 -5.08149,0 -7.79625,3.96773 -2.67997,3.93293 -2.67997,11.1375 0,7.30899 2.67997,11.03309 2.67996,3.7241 7.86585,3.7241 z" />
+ <path d="m 703.58832,323.43224 q 0,9.32765 -4.69863,14.58316 -4.69864,5.2207 -12.98215,5.2207 -5.11629,0 -9.08403,-2.40152 -3.96773,-2.40152 -6.12562,-6.89133 -2.15789,-4.4898 -2.15789,-10.51101 0,-9.32766 4.66383,-14.51356 4.66383,-5.2207 12.94734,-5.2207 8.00508,0 12.70371,5.32512 4.73344,5.32511 4.73344,14.40914 z m -29.06191,0 q 0,7.30898 2.92359,11.1375 2.92359,3.82851 8.59676,3.82851 5.67316,0 8.59675,-3.79371 2.9584,-3.82852 2.9584,-11.1723 0,-7.27418 -2.9584,-11.03309 -2.92359,-3.79371 -8.66636,-3.79371 -5.67317,0 -8.56196,3.7241 -2.88878,3.7241 -2.88878,11.1027 z" />
+ <path d="m 744.83187,342.54001 -6.99575,-22.37942 q -0.66129,-2.05347 -2.47113,-9.32765 l -0.27844,0 q -1.39218,6.09082 -2.43633,9.39726 l -7.20457,22.30981 -6.6825,0 -10.4066,-38.14594 6.05602,0 q 3.6893,14.37434 5.60355,21.89215 1.94907,7.51781 2.2275,10.12816 l 0.27844,0 q 0.38285,-1.98386 1.21816,-5.11629 0.87012,-3.16722 1.49661,-5.01187 l 6.99574,-21.89215 6.26484,0 6.82172,21.89215 q 1.94906,5.98641 2.64516,10.05855 l 0.27843,0 q 0.13922,-1.25296 0.7309,-3.86332 0.62649,-2.61035 7.27418,-28.08738 l 5.98641,0 -10.54582,38.14594 -6.85652,0 z" />
+ <path d="m 793.69766,332.13341 q 0,5.32511 -3.96774,8.2139 -3.96773,2.88879 -11.1375,2.88879 -7.58742,0 -11.83359,-2.40152 l 0,-5.35992 q 2.74957,1.39218 5.88199,2.19269 3.16723,0.80051 6.09082,0.80051 4.52461,0 6.96094,-1.42699 2.43633,-1.4618 2.43633,-4.4202 0,-2.2275 -1.94907,-3.79371 -1.91425,-1.60101 -7.51781,-3.7589 -5.32511,-1.98387 -7.58742,-3.44567 -2.2275,-1.4966 -3.34125,-3.37605 -1.07894,-1.87946 -1.07894,-4.48981 0,-4.66383 3.79371,-7.34379 3.79371,-2.71476 10.4066,-2.71476 6.16043,0 12.04242,2.50594 l -2.05348,4.69863 q -5.74277,-2.36672 -10.4066,-2.36672 -4.10695,0 -6.19523,1.28777 -2.08828,1.28778 -2.08828,3.55008 0,1.53141 0.7657,2.61035 0.80051,1.07895 2.54074,2.05348 1.74024,0.97453 6.6825,2.81918 6.78691,2.47113 9.15363,4.97707 2.40153,2.50594 2.40153,6.29965 z" />
+ <path d="m 809.11612,334.25649 0.52207,0.80051 q -0.90492,3.48047 -2.61035,8.07469 -1.70543,4.62902 -3.55008,8.59676 l -4.35059,0 q 0.93973,-3.61969 2.05348,-8.94481 1.14856,-5.32512 1.60102,-8.52715 l 6.33445,0 z" />
+ <path d="m 884.15502,317.02817 q 0,12.21645 -6.19524,19.21219 -6.16043,6.99574 -17.15871,6.99574 -11.24191,0 -17.36754,-6.85652 -6.09082,-6.89133 -6.09082,-19.42102 0,-12.42527 6.12563,-19.24699 6.12562,-6.85652 17.40234,-6.85652 10.96348,0 17.12391,6.96094 6.16043,6.96093 6.16043,19.21218 z m -40.54746,0 q 0,10.337 4.38539,15.69692 4.42019,5.32511 12.80812,5.32511 8.45754,0 12.77332,-5.32511 4.31578,-5.32512 4.31578,-15.69692 0,-10.26738 -4.31578,-15.55769 -4.28098,-5.32512 -12.70371,-5.32512 -8.45754,0 -12.87773,5.35992 -4.38539,5.32512 -4.38539,15.52289 z" />
+ <path d="m 924.25001,329.00099 q 0,6.7173 -4.87265,10.47621 -4.87266,3.7589 -13.22578,3.7589 -9.04922,0 -13.92188,-2.33191 l 0,-5.70797 q 3.13242,1.32258 6.82172,2.08828 3.6893,0.7657 7.30898,0.7657 5.9168,0 8.91,-2.2275 2.99321,-2.2623 2.99321,-6.26484 0,-2.64516 -1.07895,-4.31578 -1.04414,-1.70543 -3.55008,-3.13242 -2.47113,-1.42699 -7.55261,-3.23684 -7.10016,-2.54074 -10.16297,-6.02121 -3.02801,-3.48047 -3.02801,-9.08402 0,-5.88199 4.4202,-9.36246 4.42019,-3.48047 11.69437,-3.48047 7.58742,0 13.95668,2.78437 l -1.84465,5.1511 q -6.29965,-2.64516 -12.25125,-2.64516 -4.69863,0 -7.34379,2.01867 -2.64515,2.01867 -2.64515,5.60356 0,2.64515 0.97453,4.35058 0.97453,1.67063 3.27164,3.09762 2.33191,1.39219 7.10016,3.09762 8.00507,2.85398 10.99828,6.12562 3.028,3.27164 3.028,8.49235 z" />
+ <path d="m 987.03767,342.54001 -6.7173,0 -13.67824,-22.37942 -13.92188,22.37942 -6.26484,0 16.91508,-26.59078 -15.76653,-24.29367 6.54328,0 12.63411,20.15191 12.73851,-20.15191 6.29965,0 -15.76652,24.08484 16.98468,26.79961 z" />
+ <path d="m 999.56738,334.25649 0.52212,0.80051 q -0.90497,3.48047 -2.6104,8.07469 -1.70543,4.62902 -3.55008,8.59676 l -4.35058,0 q 0.93972,-3.61969 2.05347,-8.94481 1.14856,-5.32512 1.60102,-8.52715 l 6.33445,0 z" />
+ <path d="m 1030.4391,342.54001 0,-50.88445 5.9168,0 0,45.52453 22.449,0 0,5.35992 -28.3658,0 z" />
+ <path d="m 1072.3788,342.54001 -5.7776,0 0,-38.14594 5.7776,0 0,38.14594 z m -6.2649,-48.48293 q 0,-1.98387 0.9746,-2.88879 0.9745,-0.93973 2.4363,-0.93973 1.3922,0 2.4015,0.93973 1.0094,0.93973 1.0094,2.88879 0,1.94906 -1.0094,2.92359 -1.0093,0.93973 -2.4015,0.93973 -1.4618,0 -2.4363,-0.93973 -0.9746,-0.97453 -0.9746,-2.92359 z" />
+ <path d="m 1110.8032,342.54001 0,-24.67652 q 0,-4.66383 -2.1231,-6.96094 -2.1231,-2.29711 -6.6477,-2.29711 -5.9864,0 -8.7708,3.23683 -2.7844,3.23684 -2.7844,10.68504 l 0,20.0127 -5.7775,0 0,-38.14594 4.6986,0 0.9397,5.2207 0.2785,0 q 1.775,-2.81917 4.977,-4.35058 3.2021,-1.56621 7.135,-1.56621 6.8913,0 10.3718,3.34125 3.4805,3.30644 3.4805,10.61543 l 0,24.88535 -5.7776,0 z" />
+ <path d="m 1133.8439,304.39407 0,24.74613 q 0,4.66383 2.123,6.96094 2.1231,2.29711 6.6477,2.29711 5.9864,0 8.736,-3.27164 2.7844,-3.27164 2.7844,-10.68504 l 0,-20.0475 5.7776,0 0,38.14594 -4.7683,0 -0.8353,-5.11629 -0.3132,0 q -1.7751,2.81918 -4.9423,4.31578 -3.1324,1.4966 -7.1698,1.4966 -6.9609,0 -10.4414,-3.30644 -3.4456,-3.30645 -3.4456,-10.58063 l 0,-24.95496 5.8472,0 z" />
+ <path d="m 1181.3174,323.01458 -13.2606,-18.62051 6.5781,0 10.0586,14.61797 10.0237,-14.61797 6.5085,0 -13.2606,18.62051 13.9567,19.52543 -6.5433,0 -10.685,-15.45328 -10.7895,15.45328 -6.5433,0 13.9567,-19.52543 z" />
+ </g>
</svg>
diff --git a/core/img/googleplay.png b/core/img/googleplay.png
index 9b33dab692b..640c3c2ba08 100644
--- a/core/img/googleplay.png
+++ b/core/img/googleplay.png
Binary files differ
diff --git a/core/js/files/client.js b/core/js/files/client.js
index 3d31f974ff8..b736447d65e 100644
--- a/core/js/files/client.js
+++ b/core/js/files/client.js
@@ -239,7 +239,7 @@
path = path.substr(0, path.length - 1);
}
- path = '/' + decodeURIComponent(path);
+ path = decodeURIComponent(path);
if (response.propStat.length === 1 && response.propStat[0].status !== 200) {
return null;
@@ -505,7 +505,7 @@
var promise = deferred.promise();
options = options || {};
var headers = _.extend({}, this._defaultHeaders);
- var contentType = 'text/plain';
+ var contentType = 'text/plain;charset=utf-8';
if (options.contentType) {
contentType = options.contentType;
}
diff --git a/core/js/js.js b/core/js/js.js
index bc8c51e40d3..83658a537b8 100644
--- a/core/js/js.js
+++ b/core/js/js.js
@@ -243,9 +243,15 @@ var OC={
},
/**
- * Returns the host name used to access this ownCloud instance
+ * Returns the host used to access this ownCloud instance
+ * Host is sometimes the same as the hostname but now always.
*
- * @return {string} host name
+ * Examples:
+ * http://example.com => example.com
+ * https://example.com => exmaple.com
+ * http://example.com:8080 => example.com:8080
+ *
+ * @return {string} host
*
* @since 8.2
*/
@@ -254,6 +260,17 @@ var OC={
},
/**
+ * Returns the hostname used to access this ownCloud instance
+ * The hostname is always stripped of the port
+ *
+ * @return {string} hostname
+ * @since 9.0
+ */
+ getHostName: function() {
+ return window.location.hostname;
+ },
+
+ /**
* Returns the port number used to access this ownCloud instance
*
* @return {int} port number
diff --git a/core/js/mimetypelist.js b/core/js/mimetypelist.js
index dea065814d1..89c6e8c4d4e 100644
--- a/core/js/mimetypelist.js
+++ b/core/js/mimetypelist.js
@@ -17,12 +17,14 @@ OC.MimeTypeList={
"application/json": "text/code",
"application/msaccess": "file",
"application/msexcel": "x-office/spreadsheet",
+ "application/msonenote": "x-office/document",
"application/mspowerpoint": "x-office/presentation",
"application/msword": "x-office/document",
"application/octet-stream": "file",
"application/postscript": "image",
"application/rss+xml": "application/xml",
"application/vnd.android.package-archive": "package/x-generic",
+ "application/vnd.lotus-wordpro": "x-office/document",
"application/vnd.ms-excel": "x-office/spreadsheet",
"application/vnd.ms-excel.addin.macroEnabled.12": "x-office/spreadsheet",
"application/vnd.ms-excel.sheet.binary.macroEnabled.12": "x-office/spreadsheet",
@@ -51,6 +53,8 @@ OC.MimeTypeList={
"application/vnd.openxmlformats-officedocument.spreadsheetml.template": "x-office/spreadsheet",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": "x-office/document",
"application/vnd.openxmlformats-officedocument.wordprocessingml.template": "x-office/document",
+ "application/vnd.visio": "x-office/document",
+ "application/vnd.wordperfect": "x-office/document",
"application/x-7z-compressed": "package/x-generic",
"application/x-cbr": "text",
"application/x-compressed": "package/x-generic",
diff --git a/core/js/setupchecks.js b/core/js/setupchecks.js
index bc49c61a5aa..de41b66ec32 100644
--- a/core/js/setupchecks.js
+++ b/core/js/setupchecks.js
@@ -194,7 +194,7 @@
}
var afterCall = function(xhr) {
var messages = [];
- if (xhr.status !== 403 && xhr.status !== 307 && xhr.status !== 301) {
+ if (xhr.status !== 403 && xhr.status !== 307 && xhr.status !== 301 && xhr.responseText === '') {
messages.push({
msg: t('core', 'Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root.'),
type: OC.SetupChecks.MESSAGE_TYPE_ERROR
diff --git a/core/js/tests/specs/files/clientSpec.js b/core/js/tests/specs/files/clientSpec.js
index 61cff0a66ec..b945e1bb4da 100644
--- a/core/js/tests/specs/files/clientSpec.js
+++ b/core/js/tests/specs/files/clientSpec.js
@@ -19,12 +19,18 @@
*
*/
+/* global dav */
+
describe('OC.Files.Client tests', function() {
var Client = OC.Files.Client;
var baseUrl;
var client;
+ var requestStub;
+ var requestDeferred;
beforeEach(function() {
+ requestDeferred = new $.Deferred();
+ requestStub = sinon.stub(dav.Client.prototype, 'request').returns(requestDeferred.promise());
baseUrl = 'https://testhost/owncloud/remote.php/webdav/';
client = new Client({
@@ -35,6 +41,7 @@ describe('OC.Files.Client tests', function() {
});
afterEach(function() {
client = null;
+ requestStub.restore();
});
/**
@@ -51,11 +58,10 @@ describe('OC.Files.Client tests', function() {
promise.done(successHandler);
promise.fail(failHandler);
- fakeServer.requests[0].respond(
- status,
- {'Content-Type': 'application/xml'},
- ''
- );
+ requestDeferred.resolve({
+ status: status,
+ body: ''
+ });
promise.then(function() {
expect(successHandler.calledOnce).toEqual(true);
@@ -81,19 +87,16 @@ describe('OC.Files.Client tests', function() {
promise.done(successHandler);
promise.fail(failHandler);
- fakeServer.requests[0].respond(
- status,
- {'Content-Type': 'application/xml'},
- ''
- );
+ requestDeferred.resolve({
+ status: status,
+ body: ''
+ });
promise.then(function() {
expect(failHandler.calledOnce).toEqual(true);
expect(failHandler.calledWith(status)).toEqual(true);
expect(successHandler.notCalled).toEqual(true);
-
- fulfill();
});
return promise;
@@ -149,7 +152,8 @@ describe('OC.Files.Client tests', function() {
describe('file listing', function() {
- var folderContentsXml =
+ // TODO: switch this to the already parsed structure
+ var folderContentsXml = dav.Client.prototype.parseMultiStatus(
'<?xml version="1.0" encoding="utf-8"?>' +
'<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:oc="http://owncloud.org/ns">' +
makeResponseBlock(
@@ -159,8 +163,9 @@ describe('OC.Files.Client tests', function() {
'd:getetag': '"56cfcabd79abb"',
'd:resourcetype': '<d:collection/>',
'oc:id': '00000011oc2d13a6a068',
+ 'oc:fileid': '11',
'oc:permissions': 'RDNVCK',
- 'oc:size': 120
+ 'oc:size': '120'
},
[
'd:getcontenttype',
@@ -176,6 +181,7 @@ describe('OC.Files.Client tests', function() {
'd:getcontentlength': 250,
'd:resourcetype': '',
'oc:id': '00000051oc2d13a6a068',
+ 'oc:fileid': '51',
'oc:permissions': 'RDNVW'
},
[
@@ -189,25 +195,27 @@ describe('OC.Files.Client tests', function() {
'd:getetag': '"66cfcabd79abb"',
'd:resourcetype': '<d:collection/>',
'oc:id': '00000015oc2d13a6a068',
+ 'oc:fileid': '15',
'oc:permissions': 'RDNVCK',
- 'oc:size': 100
+ 'oc:size': '100'
},
[
'd:getcontenttype',
'd:getcontentlength'
]
) +
- '</d:multistatus>';
+ '</d:multistatus>'
+ );
it('sends PROPFIND with explicit properties to get file list', function() {
client.getFolderContents('path/to space/文件夹');
- expect(fakeServer.requests.length).toEqual(1);
- expect(fakeServer.requests[0].method).toEqual('PROPFIND');
- expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9');
- expect(fakeServer.requests[0].requestHeaders.Depth).toEqual(1);
+ expect(requestStub.calledOnce).toEqual(true);
+ expect(requestStub.lastCall.args[0]).toEqual('PROPFIND');
+ expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9');
+ expect(requestStub.lastCall.args[2].Depth).toEqual(1);
- var props = getRequestedProperties(fakeServer.requests[0].requestBody);
+ var props = getRequestedProperties(requestStub.lastCall.args[3]);
expect(props).toContain('{DAV:}getlastmodified');
expect(props).toContain('{DAV:}getcontentlength');
expect(props).toContain('{DAV:}getcontenttype');
@@ -219,24 +227,23 @@ describe('OC.Files.Client tests', function() {
});
it('sends PROPFIND to base url when empty path given', function() {
client.getFolderContents('');
- expect(fakeServer.requests.length).toEqual(1);
- expect(fakeServer.requests[0].url).toEqual(baseUrl);
+ expect(requestStub.calledOnce).toEqual(true);
+ expect(requestStub.lastCall.args[1]).toEqual(baseUrl);
});
it('sends PROPFIND to base url when root path given', function() {
client.getFolderContents('/');
- expect(fakeServer.requests.length).toEqual(1);
- expect(fakeServer.requests[0].url).toEqual(baseUrl);
+ expect(requestStub.calledOnce).toEqual(true);
+ expect(requestStub.lastCall.args[1]).toEqual(baseUrl);
});
it('parses the result list into a FileInfo array', function() {
var promise = client.getFolderContents('path/to space/文件夹');
- expect(fakeServer.requests.length).toEqual(1);
+ expect(requestStub.calledOnce).toEqual(true);
- fakeServer.requests[0].respond(
- 207,
- {'Content-Type': 'application/xml'},
- folderContentsXml
- );
+ requestDeferred.resolve({
+ status: 207,
+ body: folderContentsXml
+ });
promise.then(function(status, response) {
expect(status).toEqual(207);
@@ -250,7 +257,7 @@ describe('OC.Files.Client tests', function() {
expect(info.id).toEqual(51);
expect(info.path).toEqual('/path/to space/文件夹');
expect(info.name).toEqual('One.txt');
- expect(info.permissions).toEqual(31);
+ expect(info.permissions).toEqual(27);
expect(info.size).toEqual(250);
expect(info.mtime).toEqual(1436535485000);
expect(info.mimetype).toEqual('text/plain');
@@ -268,18 +275,16 @@ describe('OC.Files.Client tests', function() {
expect(info.mimetype).toEqual('httpd/unix-directory');
expect(info.etag).toEqual('66cfcabd79abb');
});
- return promise.promise();
});
it('returns parent node in result if specified', function() {
var promise = client.getFolderContents('path/to space/文件夹', {includeParent: true});
- expect(fakeServer.requests.length).toEqual(1);
+ expect(requestStub.calledOnce).toEqual(true);
- fakeServer.requests[0].respond(
- 207,
- {'Content-Type': 'application/xml'},
- folderContentsXml
- );
+ requestDeferred.resolve({
+ status: 207,
+ body: folderContentsXml
+ });
promise.then(function(status, response) {
expect(status).toEqual(207);
@@ -303,12 +308,10 @@ describe('OC.Files.Client tests', function() {
expect(response[1].id).toEqual(51);
expect(response[2].id).toEqual(15);
});
-
- return promise;
});
it('rejects promise when an error occurred', function() {
var promise = client.getFolderContents('path/to space/文件夹', {includeParent: true});
- return respondAndCheckError(promise, 404);
+ respondAndCheckError(promise, 404);
});
it('throws exception if arguments are missing', function() {
// TODO
@@ -316,7 +319,7 @@ describe('OC.Files.Client tests', function() {
});
describe('file info', function() {
- var responseXml =
+ var responseXml = dav.Client.prototype.parseMultiStatus(
'<?xml version="1.0" encoding="utf-8"?>' +
'<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:oc="http://owncloud.org/ns">' +
makeResponseBlock(
@@ -326,25 +329,27 @@ describe('OC.Files.Client tests', function() {
'd:getetag': '"56cfcabd79abb"',
'd:resourcetype': '<d:collection/>',
'oc:id': '00000011oc2d13a6a068',
+ 'oc:fileid': '11',
'oc:permissions': 'RDNVCK',
- 'oc:size': 120
+ 'oc:size': '120'
},
[
'd:getcontenttype',
'd:getcontentlength'
]
) +
- '</d:multistatus>';
+ '</d:multistatus>'
+ );
it('sends PROPFIND with zero depth to get single file info', function() {
client.getFileInfo('path/to space/文件夹');
- expect(fakeServer.requests.length).toEqual(1);
- expect(fakeServer.requests[0].method).toEqual('PROPFIND');
- expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9');
- expect(fakeServer.requests[0].requestHeaders.Depth).toEqual(0);
+ expect(requestStub.calledOnce).toEqual(true);
+ expect(requestStub.lastCall.args[0]).toEqual('PROPFIND');
+ expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9');
+ expect(requestStub.lastCall.args[2].Depth).toEqual(0);
- var props = getRequestedProperties(fakeServer.requests[0].requestBody);
+ var props = getRequestedProperties(requestStub.lastCall.args[3]);
expect(props).toContain('{DAV:}getlastmodified');
expect(props).toContain('{DAV:}getcontentlength');
expect(props).toContain('{DAV:}getcontenttype');
@@ -357,13 +362,12 @@ describe('OC.Files.Client tests', function() {
it('parses the result into a FileInfo', function() {
var promise = client.getFileInfo('path/to space/文件夹');
- expect(fakeServer.requests.length).toEqual(1);
+ expect(requestStub.calledOnce).toEqual(true);
- fakeServer.requests[0].respond(
- 207,
- {'Content-Type': 'application/xml'},
- responseXml
- );
+ requestDeferred.resolve({
+ status: 207,
+ body: responseXml
+ });
promise.then(function(status, response) {
expect(status).toEqual(207);
@@ -380,11 +384,9 @@ describe('OC.Files.Client tests', function() {
expect(info.mimetype).toEqual('httpd/unix-directory');
expect(info.etag).toEqual('56cfcabd79abb');
});
-
- return promise;
});
it('properly parses entry inside root', function() {
- var responseXml =
+ var responseXml = dav.Client.prototype.parseMultiStatus(
'<?xml version="1.0" encoding="utf-8"?>' +
'<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:oc="http://owncloud.org/ns">' +
makeResponseBlock(
@@ -394,25 +396,26 @@ describe('OC.Files.Client tests', function() {
'd:getetag': '"56cfcabd79abb"',
'd:resourcetype': '<d:collection/>',
'oc:id': '00000011oc2d13a6a068',
+ 'oc:fileid': '11',
'oc:permissions': 'RDNVCK',
- 'oc:size': 120
+ 'oc:size': '120'
},
[
'd:getcontenttype',
'd:getcontentlength'
]
) +
- '</d:multistatus>';
+ '</d:multistatus>'
+ );
var promise = client.getFileInfo('in root');
- expect(fakeServer.requests.length).toEqual(1);
+ expect(requestStub.calledOnce).toEqual(true);
- fakeServer.requests[0].respond(
- 207,
- {'Content-Type': 'application/xml'},
- responseXml
- );
+ requestDeferred.resolve({
+ status: 207,
+ body: responseXml
+ });
promise.then(function(status, response) {
expect(status).toEqual(207);
@@ -429,12 +432,10 @@ describe('OC.Files.Client tests', function() {
expect(info.mimetype).toEqual('httpd/unix-directory');
expect(info.etag).toEqual('56cfcabd79abb');
});
-
- return promise;
});
it('rejects promise when an error occurred', function() {
var promise = client.getFileInfo('path/to space/文件夹');
- return respondAndCheckError(promise, 404);
+ respondAndCheckError(promise, 404);
});
it('throws exception if arguments are missing', function() {
// TODO
@@ -449,6 +450,7 @@ describe('OC.Files.Client tests', function() {
'd:getetag': '"559fcabd79a38"',
'd:getcontentlength': 250,
'oc:id': '00000051oc2d13a6a068',
+ 'oc:fileid': '51',
'oc:permissions': webdavPerm,
};
@@ -458,25 +460,28 @@ describe('OC.Files.Client tests', function() {
props['d:resourcetype'] = '<d:collection/>';
}
- var responseXml =
+ var def = new $.Deferred();
+ requestStub.reset();
+ requestStub.returns(def);
+
+ var responseXml = dav.Client.prototype.parseMultiStatus(
'<?xml version="1.0" encoding="utf-8"?>' +
'<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:oc="http://owncloud.org/ns">' +
makeResponseBlock(
'/owncloud/remote.php/webdav/file.txt',
props
) +
- '</d:multistatus>';
+ '</d:multistatus>'
+ );
+
var promise = client.getFileInfo('file.txt');
- expect(fakeServer.requests.length).toEqual(1);
- fakeServer.requests[0].respond(
- 207,
- {'Content-Type': 'application/xml'},
- responseXml
- );
+ expect(requestStub.calledOnce).toEqual(true);
- fakeServer.restore();
- fakeServer = sinon.fakeServer.create();
+ def.resolve({
+ status: 207,
+ body: responseXml
+ });
return promise;
}
@@ -486,7 +491,6 @@ describe('OC.Files.Client tests', function() {
promise.then(function(result) {
expect(result.permissions).toEqual(expectedPermissions);
});
- return promise;
}
function testMountType(permission, isFile, expectedMountType) {
@@ -494,7 +498,6 @@ describe('OC.Files.Client tests', function() {
promise.then(function(result) {
expect(result.mountType).toEqual(expectedMountType);
});
- return promise;
}
it('properly parses file permissions', function() {
@@ -508,11 +511,9 @@ describe('OC.Files.Client tests', function() {
['R', true, OC.PERMISSION_READ | OC.PERMISSION_SHARE],
['CKWDR', true, OC.PERMISSION_ALL]
];
- return Promise.all(
- _.map(testCases, function(testCase) {
- return testPermission.apply(testCase);
- })
- );
+ _.each(testCases, function(testCase) {
+ return testPermission.apply(testCase);
+ });
});
it('properly parses folder permissions', function() {
var testCases = [
@@ -525,11 +526,9 @@ describe('OC.Files.Client tests', function() {
['CKWDR', false, OC.PERMISSION_ALL]
];
- return Promise.all(
- _.map(testCases, function(testCase) {
- return testPermission.apply(testCase);
- })
- );
+ _.each(testCases, function(testCase) {
+ return testPermission.apply(testCase);
+ });
});
it('properly parses mount types', function() {
var testCases = [
@@ -539,11 +538,9 @@ describe('OC.Files.Client tests', function() {
['SM', false, 'shared']
];
- return Promise.all(
- _.map(testCases, function(testCase) {
- return testMountType.apply(testCase);
- })
- );
+ _.each(testCases, function(testCase) {
+ return testMountType.apply(testCase);
+ });
});
});
@@ -551,26 +548,23 @@ describe('OC.Files.Client tests', function() {
it('returns file contents', function() {
var promise = client.getFileContents('path/to space/文件夹/One.txt');
- expect(fakeServer.requests.length).toEqual(1);
- expect(fakeServer.requests[0].method).toEqual('GET');
- expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt');
+ expect(requestStub.calledOnce).toEqual(true);
+ expect(requestStub.lastCall.args[0]).toEqual('GET');
+ expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt');
- fakeServer.requests[0].respond(
- 200,
- {'Content-Type': 'text/plain'},
- 'some contents'
- );
+ requestDeferred.resolve({
+ status: 200,
+ body: 'some contents'
+ });
promise.then(function(status, response) {
expect(status).toEqual(200);
expect(response).toEqual('some contents');
});
-
- return promise;
});
it('rejects promise when an error occurred', function() {
var promise = client.getFileContents('path/to space/文件夹/One.txt');
- return respondAndCheckError(promise, 409);
+ respondAndCheckError(promise, 409);
});
it('throws exception if arguments are missing', function() {
// TODO
@@ -584,14 +578,14 @@ describe('OC.Files.Client tests', function() {
'some contents'
);
- expect(fakeServer.requests.length).toEqual(1);
- expect(fakeServer.requests[0].method).toEqual('PUT');
- expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt');
- expect(fakeServer.requests[0].requestBody).toEqual('some contents');
- expect(fakeServer.requests[0].requestHeaders['If-None-Match']).toEqual('*');
- expect(fakeServer.requests[0].requestHeaders['Content-Type']).toEqual('text/plain;charset=utf-8');
+ expect(requestStub.calledOnce).toEqual(true);
+ expect(requestStub.lastCall.args[0]).toEqual('PUT');
+ expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt');
+ expect(requestStub.lastCall.args[2]['If-None-Match']).toEqual('*');
+ expect(requestStub.lastCall.args[2]['Content-Type']).toEqual('text/plain;charset=utf-8');
+ expect(requestStub.lastCall.args[3]).toEqual('some contents');
- return respondAndCheckStatus(promise, 201);
+ respondAndCheckStatus(promise, 201);
});
it('sends PUT with file contents with headers matching options', function() {
var promise = client.putFileContents(
@@ -603,21 +597,21 @@ describe('OC.Files.Client tests', function() {
}
);
- expect(fakeServer.requests.length).toEqual(1);
- expect(fakeServer.requests[0].method).toEqual('PUT');
- expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt');
- expect(fakeServer.requests[0].requestBody).toEqual('some contents');
- expect(fakeServer.requests[0].requestHeaders['If-None-Match']).not.toBeDefined();
- expect(fakeServer.requests[0].requestHeaders['Content-Type']).toEqual('text/markdown;charset=utf-8');
+ expect(requestStub.calledOnce).toEqual(true);
+ expect(requestStub.lastCall.args[0]).toEqual('PUT');
+ expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt');
+ expect(requestStub.lastCall.args[2]['If-None-Match']).not.toBeDefined();
+ expect(requestStub.lastCall.args[2]['Content-Type']).toEqual('text/markdown');
+ expect(requestStub.lastCall.args[3]).toEqual('some contents');
- return respondAndCheckStatus(promise, 201);
+ respondAndCheckStatus(promise, 201);
});
it('rejects promise when an error occurred', function() {
var promise = client.putFileContents(
'path/to space/文件夹/One.txt',
'some contents'
);
- return respondAndCheckError(promise, 409);
+ respondAndCheckError(promise, 409);
});
it('throws exception if arguments are missing', function() {
// TODO
@@ -628,15 +622,15 @@ describe('OC.Files.Client tests', function() {
it('sends MKCOL with specified path', function() {
var promise = client.createDirectory('path/to space/文件夹/new dir');
- expect(fakeServer.requests.length).toEqual(1);
- expect(fakeServer.requests[0].method).toEqual('MKCOL');
- expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/new%20dir');
+ expect(requestStub.calledOnce).toEqual(true);
+ expect(requestStub.lastCall.args[0]).toEqual('MKCOL');
+ expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/new%20dir');
- return respondAndCheckStatus(promise, 201);
+ respondAndCheckStatus(promise, 201);
});
it('rejects promise when an error occurred', function() {
var promise = client.createDirectory('path/to space/文件夹/new dir');
- return respondAndCheckError(promise, 404);
+ respondAndCheckError(promise, 404);
});
it('throws exception if arguments are missing', function() {
// TODO
@@ -647,15 +641,15 @@ describe('OC.Files.Client tests', function() {
it('sends DELETE with specified path', function() {
var promise = client.remove('path/to space/文件夹');
- expect(fakeServer.requests.length).toEqual(1);
- expect(fakeServer.requests[0].method).toEqual('DELETE');
- expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9');
+ expect(requestStub.calledOnce).toEqual(true);
+ expect(requestStub.lastCall.args[0]).toEqual('DELETE');
+ expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9');
- return respondAndCheckStatus(promise, 201);
+ respondAndCheckStatus(promise, 201);
});
it('rejects promise when an error occurred', function() {
var promise = client.remove('path/to space/文件夹');
- return respondAndCheckError(promise, 404);
+ respondAndCheckError(promise, 404);
});
it('throws exception if arguments are missing', function() {
// TODO
@@ -669,15 +663,15 @@ describe('OC.Files.Client tests', function() {
'path/to space/anotherdir/文件夹'
);
- expect(fakeServer.requests.length).toEqual(1);
- expect(fakeServer.requests[0].method).toEqual('MOVE');
- expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9');
- expect(fakeServer.requests[0].requestHeaders.Destination)
+ expect(requestStub.calledOnce).toEqual(true);
+ expect(requestStub.lastCall.args[0]).toEqual('MOVE');
+ expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9');
+ expect(requestStub.lastCall.args[2].Destination)
.toEqual(baseUrl + 'path/to%20space/anotherdir/%E6%96%87%E4%BB%B6%E5%A4%B9');
- expect(fakeServer.requests[0].requestHeaders.Overwrite)
+ expect(requestStub.lastCall.args[2].Overwrite)
.toEqual('F');
- return respondAndCheckStatus(promise, 201);
+ respondAndCheckStatus(promise, 201);
});
it('sends MOVE with silent overwrite mode when specified', function() {
var promise = client.move(
@@ -686,15 +680,15 @@ describe('OC.Files.Client tests', function() {
{allowOverwrite: true}
);
- expect(fakeServer.requests.length).toEqual(1);
- expect(fakeServer.requests[0].method).toEqual('MOVE');
- expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9');
- expect(fakeServer.requests[0].requestHeaders.Destination)
+ expect(requestStub.calledOnce).toEqual(true);
+ expect(requestStub.lastCall.args[0]).toEqual('MOVE');
+ expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9');
+ expect(requestStub.lastCall.args[2].Destination)
.toEqual(baseUrl + 'path/to%20space/anotherdir/%E6%96%87%E4%BB%B6%E5%A4%B9');
- expect(fakeServer.requests[0].requestHeaders.Overwrite)
+ expect(requestStub.lastCall.args[2].Overwrite)
.not.toBeDefined();
- return respondAndCheckStatus(promise, 201);
+ respondAndCheckStatus(promise, 201);
});
it('rejects promise when an error occurred', function() {
var promise = client.move(
@@ -702,7 +696,7 @@ describe('OC.Files.Client tests', function() {
'path/to space/anotherdir/文件夹',
{allowOverwrite: true}
);
- return respondAndCheckError(promise, 404);
+ respondAndCheckError(promise, 404);
});
it('throws exception if arguments are missing', function() {
// TODO
diff --git a/core/l10n/th_TH.js b/core/l10n/th_TH.js
index 127e34c997f..b8b191ae8a3 100644
--- a/core/l10n/th_TH.js
+++ b/core/l10n/th_TH.js
@@ -120,7 +120,6 @@ OC.L10N.register(
"Your web server is not yet set up properly to allow file synchronization because the WebDAV interface seems to be broken." : "เว็บเซิร์ฟเวอร์ของคุณยังไม่ถูกติดตั้งอย่างถูกต้องเพื่ออนุญาตให้ประสานข้อมูลให้ตรงกัน เนื่องจากอินเตอร์เฟซ WebDAV อาจเสียหาย",
"Your web server is not set up properly to resolve \"{url}\". Further information can be found in our <a target=\"_blank\" href=\"{docLink}\">documentation</a>." : "เว็บเซิร์ฟเวอร์ของคุณไม่ได้ติดตั้งอย่างถูกต้องเพื่อที่จะแก้ไข \"{url}\" สามารถข้อมูลเพิ่มเติมได้ใน <a target=\"_blank\" href=\"{docLink}\">เอกสาร</a> ของเรา",
"This server has no working Internet connection. This means that some of the features like mounting external storage, notifications about updates or installation of third-party apps will not work. Accessing files remotely and sending of notification emails might not work, either. We suggest to enable Internet connection for this server if you want to have all features." : "เซิร์ฟเวอร์นี้ไม่มีการเชื่อมต่ออินเทอร์เน็ตซึ่งหมายความว่าบางส่วนของคุณสมบัติ เช่น การจัดเก็บข้อมูลภายนอก การแจ้งเตือนเกี่ยวกับการปรับปรุงหรือการติดตั้งแอพพลิเคชันของบุคคลที่สามจะไม่ทำงาน การเข้าถึงไฟล์จากระยะไกลและการส่งอีเมล์แจ้งเตือนอาจจะไม่ทำงาน เราขอแนะนำให้เปิดใช้งานการเชื่อมต่ออินเทอร์เน็ตสำหรับเซิร์ฟเวอร์นี้ถ้าคุณต้องการใช้งานคุณสมบัติทั้งหมด",
- "Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "ข้อมูลไดเรกทอรีและไฟล์ของคุณอาจจะสามารถเข้าถึงได้จากอินเทอร์เน็ต ขณะที่ htaccess ไฟล์ไม่ทำงาน เราขอแนะนำให้คุณกำหนดค่าเว็บเซิร์ฟเวอร์ของคุณในทางที่ข้อมูลไดเรกทอรีไม่สามารถเข้าถึงได้หรือคุณย้ายข้อมูลไดเรกทอรีไปยังนอกเว็บเซิร์ฟเวอร์หรือเอกสาร",
"No memory cache has been configured. To enhance your performance please configure a memcache if available. Further information can be found in our <a target=\"_blank\" href=\"{docLink}\">documentation</a>." : "ไม่ได้กำหนดค่าหน่วยความจำแคช เพื่อเพิ่มประสิทธิภาพของคุณโปรดกำหนดค่า memcache หากต้องการข้อมูลเพิ่มเติมสามารถอ่านได้ใน <a target=\"_blank\" href=\"{docLink}\">เอกสาร</a> ของเรา",
"/dev/urandom is not readable by PHP which is highly discouraged for security reasons. Further information can be found in our <a target=\"_blank\" href=\"{docLink}\">documentation</a>." : "ไม่สามารถอ่าน /dev/urandom โดย PHP ซึ่งมีผลอย่างมากสำหรับเหตุผลด้านความปลอดภัย สามารถข้อมูลเพิ่มเติมได้ใน <a target=\"_blank\" href=\"{docLink}\">เอกสาร</a> ของเรา",
"Your PHP version ({version}) is no longer <a target=\"_blank\" href=\"{phpLink}\">supported by PHP</a>. We encourage you to upgrade your PHP version to take advantage of performance and security updates provided by PHP." : "PHP ของคุณรุ่น ({version}) <a target=\"_blank\" href=\"{phpLink}\">ไม่สนับสนุน PHP</a> เราขอแนะนำให้อัพเกรดรุ่น PHP ของคุณ เพื่อปรับปรุงประสิทธิภาพการทำงานและเนื้อหาด้านความปลอดภัย",
@@ -128,6 +127,7 @@ OC.L10N.register(
"Memcached is configured as distributed cache, but the wrong PHP module \"memcache\" is installed. \\OC\\Memcache\\Memcached only supports \"memcached\" and not \"memcache\". See the <a target=\"_blank\" href=\"{wikiLink}\">memcached wiki about both modules</a>." : "การกำหนดค่า memcach ผิดพลาดเนื่องจากมีโมดูล PHP ของ memcache ได้ถูกติดตั้งไปแล้ว มีการติดตั้ง \\OC\\Memcache\\Memcached สนับสนุนเฉพาะ \"memcached\" แต่ไม่สนับสนุน \"memcache\" คุณสามารถดู <a target=\"_blank\" href=\"{wikiLink}\">ข้อมูลเกี่ยวกับทั้ง 2 โมดูล</a>",
"Some files have not passed the integrity check. Further information on how to resolve this issue can be found in our <a target=\"_blank\" href=\"{docLink}\">documentation</a>. (<a href=\"{codeIntegrityDownloadEndpoint}\">List of invalid files…</a> / <a href=\"{rescanEndpoint}\">Rescan…</a>)" : "บางไฟล์ยังไม่ผ่านการตรวจสอบความสมบูรณ์ ข้อมูลเพิ่มเติมเกี่ยวกับวิธีการแก้ไขปัญหาเหล่านี้สามารถอ่านได้จาก <a target=\"_blank\" href=\"{docLink}\">เอกสาร</a> ของเรา (<a href=\"{codeIntegrityDownloadEndpoint}\">รายชื่อของไฟล์ที่ไม่ถูกต้อง…</a> / <a href=\"{rescanEndpoint}\">ค้นหาใหม่…</a>)",
"Error occurred while checking server setup" : "เกิดข้อผิดพลาดขณะที่ทำการตรวจสอบการติดตั้งเซิร์ฟเวอร์",
+ "Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "ข้อมูลไดเรกทอรีและไฟล์ของคุณอาจจะสามารถเข้าถึงได้จากอินเทอร์เน็ต ขณะที่ htaccess ไฟล์ไม่ทำงาน เราขอแนะนำให้คุณกำหนดค่าเว็บเซิร์ฟเวอร์ของคุณในทางที่ข้อมูลไดเรกทอรีไม่สามารถเข้าถึงได้หรือคุณย้ายข้อมูลไดเรกทอรีไปยังนอกเว็บเซิร์ฟเวอร์หรือเอกสาร",
"The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "\"{header}\" ไม่ได้กำหนดค่าส่วนหัว Http ให้เท่ากับ \"{expected}\" นี่คือระบบการรักษาความปลอดภัยที่มีศักยภาพหรือลดความเสี่ยงที่จะเกิดขึ้นเราขอแนะนำให้ปรับการตั้งค่านี้",
"The \"Strict-Transport-Security\" HTTP header is not configured to least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our <a href=\"{docUrl}\">security tips</a>." : "\"Strict-Transport-Security\" ส่วนหัว HTTP ไม่ได้กำหนดค่าให้น้อยกว่า \"{seconds}\" วินาที เพื่อความปลอดภัยที่เพิ่มขึ้นเราขอแนะนำให้เปิดใช้งาน HSTS ที่อธิบายไว้ใน <a href=\"{docUrl}\">เคล็ดลับการรักษาความปลอดภัย</a> ของเรา",
"You are accessing this site via HTTP. We strongly suggest you configure your server to require using HTTPS instead as described in our <a href=\"{docUrl}\">security tips</a>." : "คุณกำลังเข้าถึงเว็บไซต์นี้ผ่านทาง HTTP เราขอแนะนำให้คุณกำหนดค่าเซิร์ฟเวอร์ของคุณที่จะต้องใช้ HTTPS แทนตามที่อธิบายไว้ใน <a href=\"{docUrl}\">เคล็ดลับการรักษาความปลอดภัย</a> ของเรา",
@@ -164,17 +164,20 @@ OC.L10N.register(
"change" : "เปลี่ยนแปลง",
"delete" : "ลบ",
"access control" : "ควบคุมการเข้าถึง",
+ "Could not unshare" : "ไม่สามารถยกเลิกการแชร์ได้",
"Share details could not be loaded for this item." : "รายละเอียดการแชร์ไม่สามารถโหลดสำหรับรายการนี้",
"An error occured. Please try again" : "เกิดข้อผิดพลาด กรุณาลองอีกครั้ง",
"Share" : "แชร์",
"Share with people on other ownClouds using the syntax username@example.com/owncloud" : "แชร์กับคนใน ownClouds อื่นๆ ที่ใช้ไวยากรณ์ username@example.com/owncloud ",
"Share with users or groups …" : "แชร์กับผู้ใช้หรือกลุ่ม ...",
"Share with users, groups or remote users …" : "แชร์กับผู้ใช้กลุ่มหรือผู้ใช้ระยะไกล ...",
+ "Error removing share" : "พบข้อผิดพลาดในรายการที่แชร์ออก",
"Warning" : "คำเตือน",
"Error while sending notification" : "เกิดข้อผิดพลาดขณะกำลังส่งการแจ้งเตือน",
"Non-existing tag #{tag}" : "ไม่มีแท็กนี้อยู่ #{tag}",
"not assignable" : "ไม่ได้รับมอบหมาย",
"invisible" : "จะมองไม่เห็น",
+ "({scope})" : "({scope})",
"Delete" : "ลบ",
"Rename" : "เปลี่ยนชื่อ",
"Global tags" : "แท็กทั่วไป",
diff --git a/core/l10n/th_TH.json b/core/l10n/th_TH.json
index 059cfd75f04..1a72dec0b22 100644
--- a/core/l10n/th_TH.json
+++ b/core/l10n/th_TH.json
@@ -118,7 +118,6 @@
"Your web server is not yet set up properly to allow file synchronization because the WebDAV interface seems to be broken." : "เว็บเซิร์ฟเวอร์ของคุณยังไม่ถูกติดตั้งอย่างถูกต้องเพื่ออนุญาตให้ประสานข้อมูลให้ตรงกัน เนื่องจากอินเตอร์เฟซ WebDAV อาจเสียหาย",
"Your web server is not set up properly to resolve \"{url}\". Further information can be found in our <a target=\"_blank\" href=\"{docLink}\">documentation</a>." : "เว็บเซิร์ฟเวอร์ของคุณไม่ได้ติดตั้งอย่างถูกต้องเพื่อที่จะแก้ไข \"{url}\" สามารถข้อมูลเพิ่มเติมได้ใน <a target=\"_blank\" href=\"{docLink}\">เอกสาร</a> ของเรา",
"This server has no working Internet connection. This means that some of the features like mounting external storage, notifications about updates or installation of third-party apps will not work. Accessing files remotely and sending of notification emails might not work, either. We suggest to enable Internet connection for this server if you want to have all features." : "เซิร์ฟเวอร์นี้ไม่มีการเชื่อมต่ออินเทอร์เน็ตซึ่งหมายความว่าบางส่วนของคุณสมบัติ เช่น การจัดเก็บข้อมูลภายนอก การแจ้งเตือนเกี่ยวกับการปรับปรุงหรือการติดตั้งแอพพลิเคชันของบุคคลที่สามจะไม่ทำงาน การเข้าถึงไฟล์จากระยะไกลและการส่งอีเมล์แจ้งเตือนอาจจะไม่ทำงาน เราขอแนะนำให้เปิดใช้งานการเชื่อมต่ออินเทอร์เน็ตสำหรับเซิร์ฟเวอร์นี้ถ้าคุณต้องการใช้งานคุณสมบัติทั้งหมด",
- "Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "ข้อมูลไดเรกทอรีและไฟล์ของคุณอาจจะสามารถเข้าถึงได้จากอินเทอร์เน็ต ขณะที่ htaccess ไฟล์ไม่ทำงาน เราขอแนะนำให้คุณกำหนดค่าเว็บเซิร์ฟเวอร์ของคุณในทางที่ข้อมูลไดเรกทอรีไม่สามารถเข้าถึงได้หรือคุณย้ายข้อมูลไดเรกทอรีไปยังนอกเว็บเซิร์ฟเวอร์หรือเอกสาร",
"No memory cache has been configured. To enhance your performance please configure a memcache if available. Further information can be found in our <a target=\"_blank\" href=\"{docLink}\">documentation</a>." : "ไม่ได้กำหนดค่าหน่วยความจำแคช เพื่อเพิ่มประสิทธิภาพของคุณโปรดกำหนดค่า memcache หากต้องการข้อมูลเพิ่มเติมสามารถอ่านได้ใน <a target=\"_blank\" href=\"{docLink}\">เอกสาร</a> ของเรา",
"/dev/urandom is not readable by PHP which is highly discouraged for security reasons. Further information can be found in our <a target=\"_blank\" href=\"{docLink}\">documentation</a>." : "ไม่สามารถอ่าน /dev/urandom โดย PHP ซึ่งมีผลอย่างมากสำหรับเหตุผลด้านความปลอดภัย สามารถข้อมูลเพิ่มเติมได้ใน <a target=\"_blank\" href=\"{docLink}\">เอกสาร</a> ของเรา",
"Your PHP version ({version}) is no longer <a target=\"_blank\" href=\"{phpLink}\">supported by PHP</a>. We encourage you to upgrade your PHP version to take advantage of performance and security updates provided by PHP." : "PHP ของคุณรุ่น ({version}) <a target=\"_blank\" href=\"{phpLink}\">ไม่สนับสนุน PHP</a> เราขอแนะนำให้อัพเกรดรุ่น PHP ของคุณ เพื่อปรับปรุงประสิทธิภาพการทำงานและเนื้อหาด้านความปลอดภัย",
@@ -126,6 +125,7 @@
"Memcached is configured as distributed cache, but the wrong PHP module \"memcache\" is installed. \\OC\\Memcache\\Memcached only supports \"memcached\" and not \"memcache\". See the <a target=\"_blank\" href=\"{wikiLink}\">memcached wiki about both modules</a>." : "การกำหนดค่า memcach ผิดพลาดเนื่องจากมีโมดูล PHP ของ memcache ได้ถูกติดตั้งไปแล้ว มีการติดตั้ง \\OC\\Memcache\\Memcached สนับสนุนเฉพาะ \"memcached\" แต่ไม่สนับสนุน \"memcache\" คุณสามารถดู <a target=\"_blank\" href=\"{wikiLink}\">ข้อมูลเกี่ยวกับทั้ง 2 โมดูล</a>",
"Some files have not passed the integrity check. Further information on how to resolve this issue can be found in our <a target=\"_blank\" href=\"{docLink}\">documentation</a>. (<a href=\"{codeIntegrityDownloadEndpoint}\">List of invalid files…</a> / <a href=\"{rescanEndpoint}\">Rescan…</a>)" : "บางไฟล์ยังไม่ผ่านการตรวจสอบความสมบูรณ์ ข้อมูลเพิ่มเติมเกี่ยวกับวิธีการแก้ไขปัญหาเหล่านี้สามารถอ่านได้จาก <a target=\"_blank\" href=\"{docLink}\">เอกสาร</a> ของเรา (<a href=\"{codeIntegrityDownloadEndpoint}\">รายชื่อของไฟล์ที่ไม่ถูกต้อง…</a> / <a href=\"{rescanEndpoint}\">ค้นหาใหม่…</a>)",
"Error occurred while checking server setup" : "เกิดข้อผิดพลาดขณะที่ทำการตรวจสอบการติดตั้งเซิร์ฟเวอร์",
+ "Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "ข้อมูลไดเรกทอรีและไฟล์ของคุณอาจจะสามารถเข้าถึงได้จากอินเทอร์เน็ต ขณะที่ htaccess ไฟล์ไม่ทำงาน เราขอแนะนำให้คุณกำหนดค่าเว็บเซิร์ฟเวอร์ของคุณในทางที่ข้อมูลไดเรกทอรีไม่สามารถเข้าถึงได้หรือคุณย้ายข้อมูลไดเรกทอรีไปยังนอกเว็บเซิร์ฟเวอร์หรือเอกสาร",
"The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "\"{header}\" ไม่ได้กำหนดค่าส่วนหัว Http ให้เท่ากับ \"{expected}\" นี่คือระบบการรักษาความปลอดภัยที่มีศักยภาพหรือลดความเสี่ยงที่จะเกิดขึ้นเราขอแนะนำให้ปรับการตั้งค่านี้",
"The \"Strict-Transport-Security\" HTTP header is not configured to least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our <a href=\"{docUrl}\">security tips</a>." : "\"Strict-Transport-Security\" ส่วนหัว HTTP ไม่ได้กำหนดค่าให้น้อยกว่า \"{seconds}\" วินาที เพื่อความปลอดภัยที่เพิ่มขึ้นเราขอแนะนำให้เปิดใช้งาน HSTS ที่อธิบายไว้ใน <a href=\"{docUrl}\">เคล็ดลับการรักษาความปลอดภัย</a> ของเรา",
"You are accessing this site via HTTP. We strongly suggest you configure your server to require using HTTPS instead as described in our <a href=\"{docUrl}\">security tips</a>." : "คุณกำลังเข้าถึงเว็บไซต์นี้ผ่านทาง HTTP เราขอแนะนำให้คุณกำหนดค่าเซิร์ฟเวอร์ของคุณที่จะต้องใช้ HTTPS แทนตามที่อธิบายไว้ใน <a href=\"{docUrl}\">เคล็ดลับการรักษาความปลอดภัย</a> ของเรา",
@@ -162,17 +162,20 @@
"change" : "เปลี่ยนแปลง",
"delete" : "ลบ",
"access control" : "ควบคุมการเข้าถึง",
+ "Could not unshare" : "ไม่สามารถยกเลิกการแชร์ได้",
"Share details could not be loaded for this item." : "รายละเอียดการแชร์ไม่สามารถโหลดสำหรับรายการนี้",
"An error occured. Please try again" : "เกิดข้อผิดพลาด กรุณาลองอีกครั้ง",
"Share" : "แชร์",
"Share with people on other ownClouds using the syntax username@example.com/owncloud" : "แชร์กับคนใน ownClouds อื่นๆ ที่ใช้ไวยากรณ์ username@example.com/owncloud ",
"Share with users or groups …" : "แชร์กับผู้ใช้หรือกลุ่ม ...",
"Share with users, groups or remote users …" : "แชร์กับผู้ใช้กลุ่มหรือผู้ใช้ระยะไกล ...",
+ "Error removing share" : "พบข้อผิดพลาดในรายการที่แชร์ออก",
"Warning" : "คำเตือน",
"Error while sending notification" : "เกิดข้อผิดพลาดขณะกำลังส่งการแจ้งเตือน",
"Non-existing tag #{tag}" : "ไม่มีแท็กนี้อยู่ #{tag}",
"not assignable" : "ไม่ได้รับมอบหมาย",
"invisible" : "จะมองไม่เห็น",
+ "({scope})" : "({scope})",
"Delete" : "ลบ",
"Rename" : "เปลี่ยนชื่อ",
"Global tags" : "แท็กทั่วไป",
diff --git a/core/shipped.json b/core/shipped.json
index 5f995326625..069bb210ba7 100644
--- a/core/shipped.json
+++ b/core/shipped.json
@@ -13,7 +13,6 @@
"files_drop",
"files_external",
"files_ldap_home",
- "files_locking",
"files_pdfviewer",
"files_sharing",
"files_sharing_log",
diff --git a/lib/l10n/fi_FI.js b/lib/l10n/fi_FI.js
index 2d9bd6f681d..8b273fcc238 100644
--- a/lib/l10n/fi_FI.js
+++ b/lib/l10n/fi_FI.js
@@ -105,6 +105,7 @@ OC.L10N.register(
"Apps" : "Sovellukset",
"Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Vain seuraavat merkit ovat sallittuja käyttäjätunnuksessa: \"a-z\", \"A-Z\", \"0-9\" ja \"_.@-'\"",
"A valid username must be provided" : "Anna kelvollinen käyttäjätunnus",
+ "Username contains whitespace at the beginning or at the end" : "Käyttäjätunnus sisältää tyhjätilaa joko alussa tai lopussa",
"A valid password must be provided" : "Anna kelvollinen salasana",
"The username is already being used" : "Käyttäjätunnus on jo käytössä",
"No database drivers (sqlite, mysql, or postgresql) installed." : "Tietokanta-ajureita (sqlite, mysql tai postgresql) ei ole asennettu.",
diff --git a/lib/l10n/fi_FI.json b/lib/l10n/fi_FI.json
index 31ef261b6c9..3db25f9f220 100644
--- a/lib/l10n/fi_FI.json
+++ b/lib/l10n/fi_FI.json
@@ -103,6 +103,7 @@
"Apps" : "Sovellukset",
"Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Vain seuraavat merkit ovat sallittuja käyttäjätunnuksessa: \"a-z\", \"A-Z\", \"0-9\" ja \"_.@-'\"",
"A valid username must be provided" : "Anna kelvollinen käyttäjätunnus",
+ "Username contains whitespace at the beginning or at the end" : "Käyttäjätunnus sisältää tyhjätilaa joko alussa tai lopussa",
"A valid password must be provided" : "Anna kelvollinen salasana",
"The username is already being used" : "Käyttäjätunnus on jo käytössä",
"No database drivers (sqlite, mysql, or postgresql) installed." : "Tietokanta-ajureita (sqlite, mysql tai postgresql) ei ole asennettu.",
diff --git a/lib/l10n/it.js b/lib/l10n/it.js
index eaaa186a41a..7aab74e24e5 100644
--- a/lib/l10n/it.js
+++ b/lib/l10n/it.js
@@ -120,6 +120,7 @@ OC.L10N.register(
"Apps" : "Applicazioni",
"Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Solo i seguenti caratteri sono consentiti in un nome utente: \"a-z\", \"A-Z\", \"0-9\", e \"_.@-'\"",
"A valid username must be provided" : "Deve essere fornito un nome utente valido",
+ "Username contains whitespace at the beginning or at the end" : "Il nome utente contiene spazi all'inizio o alla fine",
"A valid password must be provided" : "Deve essere fornita una password valida",
"The username is already being used" : "Il nome utente è già utilizzato",
"No database drivers (sqlite, mysql, or postgresql) installed." : "Nessun driver di database (sqlite, mysql o postgresql) installato",
diff --git a/lib/l10n/it.json b/lib/l10n/it.json
index f29b3a2a740..f4238e6e598 100644
--- a/lib/l10n/it.json
+++ b/lib/l10n/it.json
@@ -118,6 +118,7 @@
"Apps" : "Applicazioni",
"Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Solo i seguenti caratteri sono consentiti in un nome utente: \"a-z\", \"A-Z\", \"0-9\", e \"_.@-'\"",
"A valid username must be provided" : "Deve essere fornito un nome utente valido",
+ "Username contains whitespace at the beginning or at the end" : "Il nome utente contiene spazi all'inizio o alla fine",
"A valid password must be provided" : "Deve essere fornita una password valida",
"The username is already being used" : "Il nome utente è già utilizzato",
"No database drivers (sqlite, mysql, or postgresql) installed." : "Nessun driver di database (sqlite, mysql o postgresql) installato",
diff --git a/lib/l10n/pt_BR.js b/lib/l10n/pt_BR.js
index 1ffbdc17a7b..9baa9f51a44 100644
--- a/lib/l10n/pt_BR.js
+++ b/lib/l10n/pt_BR.js
@@ -120,6 +120,7 @@ OC.L10N.register(
"Apps" : "Aplicações",
"Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Somente os seguintes caracteres são permitidos em um nome de usuário: \"a-z\", \"A-Z\", \"0-9\", e \"_.@-'\"",
"A valid username must be provided" : "Forneça um nome de usuário válido",
+ "Username contains whitespace at the beginning or at the end" : "O nome de usuário contém espaço em branco no início ou no fim",
"A valid password must be provided" : "Forneça uma senha válida",
"The username is already being used" : "Este nome de usuário já está sendo usado",
"No database drivers (sqlite, mysql, or postgresql) installed." : "Nenhum driver de banco de dados (sqlite, mysql, or postgresql) instalado.",
diff --git a/lib/l10n/pt_BR.json b/lib/l10n/pt_BR.json
index cb0e48af0db..e2bb90fd0ce 100644
--- a/lib/l10n/pt_BR.json
+++ b/lib/l10n/pt_BR.json
@@ -118,6 +118,7 @@
"Apps" : "Aplicações",
"Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Somente os seguintes caracteres são permitidos em um nome de usuário: \"a-z\", \"A-Z\", \"0-9\", e \"_.@-'\"",
"A valid username must be provided" : "Forneça um nome de usuário válido",
+ "Username contains whitespace at the beginning or at the end" : "O nome de usuário contém espaço em branco no início ou no fim",
"A valid password must be provided" : "Forneça uma senha válida",
"The username is already being used" : "Este nome de usuário já está sendo usado",
"No database drivers (sqlite, mysql, or postgresql) installed." : "Nenhum driver de banco de dados (sqlite, mysql, or postgresql) instalado.",
diff --git a/lib/l10n/pt_PT.js b/lib/l10n/pt_PT.js
index b2f2a21afb5..9ea7b813e70 100644
--- a/lib/l10n/pt_PT.js
+++ b/lib/l10n/pt_PT.js
@@ -117,6 +117,7 @@ OC.L10N.register(
"Apps" : "Apps",
"Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Apenas os seguintes caracteres são permitidos num nome de utilizador: \"a-z\", \"A-Z\", \"0-9\", e \"_.@-'\"",
"A valid username must be provided" : "Um nome de utilizador válido deve ser fornecido",
+ "Username contains whitespace at the beginning or at the end" : "Nome de utilizador contém espaço em branco no início ou no fim",
"A valid password must be provided" : "Uma password válida deve ser fornecida",
"The username is already being used" : "O nome de utilizador já está a ser usado",
"No database drivers (sqlite, mysql, or postgresql) installed." : "Nenhuma base de dados de drivers (sqlite, mysql, or postgresql) instaladas.",
diff --git a/lib/l10n/pt_PT.json b/lib/l10n/pt_PT.json
index c1a7f6dfd4a..60a31bb4393 100644
--- a/lib/l10n/pt_PT.json
+++ b/lib/l10n/pt_PT.json
@@ -115,6 +115,7 @@
"Apps" : "Apps",
"Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Apenas os seguintes caracteres são permitidos num nome de utilizador: \"a-z\", \"A-Z\", \"0-9\", e \"_.@-'\"",
"A valid username must be provided" : "Um nome de utilizador válido deve ser fornecido",
+ "Username contains whitespace at the beginning or at the end" : "Nome de utilizador contém espaço em branco no início ou no fim",
"A valid password must be provided" : "Uma password válida deve ser fornecida",
"The username is already being used" : "O nome de utilizador já está a ser usado",
"No database drivers (sqlite, mysql, or postgresql) installed." : "Nenhuma base de dados de drivers (sqlite, mysql, or postgresql) instaladas.",
diff --git a/lib/l10n/sq.js b/lib/l10n/sq.js
index 18805d6337a..bfb5b12cc32 100644
--- a/lib/l10n/sq.js
+++ b/lib/l10n/sq.js
@@ -120,6 +120,7 @@ OC.L10N.register(
"Apps" : "Aplikacione",
"Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Në një emër përdoruesi lejohen vetëm shenjat vijuese: \"a-z\", \"A-Z\", \"0-9\", dhe \"_.@-\"",
"A valid username must be provided" : "Duhet dhënë një emër i vlefshëm përdoruesi",
+ "Username contains whitespace at the beginning or at the end" : "Emri i përdoruesit përmban hapësirë në fillim ose në fund",
"A valid password must be provided" : "Duhet dhënë një fjalëkalim i vlefshëm",
"The username is already being used" : "Emri i përdoruesit është tashmë i përdorur",
"No database drivers (sqlite, mysql, or postgresql) installed." : "S’ka baza të dhënash (sqlite, mysql, ose postgresql) të instaluara.",
diff --git a/lib/l10n/sq.json b/lib/l10n/sq.json
index 353659069e5..7768167dc4f 100644
--- a/lib/l10n/sq.json
+++ b/lib/l10n/sq.json
@@ -118,6 +118,7 @@
"Apps" : "Aplikacione",
"Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Në një emër përdoruesi lejohen vetëm shenjat vijuese: \"a-z\", \"A-Z\", \"0-9\", dhe \"_.@-\"",
"A valid username must be provided" : "Duhet dhënë një emër i vlefshëm përdoruesi",
+ "Username contains whitespace at the beginning or at the end" : "Emri i përdoruesit përmban hapësirë në fillim ose në fund",
"A valid password must be provided" : "Duhet dhënë një fjalëkalim i vlefshëm",
"The username is already being used" : "Emri i përdoruesit është tashmë i përdorur",
"No database drivers (sqlite, mysql, or postgresql) installed." : "S’ka baza të dhënash (sqlite, mysql, ose postgresql) të instaluara.",
diff --git a/lib/private/appframework/dependencyinjection/dicontainer.php b/lib/private/appframework/dependencyinjection/dicontainer.php
index 5fc45fdd2e8..f74fe4aeb99 100644
--- a/lib/private/appframework/dependencyinjection/dicontainer.php
+++ b/lib/private/appframework/dependencyinjection/dicontainer.php
@@ -104,6 +104,10 @@ class DIContainer extends SimpleContainer implements IAppContainer {
return $this->getServer()->getCapabilitiesManager();
});
+ $this->registerService('OCP\Comments\ICommentsManager', function($c) {
+ return $this->getServer()->getCommentsManager();
+ });
+
$this->registerService('OCP\\IConfig', function($c) {
return $this->getServer()->getConfig();
});
diff --git a/lib/private/comments/comment.php b/lib/private/comments/comment.php
index 75964603f9f..36189d9523b 100644
--- a/lib/private/comments/comment.php
+++ b/lib/private/comments/comment.php
@@ -242,7 +242,7 @@ class Comment implements IComment {
/**
* sets (overwrites) the actor type and id
*
- * @param string $actorType e.g. 'user'
+ * @param string $actorType e.g. 'users'
* @param string $actorId e.g. 'zombie234'
* @return IComment
* @since 9.0.0
@@ -328,7 +328,7 @@ class Comment implements IComment {
/**
* sets (overwrites) the object of the comment
*
- * @param string $objectType e.g. 'file'
+ * @param string $objectType e.g. 'files'
* @param string $objectId e.g. '16435'
* @return IComment
* @since 9.0.0
diff --git a/lib/private/comments/manager.php b/lib/private/comments/manager.php
index 28bd3b0916a..36b2d9d08b8 100644
--- a/lib/private/comments/manager.php
+++ b/lib/private/comments/manager.php
@@ -21,6 +21,7 @@
namespace OC\Comments;
use Doctrine\DBAL\Exception\DriverException;
+use OCP\Comments\CommentsEvent;
use OCP\Comments\IComment;
use OCP\Comments\ICommentsManager;
use OCP\Comments\NotFoundException;
@@ -28,6 +29,7 @@ use OCP\IDBConnection;
use OCP\IConfig;
use OCP\ILogger;
use OCP\IUser;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
class Manager implements ICommentsManager {
@@ -37,20 +39,33 @@ class Manager implements ICommentsManager {
/** @var ILogger */
protected $logger;
- /** @var IComment[] */
- protected $commentsCache = [];
-
/** @var IConfig */
protected $config;
+ /** @var EventDispatcherInterface */
+ protected $dispatcher;
+
+ /** @var IComment[] */
+ protected $commentsCache = [];
+
+ /**
+ * Manager constructor.
+ *
+ * @param IDBConnection $dbConn
+ * @param ILogger $logger
+ * @param IConfig $config
+ * @param EventDispatcherInterface $dispatcher
+ */
public function __construct(
IDBConnection $dbConn,
ILogger $logger,
- IConfig $config
+ IConfig $config,
+ EventDispatcherInterface $dispatcher
) {
$this->dbConn = $dbConn;
$this->logger = $logger;
$this->config = $config;
+ $this->dispatcher = $dispatcher;
}
/**
@@ -384,7 +399,7 @@ class Manager implements ICommentsManager {
* saved in the used data storage. Use save() after setting other fields
* of the comment (e.g. message or verb).
*
- * @param string $actorType the actor type (e.g. 'user')
+ * @param string $actorType the actor type (e.g. 'users')
* @param string $actorId a user id
* @param string $objectType the object type the comment is attached to
* @param string $objectId the object id the comment is attached to
@@ -415,6 +430,13 @@ class Manager implements ICommentsManager {
throw new \InvalidArgumentException('Parameter must be string');
}
+ try {
+ $comment = $this->get($id);
+ } catch (\Exception $e) {
+ // Ignore exceptions, we just don't fire a hook then
+ $comment = null;
+ }
+
$qb = $this->dbConn->getQueryBuilder();
$query = $qb->delete('comments')
->where($qb->expr()->eq('id', $qb->createParameter('id')))
@@ -427,11 +449,19 @@ class Manager implements ICommentsManager {
$this->logger->logException($e, ['app' => 'core_comments']);
return false;
}
+
+ if ($affectedRows > 0 && $comment instanceof IComment) {
+ $this->dispatcher->dispatch(CommentsEvent::EVENT_DELETE, new CommentsEvent(
+ CommentsEvent::EVENT_DELETE,
+ $comment
+ ));
+ }
+
return ($affectedRows > 0);
}
/**
- * saves the comment permanently and returns it
+ * saves the comment permanently
*
* if the supplied comment has an empty ID, a new entry comment will be
* saved and the instance updated with the new ID.
@@ -493,6 +523,11 @@ class Manager implements ICommentsManager {
$comment->setId(strval($qb->getLastInsertId()));
}
+ $this->dispatcher->dispatch(CommentsEvent::EVENT_ADD, new CommentsEvent(
+ CommentsEvent::EVENT_ADD,
+ $comment
+ ));
+
return $affectedRows > 0;
}
@@ -526,6 +561,11 @@ class Manager implements ICommentsManager {
throw new NotFoundException('Comment to update does ceased to exist');
}
+ $this->dispatcher->dispatch(CommentsEvent::EVENT_UPDATE, new CommentsEvent(
+ CommentsEvent::EVENT_UPDATE,
+ $comment
+ ));
+
return $affectedRows > 0;
}
@@ -533,7 +573,7 @@ class Manager implements ICommentsManager {
* removes references to specific actor (e.g. on user delete) of a comment.
* The comment itself must not get lost/deleted.
*
- * @param string $actorType the actor type (e.g. 'user')
+ * @param string $actorType the actor type (e.g. 'users')
* @param string $actorId a user id
* @return boolean
* @since 9.0.0
@@ -560,7 +600,7 @@ class Manager implements ICommentsManager {
/**
* deletes all comments made of a specific object (e.g. on file delete)
*
- * @param string $objectType the object type (e.g. 'file')
+ * @param string $objectType the object type (e.g. 'files')
* @param string $objectId e.g. the file id
* @return boolean
* @since 9.0.0
diff --git a/lib/private/comments/managerfactory.php b/lib/private/comments/managerfactory.php
index d3f6c44e539..b8e77c64fae 100644
--- a/lib/private/comments/managerfactory.php
+++ b/lib/private/comments/managerfactory.php
@@ -52,7 +52,8 @@ class ManagerFactory implements ICommentsManagerFactory {
return new Manager(
$this->serverContainer->getDatabaseConnection(),
$this->serverContainer->getLogger(),
- $this->serverContainer->getConfig()
+ $this->serverContainer->getConfig(),
+ $this->serverContainer->getEventDispatcher()
);
}
}
diff --git a/lib/private/console/application.php b/lib/private/console/application.php
index c7d9c24d7cb..10ff69b1c80 100644
--- a/lib/private/console/application.php
+++ b/lib/private/console/application.php
@@ -25,25 +25,34 @@ namespace OC\Console;
use OC_App;
use OC_Defaults;
+use OCP\Console\ConsoleEvent;
use OCP\IConfig;
+use OCP\IRequest;
use Symfony\Component\Console\Application as SymfonyApplication;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
class Application {
- /**
- * @var IConfig
- */
+ /** @var IConfig */
private $config;
+ /** @var EventDispatcherInterface */
+ private $dispatcher;
+ /** @var IRequest */
+ private $request;
/**
* @param IConfig $config
+ * @param EventDispatcherInterface $dispatcher
+ * @param IRequest $request
*/
- public function __construct(IConfig $config) {
+ public function __construct(IConfig $config, EventDispatcherInterface $dispatcher, IRequest $request) {
$defaults = new OC_Defaults;
$this->config = $config;
$this->application = new SymfonyApplication($defaults->getName(), \OC_Util::getVersionString());
+ $this->dispatcher = $dispatcher;
+ $this->request = $request;
}
/**
@@ -107,6 +116,10 @@ class Application {
* @throws \Exception
*/
public function run(InputInterface $input = null, OutputInterface $output = null) {
+ $this->dispatcher->dispatch(ConsoleEvent::EVENT_RUN, new ConsoleEvent(
+ ConsoleEvent::EVENT_RUN,
+ $this->request->server['argv']
+ ));
return $this->application->run($input, $output);
}
}
diff --git a/lib/private/db/mdb2schemamanager.php b/lib/private/db/mdb2schemamanager.php
index 495ccb902d6..bcabb6fe57a 100644
--- a/lib/private/db/mdb2schemamanager.php
+++ b/lib/private/db/mdb2schemamanager.php
@@ -49,7 +49,6 @@ class MDB2SchemaManager {
/**
* saves database scheme to xml file
* @param string $file name of file
- * @param int|string $mode
* @return bool
*
* TODO: write more documentation
@@ -123,7 +122,7 @@ class MDB2SchemaManager {
/**
* update the database scheme
* @param string $file file to read structure from
- * @return string|boolean
+ * @return boolean
*/
public function simulateUpdateDbFromStructure($file) {
$toSchema = $this->readSchemaFromFile($file);
diff --git a/lib/private/db/querybuilder/expressionbuilder.php b/lib/private/db/querybuilder/expressionbuilder/expressionbuilder.php
index b688ebfabbe..7ab4c03d97c 100644
--- a/lib/private/db/querybuilder/expressionbuilder.php
+++ b/lib/private/db/querybuilder/expressionbuilder/expressionbuilder.php
@@ -19,9 +19,13 @@
*
*/
-namespace OC\DB\QueryBuilder;
+namespace OC\DB\QueryBuilder\ExpressionBuilder;
use Doctrine\DBAL\Query\Expression\ExpressionBuilder as DoctrineExpressionBuilder;
+use OC\DB\QueryBuilder\CompositeExpression;
+use OC\DB\QueryBuilder\Literal;
+use OC\DB\QueryBuilder\QueryFunction;
+use OC\DB\QueryBuilder\QuoteHelper;
use OCP\DB\QueryBuilder\IExpressionBuilder;
use OCP\IDBConnection;
@@ -331,4 +335,17 @@ class ExpressionBuilder implements IExpressionBuilder {
public function literal($input, $type = null) {
return new Literal($this->expressionBuilder->literal($input, $type));
}
+
+ /**
+ * Returns a IQueryFunction that casts the column to the given type
+ *
+ * @param string $column
+ * @param mixed $type One of IQueryBuilder::PARAM_*
+ * @return string
+ */
+ public function castColumn($column, $type) {
+ return new QueryFunction(
+ $this->helper->quoteColumnName($column)
+ );
+ }
}
diff --git a/lib/private/db/querybuilder/ociexpressionbuilder.php b/lib/private/db/querybuilder/expressionbuilder/ociexpressionbuilder.php
index 4c127bd752d..6a6d0f455f6 100644
--- a/lib/private/db/querybuilder/ociexpressionbuilder.php
+++ b/lib/private/db/querybuilder/expressionbuilder/ociexpressionbuilder.php
@@ -19,24 +19,25 @@
*
*/
-namespace OC\DB\QueryBuilder;
+namespace OC\DB\QueryBuilder\ExpressionBuilder;
+use OC\DB\QueryBuilder\QueryFunction;
use OCP\DB\QueryBuilder\ILiteral;
use OCP\DB\QueryBuilder\IParameter;
use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\DB\QueryBuilder\IQueryFunction;
class OCIExpressionBuilder extends ExpressionBuilder {
/**
* @param mixed $column
* @param mixed|null $type
- * @return array|QueryFunction|string
+ * @return array|IQueryFunction|string
*/
protected function prepareColumn($column, $type) {
if ($type === IQueryBuilder::PARAM_STR && !is_array($column) && !($column instanceof IParameter) && !($column instanceof ILiteral)) {
- $column = $this->helper->quoteColumnName($column);
- $column = new QueryFunction('to_char(' . $column . ')');
+ $column = $this->castColumn($column, $type);
} else {
$column = $this->helper->quoteColumnNames($column);
}
@@ -132,4 +133,20 @@ class OCIExpressionBuilder extends ExpressionBuilder {
return $this->expressionBuilder->notIn($x, $y);
}
+
+ /**
+ * Returns a IQueryFunction that casts the column to the given type
+ *
+ * @param string $column
+ * @param mixed $type One of IQueryBuilder::PARAM_*
+ * @return IQueryFunction
+ */
+ public function castColumn($column, $type) {
+ if ($type === IQueryBuilder::PARAM_STR) {
+ $column = $this->helper->quoteColumnName($column);
+ return new QueryFunction('to_char(' . $column . ')');
+ }
+
+ return parent::castColumn($column, $type);
+ }
}
diff --git a/lib/private/db/querybuilder/expressionbuilder/pgsqlexpressionbuilder.php b/lib/private/db/querybuilder/expressionbuilder/pgsqlexpressionbuilder.php
new file mode 100644
index 00000000000..8a0b68db998
--- /dev/null
+++ b/lib/private/db/querybuilder/expressionbuilder/pgsqlexpressionbuilder.php
@@ -0,0 +1,45 @@
+<?php
+/**
+ * @author Joas Schilling <nickvergessen@owncloud.com>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\DB\QueryBuilder\ExpressionBuilder;
+
+
+use OC\DB\QueryBuilder\QueryFunction;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+
+class PgSqlExpressionBuilder extends ExpressionBuilder {
+
+ /**
+ * Returns a IQueryFunction that casts the column to the given type
+ *
+ * @param string $column
+ * @param mixed $type One of IQueryBuilder::PARAM_*
+ * @return string
+ */
+ public function castColumn($column, $type) {
+ if ($type === IQueryBuilder::PARAM_INT) {
+ $column = $this->helper->quoteColumnName($column);
+ return new QueryFunction('CAST(' . $column . ' AS INT)');
+ }
+
+ return parent::castColumn($column, $type);
+ }
+}
diff --git a/lib/private/db/querybuilder/querybuilder.php b/lib/private/db/querybuilder/querybuilder.php
index 42b290b90e7..ff31ffbc043 100644
--- a/lib/private/db/querybuilder/querybuilder.php
+++ b/lib/private/db/querybuilder/querybuilder.php
@@ -21,7 +21,11 @@
namespace OC\DB\QueryBuilder;
+use Doctrine\DBAL\Platforms\PostgreSqlPlatform;
use OC\DB\OracleConnection;
+use OC\DB\QueryBuilder\ExpressionBuilder\ExpressionBuilder;
+use OC\DB\QueryBuilder\ExpressionBuilder\OCIExpressionBuilder;
+use OC\DB\QueryBuilder\ExpressionBuilder\PgSqlExpressionBuilder;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\DB\QueryBuilder\IQueryFunction;
use OCP\DB\QueryBuilder\IParameter;
@@ -85,6 +89,8 @@ class QueryBuilder implements IQueryBuilder {
public function expr() {
if ($this->connection instanceof OracleConnection) {
return new OCIExpressionBuilder($this->connection);
+ } else if ($this->connection->getDatabasePlatform() instanceof PostgreSqlPlatform) {
+ return new PgSqlExpressionBuilder($this->connection);
} else {
return new ExpressionBuilder($this->connection);
}
diff --git a/lib/private/diagnostics/querylogger.php b/lib/private/diagnostics/querylogger.php
index 794e7a5e263..66a65b71d04 100644
--- a/lib/private/diagnostics/querylogger.php
+++ b/lib/private/diagnostics/querylogger.php
@@ -53,7 +53,7 @@ class QueryLogger implements IQueryLogger {
}
/**
- * @return \OCP\Diagnostics\IQuery[]
+ * @return Query[]
*/
public function getQueries() {
return $this->queries;
diff --git a/lib/private/files.php b/lib/private/files.php
index 7b451ac19be..a18bcc76519 100644
--- a/lib/private/files.php
+++ b/lib/private/files.php
@@ -160,6 +160,8 @@ class OC_Files {
/**
* @param View $view
* @param string $name
+ * @param string $dir
+ * @param boolean $onlyHeader
*/
private static function getSingleFile($view, $dir, $name, $onlyHeader) {
$filename = $dir . '/' . $name;
@@ -185,7 +187,7 @@ class OC_Files {
/**
* @param View $view
- * @param $dir
+ * @param string $dir
* @param string[]|string $files
*/
public static function lockFiles($view, $dir, $files) {
@@ -290,11 +292,11 @@ class OC_Files {
}
/**
- * @param $dir
+ * @param string $dir
* @param $files
- * @param $getType
+ * @param integer $getType
* @param View $view
- * @param $filename
+ * @param string $filename
*/
private static function unlockAllTheFiles($dir, $files, $getType, $view, $filename) {
if ($getType === self::FILE) {
diff --git a/lib/private/files/cache/cache.php b/lib/private/files/cache/cache.php
index cbe48f21bd8..22b9f49e528 100644
--- a/lib/private/files/cache/cache.php
+++ b/lib/private/files/cache/cache.php
@@ -201,7 +201,7 @@ class Cache implements ICache {
}
/**
- * store meta data for a file or folder
+ * insert or update meta data for a file or folder
*
* @param string $file
* @param array $data
@@ -214,49 +214,62 @@ class Cache implements ICache {
$this->update($id, $data);
return $id;
} else {
- // normalize file
- $file = $this->normalize($file);
+ return $this->insert($file, $data);
+ }
+ }
- if (isset($this->partial[$file])) { //add any saved partial data
- $data = array_merge($this->partial[$file], $data);
- unset($this->partial[$file]);
- }
+ /**
+ * insert meta data for a new file or folder
+ *
+ * @param string $file
+ * @param array $data
+ *
+ * @return int file id
+ * @throws \RuntimeException
+ */
+ public function insert($file, array $data) {
+ // normalize file
+ $file = $this->normalize($file);
- $requiredFields = array('size', 'mtime', 'mimetype');
- foreach ($requiredFields as $field) {
- if (!isset($data[$field])) { //data not complete save as partial and return
- $this->partial[$file] = $data;
- return -1;
- }
- }
+ if (isset($this->partial[$file])) { //add any saved partial data
+ $data = array_merge($this->partial[$file], $data);
+ unset($this->partial[$file]);
+ }
- $data['path'] = $file;
- $data['parent'] = $this->getParentId($file);
- $data['name'] = \OC_Util::basename($file);
-
- list($queryParts, $params) = $this->buildParts($data);
- $queryParts[] = '`storage`';
- $params[] = $this->getNumericStorageId();
-
- $queryParts = array_map(function ($item) {
- return trim($item, "`");
- }, $queryParts);
- $values = array_combine($queryParts, $params);
- if (\OC::$server->getDatabaseConnection()->insertIfNotExist('*PREFIX*filecache', $values, [
- 'storage',
- 'path_hash',
- ])
- ) {
- return (int)$this->connection->lastInsertId('*PREFIX*filecache');
+ $requiredFields = array('size', 'mtime', 'mimetype');
+ foreach ($requiredFields as $field) {
+ if (!isset($data[$field])) { //data not complete save as partial and return
+ $this->partial[$file] = $data;
+ return -1;
}
+ }
- // The file was created in the mean time
- if (($id = $this->getId($file)) > -1) {
- $this->update($id, $data);
- return $id;
- } else {
- throw new \RuntimeException('File entry could not be inserted with insertIfNotExist() but could also not be selected with getId() in order to perform an update. Please try again.');
- }
+ $data['path'] = $file;
+ $data['parent'] = $this->getParentId($file);
+ $data['name'] = \OC_Util::basename($file);
+
+ list($queryParts, $params) = $this->buildParts($data);
+ $queryParts[] = '`storage`';
+ $params[] = $this->getNumericStorageId();
+
+ $queryParts = array_map(function ($item) {
+ return trim($item, "`");
+ }, $queryParts);
+ $values = array_combine($queryParts, $params);
+ if (\OC::$server->getDatabaseConnection()->insertIfNotExist('*PREFIX*filecache', $values, [
+ 'storage',
+ 'path_hash',
+ ])
+ ) {
+ return (int)$this->connection->lastInsertId('*PREFIX*filecache');
+ }
+
+ // The file was created in the mean time
+ if (($id = $this->getId($file)) > -1) {
+ $this->update($id, $data);
+ return $id;
+ } else {
+ throw new \RuntimeException('File entry could not be inserted with insertIfNotExist() but could also not be selected with getId() in order to perform an update. Please try again.');
}
}
diff --git a/lib/private/files/cache/wrapper/cachejail.php b/lib/private/files/cache/wrapper/cachejail.php
index 32bd3626fcb..868e63cdf81 100644
--- a/lib/private/files/cache/wrapper/cachejail.php
+++ b/lib/private/files/cache/wrapper/cachejail.php
@@ -95,15 +95,16 @@ class CacheJail extends CacheWrapper {
}
/**
- * store meta data for a file or folder
+ * insert meta data for a new file or folder
*
* @param string $file
* @param array $data
*
* @return int file id
+ * @throws \RuntimeException
*/
- public function put($file, array $data) {
- return $this->cache->put($this->getSourcePath($file), $data);
+ public function insert($file, array $data) {
+ return $this->cache->insert($this->getSourcePath($file), $data);
}
/**
diff --git a/lib/private/files/cache/wrapper/cachewrapper.php b/lib/private/files/cache/wrapper/cachewrapper.php
index 1ce4f028c75..4080883419e 100644
--- a/lib/private/files/cache/wrapper/cachewrapper.php
+++ b/lib/private/files/cache/wrapper/cachewrapper.php
@@ -90,15 +90,34 @@ class CacheWrapper extends Cache {
}
/**
- * store meta data for a file or folder
+ * insert or update meta data for a file or folder
*
* @param string $file
* @param array $data
*
* @return int file id
+ * @throws \RuntimeException
*/
public function put($file, array $data) {
- return $this->cache->put($file, $data);
+ if (($id = $this->getId($file)) > -1) {
+ $this->update($id, $data);
+ return $id;
+ } else {
+ return $this->insert($file, $data);
+ }
+ }
+
+ /**
+ * insert meta data for a new file or folder
+ *
+ * @param string $file
+ * @param array $data
+ *
+ * @return int file id
+ * @throws \RuntimeException
+ */
+ public function insert($file, array $data) {
+ return $this->cache->insert($file, $data);
}
/**
diff --git a/lib/private/files/node/root.php b/lib/private/files/node/root.php
index 35163be0a0d..40ed531d5df 100644
--- a/lib/private/files/node/root.php
+++ b/lib/private/files/node/root.php
@@ -169,7 +169,7 @@ class Root extends Folder implements IRootFolder {
* @param string $path
* @throws \OCP\Files\NotFoundException
* @throws \OCP\Files\NotPermittedException
- * @return \OCP\Files\Node
+ * @return string
*/
public function get($path) {
$path = $this->normalizePath($path);
diff --git a/lib/private/files/storage/common.php b/lib/private/files/storage/common.php
index 95bb3f74ba7..3d5898dcd80 100644
--- a/lib/private/files/storage/common.php
+++ b/lib/private/files/storage/common.php
@@ -248,12 +248,6 @@ abstract class Common implements Storage, ILockingStorage {
return $this->getCachedFile($path);
}
- public function getLocalFolder($path) {
- $baseDir = \OC::$server->getTempManager()->getTemporaryFolder();
- $this->addLocalFolder($path, $baseDir);
- return $baseDir;
- }
-
/**
* @param string $path
* @param string $target
@@ -396,7 +390,7 @@ abstract class Common implements Storage, ILockingStorage {
* get the ETag for a file or folder
*
* @param string $path
- * @return string|false
+ * @return string
*/
public function getETag($path) {
return uniqid();
diff --git a/lib/private/files/storage/wrapper/availability.php b/lib/private/files/storage/wrapper/availability.php
index 1550c318ce3..55ddb0d5e8f 100644
--- a/lib/private/files/storage/wrapper/availability.php
+++ b/lib/private/files/storage/wrapper/availability.php
@@ -377,17 +377,6 @@ class Availability extends Wrapper {
}
/** {@inheritdoc} */
- public function getLocalFolder($path) {
- $this->checkAvailability();
- try {
- return parent::getLocalFolder($path);
- } catch (\OCP\Files\StorageNotAvailableException $e) {
- $this->setAvailability(false);
- throw $e;
- }
- }
-
- /** {@inheritdoc} */
public function hasUpdated($path, $time) {
$this->checkAvailability();
try {
diff --git a/lib/private/files/storage/wrapper/jail.php b/lib/private/files/storage/wrapper/jail.php
index 40738befd93..e5f5ab90359 100644
--- a/lib/private/files/storage/wrapper/jail.php
+++ b/lib/private/files/storage/wrapper/jail.php
@@ -353,17 +353,6 @@ class Jail extends Wrapper {
}
/**
- * get the path to a local version of the folder.
- * The local version of the folder can be temporary and doesn't have to be persistent across requests
- *
- * @param string $path
- * @return string
- */
- public function getLocalFolder($path) {
- return $this->storage->getLocalFolder($this->getSourcePath($path));
- }
-
- /**
* check if a file or folder has been updated since $time
*
* @param string $path
diff --git a/lib/private/files/storage/wrapper/wrapper.php b/lib/private/files/storage/wrapper/wrapper.php
index c632aa399e1..12914e7a1b8 100644
--- a/lib/private/files/storage/wrapper/wrapper.php
+++ b/lib/private/files/storage/wrapper/wrapper.php
@@ -354,17 +354,6 @@ class Wrapper implements \OC\Files\Storage\Storage, ILockingStorage {
}
/**
- * get the path to a local version of the folder.
- * The local version of the folder can be temporary and doesn't have to be persistent across requests
- *
- * @param string $path
- * @return string
- */
- public function getLocalFolder($path) {
- return $this->storage->getLocalFolder($path);
- }
-
- /**
* check if a file or folder has been updated since $time
*
* @param string $path
diff --git a/lib/private/files/stream/dir.php b/lib/private/files/stream/dir.php
index fabadb0d596..7489ee683a2 100644
--- a/lib/private/files/stream/dir.php
+++ b/lib/private/files/stream/dir.php
@@ -58,6 +58,7 @@ class Dir {
/**
* @param string $path
+ * @param string[] $content
*/
public static function register($path, $content) {
self::$dirs[$path] = $content;
diff --git a/lib/private/files/type/detection.php b/lib/private/files/type/detection.php
index 9cc2e97c3cc..f106a98064f 100644
--- a/lib/private/files/type/detection.php
+++ b/lib/private/files/type/detection.php
@@ -121,7 +121,7 @@ class Detection implements IMimeTypeDetector {
}
/**
- * @return array
+ * @return string[]
*/
public function getAllAliases() {
$this->loadAliases();
@@ -264,7 +264,7 @@ class Detection implements IMimeTypeDetector {
/**
* Get path to the icon of a file type
- * @param string $mimeType the MIME type
+ * @param string $mimetype the MIME type
* @return string the url
*/
public function mimeTypeIcon($mimetype) {
diff --git a/lib/private/integritycheck/checker.php b/lib/private/integritycheck/checker.php
index c256fe66d32..e6f9f9a1457 100644
--- a/lib/private/integritycheck/checker.php
+++ b/lib/private/integritycheck/checker.php
@@ -90,6 +90,8 @@ class Checker {
// FIXME: Once the signing server is instructed to sign daily, beta and
// RCs as well these need to be included also.
$signedChannels = [
+ 'daily',
+ 'testing',
'stable',
];
if(!in_array($this->environmentHelper->getChannel(), $signedChannels, true)) {
@@ -113,16 +115,22 @@ class Checker {
* Enumerates all files belonging to the folder. Sensible defaults are excluded.
*
* @param string $folderToIterate
+ * @param string $root
* @return \RecursiveIteratorIterator
* @throws \Exception
*/
- private function getFolderIterator($folderToIterate) {
+ private function getFolderIterator($folderToIterate, $root = '') {
$dirItr = new \RecursiveDirectoryIterator(
$folderToIterate,
\RecursiveDirectoryIterator::SKIP_DOTS
);
+ if($root === '') {
+ $root = \OC::$SERVERROOT;
+ }
+ $root = rtrim($root, '/');
+
$excludeGenericFilesIterator = new ExcludeFileByNameFilterIterator($dirItr);
- $excludeFoldersIterator = new ExcludeFoldersByPathFilterIterator($excludeGenericFilesIterator);
+ $excludeFoldersIterator = new ExcludeFoldersByPathFilterIterator($excludeGenericFilesIterator, $root);
return new \RecursiveIteratorIterator(
$excludeFoldersIterator,
@@ -234,14 +242,16 @@ class Checker {
*
* @param X509 $certificate
* @param RSA $rsa
+ * @param string $path
*/
public function writeCoreSignature(X509 $certificate,
- RSA $rsa) {
- $iterator = $this->getFolderIterator($this->environmentHelper->getServerRoot());
- $hashes = $this->generateHashes($iterator, $this->environmentHelper->getServerRoot());
+ RSA $rsa,
+ $path) {
+ $iterator = $this->getFolderIterator($path, $path);
+ $hashes = $this->generateHashes($iterator, $path);
$signatureData = $this->createSignatureData($hashes, $certificate, $rsa);
$this->fileAccessHelper->file_put_contents(
- $this->environmentHelper->getServerRoot() . '/core/signature.json',
+ $path . '/core/signature.json',
json_encode($signatureData, JSON_PRETTY_PRINT)
);
}
diff --git a/lib/private/integritycheck/iterator/excludefoldersbypathfilteriterator.php b/lib/private/integritycheck/iterator/excludefoldersbypathfilteriterator.php
index c3994197fc6..67bcd423b68 100644
--- a/lib/private/integritycheck/iterator/excludefoldersbypathfilteriterator.php
+++ b/lib/private/integritycheck/iterator/excludefoldersbypathfilteriterator.php
@@ -24,7 +24,7 @@ namespace OC\IntegrityCheck\Iterator;
class ExcludeFoldersByPathFilterIterator extends \RecursiveFilterIterator {
private $excludedFolders = [];
- public function __construct(\RecursiveIterator $iterator) {
+ public function __construct(\RecursiveIterator $iterator, $root = '') {
parent::__construct($iterator);
$appFolders = \OC::$APPSROOTS;
@@ -33,9 +33,10 @@ class ExcludeFoldersByPathFilterIterator extends \RecursiveFilterIterator {
}
$this->excludedFolders = array_merge([
- rtrim(\OC::$server->getConfig()->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data'), '/'),
- rtrim(\OC::$SERVERROOT.'/themes', '/'),
- rtrim(\OC::$SERVERROOT.'/config', '/'),
+ rtrim($root . '/data', '/'),
+ rtrim($root .'/themes', '/'),
+ rtrim($root.'/config', '/'),
+ rtrim($root.'/apps', '/'),
], $appFolders);
}
diff --git a/lib/private/repair/dropoldjobs.php b/lib/private/repair/dropoldjobs.php
index 2d6172047c2..b2e9b05caa2 100644
--- a/lib/private/repair/dropoldjobs.php
+++ b/lib/private/repair/dropoldjobs.php
@@ -71,6 +71,7 @@ class DropOldJobs extends BasicEmitter implements RepairStep {
return [
['class' => 'OC_Cache_FileGlobalGC', 'arguments' => null],
['class' => 'OC\Cache\FileGlobalGC', 'arguments' => null],
+ ['class' => 'OCA\Files\BackgroundJob\DeleteOrphanedTagsJob', 'arguments' => null],
];
}
diff --git a/lib/private/repair/repairmimetypes.php b/lib/private/repair/repairmimetypes.php
index 692a7120a63..b84f19a3082 100644
--- a/lib/private/repair/repairmimetypes.php
+++ b/lib/private/repair/repairmimetypes.php
@@ -293,6 +293,17 @@ class RepairMimeTypes extends BasicEmitter implements \OC\RepairStep {
self::updateMimetypes($updatedMimetypes);
}
+ private function introduceRichDocumentsMimeTypes() {
+ $updatedMimetypes = array(
+ 'lwp' => 'application/vnd.lotus-wordpro',
+ 'one' => 'application/msonenote',
+ 'vsd' => 'application/vnd.visio',
+ 'wpd' => 'application/vnd.wordperfect',
+ );
+
+ self::updateMimetypes($updatedMimetypes);
+ }
+
/**
* Fix mime types
*/
@@ -356,5 +367,11 @@ class RepairMimeTypes extends BasicEmitter implements \OC\RepairStep {
$this->emit('\OC\Repair', 'info', array('Fixed rtf mime type'));
}
}
+
+ if (version_compare($ocVersionFromBeforeUpdate, '9.0.0.10', '<')) {
+ if ($this->introduceRichDocumentsMimeTypes()) {
+ $this->emit('\OC\Repair', 'info', array('Fixed richdocuments additional office mime types'));
+ }
+ }
}
}
diff --git a/lib/private/server.php b/lib/private/server.php
index d3dbcba86ba..55ac64a0c2d 100644
--- a/lib/private/server.php
+++ b/lib/private/server.php
@@ -617,7 +617,9 @@ class Server extends ServerContainer implements IServerContainer {
$c->getMountManager(),
$c->getGroupManager(),
$c->getL10N('core'),
- $factory
+ $factory,
+ $c->getUserManager(),
+ $c->getRootFolder()
);
return $manager;
diff --git a/lib/private/share/hooks.php b/lib/private/share/hooks.php
index 1fa233916d1..c939164e39e 100644
--- a/lib/private/share/hooks.php
+++ b/lib/private/share/hooks.php
@@ -38,7 +38,7 @@ class Hooks extends \OC\Share\Constants {
public static function post_deleteUser($arguments) {
// Delete any items shared with the deleted user
$query = \OC_DB::prepare('DELETE FROM `*PREFIX*share`'
- .' WHERE `share_with` = ? AND `share_type` = ? OR `share_type` = ?');
+ .' WHERE `share_with` = ? AND (`share_type` = ? OR `share_type` = ?)');
$query->execute(array($arguments['uid'], self::SHARE_TYPE_USER, self::$shareTypeGroupUserUnique));
// Delete any items the deleted user shared
$query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*share` WHERE `uid_owner` = ?');
diff --git a/lib/private/share20/defaultshareprovider.php b/lib/private/share20/defaultshareprovider.php
index 224dddf4019..0ab0dc81fa7 100644
--- a/lib/private/share20/defaultshareprovider.php
+++ b/lib/private/share20/defaultshareprovider.php
@@ -24,12 +24,11 @@ use OCP\Files\File;
use OCP\Share\IShareProvider;
use OC\Share20\Exception\InvalidShare;
use OC\Share20\Exception\ProviderException;
-use OC\Share20\Exception\ShareNotFound;
+use OCP\Share\Exceptions\ShareNotFound;
use OC\Share20\Exception\BackendError;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Files\NotFoundException;
use OCP\IGroup;
-use OCP\IUser;
use OCP\IGroupManager;
use OCP\IUserManager;
use OCP\Files\IRootFolder;
@@ -102,14 +101,10 @@ class DefaultShareProvider implements IShareProvider {
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
//Set the UID of the user we share with
- /** @var IUser $sharedWith */
- $sharedWith = $share->getSharedWith();
- $qb->setValue('share_with', $qb->createNamedParameter($sharedWith->getUID()));
+ $qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()));
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
//Set the GID of the group we share with
- /** @var IGroup $sharedWith */
- $sharedWith = $share->getSharedWith();
- $qb->setValue('share_with', $qb->createNamedParameter($sharedWith->getGID()));
+ $qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()));
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
//Set the token of the share
$qb->setValue('token', $qb->createNamedParameter($share->getToken()));
@@ -143,10 +138,10 @@ class DefaultShareProvider implements IShareProvider {
$qb->setValue('permissions', $qb->createNamedParameter($share->getPermissions()));
// Set who created this share
- $qb->setValue('uid_initiator', $qb->createNamedParameter($share->getSharedBy()->getUID()));
+ $qb->setValue('uid_initiator', $qb->createNamedParameter($share->getSharedBy()));
// Set who is the owner of this file/folder (and this the owner of the share)
- $qb->setValue('uid_owner', $qb->createNamedParameter($share->getShareOwner()->getUID()));
+ $qb->setValue('uid_owner', $qb->createNamedParameter($share->getShareOwner()));
// Set the file target
$qb->setValue('file_target', $qb->createNamedParameter($share->getTarget()));
@@ -192,9 +187,9 @@ class DefaultShareProvider implements IShareProvider {
$qb = $this->dbConn->getQueryBuilder();
$qb->update('share')
->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
- ->set('share_with', $qb->createNamedParameter($share->getSharedWith()->getUID()))
- ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()->getUID()))
- ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()->getUID()))
+ ->set('share_with', $qb->createNamedParameter($share->getSharedWith()))
+ ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
+ ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
->set('permissions', $qb->createNamedParameter($share->getPermissions()))
->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
@@ -203,8 +198,8 @@ class DefaultShareProvider implements IShareProvider {
$qb = $this->dbConn->getQueryBuilder();
$qb->update('share')
->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
- ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()->getUID()))
- ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()->getUID()))
+ ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
+ ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
->set('permissions', $qb->createNamedParameter($share->getPermissions()))
->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
@@ -216,8 +211,8 @@ class DefaultShareProvider implements IShareProvider {
$qb = $this->dbConn->getQueryBuilder();
$qb->update('share')
->where($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
- ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()->getUID()))
- ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()->getUID()))
+ ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
+ ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
->execute();
@@ -237,8 +232,8 @@ class DefaultShareProvider implements IShareProvider {
$qb->update('share')
->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
->set('share_with', $qb->createNamedParameter($share->getPassword()))
- ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()->getUID()))
- ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()->getUID()))
+ ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
+ ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
->set('permissions', $qb->createNamedParameter($share->getPermissions()))
->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
@@ -255,7 +250,7 @@ class DefaultShareProvider implements IShareProvider {
* FIXME: remove once https://github.com/owncloud/core/pull/21660 is in
*
* @param \OCP\Share\IShare $parent
- * @return IShare[]
+ * @return \OCP\Share\IShare[]
*/
public function getChildren(\OCP\Share\IShare $parent) {
$children = [];
@@ -311,17 +306,17 @@ class DefaultShareProvider implements IShareProvider {
* this means we need a special entry in the share db.
*
* @param \OCP\Share\IShare $share
- * @param IUser $recipient
+ * @param string $recipient UserId of recipient
* @throws BackendError
* @throws ProviderException
*/
- public function deleteFromSelf(\OCP\Share\IShare $share, IUser $recipient) {
+ public function deleteFromSelf(\OCP\Share\IShare $share, $recipient) {
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
- /** @var IGroup $group */
- $group = $share->getSharedWith();
+ $group = $this->groupManager->get($share->getSharedWith());
+ $user = $this->userManager->get($recipient);
- if (!$group->inGroup($recipient)) {
+ if (!$group->inGroup($user)) {
throw new ProviderException('Recipient not in receiving group');
}
@@ -330,7 +325,7 @@ class DefaultShareProvider implements IShareProvider {
$stmt = $qb->select('*')
->from('share')
->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
- ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient->getUID())))
+ ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient)))
->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
->execute();
@@ -349,9 +344,9 @@ class DefaultShareProvider implements IShareProvider {
$qb->insert('share')
->values([
'share_type' => $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP),
- 'share_with' => $qb->createNamedParameter($recipient->getUID()),
- 'uid_owner' => $qb->createNamedParameter($share->getShareOwner()->getUID()),
- 'uid_initiator' => $qb->createNamedParameter($share->getSharedBy()->getUID()),
+ 'share_with' => $qb->createNamedParameter($recipient),
+ 'uid_owner' => $qb->createNamedParameter($share->getShareOwner()),
+ 'uid_initiator' => $qb->createNamedParameter($share->getSharedBy()),
'parent' => $qb->createNamedParameter($share->getId()),
'item_type' => $qb->createNamedParameter($type),
'item_source' => $qb->createNamedParameter($share->getNode()->getId()),
@@ -387,7 +382,7 @@ class DefaultShareProvider implements IShareProvider {
/**
* @inheritdoc
*/
- public function move(\OCP\Share\IShare $share, IUser $recipient) {
+ public function move(\OCP\Share\IShare $share, $recipient) {
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
// Just update the target
$qb = $this->dbConn->getQueryBuilder();
@@ -403,7 +398,7 @@ class DefaultShareProvider implements IShareProvider {
$stmt = $qb->select('id')
->from('share')
->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
- ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient->getUID())))
+ ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient)))
->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
->setMaxResults(1)
->execute();
@@ -417,9 +412,9 @@ class DefaultShareProvider implements IShareProvider {
$qb->insert('share')
->values([
'share_type' => $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP),
- 'share_with' => $qb->createNamedParameter($recipient->getUID()),
- 'uid_owner' => $qb->createNamedParameter($share->getShareOwner()->getUID()),
- 'uid_initiator' => $qb->createNamedParameter($share->getSharedBy()->getUID()),
+ 'share_with' => $qb->createNamedParameter($recipient),
+ 'uid_owner' => $qb->createNamedParameter($share->getShareOwner()),
+ 'uid_initiator' => $qb->createNamedParameter($share->getSharedBy()),
'parent' => $qb->createNamedParameter($share->getId()),
'item_type' => $qb->createNamedParameter($share->getNode() instanceof File ? 'file' : 'folder'),
'item_source' => $qb->createNamedParameter($share->getNode()->getId()),
@@ -444,7 +439,7 @@ class DefaultShareProvider implements IShareProvider {
/**
* Get all shares by the given user. Sharetype and path can be used to filter.
*
- * @param IUser $user
+ * @param string $userId
* @param int $shareType
* @param \OCP\Files\File|\OCP\Files\Folder $node
* @param bool $reshares Also get the shares where $user is the owner instead of just the shares where $user is the initiator
@@ -452,7 +447,7 @@ class DefaultShareProvider implements IShareProvider {
* @param int $offset
* @return Share[]
*/
- public function getSharesBy(IUser $user, $shareType, $node, $reshares, $limit, $offset) {
+ public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
$qb = $this->dbConn->getQueryBuilder();
$qb->select('*')
->from('share');
@@ -465,21 +460,21 @@ class DefaultShareProvider implements IShareProvider {
if ($reshares === false) {
//Special case for old shares created via the web UI
$or1 = $qb->expr()->andX(
- $qb->expr()->eq('uid_owner', $qb->createNamedParameter($user->getUID())),
+ $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
$qb->expr()->isNull('uid_initiator')
);
$qb->andWhere(
$qb->expr()->orX(
- $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($user->getUID())),
+ $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
$or1
)
);
} else {
$qb->andWhere(
$qb->expr()->orX(
- $qb->expr()->eq('uid_owner', $qb->createNamedParameter($user->getUID())),
- $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($user->getUID()))
+ $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
+ $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
)
);
}
@@ -508,7 +503,7 @@ class DefaultShareProvider implements IShareProvider {
/**
* @inheritdoc
*/
- public function getShareById($id, $recipient = null) {
+ public function getShareById($id, $recipientId = null) {
$qb = $this->dbConn->getQueryBuilder();
$qb->select('*')
@@ -540,8 +535,8 @@ class DefaultShareProvider implements IShareProvider {
}
// If the recipient is set for a group share resolve to that user
- if ($recipient !== null && $share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
- $share = $this->resolveGroupShare($share, $recipient);
+ if ($recipientId !== null && $share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
+ $share = $this->resolveGroupShare($share, $recipientId);
}
return $share;
@@ -551,7 +546,7 @@ class DefaultShareProvider implements IShareProvider {
* Get shares for a given path
*
* @param \OCP\Files\Node $path
- * @return IShare[]
+ * @return \OCP\Share\IShare[]
*/
public function getSharesByPath(Node $path) {
$qb = $this->dbConn->getQueryBuilder();
@@ -578,7 +573,7 @@ class DefaultShareProvider implements IShareProvider {
/**
* @inheritdoc
*/
- public function getSharedWith(IUser $user, $shareType, $node, $limit, $offset) {
+ public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
/** @var Share[] $shares */
$shares = [];
@@ -598,7 +593,7 @@ class DefaultShareProvider implements IShareProvider {
$qb->setFirstResult($offset);
$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_USER)));
- $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($user->getUID())));
+ $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
// Filter by node if provided
if ($node !== null) {
@@ -613,6 +608,7 @@ class DefaultShareProvider implements IShareProvider {
$cursor->closeCursor();
} else if ($shareType === \OCP\Share::SHARE_TYPE_GROUP) {
+ $user = $this->userManager->get($userId);
$allGroups = $this->groupManager->getUserGroups($user);
/** @var Share[] $shares2 */
@@ -666,7 +662,7 @@ class DefaultShareProvider implements IShareProvider {
* TODO: Optmize this!
*/
foreach($shares2 as $share) {
- $shares[] = $this->resolveGroupShare($share, $user);
+ $shares[] = $this->resolveGroupShare($share, $userId);
}
} else {
throw new BackendError('Invalid backend');
@@ -680,7 +676,7 @@ class DefaultShareProvider implements IShareProvider {
* Get a share by token
*
* @param string $token
- * @return IShare
+ * @return \OCP\Share\IShare
* @throws ShareNotFound
*/
public function getShareByToken($token) {
@@ -715,7 +711,7 @@ class DefaultShareProvider implements IShareProvider {
* @throws InvalidShare
*/
private function createShare($data) {
- $share = new Share();
+ $share = new Share($this->rootFolder);
$share->setId((int)$data['id'])
->setShareType((int)$data['share_type'])
->setPermissions((int)$data['permissions'])
@@ -727,17 +723,9 @@ class DefaultShareProvider implements IShareProvider {
$share->setShareTime($shareTime);
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
- $sharedWith = $this->userManager->get($data['share_with']);
- if ($sharedWith === null) {
- throw new InvalidShare();
- }
- $share->setSharedWith($sharedWith);
+ $share->setSharedWith($data['share_with']);
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
- $sharedWith = $this->groupManager->get($data['share_with']);
- if ($sharedWith === null) {
- throw new InvalidShare();
- }
- $share->setSharedWith($sharedWith);
+ $share->setSharedWith($data['share_with']);
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
$share->setPassword($data['share_with']);
$share->setToken($data['token']);
@@ -745,28 +733,19 @@ class DefaultShareProvider implements IShareProvider {
if ($data['uid_initiator'] === null) {
//OLD SHARE
- $sharedBy = $this->userManager->get($data['uid_owner']);
- if ($sharedBy === null) {
- throw new InvalidShare();
- }
- $share->setSharedBy($sharedBy);
+ $share->setSharedBy($data['uid_owner']);
$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
$owner = $path->getOwner();
- $share->setShareOwner($owner);
+ $share->setShareOwner($owner->getUID());
} else {
//New share!
- $sharedBy = $this->userManager->get($data['uid_initiator']);
- $shareOwner = $this->userManager->get($data['uid_owner']);
- if ($sharedBy === null || $shareOwner === null) {
- throw new InvalidShare();
- }
- $share->setSharedBy($sharedBy);
- $share->setShareOwner($shareOwner);
+ $share->setSharedBy($data['uid_initiator']);
+ $share->setShareOwner($data['uid_owner']);
}
- $path = $this->getNode($share->getShareOwner(), (int)$data['file_source']);
- $share->setNode($path);
+ $share->setNodeId((int)$data['file_source']);
+ $share->setNodeType($data['item_type']);
if ($data['expiration'] !== null) {
$expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
@@ -781,14 +760,14 @@ class DefaultShareProvider implements IShareProvider {
/**
* Get the node with file $id for $user
*
- * @param IUser $user
+ * @param string $user The userId
* @param int $id
* @return \OCP\Files\File|\OCP\Files\Folder
* @throws InvalidShare
*/
- private function getNode(IUser $user, $id) {
+ private function getNode($user, $id) {
try {
- $userFolder = $this->rootFolder->getUserFolder($user->getUID());
+ $userFolder = $this->rootFolder->getUserFolder($user);
} catch (NotFoundException $e) {
throw new InvalidShare();
}
@@ -806,18 +785,18 @@ class DefaultShareProvider implements IShareProvider {
* Resolve a group share to a user specific share
* Thus if the user moved their group share make sure this is properly reflected here.
*
- * @param Share $share
- * @param IUser $user
+ * @param \OCP\Share\IShare $share
+ * @param string $userId
* @return Share Returns the updated share if one was found else return the original share.
*/
- private function resolveGroupShare(Share $share, IUser $user) {
+ private function resolveGroupShare(\OCP\Share\IShare $share, $userId) {
$qb = $this->dbConn->getQueryBuilder();
$stmt = $qb->select('*')
->from('share')
->where($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
- ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($user->getUID())))
+ ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)))
->setMaxResults(1)
->execute();
diff --git a/lib/private/share20/manager.php b/lib/private/share20/manager.php
index b22b81bb404..d65fb927f9b 100644
--- a/lib/private/share20/manager.php
+++ b/lib/private/share20/manager.php
@@ -21,7 +21,8 @@
namespace OC\Share20;
-use OCP\Files\Node;
+use OCP\Files\IRootFolder;
+use OCP\IUserManager;
use OCP\Share\IManager;
use OCP\Share\IProviderFactory;
use OC\Share20\Exception\BackendError;
@@ -34,10 +35,9 @@ use OCP\Files\Mount\IMountManager;
use OCP\IGroupManager;
use OCP\Files\File;
use OCP\Files\Folder;
-use OCP\IUser;
-use OC\Share20\Exception\ShareNotFound;
-use OC\HintException;
+use OCP\Share\Exceptions\ShareNotFound;
+use OCP\Share\Exceptions\GenericShareException;
/**
* This class is the communication hub for all sharing related operations.
@@ -46,27 +46,24 @@ class Manager implements IManager {
/** @var IProviderFactory */
private $factory;
-
/** @var ILogger */
private $logger;
-
/** @var IConfig */
private $config;
-
/** @var ISecureRandom */
private $secureRandom;
-
/** @var IHasher */
private $hasher;
-
/** @var IMountManager */
private $mountManager;
-
/** @var IGroupManager */
private $groupManager;
-
/** @var IL10N */
private $l;
+ /** @var IUserManager */
+ private $userManager;
+ /** @var IRootFolder */
+ private $rootFolder;
/**
* Manager constructor.
@@ -79,6 +76,8 @@ class Manager implements IManager {
* @param IGroupManager $groupManager
* @param IL10N $l
* @param IProviderFactory $factory
+ * @param IUserManager $userManager
+ * @param IRootFolder $rootFolder
*/
public function __construct(
ILogger $logger,
@@ -88,7 +87,9 @@ class Manager implements IManager {
IMountManager $mountManager,
IGroupManager $groupManager,
IL10N $l,
- IProviderFactory $factory
+ IProviderFactory $factory,
+ IUserManager $userManager,
+ IRootFolder $rootFolder
) {
$this->logger = $logger;
$this->config = $config;
@@ -98,6 +99,8 @@ class Manager implements IManager {
$this->groupManager = $groupManager;
$this->l = $l;
$this->factory = $factory;
+ $this->userManager = $userManager;
+ $this->rootFolder = $rootFolder;
}
/**
@@ -144,18 +147,19 @@ class Manager implements IManager {
* Check for generic requirements before creating a share
*
* @param \OCP\Share\IShare $share
- * @throws \Exception
+ * @throws \InvalidArgumentException
+ * @throws GenericShareException
*/
protected function generalCreateChecks(\OCP\Share\IShare $share) {
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
// We expect a valid user as sharedWith for user shares
- if (!($share->getSharedWith() instanceof \OCP\IUser)) {
- throw new \InvalidArgumentException('SharedWith should be an IUser');
+ if (!$this->userManager->userExists($share->getSharedWith())) {
+ throw new \InvalidArgumentException('SharedWith is not a valid user');
}
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
// We expect a valid group as sharedWith for group shares
- if (!($share->getSharedWith() instanceof \OCP\IGroup)) {
- throw new \InvalidArgumentException('SharedWith should be an IGroup');
+ if (!$this->groupManager->groupExists($share->getSharedWith())) {
+ throw new \InvalidArgumentException('SharedWith is not a valid group');
}
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
if ($share->getSharedWith() !== null) {
@@ -172,7 +176,8 @@ class Manager implements IManager {
}
// Cannot share with yourself
- if ($share->getSharedWith() === $share->getSharedBy()) {
+ if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
+ $share->getSharedWith() === $share->getSharedBy()) {
throw new \InvalidArgumentException('Can\'t share with yourself');
}
@@ -190,7 +195,7 @@ class Manager implements IManager {
// Check if we actually have share permissions
if (!$share->getNode()->isShareable()) {
$message_t = $this->l->t('You are not allowed to share %s', [$share->getNode()->getPath()]);
- throw new HintException($message_t, $message_t, 404);
+ throw new GenericShareException($message_t, $message_t, 404);
}
// Permissions should be set
@@ -201,7 +206,7 @@ class Manager implements IManager {
// Check that we do not share with more permissions than we have
if ($share->getPermissions() & ~$share->getNode()->getPermissions()) {
$message_t = $this->l->t('Cannot increase permissions of %s', [$share->getNode()->getPath()]);
- throw new HintException($message_t, $message_t, 404);
+ throw new GenericShareException($message_t, $message_t, 404);
}
// Check that read permissions are always set
@@ -213,9 +218,11 @@ class Manager implements IManager {
/**
* Validate if the expiration date fits the system settings
*
- * @param \DateTime $expirationDate The current expiration date (can be null)
- * @return \DateTime|null The expiration date or null if $expireDate was null and it is not required
- * @throws \OC\HintException
+ * @param \OCP\Share\IShare $share The share to validate the expiration date of
+ * @return \OCP\Share\IShare The expiration date or null if $expireDate was null and it is not required
+ * @throws GenericShareException
+ * @throws \InvalidArgumentException
+ * @throws \Exception
*/
protected function validateExpirationDate(\OCP\Share\IShare $share) {
@@ -229,7 +236,7 @@ class Manager implements IManager {
$date->setTime(0, 0, 0);
if ($date >= $expirationDate) {
$message = $this->l->t('Expiration date is in the past');
- throw new \OC\HintException($message, $message, 404);
+ throw new GenericShareException($message, $message, 404);
}
}
@@ -244,7 +251,7 @@ class Manager implements IManager {
$date->add(new \DateInterval('P' . $this->shareApiLinkDefaultExpireDays() . 'D'));
if ($date < $expirationDate) {
$message = $this->l->t('Cannot set expiration date more than %s days in the future', [$this->shareApiLinkDefaultExpireDays()]);
- throw new \OC\HintException($message, $message, 404);
+ throw new GenericShareException($message, $message, 404);
}
}
@@ -282,10 +289,12 @@ class Manager implements IManager {
protected function userCreateChecks(\OCP\Share\IShare $share) {
// Check if we can share with group members only
if ($this->shareWithGroupMembersOnly()) {
+ $sharedBy = $this->userManager->get($share->getSharedBy());
+ $sharedWith = $this->userManager->get($share->getSharedWith());
// Verify we can share with this user
$groups = array_intersect(
- $this->groupManager->getUserGroupIds($share->getSharedBy()),
- $this->groupManager->getUserGroupIds($share->getSharedWith())
+ $this->groupManager->getUserGroupIds($sharedBy),
+ $this->groupManager->getUserGroupIds($sharedWith)
);
if (empty($groups)) {
throw new \Exception('Only sharing with group members is allowed');
@@ -311,10 +320,13 @@ class Manager implements IManager {
}
// The share is already shared with this user via a group share
- if ($existingShare->getShareType() === \OCP\Share::SHARE_TYPE_GROUP &&
- $existingShare->getSharedWith()->inGroup($share->getSharedWith()) &&
- $existingShare->getShareOwner() !== $share->getShareOwner()) {
- throw new \Exception('Path already shared with this user');
+ if ($existingShare->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
+ $group = $this->groupManager->get($existingShare->getSharedWith());
+ $user = $this->userManager->get($share->getSharedWith());
+
+ if ($group->inGroup($user) && $existingShare->getShareOwner() !== $share->getShareOwner()) {
+ throw new \Exception('Path already shared with this user');
+ }
}
}
}
@@ -328,7 +340,9 @@ class Manager implements IManager {
protected function groupCreateChecks(\OCP\Share\IShare $share) {
// Verify if the user can share with this group
if ($this->shareWithGroupMembersOnly()) {
- if (!$share->getSharedWith()->inGroup($share->getSharedBy())) {
+ $sharedBy = $this->userManager->get($share->getSharedBy());
+ $sharedWith = $this->groupManager->get($share->getSharedWith());
+ if (!$sharedWith->inGroup($sharedBy)) {
throw new \Exception('Only sharing within your own groups is allowed');
}
}
@@ -465,10 +479,11 @@ class Manager implements IManager {
$this->pathCreateChecks($share->getNode());
// On creation of a share the owner is always the owner of the path
- $share->setShareOwner($share->getNode()->getOwner());
+ $share->setShareOwner($share->getNode()->getOwner()->getUID());
// Cannot share with the owner
- if ($share->getSharedWith() === $share->getShareOwner()) {
+ if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
+ $share->getSharedWith() === $share->getShareOwner()) {
throw new \InvalidArgumentException('Can\'t share with the share owner');
}
@@ -477,16 +492,6 @@ class Manager implements IManager {
$target = \OC\Files\Filesystem::normalizePath($target);
$share->setTarget($target);
- //Get sharewith for hooks
- $sharedWith = null;
- if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
- $sharedWith = $share->getSharedWith()->getUID();
- } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
- $sharedWith = $share->getSharedWith()->getGID();
- } else {
- $sharedWith = $share->getSharedWith();
- }
-
// Pre share hook
$run = true;
$error = '';
@@ -494,13 +499,13 @@ class Manager implements IManager {
'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
'itemSource' => $share->getNode()->getId(),
'shareType' => $share->getShareType(),
- 'uidOwner' => $share->getSharedBy()->getUID(),
+ 'uidOwner' => $share->getSharedBy(),
'permissions' => $share->getPermissions(),
'fileSource' => $share->getNode()->getId(),
'expiration' => $share->getExpirationDate(),
'token' => $share->getToken(),
'itemTarget' => $share->getTarget(),
- 'shareWith' => $sharedWith,
+ 'shareWith' => $share->getSharedWith(),
'run' => &$run,
'error' => &$error,
];
@@ -518,13 +523,13 @@ class Manager implements IManager {
'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
'itemSource' => $share->getNode()->getId(),
'shareType' => $share->getShareType(),
- 'uidOwner' => $share->getSharedBy()->getUID(),
+ 'uidOwner' => $share->getSharedBy(),
'permissions' => $share->getPermissions(),
'fileSource' => $share->getNode()->getId(),
'expiration' => $share->getExpirationDate(),
'token' => $share->getToken(),
'id' => $share->getId(),
- 'shareWith' => $sharedWith,
+ 'shareWith' => $share->getSharedWith(),
'itemTarget' => $share->getTarget(),
'fileTarget' => $share->getTarget(),
];
@@ -539,6 +544,7 @@ class Manager implements IManager {
*
* @param \OCP\Share\IShare $share
* @return \OCP\Share\IShare The share object
+ * @throws \InvalidArgumentException
*/
public function updateShare(\OCP\Share\IShare $share) {
$expirationDateUpdated = false;
@@ -561,7 +567,8 @@ class Manager implements IManager {
}
// Cannot share with the owner
- if ($share->getSharedWith() === $share->getShareOwner()) {
+ if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
+ $share->getSharedWith() === $share->getShareOwner()) {
throw new \InvalidArgumentException('Can\'t share with the share owner');
}
@@ -603,10 +610,23 @@ class Manager implements IManager {
'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
'itemSource' => $share->getNode()->getId(),
'date' => $share->getExpirationDate(),
- 'uidOwner' => $share->getSharedBy()->getUID(),
+ 'uidOwner' => $share->getSharedBy(),
]);
}
+ if ($share->getPermissions() !== $originalShare->getPermissions()) {
+ $userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
+ \OC_Hook::emit('OCP\Share', 'post_update_permissions', array(
+ 'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
+ 'itemSource' => $share->getNode()->getId(),
+ 'shareType' => $share->getShareType(),
+ 'shareWith' => $share->getSharedWith(),
+ 'uidOwner' => $share->getSharedBy(),
+ 'permissions' => $share->getPermissions(),
+ 'path' => $userFolder->getRelativePath($share->getNode()->getPath()),
+ ));
+ }
+
return $share;
}
@@ -638,8 +658,6 @@ class Manager implements IManager {
*
* @param \OCP\Share\IShare $share
* @throws ShareNotFound
- * @throws BackendError
- * @throws ShareNotFound
*/
public function deleteShare(\OCP\Share\IShare $share) {
// Just to make sure we have all the info
@@ -650,22 +668,22 @@ class Manager implements IManager {
$shareType = $share->getShareType();
$sharedWith = '';
if ($shareType === \OCP\Share::SHARE_TYPE_USER) {
- $sharedWith = $share->getSharedWith()->getUID();
+ $sharedWith = $share->getSharedWith();
} else if ($shareType === \OCP\Share::SHARE_TYPE_GROUP) {
- $sharedWith = $share->getSharedWith()->getGID();
+ $sharedWith = $share->getSharedWith();
} else if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE) {
$sharedWith = $share->getSharedWith();
}
$hookParams = [
'id' => $share->getId(),
- 'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
- 'itemSource' => $share->getNode()->getId(),
+ 'itemType' => $share->getNodeType(),
+ 'itemSource' => $share->getNodeId(),
'shareType' => $shareType,
'shareWith' => $sharedWith,
'itemparent' => $share->getParent(),
- 'uidOwner' => $share->getSharedBy()->getUID(),
- 'fileSource' => $share->getNode()->getId(),
+ 'uidOwner' => $share->getSharedBy(),
+ 'fileSource' => $share->getNodeId(),
'fileTarget' => $share->getTarget()
];
return $hookParams;
@@ -705,38 +723,45 @@ class Manager implements IManager {
* handle this.
*
* @param \OCP\Share\IShare $share
- * @param IUser $recipient
+ * @param string $recipientId
*/
- public function deleteFromSelf(\OCP\Share\IShare $share, IUser $recipient) {
- list($providerId, $id) = $this->splitFullId($share->getId());
+ public function deleteFromSelf(\OCP\Share\IShare $share, $recipientId) {
+ list($providerId, ) = $this->splitFullId($share->getId());
$provider = $this->factory->getProvider($providerId);
- $provider->deleteFromSelf($share, $recipient);
+ $provider->deleteFromSelf($share, $recipientId);
}
/**
* @inheritdoc
*/
- public function moveShare(\OCP\Share\IShare $share, IUser $recipient) {
+ public function moveShare(\OCP\Share\IShare $share, $recipientId) {
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
throw new \InvalidArgumentException('Can\'t change target of link share');
}
- if (($share->getShareType() === \OCP\Share::SHARE_TYPE_USER && $share->getSharedWith() !== $recipient) ||
- ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP && !$share->getSharedWith()->inGroup($recipient))) {
+ if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER && $share->getSharedWith() !== $recipientId) {
throw new \InvalidArgumentException('Invalid recipient');
}
+ if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
+ $sharedWith = $this->groupManager->get($share->getSharedWith());
+ $recipient = $this->userManager->get($recipientId);
+ if (!$sharedWith->inGroup($recipient)) {
+ throw new \InvalidArgumentException('Invalid recipient');
+ }
+ }
+
list($providerId, ) = $this->splitFullId($share->getId());
$provider = $this->factory->getProvider($providerId);
- $provider->move($share, $recipient);
+ $provider->move($share, $recipientId);
}
/**
* Get shares shared by (initiated) by the provided user.
*
- * @param IUser $user
+ * @param string $userId
* @param int $shareType
* @param \OCP\Files\File|\OCP\Files\Folder $path
* @param bool $reshares
@@ -744,7 +769,7 @@ class Manager implements IManager {
* @param int $offset
* @return \OCP\Share\IShare[]
*/
- public function getSharesBy(IUser $user, $shareType, $path = null, $reshares = false, $limit = 50, $offset = 0) {
+ public function getSharesBy($userId, $shareType, $path = null, $reshares = false, $limit = 50, $offset = 0) {
if ($path !== null &&
!($path instanceof \OCP\Files\File) &&
!($path instanceof \OCP\Files\Folder)) {
@@ -753,16 +778,16 @@ class Manager implements IManager {
$provider = $this->factory->getProviderForType($shareType);
- return $provider->getSharesBy($user, $shareType, $path, $reshares, $limit, $offset);
+ return $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
}
/**
* @inheritdoc
*/
- public function getSharedWith(IUser $user, $shareType, $node = null, $limit = 50, $offset = 0) {
+ public function getSharedWith($userId, $shareType, $node = null, $limit = 50, $offset = 0) {
$provider = $this->factory->getProviderForType($shareType);
- return $provider->getSharedWith($user, $shareType, $node, $limit, $offset);
+ return $provider->getSharedWith($userId, $shareType, $node, $limit, $offset);
}
/**
@@ -874,7 +899,7 @@ class Manager implements IManager {
* @return \OCP\Share\IShare;
*/
public function newShare() {
- return new \OC\Share20\Share();
+ return new \OC\Share20\Share($this->rootFolder);
}
/**
@@ -954,10 +979,10 @@ class Manager implements IManager {
*
* TODO: Deprecate fuction from OC_Util
*
- * @param IUser $user
+ * @param string $userId
* @return bool
*/
- public function sharingDisabledForUser(IUser $user) {
+ public function sharingDisabledForUser($userId) {
if ($this->config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes') {
$groupsList = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', '');
$excludedGroups = json_decode($groupsList);
@@ -966,6 +991,7 @@ class Manager implements IManager {
$newValue = json_encode($excludedGroups);
$this->config->setAppValue('core', 'shareapi_exclude_groups_list', $newValue);
}
+ $user = $this->userManager->get($userId);
$usersGroups = $this->groupManager->getUserGroupIds($user);
if (!empty($usersGroups)) {
$remainingGroups = array_diff($usersGroups, $excludedGroups);
diff --git a/lib/private/share20/share.php b/lib/private/share20/share.php
index f9cba10a07a..cd30f24c42e 100644
--- a/lib/private/share20/share.php
+++ b/lib/private/share20/share.php
@@ -20,7 +20,10 @@
*/
namespace OC\Share20;
+use OCP\Files\File;
+use OCP\Files\IRootFolder;
use OCP\Files\Node;
+use OCP\Files\NotFoundException;
use OCP\IUser;
use OCP\IGroup;
@@ -31,14 +34,18 @@ class Share implements \OCP\Share\IShare {
/** @var string */
private $providerId;
/** @var Node */
- private $path;
+ private $node;
+ /** @var int */
+ private $fileId;
+ /** @var string */
+ private $nodeType;
/** @var int */
private $shareType;
- /** @var IUser|IGroup */
+ /** @var string */
private $sharedWith;
- /** @var IUser */
+ /** @var string */
private $sharedBy;
- /** @var IUser */
+ /** @var string */
private $shareOwner;
/** @var int */
private $permissions;
@@ -57,6 +64,13 @@ class Share implements \OCP\Share\IShare {
/** @var bool */
private $mailSend;
+ /** @var IRootFolder */
+ private $rootFolder;
+
+ public function __construct(IRootFolder $rootFolder) {
+ $this->rootFolder = $rootFolder;
+ }
+
/**
* @inheritdoc
*/
@@ -90,8 +104,10 @@ class Share implements \OCP\Share\IShare {
/**
* @inheritdoc
*/
- public function setNode(Node $path) {
- $this->path = $path;
+ public function setNode(Node $node) {
+ $this->fileId = null;
+ $this->nodeType = null;
+ $this->node = $node;
return $this;
}
@@ -99,7 +115,66 @@ class Share implements \OCP\Share\IShare {
* @inheritdoc
*/
public function getNode() {
- return $this->path;
+ if ($this->node === null) {
+
+ if ($this->shareOwner === null || $this->fileId === null) {
+ throw new NotFoundException();
+ }
+
+ $userFolder = $this->rootFolder->getUserFolder($this->shareOwner);
+
+ $nodes = $userFolder->getById($this->fileId);
+ if (empty($nodes)) {
+ throw new NotFoundException();
+ }
+
+ $this->node = $nodes[0];
+ }
+
+ return $this->node;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function setNodeId($fileId) {
+ $this->node = null;
+ $this->fileId = $fileId;
+ return $this;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getNodeId() {
+ if ($this->fileId === null) {
+ $this->fileId = $this->getNode()->getId();
+ }
+
+ return $this->fileId;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function setNodeType($type) {
+ if ($type !== 'file' && $type !== 'folder') {
+ throw new \InvalidArgumentException();
+ }
+
+ $this->nodeType = $type;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getNodeType() {
+ if ($this->nodeType === null) {
+ $node = $this->getNode();
+ $this->nodeType = $node instanceof File ? 'file' : 'folder';
+ }
+
+ return $this->nodeType;
}
/**
@@ -121,6 +196,9 @@ class Share implements \OCP\Share\IShare {
* @inheritdoc
*/
public function setSharedWith($sharedWith) {
+ if (!is_string($sharedWith)) {
+ throw new \InvalidArgumentException();
+ }
$this->sharedWith = $sharedWith;
return $this;
}
@@ -170,6 +248,9 @@ class Share implements \OCP\Share\IShare {
* @inheritdoc
*/
public function setSharedBy($sharedBy) {
+ if (!is_string($sharedBy)) {
+ throw new \InvalidArgumentException();
+ }
//TODO checks
$this->sharedBy = $sharedBy;
@@ -188,6 +269,9 @@ class Share implements \OCP\Share\IShare {
* @inheritdoc
*/
public function setShareOwner($shareOwner) {
+ if (!is_string($shareOwner)) {
+ throw new \InvalidArgumentException();
+ }
//TODO checks
$this->shareOwner = $shareOwner;
diff --git a/lib/private/user/manager.php b/lib/private/user/manager.php
index 86750dcd994..6798a7340c3 100644
--- a/lib/private/user/manager.php
+++ b/lib/private/user/manager.php
@@ -265,6 +265,10 @@ class Manager extends PublicEmitter implements IUserManager {
if (trim($uid) == '') {
throw new \Exception($l->t('A valid username must be provided'));
}
+ // No whitespace at the beginning or at the end
+ if (strlen(trim($uid, "\t\n\r\0\x0B\xe2\x80\x8b")) !== strlen(trim($uid))) {
+ throw new \Exception($l->t('Username contains whitespace at the beginning or at the end'));
+ }
// No empty password
if (trim($password) == '') {
throw new \Exception($l->t('A valid password must be provided'));
diff --git a/lib/private/user/user.php b/lib/private/user/user.php
index 5e556575118..516c1d443c6 100644
--- a/lib/private/user/user.php
+++ b/lib/private/user/user.php
@@ -210,7 +210,7 @@ class User implements IUser {
// Delete the users entry in the storage table
\OC\Files\Cache\Storage::remove('home::' . $this->uid);
- \OC::$server->getCommentsManager()->deleteReferencesOfActor('user', $this->uid);
+ \OC::$server->getCommentsManager()->deleteReferencesOfActor('users', $this->uid);
\OC::$server->getCommentsManager()->deleteReadMarksFromUser($this);
}
diff --git a/lib/public/comments/commentsevent.php b/lib/public/comments/commentsevent.php
new file mode 100644
index 00000000000..13110154479
--- /dev/null
+++ b/lib/public/comments/commentsevent.php
@@ -0,0 +1,70 @@
+<?php
+/**
+ * @author Joas Schilling <nickvergessen@owncloud.com>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCP\Comments;
+
+use Symfony\Component\EventDispatcher\Event;
+
+/**
+ * Class CommentsEvent
+ *
+ * @package OCP\Comments
+ * @since 9.0.0
+ */
+class CommentsEvent extends Event {
+
+ const EVENT_ADD = 'OCP\Comments\ICommentsManager::addComment';
+ const EVENT_UPDATE = 'OCP\Comments\ICommentsManager::updateComment';
+ const EVENT_DELETE = 'OCP\Comments\ICommentsManager::deleteComment';
+
+ /** @var string */
+ protected $event;
+ /** @var IComment */
+ protected $comment;
+
+ /**
+ * DispatcherEvent constructor.
+ *
+ * @param string $event
+ * @param IComment $comment
+ * @since 9.0.IComment
+ */
+ public function __construct($event, IComment $comment) {
+ $this->event = $event;
+ $this->comment = $comment;
+ }
+
+ /**
+ * @return string
+ * @since 9.0.0
+ */
+ public function getEvent() {
+ return $this->event;
+ }
+
+ /**
+ * @return IComment
+ * @since 9.0.0
+ */
+ public function getComment() {
+ return $this->comment;
+ }
+}
diff --git a/lib/public/comments/icomment.php b/lib/public/comments/icomment.php
index d97cfe3f1cc..e695b5193f2 100644
--- a/lib/public/comments/icomment.php
+++ b/lib/public/comments/icomment.php
@@ -161,7 +161,7 @@ interface IComment {
/**
* sets (overwrites) the actor type and id
*
- * @param string $actorType e.g. 'user'
+ * @param string $actorType e.g. 'users'
* @param string $actorId e.g. 'zombie234'
* @return IComment
* @since 9.0.0
@@ -223,7 +223,7 @@ interface IComment {
/**
* sets (overwrites) the object of the comment
*
- * @param string $objectType e.g. 'file'
+ * @param string $objectType e.g. 'files'
* @param string $objectId e.g. '16435'
* @return IComment
* @since 9.0.0
diff --git a/lib/public/comments/icommentsmanager.php b/lib/public/comments/icommentsmanager.php
index f5b290bf8b2..0b37fde24d8 100644
--- a/lib/public/comments/icommentsmanager.php
+++ b/lib/public/comments/icommentsmanager.php
@@ -39,7 +39,7 @@ interface ICommentsManager {
*
* User interfaces shall show "Deleted user" as display name, if needed.
*/
- const DELETED_USER = 'deleted_user';
+ const DELETED_USER = 'deleted_users';
/**
* returns a comment instance
@@ -127,7 +127,7 @@ interface ICommentsManager {
* saved in the used data storage. Use save() after setting other fields
* of the comment (e.g. message or verb).
*
- * @param string $actorType the actor type (e.g. 'user')
+ * @param string $actorType the actor type (e.g. 'users')
* @param string $actorId a user id
* @param string $objectType the object type the comment is attached to
* @param string $objectId the object id the comment is attached to
@@ -149,7 +149,7 @@ interface ICommentsManager {
public function delete($id);
/**
- * saves the comment permanently and returns it
+ * saves the comment permanently
*
* if the supplied comment has an empty ID, a new entry comment will be
* saved and the instance updated with the new ID.
@@ -170,10 +170,10 @@ interface ICommentsManager {
* removes references to specific actor (e.g. on user delete) of a comment.
* The comment itself must not get lost/deleted.
*
- * A 'user' type actor (type and id) should get replaced by the
+ * A 'users' type actor (type and id) should get replaced by the
* value of the DELETED_USER constant of this interface.
*
- * @param string $actorType the actor type (e.g. 'user')
+ * @param string $actorType the actor type (e.g. 'users')
* @param string $actorId a user id
* @return boolean
* @since 9.0.0
@@ -183,7 +183,7 @@ interface ICommentsManager {
/**
* deletes all comments made of a specific object (e.g. on file delete)
*
- * @param string $objectType the object type (e.g. 'file')
+ * @param string $objectType the object type (e.g. 'files')
* @param string $objectId e.g. the file id
* @return boolean
* @since 9.0.0
diff --git a/lib/public/console/consoleevent.php b/lib/public/console/consoleevent.php
new file mode 100644
index 00000000000..b3f1229f0e8
--- /dev/null
+++ b/lib/public/console/consoleevent.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * @author Joas Schilling <nickvergessen@owncloud.com>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCP\Console;
+
+use Symfony\Component\EventDispatcher\Event;
+
+/**
+ * Class ConsoleEvent
+ *
+ * @package OCP\Console
+ * @since 9.0.0
+ */
+class ConsoleEvent extends Event {
+
+ const EVENT_RUN = 'OC\Console\Application::run';
+
+ /** @var string */
+ protected $event;
+
+ /** @var string[] */
+ protected $arguments;
+
+ /**
+ * DispatcherEvent constructor.
+ *
+ * @param string $event
+ * @param string[] $arguments
+ * @since 9.0.0
+ */
+ public function __construct($event, array $arguments) {
+ $this->event = $event;
+ $this->arguments = $arguments;
+ }
+
+ /**
+ * @return string
+ * @since 9.0.0
+ */
+ public function getEvent() {
+ return $this->event;
+ }
+
+ /**
+ * @return string[]
+ * @since 9.0.0
+ */
+ public function getArguments() {
+ return $this->arguments;
+ }
+}
diff --git a/lib/public/db/querybuilder/iexpressionbuilder.php b/lib/public/db/querybuilder/iexpressionbuilder.php
index a53ae3846c2..4b53a0e0b8b 100644
--- a/lib/public/db/querybuilder/iexpressionbuilder.php
+++ b/lib/public/db/querybuilder/iexpressionbuilder.php
@@ -299,4 +299,14 @@ interface IExpressionBuilder {
* @since 8.2.0
*/
public function literal($input, $type = null);
+
+ /**
+ * Returns a IQueryFunction that casts the column to the given type
+ *
+ * @param string $column
+ * @param mixed $type One of IQueryBuilder::PARAM_*
+ * @return string
+ * @since 9.0.0
+ */
+ public function castColumn($column, $type);
}
diff --git a/lib/public/files/cache/icache.php b/lib/public/files/cache/icache.php
index e80c6fa2cb0..18641b29f9c 100644
--- a/lib/public/files/cache/icache.php
+++ b/lib/public/files/cache/icache.php
@@ -59,6 +59,8 @@ interface ICache {
/**
* get the metadata of all files stored in $folder
*
+ * Only returns files one level deep, no recursion
+ *
* @param string $folder
* @return ICacheEntry[]
* @since 9.0.0
@@ -68,6 +70,8 @@ interface ICache {
/**
* get the metadata of all files stored in $folder
*
+ * Only returns files one level deep, no recursion
+ *
* @param int $fileId the file id of the folder
* @return ICacheEntry[]
* @since 9.0.0
@@ -76,6 +80,7 @@ interface ICache {
/**
* store meta data for a file or folder
+ * This will automatically call either insert or update depending on if the file exists
*
* @param string $file
* @param array $data
@@ -87,6 +92,18 @@ interface ICache {
public function put($file, array $data);
/**
+ * insert meta data for a new file or folder
+ *
+ * @param string $file
+ * @param array $data
+ *
+ * @return int file id
+ * @throws \RuntimeException
+ * @since 9.0.0
+ */
+ public function insert($file, array $data);
+
+ /**
* update the metadata of an existing file or folder in the cache
*
* @param int $id the fileid of the existing file or folder
@@ -174,11 +191,12 @@ interface ICache {
public function getStatus($file);
/**
- * search for files matching $pattern
+ * search for files matching $pattern, files are matched if their filename matches the search pattern
*
* @param string $pattern the search pattern using SQL search syntax (e.g. '%searchstring%')
* @return ICacheEntry[] an array of cache entries where the name matches the search pattern
* @since 9.0.0
+ * @deprecated 9.0.0 due to lack of pagination, not all backends might implement this
*/
public function search($pattern);
@@ -189,6 +207,7 @@ interface ICache {
* where it will search for all mimetypes in the group ('image/*')
* @return ICacheEntry[] an array of cache entries where the mimetype matches the search
* @since 9.0.0
+ * @deprecated 9.0.0 due to lack of pagination, not all backends might implement this
*/
public function searchByMime($mimetype);
@@ -201,6 +220,7 @@ interface ICache {
* @param string $userId owner of the tags
* @return ICacheEntry[] file data
* @since 9.0.0
+ * @deprecated 9.0.0 due to lack of pagination, not all backends might implement this
*/
public function searchByTag($tag, $userId);
diff --git a/lib/public/files/storage.php b/lib/public/files/storage.php
index 1c125221449..2511690b7d3 100644
--- a/lib/public/files/storage.php
+++ b/lib/public/files/storage.php
@@ -331,15 +331,6 @@ interface Storage extends IStorage {
public function getLocalFile($path);
/**
- * get the path to a local version of the folder.
- * The local version of the folder can be temporary and doesn't have to be persistent across requests
- *
- * @param string $path
- * @return string|false
- * @since 6.0.0
- */
- public function getLocalFolder($path);
- /**
* check if a file or folder has been updated since $time
*
* @param string $path
diff --git a/lib/public/files/storage/istorage.php b/lib/public/files/storage/istorage.php
index 4bc5e3536dc..a638ddd3021 100644
--- a/lib/public/files/storage/istorage.php
+++ b/lib/public/files/storage/istorage.php
@@ -304,15 +304,6 @@ interface IStorage {
public function free_space($path);
/**
- * search for occurrences of $query in file names
- *
- * @param string $query
- * @return array|false
- * @since 9.0.0
- */
- public function search($query);
-
- /**
* see http://php.net/manual/en/function.touch.php
* If the backend does not support the operation, false should be returned
*
@@ -334,16 +325,6 @@ interface IStorage {
public function getLocalFile($path);
/**
- * get the path to a local version of the folder.
- * The local version of the folder can be temporary and doesn't have to be persistent across requests
- *
- * @param string $path
- * @return string|false
- * @since 9.0.0
- */
- public function getLocalFolder($path);
-
- /**
* check if a file or folder has been updated since $time
*
* @param string $path
diff --git a/lib/public/share/exceptions/genericshareexception.php b/lib/public/share/exceptions/genericshareexception.php
new file mode 100644
index 00000000000..83dfa12dbfc
--- /dev/null
+++ b/lib/public/share/exceptions/genericshareexception.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace OCP\Share\Exceptions;
+use OC\HintException;
+
+/**
+ * Class GenericEncryptionException
+ *
+ * @package OCP\Share\Exceptions
+ * @since 9.0.0
+ */
+class GenericShareException extends HintException {
+
+ /**
+ * @param string $message
+ * @param string $hint
+ * @param int $code
+ * @param \Exception $previous
+ * @since 9.0.0
+ */
+ public function __construct($message = '', $hint = '', $code = 0, \Exception $previous = null) {
+ if (empty($message)) {
+ $message = 'Unspecified share exception';
+ }
+ parent::__construct($message, $hint, $code, $previous);
+ }
+
+}
diff --git a/lib/private/share20/exception/sharenotfound.php b/lib/public/share/exceptions/sharenotfound.php
index b59f185939a..96e7c096492 100644
--- a/lib/private/share20/exception/sharenotfound.php
+++ b/lib/public/share/exceptions/sharenotfound.php
@@ -18,8 +18,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
-namespace OC\Share20\Exception;
-class ShareNotFound extends \Exception {
+namespace OCP\Share\Exceptions;
+
+/**
+ * Class ShareNotFound
+ *
+ * @package OCP\Share\Exceptions
+ * @since 9.0.0
+ */
+class ShareNotFound extends GenericShareException {
}
diff --git a/lib/public/share/imanager.php b/lib/public/share/imanager.php
index 15b9f34764e..4d79f97c31a 100644
--- a/lib/public/share/imanager.php
+++ b/lib/public/share/imanager.php
@@ -69,27 +69,27 @@ interface IManager {
* handle this.
*
* @param IShare $share
- * @param IUser $recipient
+ * @param string $recipientId
* @since 9.0.0
*/
- public function deleteFromSelf(IShare $share, IUser $recipient);
+ public function deleteFromSelf(IShare $share, $recipientId);
/**
* Move the share as a recipient of the share.
* This is updating the share target. So where the recipient has the share mounted.
*
* @param IShare $share
- * @param IUser $recipient
+ * @param string $recipientId
* @return IShare
* @throws \InvalidArgumentException If $share is a link share or the $recipient does not match
* @since 9.0.0
*/
- public function moveShare(IShare $share, IUser $recipient);
+ public function moveShare(IShare $share, $recipientId);
/**
* Get shares shared by (initiated) by the provided user.
*
- * @param IUser $user
+ * @param string $userId
* @param int $shareType
* @param \OCP\Files\File|\OCP\Files\Folder $path
* @param bool $reshares
@@ -98,13 +98,13 @@ interface IManager {
* @return IShare[]
* @since 9.0.0
*/
- public function getSharesBy(IUser $user, $shareType, $path = null, $reshares = false, $limit = 50, $offset = 0);
+ public function getSharesBy($userId, $shareType, $path = null, $reshares = false, $limit = 50, $offset = 0);
/**
* Get shares shared with $user.
* Filter by $node if provided
*
- * @param IUser $user
+ * @param string $userId
* @param int $shareType
* @param File|Folder|null $node
* @param int $limit The maximum number of shares returned, -1 for all
@@ -112,7 +112,7 @@ interface IManager {
* @return IShare[]
* @since 9.0.0
*/
- public function getSharedWith(IUser $user, $shareType, $node = null, $limit = 50, $offset = 0);
+ public function getSharedWith($userId, $shareType, $node = null, $limit = 50, $offset = 0);
/**
* Retrieve a share by the share id.
@@ -223,10 +223,10 @@ interface IManager {
/**
* Check if sharing is disabled for the given user
*
- * @param IUser $user
+ * @param string $userId
* @return bool
* @since 9.0.0
*/
- public function sharingDisabledForUser(IUser $user);
+ public function sharingDisabledForUser($userId);
}
diff --git a/lib/public/share/ishare.php b/lib/public/share/ishare.php
index 80e7f7f56ef..5054a886af5 100644
--- a/lib/public/share/ishare.php
+++ b/lib/public/share/ishare.php
@@ -24,8 +24,7 @@ namespace OCP\Share;
use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\Node;
-use OCP\IUser;
-use OCP\IGroup;
+use OCP\Files\NotFoundException;
/**
* Interface IShare
@@ -55,21 +54,56 @@ interface IShare {
/**
* Set the node of the file/folder that is shared
*
- * @param File|Folder $path
+ * @param Node $node
* @return \OCP\Share\IShare The modified object
* @since 9.0.0
*/
- public function setNode(Node $path);
+ public function setNode(Node $node);
/**
* Get the node of the file/folder that is shared
*
* @return File|Folder
* @since 9.0.0
+ * @throws NotFoundException
*/
public function getNode();
/**
+ * Set file id for lazy evaluation of the node
+ * @param int $fileId
+ * @return \OCP\Share\IShare The modified object
+ * @since 9.0.0
+ */
+ public function setNodeId($fileId);
+
+ /**
+ * Get the fileid of the node of this share
+ * @return int
+ * @since 9.0.0
+ * @throws NotFoundException
+ */
+ public function getNodeId();
+
+ /**
+ * Set the type of node (file/folder)
+ *
+ * @param string $type
+ * @return \OCP\Share\IShare The modified object
+ * @since 9.0.0
+ */
+ public function setNodeType($type);
+
+ /**
+ * Get the type of node (file/folder)
+ *
+ * @return string
+ * @since 9.0.0
+ * @throws NotFoundException
+ */
+ public function getNodeType();
+
+ /**
* Set the shareType
*
* @param int $shareType
@@ -89,7 +123,7 @@ interface IShare {
/**
* Set the receiver of this share.
*
- * @param IUser|IGroup
+ * @param string $sharedWith
* @return \OCP\Share\IShare The modified object
* @since 9.0.0
*/
@@ -98,7 +132,7 @@ interface IShare {
/**
* Get the receiver of this share.
*
- * @return IUser|IGroup
+ * @return string
* @since 9.0.0
*/
public function getSharedWith();
@@ -142,7 +176,7 @@ interface IShare {
/**
* Set the sharer of the path.
*
- * @param IUser $sharedBy
+ * @param string $sharedBy
* @return \OCP\Share\IShare The modified object
* @since 9.0.0
*/
@@ -151,7 +185,7 @@ interface IShare {
/**
* Get share sharer
*
- * @return IUser
+ * @return string
* @since 9.0.0
*/
public function getSharedBy();
@@ -159,7 +193,7 @@ interface IShare {
/**
* Set the original share owner (who owns the path that is shared)
*
- * @param IUser
+ * @param string $shareOwner
* @return \OCP\Share\IShare The modified object
* @since 9.0.0
*/
@@ -168,7 +202,7 @@ interface IShare {
/**
* Get the original share owner (who owns the path that is shared)
*
- * @return IUser
+ * @return string
* @since 9.0.0
*/
public function getShareOwner();
diff --git a/lib/public/share/ishareprovider.php b/lib/public/share/ishareprovider.php
index 42a2881718e..25fa76369ab 100644
--- a/lib/public/share/ishareprovider.php
+++ b/lib/public/share/ishareprovider.php
@@ -74,10 +74,10 @@ interface IShareProvider {
* share from their self then the original group share should still exist.
*
* @param \OCP\Share\IShare $share
- * @param IUser $recipient
+ * @param string $recipient UserId of the recipient
* @since 9.0.0
*/
- public function deleteFromSelf(\OCP\Share\IShare $share, IUser $recipient);
+ public function deleteFromSelf(\OCP\Share\IShare $share, $recipient);
/**
* Move a share as a recipient.
@@ -86,36 +86,36 @@ interface IShareProvider {
* the target should only be changed for them.
*
* @param \OCP\Share\IShare $share
- * @param IUser $recipient
+ * @param string $recipient userId of recipient
* @return \OCP\Share\IShare
* @since 9.0.0
*/
- public function move(\OCP\Share\IShare $share, IUser $recipient);
+ public function move(\OCP\Share\IShare $share, $recipient);
/**
* Get all shares by the given user
*
- * @param IUser $user
+ * @param string $userId
* @param int $shareType
* @param \OCP\Files\File|\OCP\Files\Folder $node
* @param bool $reshares Also get the shares where $user is the owner instead of just the shares where $user is the initiator
* @param int $limit The maximum number of shares to be returned, -1 for all shares
* @param int $offset
- * @return \OCP\Share\I Share[]
+ * @return \OCP\Share\IShare Share[]
* @since 9.0.0
*/
- public function getSharesBy(IUser $user, $shareType, $node, $reshares, $limit, $offset);
+ public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset);
/**
* Get share by id
*
* @param int $id
- * @param IUser|null $recipient
+ * @param string|null $recipientId
* @return \OCP\Share\IShare
* @throws ShareNotFound
* @since 9.0.0
*/
- public function getShareById($id, $recipient = null);
+ public function getShareById($id, $recipientId = null);
/**
* Get shares for a given path
@@ -129,7 +129,7 @@ interface IShareProvider {
/**
* Get shared with the given user
*
- * @param IUser $user get shares where this user is the recipient
+ * @param string $userId get shares where this user is the recipient
* @param int $shareType
* @param Node|null $node
* @param int $limit The max number of entries returned, -1 for all
@@ -137,7 +137,7 @@ interface IShareProvider {
* @return \OCP\Share\IShare[]
* @since 9.0.0
*/
- public function getSharedWith(IUser $user, $shareType, $node, $limit, $offset);
+ public function getSharedWith($userId, $shareType, $node, $limit, $offset);
/**
* Get a share by token
diff --git a/resources/codesigning/core.crt b/resources/codesigning/core.crt
index 475a59bddce..62f87c9d30c 100644
--- a/resources/codesigning/core.crt
+++ b/resources/codesigning/core.crt
@@ -1,28 +1,24 @@
-----BEGIN CERTIFICATE-----
-MIIEvjCCAqagAwIBAgIUc/0FxYrsgSs9rDxp03EJmbjN0NwwDQYJKoZIhvcNAQEF
-BQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw
-MzIxMDMzM1oXDTE2MTEwMzIxMDMzM1owDzENMAsGA1UEAwwEY29yZTCCAiIwDQYJ
-KoZIhvcNAQEBBQADggIPADCCAgoCggIBALb6EgHpkAqZbO5vRO8XSh7G7XGWHw5s
-iOf4RwPXR6SE9bWZEm/b72SfWk//J6AbrD8WiOzBuT/ODy6k5T1arEdHO+Pux0W1
-MxYJJI4kH74KKgMpC0SB0Rt+8WrMqV1r3hhJ46df6Xr/xolP3oD+eLbShPcblhdS
-VtkZEkoev8Sh6L2wDCeHDyPxzvj1w2dTdGVO9Kztn0xIlyfEBakqvBWtcxyi3Ln0
-klnxlMx3tPDUE4kqvpia9qNiB1AN2PV93eNr5/2riAzIssMFSCarWCx0AKYb54+d
-xLpcYFyqPJ0ydBCkF78DD45RCZet6PNYkdzgbqlUWEGGomkuDoJbBg4wzgzO0D77
-H87KFhYW8tKFFvF1V3AHl/sFQ9tDHaxM9Y0pZ2jPp/ccdiqnmdkBxBDqsiRvHvVB
-Cn6qpb4vWGFC7vHOBfYspmEL1zLlKXZv3ezMZEZw7O9ZvUP3VO/wAtd2vUW8UFiq
-s2v1QnNLN6jNh51obcwmrBvWhJy9vQIdtIjQbDxqWTHh1zUSrw9wrlklCBZ/zrM0
-i8nfCFwTxWRxp3H9KoECzO/zS5R5KIS7s3/wq/w9T2Ie4rcecgXwDizwnn0C/aKc
-bDIjujpL1s9HO05pcD/V3wKcPZ1izymBkmMyIbL52iRVN5FTVHeZdXPpFuq+CTQJ
-Q238lC+A/KOVAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBAGoKTnh8RfJV4sQItVC2
-AvfJagkrIqZ3iiQTUBQGTKBsTnAqE1H7QgUSV9vSd+8rgvHkyZsRjmtyR1e3A6Ji
-oNCXUbExC/0iCPUqdHZIVb+Lc/vWuv4ByFMybGPydgtLoEUX2ZrKFWmcgZFDUSRd
-9Uj26vtUhCC4bU4jgu6hIrR9IuxOBLQUxGTRZyAcXvj7obqRAEZwFAKQgFpfpqTb
-H+kjcbZSaAlLVSF7vBc1syyI8RGYbqpwvtREqJtl5IEIwe6huEqJ3zPnlP2th/55
-cf3Fovj6JJgbb9XFxrdnsOsDOu/tpnaRWlvv5ib4+SzG5wWFT5UUEo4Wg2STQiiX
-uVSRQxK1LE1yg84bs3NZk9FSQh4B8vZVuRr5FaJsZZkwlFlhRO//+TJtXRbyNgsf
-oMRZGi8DLGU2SGEAHcRH/QZHq/XDUWVzdxrSBYcy7GSpT7UDVzGv1rEJUrn5veP1
-0KmauAqtiIaYRm4f6YBsn0INcZxzIPZ0p8qFtVZBPeHhvQtvOt0iXI/XUxEWOa2F
-K2EqhErgMK/N07U1JJJay5tYZRtvkGq46oP/5kQG8hYST0MDK6VihJoPpvCmAm4E
-pEYKQ96x6A4EH9Y9mZlYozH/eqmxPbTK8n89/p7Ydun4rI+B2iiLnY8REWWy6+UQ
-V204fGUkJqW5CrKy3P3XvY9X
------END CERTIFICATE----- \ No newline at end of file
+MIID8TCCAdkCAhAAMA0GCSqGSIb3DQEBCwUAMG0xCzAJBgNVBAYTAlVTMQ8wDQYD
+VQQIDAZCb3N0b24xFjAUBgNVBAoMDW93bkNsb3VkIEluYy4xNTAzBgNVBAMMLG93
+bkNsb3VkIENvZGUgU2lnbmluZyBJbnRlcm1lZGlhdGUgQXV0aG9yaXR5MB4XDTE2
+MDIwMzE3NTE0OVoXDTI2MDEzMTE3NTE0OVowDzENMAsGA1UEAwwEY29yZTCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPHdSljnHI+ueQd27UyWPO9n4Lqt
+bK0kdekiC3si7Mee7uXXJaGuqXJozHEZYB1LIFLdCU/itCxEk9hyLcyNzeT+nRT/
+zDuOYdbLgCj7/A5bX+u3jc29UlCYybSFchfMdvn7a0njCna4dE+73b4yEj16tS2h
+S1EUygSzgicWlJqMD3Z9Qc+zLEpdhq9oDdDB8HURi2NW4KzIraVncSH+zF1QduOh
+nERDnF8x48D3FLdTxGA0W/Kg4gYsq4NRvU6g3DJNdp4YfqRSFMmLFDCgzDuhan7D
+wgRlI9NAeHbnyoUPtrDBUceI7shIbC/i87xk9ptqV0AyFonkJtK6lWwZjNkCAwEA
+ATANBgkqhkiG9w0BAQsFAAOCAgEAAMgymqZE1YaHYlRGwvTE7gGDY3gmFOMaxQL4
+E5m0CnkBz4BdIPRsQFFdOv3l/MIWkw5ED3vUB925VpQZYFSiEuv5NbnlPaHZlIMI
+n8AV/sTP5jue3LhtAN4EM63xNBhudAT6wVsvGwOuQOx9Xv+ptO8Po7sTuNYP0CMH
+EOQN+/q8tYlSm2VW+dAlaJ+zVZwZldhVjL+lSH4E9ktWn3PmgNQeKfcnJISUbus6
+ZtsYDF/X96/Z2ZQvMXOKksgvU6XlvIxllcyebC9Bxe/h0D63GCO2tqN5CWQzIIqn
+apUynPX8BlLaaExqYGERwlUi/yOGaUVPUjEPVehviOQYgAqxlrkJk1dWeCrwUori
+CXpi+IUYkidfgiJ9F88M3ElpwqIaXp7G3/4oHBuE2u6M+L+1/vqPJeTCAWUxxpJE
+yYmM+db6D4TySFpQPENNzPS8bpR6T8w2hRumkldC42HrnyJJbpjOieTXhXzjdPvZ
+IEP9JGtkhB2du6nBF2MNAq2TqRXpcfQrQEbnQ13aV9bl+roTwwO+SOWK/wgvdOMI
+STQ0Xk0sTGlmQjPYPkibVceaWMR3sX4cNt5c33YhJys5jxHoAh42km4nN9tfykR5
+crl5lBlKjXh2GP0+omSO3x1jX4+iQPCW2TWoyKkUdLu/hGHG2w8RrTeme+kATECH
+YSu356M=
+-----END CERTIFICATE-----
diff --git a/resources/codesigning/core.key b/resources/codesigning/core.key
deleted file mode 100644
index 4a588d47356..00000000000
--- a/resources/codesigning/core.key
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKQIBAAKCAgEAtvoSAemQCpls7m9E7xdKHsbtcZYfDmyI5/hHA9dHpIT1tZkS
-b9vvZJ9aT/8noBusPxaI7MG5P84PLqTlPVqsR0c74+7HRbUzFgkkjiQfvgoqAykL
-RIHRG37xasypXWveGEnjp1/pev/GiU/egP54ttKE9xuWF1JW2RkSSh6/xKHovbAM
-J4cPI/HO+PXDZ1N0ZU70rO2fTEiXJ8QFqSq8Fa1zHKLcufSSWfGUzHe08NQTiSq+
-mJr2o2IHUA3Y9X3d42vn/auIDMiywwVIJqtYLHQAphvnj53EulxgXKo8nTJ0EKQX
-vwMPjlEJl63o81iR3OBuqVRYQYaiaS4OglsGDjDODM7QPvsfzsoWFhby0oUW8XVX
-cAeX+wVD20MdrEz1jSlnaM+n9xx2KqeZ2QHEEOqyJG8e9UEKfqqlvi9YYULu8c4F
-9iymYQvXMuUpdm/d7MxkRnDs71m9Q/dU7/AC13a9RbxQWKqza/VCc0s3qM2HnWht
-zCasG9aEnL29Ah20iNBsPGpZMeHXNRKvD3CuWSUIFn/OszSLyd8IXBPFZHGncf0q
-gQLM7/NLlHkohLuzf/Cr/D1PYh7itx5yBfAOLPCefQL9opxsMiO6OkvWz0c7Tmlw
-P9XfApw9nWLPKYGSYzIhsvnaJFU3kVNUd5l1c+kW6r4JNAlDbfyUL4D8o5UCAwEA
-AQKCAgBOkCKpNYqGMogF/DqB2eMWQd1zdryQ6eMCjqSXLpjxN7F0LmwvISSxdIZH
-cMunwBn94IQb+7W5gpUcNurCpCryU9CQNlbTRFDR9kz+xt3mL+EICFhxKrgI8UFg
-1M0ncogir58Sn2jVSfsJvARSKHDWNp+mpe6UxuLJRi2HK5q1J7uRroQZeLD0gv+V
-/5fNxpRkZzlBAqnyC/zyswSnNNUbDaUuN3NEWJF6EvMLs546BST6MSMyzN53GkD/
-i2KLTWa3Hf62+S5qJsYyXBM1nz41n/0jVTngfSIZzk4Fm4Z5DE+vUXVsqzjDp2HS
-AXbS/UVrq+V3yOI4CEG1nXPXXpPDS/werQcSvANGHd/LLiQ3qfcs1S/SBihDjSFQ
-CBgH3y06qDdnKxdPjpRYZpOBnkdQLHF4OwlhPXBd083Ep7jiF1WIgzwBP9o9wEWi
-dVT0Vr5vsB61MQ+4p26Us1yWm51g6AxpTu5y2RPmbuDh1IvNbheeITQMSmbtGf1R
-JZ4yqrnYpd3akja9hwko1xoWuHT15rr2pTs8g/PtHH7sNkZdThMtJscEt4YIIxoN
-CQ+VM4lGYogtySbYEiUkRNF3t06AsPhBehcH7oldUqb6UKKoi6NCZOiC5RsdpOY3
-JJX2nkCMk52264sI+kWl6kEVBpMzeLW+BM0Xi1AQRyHPIY+VZQKCAQEA4sjNh35x
-ezjiOWsq84UOUHdvei9HAm+MQMM2pEgdHWjjawhoH122gi2G/tpgNGONl/XNmZkk
-ni00jFtNRA9xDF6mv1CynxiWhKGLdEH3MELQqGyeNOE9GBQVMo2W2J2mvOj+GzC+
-cRrEBjR1MDGx+XLO8FbYyKiwVg8/OIT9hIYSlBIsu0bPwYb6X3KlfZfmdh/MZvCs
-HDthzRYnJlkVerB/2ZnfTVYflQh7XoKFipVXFMs+oG0mKCUT4HpqXWTek1Jqt8bQ
-og9235C0jEcFWjSHtp2Jhena8yMD4YKQGI7tFVFm9UkHkKPcdfIW+hoVC4vLI0fs
-LMwhzOvFof4pawKCAQEAzoyGHKUA2KG8JVV49C5LKLmJv0nBj7aT5EXcg1J9OZn7
-zP/o/BHJQpeLNI2UD5c0Ron33iRLVqNvU4sTdo597Qoc2jWsZWRmdTz2Q4VvnxHu
-VBvao0vUG4xqIbMtv4VRkuNg9EmlF4luT5+x30E6DWDMK0RhSmM9yWG7My6JG2IN
-LZ457tWvk7F1HTKNt3uFJTAOx0VqjJsbaw7Gsq7hTmObTUa+q8Ss0oK+iRkP5Obv
-9F9zUWv2UjKs/G4JYADfFhS1Ovha8pu5p+NszlGBGvG99EErRpiUPcxCTjSiUvDl
-ALn3YTDc9oSC+6b/sI7/4uQVSri5ybXLGzbtMWKm/wKCAQEAvO12M6uF1Ja1+Ams
-lYTCQQzO5OZf7MqK+CTo74FYJ/kKhE9TltXWRqqw7L12Kg7Jlc/jgVNQaynTvh4N
-x2Zp0llD5tvOgrXUJxgBek++Iwl2lOkv/3OpFtccNao5AaqMjpI3puU7sjQPG/A1
-tHmh/+LCPPzMypWlmXxIOcio/u9GqO5fL4E1cM8G4985uOCD0OJ6wUM8zqQ1vMn4
-wXyzZSuGxvvmSKI320teo4Ruxd3V1u/e830arZT98yNoWve+aNLfLszFYE0rxeHi
-V36PGe/rI5ooSFRi3+zKveKsMplXL0xKTouRbtDjx6pvs9losN6701+GhGdmvTWp
-xmNbkwKCAQEAmY94FcvG+UglbUxChKf2UOzAMGtRcNs40Lnv2+J0H2MQBbUtLlq6
-2rt4TzYDIiQ0RU1F7u3k5SDVH7OCYN5HWPfvw3usFCW01uzf2gtWlVjra7TZtBYo
-N+MI9M0V8hHYN/C8oGIwT3Npg+EiiO0hj9ircm+ANaHayeHTH5Y1cRpQ2d2NDLfp
-tVB11aNEIWm/74nvMs+1C5w1oj52E1pZP8JmL+ms0F+EbW2u4pazbmcTdweP4LT3
-iN0MJxBX//wl33C93H3QgBauzNcUib+m0LVxmCrrVa0SaW92zFXtaOSYHRYliSie
-3thd2WKrLkTikXkpK0hzODfkLPOFHPZPWQKCAQAG0Yz7eQblxIHII60ReeYIovum
-Gmn+ot0jeuPg5gYpopQygL87ygc00ER+SHgZLBjIx3uCYDbC6Q4SzEPLa/aUS3/e
-94vYBVoWYvTYUazuwgJBA1Xm7BnlqG7cQziJOQxBIJBXaX96xUptcmlKrIIYD9Jz
-qeUbbbqN4bBYjXJdNdMqU1f6t2IK7hcjFXJMpS2wJdv1AlYCUWDquQ0BUePCJAPf
-N0rKm12ffhi564NqN/6PtT7iEkSPKT2CEyqrvXwx0Lajz0ZokFzRm2iYUTxik2fI
-Lcq5zXyM4gs1hDnrasn1g0JyfeUgnPNNuWeFG0cMb8o7FeYQImhqheIgMJLP
------END RSA PRIVATE KEY----- \ No newline at end of file
diff --git a/resources/codesigning/root.crt b/resources/codesigning/root.crt
index 539bd9a199f..cbd82898bab 100644
--- a/resources/codesigning/root.crt
+++ b/resources/codesigning/root.crt
@@ -1,28 +1,66 @@
-----BEGIN CERTIFICATE-----
-MIIE1DCCArygAwIBAgIUFgEnT7tUWNgEKfbMiRTOm3Z8figwDQYJKoZIhvcNAQEF
-BQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMCAXDTE1MTEw
-MzIxMDMzMloYDzk5OTkxMjMxMjM1OTU5WjAjMSEwHwYDVQQKDBhvd25DbG91ZCBD
-b2RlIFNpZ25pbmcgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCt
-rYEwiwpuhzRNx1L2SntkL/zalA7OkwEcsBn4Ysw47nEdvp648AVohT7d+U7+DWix
-O06xvlAJUhqYTXX7EG9n+mBnG+TIMq2zlei0Jj3uq1pEZE9elfGZael2uc8gRXMZ
-YFmSlTvzexqvfK4B3DwoZaMaWJecEO9iyuUyzHMBpE8bHtGDOUGy/oTO9WASbtl9
-Rfk38VLLV6csCPwKjii6Q3YZ+AYU0YqLg22BwZlqlTexUjWAmVIqaoxmSEuKa41X
-nuAIHfP65oiob86s4IvJXVr3r7NjdF2IJ/ZrwmjGKaWgSZKcoZBPLArZJeJiIQ4Y
-KzLZATwba5dWswV0mbDj8eP2BG+02NVKxylOBbeoBESnahZeZ5nJ5XKZr+ErJAUW
-b417fEnYaQNBlNnijjkqXaDipmTktUfnv4lm30sUAgho6I3Ga7gQrFPzKg9V4j2S
-+LOTc1HmJOnR6Kfttx+yAHYLKtvV5yIMMpz+rZ2X5g/N2GdgleZj5VU9nmKzTPeG
-x6V+dBaIkqNe8/AXaVnxt9KSb03Q/+CFjKTNDtEN5fNJuXS0+h+oop6nhpktM2i7
-gCpxeLNEaQaeoxR5093VN00oOJOYBvQoVGEDftEwdG6dWbTZsIykBF7aK+p8DMy9
-tCdc2GnGMEuFlUNA9ucv2Rv7IcuPdspnK31CZoMNKwIDAQABMA0GCSqGSIb3DQEB
-BQUAA4ICAQBROWec0HOsnLPN40gkBQ62mNBUJgcAr5K2eMIEMSRFRD2ldEVOvmCO
-u1Q62umy9tiSRiFQTcG1J9k0zlOjy/hfpBl2G1Zce0OoEeuNkH7c0W/idHSloWRZ
-YlK3tVJD6DzY6s9VbO6e/ncecNsXkirkWp/cvMYquH2d4OmSl0/hW0VMdxOCLxkA
-xbW+3Dh05u7tgKVRD67/GRvLtg+xHaOJqiOh3MpMaHy+6xT5Fd5K2QC0pcGtZuqF
-EnnfdeUI/Dy76yQE8pBfjaUFf3TS1n1E6kun1Nkf0X4pvwi8W1goLsPu5sWDNNga
-1RGYj0o5OdIo27qebfmu76WX0fNNd47VabtzNV+W7Msj0yeZg+hxAtAvs0ZEyJh+
-4biWsv+ALSlqz4sSdoOVGUEBdnkUrWN19lou62ix9vTmuCrVEA3TuZA3PR0+hqqQ
-/A/DcmWwxWYKyaBgxwHc/nGo1qWrDh22P5Rp7++Zw3kOCY6QmeJkAiHFs6Crw4ub
-HKVMw3fV5H9oiUFjadPZoCU51uXKX4YRqKxWJ5djlp4r1GCEQHyxngTsmH3komnw
-kh4LsEQRqdhuT0A4sZN7CenMJfQiFqupL7RVSycJFQpgzwVFmOzjCVT4PT/W5ARv
-9YtqEkvyoRTwErwuN/FIVvhWnIP/C69Z1/T/nXyj86P2G7PMgnchIQ==
+MIIFtDCCA5ygAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCVVMx
+DzANBgNVBAgMBkJvc3RvbjEWMBQGA1UECgwNb3duQ2xvdWQgSW5jLjEtMCsGA1UE
+Awwkb3duQ2xvdWQgQ29kZSBTaWduaW5nIFJvb3QgQXV0aG9yaXR5MB4XDTE2MDIw
+MzE3NDMyNVoXDTI2MDEzMTE3NDMyNVowbTELMAkGA1UEBhMCVVMxDzANBgNVBAgM
+BkJvc3RvbjEWMBQGA1UECgwNb3duQ2xvdWQgSW5jLjE1MDMGA1UEAwwsb3duQ2xv
+dWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBBdXRob3JpdHkwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQDKMul4pWev6vtgzB73CLQPMy8nDZGbvqII
+IgukQluMeLCW0P09I+J/mCiDd99mQTtWO+/LcpOChHYJ59qQz+g9TzKlVSuFDg47
+pc+jUvTLGGEDf9cAWtzsXYXlb9z7sTln/8JAvy8ghmaR/4JWU4hM/nmgDCpeXLLJ
+NFrxKDbzPLYj53iHN+XyE9GT6sDYoQd1BIWhTsMdvMqg870Jw2yN4hKw3V7/KoI/
+Z5CAA9dP4tAmltBpMz79dmLCciqXOD8mWEWl2tSZU+/WVyPxiE19IHoJETOhSg4c
+eud4DDdFt9Ohm4owvpxxRDbvV+Ic6sWb1gJBrM7/XJDmaUObpowjx8Daof1MuoHs
+FKh6/Y7RBdVlrp/ig3htxfm9BBMqnXIxgFWDiSbjCMk0Ygvx49gKMnVoRhZ/7pla
+j5nTRdbhsjS50E9zfc53EltM27YSwNZu62QKsU4yumg8UOhOYPRLHcySvNyyMZXS
+o+Kst27oGSgurHytFS7FVG1M3UUn67zkMpnnMYhfx8dz7+tupY9e0l0kDciwvNAO
+YrnvHoEiIbJmoyYOhL2j9WErUhAb3JKTSdYC0MmjaZZPv0HwCemx+rnApcoszmFG
+woZTRAa6Q64WGxlmFq0vsgmcTNsTzlYY20Kv+ZpZOiVYonyHFkorKWdsXKZQcnYq
+dcMqYxQE6wIDAQABo2YwZDAdBgNVHQ4EFgQUfZoNPRneQ1pk9SZT9A2lpG4Hw7Mw
+HwYDVR0jBBgwFoAUcZdiBiGr+Y+OH2DrlNwK03zWH+YwEgYDVR0TAQH/BAgwBgEB
+/wIBADAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBAA2hoAEdbdM9
++ZA/q7UppF4BiKrSQNAQHLDwodutRY+gBYQsWpo8wLqdLvRVhlwDn3KmJEMfaDQm
+5YM+/snBkew9olCIyYw+t7xYtNhoW1et/nNNDL+Qq7uyH6g+uOMp4m3c+BMv4x5H
+EP3z7PY1qrPOVvzZu8o2iL8qpC0sXTKZy+xG/9VTYGnxCcG+V/Ua5aHOyetUttoN
+bxEcEQHHe07V+JlCPuI53hPsiGgzHv+nz/1sJV95mn9w88SHY0JO9bHp9w+mq92K
+r0Nv6Wctf7vNVmIOdRFHWOFie4+D3TpBSnB5PPQRbtf6IVEhjmcnWYBWcRGhH6cR
+4dqpuqzwVFopIFLYMeaeKGu8wZHi2YRrkFcrnqqmFI9RtBbt3eyfUQcKH7b9P4Ri
+qamb/h9sVjDM4wSQ6n+Qa2dgV28O0il35roa3qwvqySgn1wXS5CsAaeB1VWAS6/S
+v1WFt93n9LrraV4EUuu1BGXp525aVn6v+B71zN4JzYnHVE4yAb0EdOpKrlfmCCm/
+9Z90+BF2uK3QnpkyrH+LEOQoHrlAt80RZYd2Tl/K1WWNrPUlnCGXdxjVYakVRnfy
+Ud0KV4RsD93mNw/t2gU5U+SyYWU2fTJUE9qdJ4Ndw7B2DZ/5dcsu0rDV4sXkUoDY
++Dr25NoOcuqjCWRw2T3SBPSXBxjlhRTQ
-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFsDCCA5igAwIBAgIJALFuk51OGp2KMA0GCSqGSIb3DQEBCwUAMGUxCzAJBgNV
+BAYTAlVTMQ8wDQYDVQQIDAZCb3N0b24xFjAUBgNVBAoMDW93bkNsb3VkIEluYy4x
+LTArBgNVBAMMJG93bkNsb3VkIENvZGUgU2lnbmluZyBSb290IEF1dGhvcml0eTAe
+Fw0xNjAyMDMxNzM5NThaFw0yNjAxMzExNzM5NThaMGUxCzAJBgNVBAYTAlVTMQ8w
+DQYDVQQIDAZCb3N0b24xFjAUBgNVBAoMDW93bkNsb3VkIEluYy4xLTArBgNVBAMM
+JG93bkNsb3VkIENvZGUgU2lnbmluZyBSb290IEF1dGhvcml0eTCCAiIwDQYJKoZI
+hvcNAQEBBQADggIPADCCAgoCggIBAJmTnGtGaB0cDtQPxWr2r5FyXFzJ6GIkm4Lb
+7iY/DYpIEarbRFwqDCDZ00V+PWsTBBF6qXW5W7eZ+fOOdIEGoNaDuGtIlGVjj3Dz
+TZtmcFg0euimfLNYVvYZlPPh4kS3zDRZs30AgAdgq4RHWC4qjElWcVKTwERNQ2ln
+gRFRQEv+i2DI7sEK9ZpK7B1SfJ1o1fm/kPL7bVfiYda+QKp0vOxBecDnGV+rfz4t
+DT6mBOgwAiZnwojuiigfUJxSisv3roWri+0O+0TiXglV+oUtkIRrs0etkQGWAlgn
+H4CC+sZ5N2TiGPH1hksLkXP4mymlio8/x7ax0WfcxeTZu3ok9eK5fwIQVWam6dd9
+klCqZVttKodZYspvdFfwqMlf4lPEIY+r2PIdGjUhKu4FsDhORaGj8WMYRJUR44ls
+/r2ktCB/TOsh8DW2Pi9HAgxI4mrdmvL0WMSOBFZRcSC/nTz977oi1iiB2T+s7V0Z
+Y0AHMQYiIn83MFB7rb+mVlEoLID/evVSTfUaUaO8DqcfeQN/OFM/zcJY9YHv8AlJ
+3b8CPdeX9edMnyZWNdrhOSawjAbOBIna3o66RXdeC3oWg7FuckJmy7JLtRCJ2Owu
+losRAxe0z5mQmjFzMczxCYJQ4A+4U5UZwbd/MQJg508StcOumroYqruDic/Wbc3C
+v6DupG8dAgMBAAGjYzBhMB0GA1UdDgQWBBRxl2IGIav5j44fYOuU3ArTfNYf5jAf
+BgNVHSMEGDAWgBRxl2IGIav5j44fYOuU3ArTfNYf5jAPBgNVHRMBAf8EBTADAQH/
+MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAR6IZBOBw3KzRxvUP
++46RZYayMrdLyAgMzbDvQe7WCaeuA2UoPVL8jN7X2Lvw12Mz84+EKs1voR0OBxlY
+6muuyl0SETa2k4UtklVscMvcokG+m5aVNJ7/HHGFmKsTyJDMxSzDA/r3KRPXZOwV
+CLUVTkr5fQbIaVljA89U2p3pN/X7gNq89xi/XiszNCEIvvSscRmBGlRmx4XbjXHK
+XKO74+HiM/ahqUI792ae97jlsy9jG4OIelse3+e1KBWNsGtU90asnUHgyMXVL8gp
+ocznGvWceAhkcogUCUCXq1Rh/mKcGQdi2z0g/X+MGzfA9Ij4NQZLnNPh2UjgxCtG
+KWPUzs0t/xoCtJh1WpwqTrOUcYqFAaBa282sD/O8tX4t076aGKdbhfo6tvaOFwDU
+iRPgdMol++BFnfCld53Yivg2+S6+xo1wzuPkNjVFXHjx9vMyiov/HHKqJoBsuCwU
+7VegzM/6Cvh32lSZfUHsfynCab/7vv923KyaANWxb0QsHZSSt+mmOK3ZmC96vCEa
+55IGNckOvOGW9yCIz3Q0kEj2hoJs1bw0SkwGWs7N1TkugQjM/S7/Im1LJUxdtqQK
+Zjn+8U6U3TR1aKLYEdqHCGcVoRXKDG/S40FHxyeV/9buTI7SSvhzZfj+qasmJe1L
+Kd08UdS/im8RwbVSS1mih5hbAHg=
+-----END CERTIFICATE----- \ No newline at end of file
diff --git a/resources/codesigning/root.key b/resources/codesigning/root.key
deleted file mode 100644
index 557b0a26e3a..00000000000
--- a/resources/codesigning/root.key
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKgIBAAKCAgEAra2BMIsKboc0TcdS9kp7ZC/82pQOzpMBHLAZ+GLMOO5xHb6e
-uPAFaIU+3flO/g1osTtOsb5QCVIamE11+xBvZ/pgZxvkyDKts5XotCY97qtaRGRP
-XpXxmWnpdrnPIEVzGWBZkpU783sar3yuAdw8KGWjGliXnBDvYsrlMsxzAaRPGx7R
-gzlBsv6EzvVgEm7ZfUX5N/FSy1enLAj8Co4oukN2GfgGFNGKi4NtgcGZapU3sVI1
-gJlSKmqMZkhLimuNV57gCB3z+uaIqG/OrOCLyV1a96+zY3RdiCf2a8JoximloEmS
-nKGQTywK2SXiYiEOGCsy2QE8G2uXVrMFdJmw4/Hj9gRvtNjVSscpTgW3qAREp2oW
-XmeZyeVyma/hKyQFFm+Ne3xJ2GkDQZTZ4o45Kl2g4qZk5LVH57+JZt9LFAIIaOiN
-xmu4EKxT8yoPVeI9kvizk3NR5iTp0ein7bcfsgB2Cyrb1eciDDKc/q2dl+YPzdhn
-YJXmY+VVPZ5is0z3hselfnQWiJKjXvPwF2lZ8bfSkm9N0P/ghYykzQ7RDeXzSbl0
-tPofqKKep4aZLTNou4AqcXizRGkGnqMUedPd1TdNKDiTmAb0KFRhA37RMHRunVm0
-2bCMpARe2ivqfAzMvbQnXNhpxjBLhZVDQPbnL9kb+yHLj3bKZyt9QmaDDSsCAwEA
-AQKCAgEAnR6/JkRTPqTQW6D8W9YMBRoovTF+p8F0GxjxlbUDnmmQKeGeRB7YNbN9
-qWD25n0I/nVx/vj1/UiqyKgjGOvIbZ+kAQPKGJdIb5Qp/nguRTH9qqu45g/ujuSz
-EfaM/Fv4AbgZsLOTlfUDskiwPvyX68/vG1GUbtsfRhfZ+/fb/1s/OYDK99Ufq6f4
-TCbOMD7aQSvBh6upRE5a7Up/gakUDVYkjN/F2KWsmgRfWCjl+vddd+ywfFO4cqkL
-tSioNmSQbPlNIeq/I3fVn9PufJVzwMrVFgh82HeYein1E43ALa3VqcmFem/rVsS4
-V7SfNjlDP/gsuwcT8paGRigUwmScEkyXYJ7oSNEN8Xe4kWWakfwGpa1HmaYPdHx+
-O+G8coHp2kcc/tUZma+Ffo3tNRMfGcpowG+PetbCh4uSNPo5U5U5W53+vxgyZHFi
-lY7gc5HVi5JBSxmWwTa3RDcz1dByWS83NdObrxAntp3W9g8tVj2N9gfUnJS+wp3d
-m8HvO3bzIUuhQcWAtcnXqRAGsl+uc/xgdF2membV/yOHdn2Z1zXKEnjC1T6cEV06
-qocwgp0/EAMhzL4FP8xA9MvztZR7bJOyUihTIadG7Zb18XBea7yA73KvfYGrzjsg
-lmqV4CbGuo0If8SJD03xXthMqi5cBXu4V13sYAbNO8pPDjhfPIkCggEBAOUjScLN
-RoaoOBO3JUWoYauZrf9sa72/zzTOg+c8unQquExMjnsyEVJPD4+TpKGN5/sewwb5
-zksI5c1njOrdFdSKoKlgB/6owv2v70Uqe+HeVA+m5Qy6JSgMAAXZgJ5PtaCCu+Xq
-MOqTd/xInfP1oCecJF9UvqeQJBJN16fMXBib9J5+sLCRJnFNywfmlfAiIOa4MIoY
-Tz7LW+r4Zot0x2o6KcCT8AB3LJIz2seHmTf9Jjk17kw7pFJWtZf6eA1lgDlzadKJ
-iHgrdSbchDZv410B0df/ZV+gZ7PMgK/cbo3H3JOXPV1dxmTONTIIvxYj1LmOdMP4
-p5oeM367LUWQN20CggEBAMIJykbsm7IVthkMeCm/VhG/wd44iB0g5+us8q8pUO1+
-KfTzytHPjMack5a/XaEApRRiJpCAJNcBpUNbJqaOZQ1QqnX6ozlSR2aUi27noVz6
-/heG+3qZElejYfLMpJAF1crjdFJIqKucizc+E6AZ+nOixpJcDABYWby9QQw4O1Pr
-Ii3E7xyFvqizYzE7P/HG6P0gMxta9aKHKGhGHX51Uc+BUfF0T0ymXVvWLlfMg+HI
-SBPqMphW+YR0xwK21A2LvqYBM2MyaThY2wyVSZs9akjiAukRwX8l7lA5A/try0Q0
-1POyN6oo1H7iSHuraqXfDjcSpK5M/QOpXMuoPyTI//cCggEBAKCn00mwH6i+PUMl
-gA6M9p4YTDTwUcJiv+cofLcejyRv53QnoSajfh2VrTVfsWhMVMBvWxKDB674eBdC
-aT0q8elpoSfgWvqkXML+HecC2IUPGyU2QRZhVTf04fc3/sQA4zm9L/0N7GosJ05N
-o+Gu8DGVerMUefCGUaQ7y96snE3s2uBdt4i03J1Ii/foJmyNoT/jGLVaQgWnE7V1
-oIBayo6iZS/PCdFpvWhszxJi8nydE7W9KG1uy9GnVf9O7+mEpxig4StqnrKS1br/
-lfuNC37kjbrCKNOZZdxcoEWtah4iaXdZ7P6Ph1CafBWuqDvft4C6bwgQSYL3ded/
-WUiSyykCggEAePeThF3TvtUsPjd43kXriYsreLdzm/08uL+MWEkAq96gl5Y5Fk43
-LEbG+A77dvko8Skzc5h/3w6mkfRMhz90njVw37ZOddjmrHvk5VJAVfAf4lkDhG3T
-cpFn6e9MlIEexKrChN3JUZt5awonQAOSEO8krm/2B20NHM47tDuGOQ34s+H3U6fJ
-sfCL4VBX0Ao6jDu7wM0XH6j1NvSnRIQtaZjslgP1wApjX3KKV7Anc+XhkZDK1BA8
-5CfNPdLvJja9t04+VBREZp12ikSzq7VBAojsWZL5N6RVCuxQoDiWc0IglIDBlTJ5
-L1Uw7PBzv07s1MappgRXJCY8tLaCDxPEBwKCAQEA1Rxj0YpQ1D+8oFQ3ck0b4ODy
-DCSCNe6Xw+Wzv5BqGVsQCmW14uVBT+S/qij5dTrGIPXudLSHtdjs9tmoDqnkxY/o
-Nj5rx6J2brnNLTD7yo/j74kgaRwSuHafpGX1C0zge0rgIgVu8DhWHan7F/38K0cO
-T1jYJbYcTAvEcO1XXXItnaHR1ETY4p0G5FvUTLWaNQnQTU3r5ZaCkjXN9UBA2k6U
-6j6A9/JXIlNPFNoB103iAD5jvHa96AlivHSyp4UTlsiwAxec316CY2zdWrVWQCF4
-J8DspH3ygeLtvKOveEYsiaiNuJLKREC2GIRUm6O4C/RdP0s0QAODpk+yGCfukg==
------END RSA PRIVATE KEY-----
diff --git a/resources/config/mimetypealiases.dist.json b/resources/config/mimetypealiases.dist.json
index ed471f228e2..545d4b0c399 100644
--- a/resources/config/mimetypealiases.dist.json
+++ b/resources/config/mimetypealiases.dist.json
@@ -17,12 +17,14 @@
"application/json": "text/code",
"application/msaccess": "file",
"application/msexcel": "x-office/spreadsheet",
+ "application/msonenote": "x-office/document",
"application/mspowerpoint": "x-office/presentation",
"application/msword": "x-office/document",
"application/octet-stream": "file",
"application/postscript": "image",
"application/rss+xml": "application/xml",
"application/vnd.android.package-archive": "package/x-generic",
+ "application/vnd.lotus-wordpro": "x-office/document",
"application/vnd.ms-excel": "x-office/spreadsheet",
"application/vnd.ms-excel.addin.macroEnabled.12": "x-office/spreadsheet",
"application/vnd.ms-excel.sheet.binary.macroEnabled.12": "x-office/spreadsheet",
@@ -51,6 +53,8 @@
"application/vnd.openxmlformats-officedocument.spreadsheetml.template": "x-office/spreadsheet",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": "x-office/document",
"application/vnd.openxmlformats-officedocument.wordprocessingml.template": "x-office/document",
+ "application/vnd.visio": "x-office/document",
+ "application/vnd.wordperfect": "x-office/document",
"application/x-7z-compressed": "package/x-generic",
"application/x-cbr": "text",
"application/x-compressed": "package/x-generic",
diff --git a/resources/config/mimetypemapping.dist.json b/resources/config/mimetypemapping.dist.json
index e26ec7038b1..d08a46bb017 100644
--- a/resources/config/mimetypemapping.dist.json
+++ b/resources/config/mimetypemapping.dist.json
@@ -76,6 +76,7 @@
"key": ["application/x-iwork-keynote-sffkey"],
"keynote": ["application/x-iwork-keynote-sffkey"],
"kra": ["application/x-krita"],
+ "lwp": ["application/vnd.lotus-wordpro"],
"m2t": ["video/mp2t"],
"m4v": ["video/mp4"],
"markdown": ["text/markdown"],
@@ -106,6 +107,7 @@
"oga": ["audio/ogg"],
"ogg": ["audio/ogg"],
"ogv": ["video/ogg"],
+ "one": ["application/msonenote"],
"opus": ["audio/ogg"],
"orf": ["image/x-dcraw"],
"otf": ["application/font-sfnt"],
@@ -154,9 +156,11 @@
"vcard": ["text/vcard"],
"vcf": ["text/vcard"],
"vob": ["video/dvd"],
+ "vsd": ["application/vnd.visio"],
"wav": ["audio/wav"],
"webm": ["video/webm"],
"woff": ["application/font-woff"],
+ "wpd": ["application/vnd.wordperfect"],
"wmv": ["video/x-ms-wmv"],
"xcf": ["application/x-gimp"],
"xla": ["application/vnd.ms-excel"],
diff --git a/settings/css/settings.css b/settings/css/settings.css
index 9e98960a715..501b8055561 100644
--- a/settings/css/settings.css
+++ b/settings/css/settings.css
@@ -54,6 +54,10 @@ input#openid, input#webdav { width:20em; }
max-width: 75%;
}
+.clientsbox img {
+ height: 60px;
+}
+
#sslCertificate tr.expired {
background-color: rgba(255, 0, 0, 0.5);
}
diff --git a/settings/js/users/users.js b/settings/js/users/users.js
index 151ab6cdecc..306e3952e53 100644
--- a/settings/js/users/users.js
+++ b/settings/js/users/users.js
@@ -732,24 +732,20 @@ $(document).ready(function () {
.focus()
.keypress(function (event) {
if (event.keyCode === 13) {
- if ($(this).val().length > 0) {
- $tr.data('mailAddress', $input.val());
- $input.blur();
- $.ajax({
- type: 'PUT',
- url: OC.generateUrl('/settings/users/{id}/mailAddress', {id: uid}),
- data: {
- mailAddress: $(this).val()
- }
- }).fail(function (result) {
- OC.Notification.show(result.responseJSON.data.message);
- // reset the values
- $tr.data('mailAddress', mailAddress);
- $tr.children('.mailAddress').children('span').text(mailAddress);
- });
- } else {
- $input.blur();
- }
+ $tr.data('mailAddress', $input.val());
+ $input.blur();
+ $.ajax({
+ type: 'PUT',
+ url: OC.generateUrl('/settings/users/{id}/mailAddress', {id: uid}),
+ data: {
+ mailAddress: $(this).val()
+ }
+ }).fail(function (result) {
+ OC.Notification.show(result.responseJSON.data.message);
+ // reset the values
+ $tr.data('mailAddress', mailAddress);
+ $tr.children('.mailAddress').children('span').text(mailAddress);
+ });
}
})
.blur(function () {
diff --git a/settings/templates/personal.php b/settings/templates/personal.php
index b00a5c5dd8a..14378899e92 100644
--- a/settings/templates/personal.php
+++ b/settings/templates/personal.php
@@ -170,7 +170,7 @@ if($_['passwordChangeSupported']) {
<div id="clientsbox" class="section clientsbox">
<h2><?php p($l->t('Get the apps to sync your files'));?></h2>
<a href="<?php p($_['clients']['desktop']); ?>" target="_blank">
- <img src="<?php print_unescaped(OCP\Util::imagePath('core', 'desktopapp.png')); ?>"
+ <img src="<?php print_unescaped(OCP\Util::imagePath('core', 'desktopapp.svg')); ?>"
alt="<?php p($l->t('Desktop client'));?>" />
</a>
<a href="<?php p($_['clients']['android']); ?>" target="_blank">
@@ -178,7 +178,7 @@ if($_['passwordChangeSupported']) {
alt="<?php p($l->t('Android app'));?>" />
</a>
<a href="<?php p($_['clients']['ios']); ?>" target="_blank">
- <img src="<?php print_unescaped(OCP\Util::imagePath('core', 'appstore.png')); ?>"
+ <img src="<?php print_unescaped(OCP\Util::imagePath('core', 'appstore.svg')); ?>"
alt="<?php p($l->t('iOS app'));?>" />
</a>
diff --git a/tests/karma.config.js b/tests/karma.config.js
index 4a7a9ad236e..2b569fb7584 100644
--- a/tests/karma.config.js
+++ b/tests/karma.config.js
@@ -89,8 +89,9 @@ module.exports = function(config) {
'apps/comments/js/app.js',
'apps/comments/js/commentmodel.js',
'apps/comments/js/commentcollection.js',
+ 'apps/comments/js/commentsummarymodel.js',
'apps/comments/js/commentstabview.js',
- 'apps/comments/js/filesplugin'
+ 'apps/comments/js/filesplugin.js'
],
testFiles: ['apps/comments/tests/js/**/*.js']
},
diff --git a/tests/lib/appframework/AppTest.php b/tests/lib/appframework/AppTest.php
index 7cba0e6db6b..3d41d6590aa 100644
--- a/tests/lib/appframework/AppTest.php
+++ b/tests/lib/appframework/AppTest.php
@@ -79,9 +79,9 @@ class AppTest extends \Test\TestCase {
$this->container['OCP\\AppFramework\\Http\\IOutput'] = $this->io;
$this->container['urlParams'] = array();
- $this->appPath = __DIR__ . '/../../../apps/namespacetestapp/appinfo';
- $infoXmlPath = $this->appPath . '/info.xml';
- mkdir($this->appPath, 0777, true);
+ $this->appPath = __DIR__ . '/../../../apps/namespacetestapp';
+ $infoXmlPath = $this->appPath . '/appinfo/info.xml';
+ mkdir($this->appPath . '/appinfo', 0777, true);
$xml = '<?xml version="1.0" encoding="UTF-8"?>' .
'<info>' .
diff --git a/tests/lib/command/integrity/SignCoreTest.php b/tests/lib/command/integrity/SignCoreTest.php
index 885c6fc664e..ff1f6b23a95 100644
--- a/tests/lib/command/integrity/SignCoreTest.php
+++ b/tests/lib/command/integrity/SignCoreTest.php
@@ -63,7 +63,7 @@ class SignCoreTest extends TestCase {
$outputInterface
->expects($this->at(0))
->method('writeln')
- ->with('--privateKey and --certificate are required.');
+ ->with('--privateKey, --certificate and --path are required.');
$this->invokePrivate($this->signCore, 'execute', [$inputInterface, $outputInterface]);
}
@@ -86,7 +86,7 @@ class SignCoreTest extends TestCase {
$outputInterface
->expects($this->at(0))
->method('writeln')
- ->with('--privateKey and --certificate are required.');
+ ->with('--privateKey, --certificate and --path are required.');
$this->invokePrivate($this->signCore, 'execute', [$inputInterface, $outputInterface]);
}
@@ -105,6 +105,11 @@ class SignCoreTest extends TestCase {
->method('getOption')
->with('certificate')
->will($this->returnValue('certificate'));
+ $inputInterface
+ ->expects($this->at(2))
+ ->method('getOption')
+ ->with('path')
+ ->will($this->returnValue('certificate'));
$this->fileAccessHelper
->expects($this->at(0))
@@ -134,6 +139,11 @@ class SignCoreTest extends TestCase {
->method('getOption')
->with('certificate')
->will($this->returnValue('certificate'));
+ $inputInterface
+ ->expects($this->at(2))
+ ->method('getOption')
+ ->with('path')
+ ->will($this->returnValue('certificate'));
$this->fileAccessHelper
->expects($this->at(0))
@@ -168,6 +178,11 @@ class SignCoreTest extends TestCase {
->method('getOption')
->with('certificate')
->will($this->returnValue('certificate'));
+ $inputInterface
+ ->expects($this->at(2))
+ ->method('getOption')
+ ->with('path')
+ ->will($this->returnValue('certificate'));
$this->fileAccessHelper
->expects($this->at(0))
diff --git a/tests/lib/comments/comment.php b/tests/lib/comments/comment.php
index 02adea8729e..e6f9c941c96 100644
--- a/tests/lib/comments/comment.php
+++ b/tests/lib/comments/comment.php
@@ -15,10 +15,10 @@ class Test_Comments_Comment extends TestCase
$childrenCount = 6;
$message = 'I like to comment comment';
$verb = 'comment';
- $actor = ['type' => 'user', 'id' => 'alice'];
+ $actor = ['type' => 'users', 'id' => 'alice'];
$creationDT = new \DateTime();
$latestChildDT = new \DateTime('yesterday');
- $object = ['type' => 'file', 'id' => 'file64'];
+ $object = ['type' => 'files', 'id' => 'file64'];
$comment
->setId($id)
@@ -87,11 +87,11 @@ class Test_Comments_Comment extends TestCase
public function roleSetterProvider() {
return [
['Actor', true, true],
- ['Actor', 'user', true],
+ ['Actor', 'users', true],
['Actor', true, 'alice'],
['Actor', ' ', ' '],
['Object', true, true],
- ['Object', 'file', true],
+ ['Object', 'files', true],
['Object', true, 'file64'],
['Object', ' ', ' '],
];
diff --git a/tests/lib/comments/manager.php b/tests/lib/comments/manager.php
index a71f78f2818..c55f4728883 100644
--- a/tests/lib/comments/manager.php
+++ b/tests/lib/comments/manager.php
@@ -35,13 +35,13 @@ class Test_Comments_Manager extends TestCase
'parent_id' => $qb->createNamedParameter($parentId),
'topmost_parent_id' => $qb->createNamedParameter($topmostParentId),
'children_count' => $qb->createNamedParameter(2),
- 'actor_type' => $qb->createNamedParameter('user'),
+ 'actor_type' => $qb->createNamedParameter('users'),
'actor_id' => $qb->createNamedParameter('alice'),
'message' => $qb->createNamedParameter('nice one'),
'verb' => $qb->createNamedParameter('comment'),
'creation_timestamp' => $qb->createNamedParameter($creationDT, 'datetime'),
'latest_child_timestamp' => $qb->createNamedParameter($latestChildDT, 'datetime'),
- 'object_type' => $qb->createNamedParameter('file'),
+ 'object_type' => $qb->createNamedParameter('files'),
'object_id' => $qb->createNamedParameter('file64'),
])
->execute();
@@ -83,13 +83,13 @@ class Test_Comments_Manager extends TestCase
'parent_id' => $qb->createNamedParameter('2'),
'topmost_parent_id' => $qb->createNamedParameter('1'),
'children_count' => $qb->createNamedParameter(2),
- 'actor_type' => $qb->createNamedParameter('user'),
+ 'actor_type' => $qb->createNamedParameter('users'),
'actor_id' => $qb->createNamedParameter('alice'),
'message' => $qb->createNamedParameter('nice one'),
'verb' => $qb->createNamedParameter('comment'),
'creation_timestamp' => $qb->createNamedParameter($creationDT, 'datetime'),
'latest_child_timestamp' => $qb->createNamedParameter($latestChildDT, 'datetime'),
- 'object_type' => $qb->createNamedParameter('file'),
+ 'object_type' => $qb->createNamedParameter('files'),
'object_id' => $qb->createNamedParameter('file64'),
])
->execute();
@@ -102,11 +102,11 @@ class Test_Comments_Manager extends TestCase
$this->assertSame($comment->getParentId(), '2');
$this->assertSame($comment->getTopmostParentId(), '1');
$this->assertSame($comment->getChildrenCount(), 2);
- $this->assertSame($comment->getActorType(), 'user');
+ $this->assertSame($comment->getActorType(), 'users');
$this->assertSame($comment->getActorId(), 'alice');
$this->assertSame($comment->getMessage(), 'nice one');
$this->assertSame($comment->getVerb(), 'comment');
- $this->assertSame($comment->getObjectType(), 'file');
+ $this->assertSame($comment->getObjectType(), 'files');
$this->assertSame($comment->getObjectId(), 'file64');
$this->assertEquals($comment->getCreationDateTime(), $creationDT);
$this->assertEquals($comment->getLatestChildDateTime(), $latestChildDT);
@@ -207,7 +207,7 @@ class Test_Comments_Manager extends TestCase
$this->addDatabaseEntry(0, 0);
$manager = $this->getManager();
- $comments = $manager->getForObject('file', 'file64');
+ $comments = $manager->getForObject('files', 'file64');
$this->assertTrue(is_array($comments));
$this->assertSame(count($comments), 1);
@@ -227,7 +227,7 @@ class Test_Comments_Manager extends TestCase
$manager = $this->getManager();
$offset = 0;
do {
- $comments = $manager->getForObject('file', 'file64', 3, $offset);
+ $comments = $manager->getForObject('files', 'file64', 3, $offset);
$this->assertTrue(is_array($comments));
foreach($comments as $comment) {
@@ -247,7 +247,7 @@ class Test_Comments_Manager extends TestCase
$id2 = $this->addDatabaseEntry(2, 2, new \DateTime('-2 hours'));
$manager = $this->getManager();
- $comments = $manager->getForObject('file', 'file64', 0, 0, new \DateTime('-4 hours'));
+ $comments = $manager->getForObject('files', 'file64', 0, 0, new \DateTime('-4 hours'));
$this->assertSame(count($comments), 2);
$this->assertSame($comments[0]->getId(), strval($id2));
@@ -266,7 +266,7 @@ class Test_Comments_Manager extends TestCase
$manager = $this->getManager();
$offset = 0;
do {
- $comments = $manager->getForObject('file', 'file64', 3, $offset, new \DateTime('-4 hours'));
+ $comments = $manager->getForObject('files', 'file64', 3, $offset, new \DateTime('-4 hours'));
$this->assertTrue(is_array($comments));
foreach($comments as $comment) {
@@ -290,7 +290,7 @@ class Test_Comments_Manager extends TestCase
$amount = $manager->getNumberOfCommentsForObject('untype', '00');
$this->assertSame($amount, 0);
- $amount = $manager->getNumberOfCommentsForObject('file', 'file64');
+ $amount = $manager->getNumberOfCommentsForObject('files', 'file64');
$this->assertSame($amount, 4);
}
@@ -357,8 +357,8 @@ class Test_Comments_Manager extends TestCase
$manager = $this->getManager();
$comment = new \OC\Comments\Comment();
$comment
- ->setActor('user', 'alice')
- ->setObject('file', 'file64')
+ ->setActor('users', 'alice')
+ ->setObject('files', 'file64')
->setMessage('very beautiful, I am impressed!')
->setVerb('comment');
@@ -377,8 +377,8 @@ class Test_Comments_Manager extends TestCase
$manager = $this->getManager();
$comment = new \OC\Comments\Comment();
$comment
- ->setActor('user', 'alice')
- ->setObject('file', 'file64')
+ ->setActor('users', 'alice')
+ ->setObject('files', 'file64')
->setMessage('very beautiful, I am impressed!')
->setVerb('comment');
@@ -398,8 +398,8 @@ class Test_Comments_Manager extends TestCase
$manager = $this->getManager();
$comment = new \OC\Comments\Comment();
$comment
- ->setActor('user', 'alice')
- ->setObject('file', 'file64')
+ ->setActor('users', 'alice')
+ ->setObject('files', 'file64')
->setMessage('very beautiful, I am impressed!')
->setVerb('comment');
@@ -428,8 +428,8 @@ class Test_Comments_Manager extends TestCase
for($i = 0; $i < 3; $i++) {
$comment = new \OC\Comments\Comment();
$comment
- ->setActor('user', 'alice')
- ->setObject('file', 'file64')
+ ->setActor('users', 'alice')
+ ->setObject('files', 'file64')
->setParentId(strval($id))
->setMessage('full ack')
->setVerb('comment')
@@ -450,7 +450,7 @@ class Test_Comments_Manager extends TestCase
[
['', ''],
[1, 'alice'],
- ['user', 1],
+ ['users', 1],
];
}
@@ -473,10 +473,10 @@ class Test_Comments_Manager extends TestCase
// just to make sure they are really set, with correct actor data
$comment = $manager->get(strval($ids[1]));
- $this->assertSame($comment->getActorType(), 'user');
+ $this->assertSame($comment->getActorType(), 'users');
$this->assertSame($comment->getActorId(), 'alice');
- $wasSuccessful = $manager->deleteReferencesOfActor('user', 'alice');
+ $wasSuccessful = $manager->deleteReferencesOfActor('users', 'alice');
$this->assertTrue($wasSuccessful);
foreach($ids as $id) {
@@ -487,7 +487,7 @@ class Test_Comments_Manager extends TestCase
// actor info is gone from DB, but when database interaction is alright,
// we still expect to get true back
- $wasSuccessful = $manager->deleteReferencesOfActor('user', 'alice');
+ $wasSuccessful = $manager->deleteReferencesOfActor('users', 'alice');
$this->assertTrue($wasSuccessful);
}
@@ -496,7 +496,7 @@ class Test_Comments_Manager extends TestCase
$this->assertTrue($user instanceof \OCP\IUser);
$manager = \OC::$server->getCommentsManager();
- $comment = $manager->create('user', $user->getUID(), 'file', 'file64');
+ $comment = $manager->create('users', $user->getUID(), 'files', 'file64');
$comment
->setMessage('Most important comment I ever left on the Internet.')
->setVerb('comment');
@@ -516,7 +516,7 @@ class Test_Comments_Manager extends TestCase
[
['', ''],
[1, 'file64'],
- ['file', 1],
+ ['files', 1],
];
}
@@ -539,10 +539,10 @@ class Test_Comments_Manager extends TestCase
// just to make sure they are really set, with correct actor data
$comment = $manager->get(strval($ids[1]));
- $this->assertSame($comment->getObjectType(), 'file');
+ $this->assertSame($comment->getObjectType(), 'files');
$this->assertSame($comment->getObjectId(), 'file64');
- $wasSuccessful = $manager->deleteCommentsAtObject('file', 'file64');
+ $wasSuccessful = $manager->deleteCommentsAtObject('files', 'file64');
$this->assertTrue($wasSuccessful);
$verified = 0;
@@ -557,7 +557,7 @@ class Test_Comments_Manager extends TestCase
// actor info is gone from DB, but when database interaction is alright,
// we still expect to get true back
- $wasSuccessful = $manager->deleteCommentsAtObject('file', 'file64');
+ $wasSuccessful = $manager->deleteCommentsAtObject('files', 'file64');
$this->assertTrue($wasSuccessful);
}
diff --git a/tests/lib/db/querybuilder/expressionbuildertest.php b/tests/lib/db/querybuilder/expressionbuildertest.php
index 8310c4adf68..f38faab9169 100644
--- a/tests/lib/db/querybuilder/expressionbuildertest.php
+++ b/tests/lib/db/querybuilder/expressionbuildertest.php
@@ -22,7 +22,7 @@
namespace Test\DB\QueryBuilder;
use Doctrine\DBAL\Query\Expression\ExpressionBuilder as DoctrineExpressionBuilder;
-use OC\DB\QueryBuilder\ExpressionBuilder;
+use OC\DB\QueryBuilder\ExpressionBuilder\ExpressionBuilder;
use OCP\DB\QueryBuilder\IQueryBuilder;
use Test\TestCase;
diff --git a/tests/lib/files/storage/home.php b/tests/lib/files/storage/home.php
index 7e10f09d554..1ed3b137cd4 100644
--- a/tests/lib/files/storage/home.php
+++ b/tests/lib/files/storage/home.php
@@ -82,18 +82,6 @@ class Home extends Storage {
}
/**
- * Tests that the root path matches the data dir
- */
- public function testRoot() {
- if (\OC_Util::runningOnWindows()) {
- // Windows removes trailing slashes when returning paths
- $this->assertEquals(rtrim($this->tmpDir, '/'), $this->instance->getLocalFolder(''));
- } else {
- $this->assertEquals($this->tmpDir, $this->instance->getLocalFolder(''));
- }
- }
-
- /**
* Tests that the home id is in the format home::user1
*/
public function testId() {
diff --git a/tests/lib/files/storage/storage.php b/tests/lib/files/storage/storage.php
index 95dd70bfdac..42bd491df5c 100644
--- a/tests/lib/files/storage/storage.php
+++ b/tests/lib/files/storage/storage.php
@@ -262,9 +262,6 @@ abstract class Storage extends \Test\TestCase {
$this->instance->file_put_contents('/folder/bar.txt', 'asd');
$this->instance->mkdir('/folder/recursive');
$this->instance->file_put_contents('/folder/recursive/file.txt', 'foo');
- $localFolder = $this->instance->getLocalFolder('/folder');
-
- $this->assertTrue(is_dir($localFolder));
// test below require to use instance->getLocalFile because the physical storage might be different
$localFile = $this->instance->getLocalFile('/folder/lorem.txt');
diff --git a/tests/lib/integritycheck/checkertest.php b/tests/lib/integritycheck/checkertest.php
index dec3ea84a64..fac60b0c123 100644
--- a/tests/lib/integritycheck/checkertest.php
+++ b/tests/lib/integritycheck/checkertest.php
@@ -465,7 +465,7 @@ class CheckerTest extends TestCase {
$rsa->loadKey($rsaPrivateKey);
$x509 = new X509();
$x509->loadX509($keyBundle);
- $this->checker->writeCoreSignature($x509, $rsa);
+ $this->checker->writeCoreSignature($x509, $rsa, \OC::$SERVERROOT . '/tests/data/integritycheck/app/');
}
public function testWriteCoreSignatureWithUnmodifiedHtaccess() {
@@ -495,7 +495,7 @@ class CheckerTest extends TestCase {
$rsa->loadKey($rsaPrivateKey);
$x509 = new X509();
$x509->loadX509($keyBundle);
- $this->checker->writeCoreSignature($x509, $rsa);
+ $this->checker->writeCoreSignature($x509, $rsa, \OC::$SERVERROOT . '/tests/data/integritycheck/htaccessUnmodified/');
}
public function testWriteCoreSignatureWithInvalidModifiedHtaccess() {
@@ -506,10 +506,6 @@ class CheckerTest extends TestCase {
"signature": "qpDddYGgAKNR3TszOgjPXRphUl2P9Ym5OQaetltocgZASGDkOun5D64+1D0QJRKb4SG2+48muxGOHyL2Ngos4NUrrSR+SIkywZacay82YQBCEdr7\/4MjW1WHRPjvboLwEJwViw0EdAjsWRpD68aPnzUGrGsy2BsCo06P5iwjk9cXcHxdjC9R39npvoC3QNvQ2jmNIbh1Lc4U97dbb+CsXEQCLU1OSa9p3q6cEFV98Easwt7uF\/DzHK+CbeZlxVZ0DwLh2\/ylT1PyGou8QC1b3vKAnPjLWMO+UsCPpCKhk3C5pV+5etQ8puGd+0x2t5tEU+qXxLzek91zWNC+rqgC\/WlqLKbwPb\/BCHs4zLGV55Q2fEQmT21x0KCUELdPs4dBnYP4Ox5tEDugtJujWFzOHzoY6gGa\/BY\/78pSZXmq9o8dWkBEtioWWvaNZ1rM0ddE83GBlBTgjigi9Ay1D++bUW\/FCBB7CMk6qyNlV81H+cBuIEODw2aymmkM9LLDD2Qbmvo8gHEPRjiQxPC5OpDlcdSNiL+zcxVxeuX4FpT+9xzz\/\/DRONhufxRpsbuCOMxd96RW7y9U2N2Uxb3Bzn\/BIqEayUUsdgZjfaGcXXYKR+chu\/LOwNYN6RlnLsgqL\/dhGKwlRVKXw1RA2\/af\/CpqyR7uVP6al1YJo\/YJ+5XJ6zE=",
"certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEvjCCAqagAwIBAgIUc\/0FxYrsgSs9rDxp03EJmbjN0NwwDQYJKoZIhvcNAQEF\r\nBQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw\r\nMzIxMDMzM1oXDTE2MTEwMzIxMDMzM1owDzENMAsGA1UEAwwEY29yZTCCAiIwDQYJ\r\nKoZIhvcNAQEBBQADggIPADCCAgoCggIBALb6EgHpkAqZbO5vRO8XSh7G7XGWHw5s\r\niOf4RwPXR6SE9bWZEm\/b72SfWk\/\/J6AbrD8WiOzBuT\/ODy6k5T1arEdHO+Pux0W1\r\nMxYJJI4kH74KKgMpC0SB0Rt+8WrMqV1r3hhJ46df6Xr\/xolP3oD+eLbShPcblhdS\r\nVtkZEkoev8Sh6L2wDCeHDyPxzvj1w2dTdGVO9Kztn0xIlyfEBakqvBWtcxyi3Ln0\r\nklnxlMx3tPDUE4kqvpia9qNiB1AN2PV93eNr5\/2riAzIssMFSCarWCx0AKYb54+d\r\nxLpcYFyqPJ0ydBCkF78DD45RCZet6PNYkdzgbqlUWEGGomkuDoJbBg4wzgzO0D77\r\nH87KFhYW8tKFFvF1V3AHl\/sFQ9tDHaxM9Y0pZ2jPp\/ccdiqnmdkBxBDqsiRvHvVB\r\nCn6qpb4vWGFC7vHOBfYspmEL1zLlKXZv3ezMZEZw7O9ZvUP3VO\/wAtd2vUW8UFiq\r\ns2v1QnNLN6jNh51obcwmrBvWhJy9vQIdtIjQbDxqWTHh1zUSrw9wrlklCBZ\/zrM0\r\ni8nfCFwTxWRxp3H9KoECzO\/zS5R5KIS7s3\/wq\/w9T2Ie4rcecgXwDizwnn0C\/aKc\r\nbDIjujpL1s9HO05pcD\/V3wKcPZ1izymBkmMyIbL52iRVN5FTVHeZdXPpFuq+CTQJ\r\nQ238lC+A\/KOVAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBAGoKTnh8RfJV4sQItVC2\r\nAvfJagkrIqZ3iiQTUBQGTKBsTnAqE1H7QgUSV9vSd+8rgvHkyZsRjmtyR1e3A6Ji\r\noNCXUbExC\/0iCPUqdHZIVb+Lc\/vWuv4ByFMybGPydgtLoEUX2ZrKFWmcgZFDUSRd\r\n9Uj26vtUhCC4bU4jgu6hIrR9IuxOBLQUxGTRZyAcXvj7obqRAEZwFAKQgFpfpqTb\r\nH+kjcbZSaAlLVSF7vBc1syyI8RGYbqpwvtREqJtl5IEIwe6huEqJ3zPnlP2th\/55\r\ncf3Fovj6JJgbb9XFxrdnsOsDOu\/tpnaRWlvv5ib4+SzG5wWFT5UUEo4Wg2STQiiX\r\nuVSRQxK1LE1yg84bs3NZk9FSQh4B8vZVuRr5FaJsZZkwlFlhRO\/\/+TJtXRbyNgsf\r\noMRZGi8DLGU2SGEAHcRH\/QZHq\/XDUWVzdxrSBYcy7GSpT7UDVzGv1rEJUrn5veP1\r\n0KmauAqtiIaYRm4f6YBsn0INcZxzIPZ0p8qFtVZBPeHhvQtvOt0iXI\/XUxEWOa2F\r\nK2EqhErgMK\/N07U1JJJay5tYZRtvkGq46oP\/5kQG8hYST0MDK6VihJoPpvCmAm4E\r\npEYKQ96x6A4EH9Y9mZlYozH\/eqmxPbTK8n89\/p7Ydun4rI+B2iiLnY8REWWy6+UQ\r\nV204fGUkJqW5CrKy3P3XvY9X\r\n-----END CERTIFICATE-----"
}';
- $this->environmentHelper
- ->expects($this->any())
- ->method('getServerRoot')
- ->will($this->returnValue(\OC::$SERVERROOT . '/tests/data/integritycheck/htaccessWithInvalidModifiedContent/'));
$this->fileAccessHelper
->expects($this->once())
->method('file_put_contents')
@@ -524,7 +520,7 @@ class CheckerTest extends TestCase {
$rsa->loadKey($rsaPrivateKey);
$x509 = new X509();
$x509->loadX509($keyBundle);
- $this->checker->writeCoreSignature($x509, $rsa);
+ $this->checker->writeCoreSignature($x509, $rsa, \OC::$SERVERROOT . '/tests/data/integritycheck/htaccessWithInvalidModifiedContent/');
}
public function testWriteCoreSignatureWithValidModifiedHtaccess() {
@@ -554,7 +550,7 @@ class CheckerTest extends TestCase {
$rsa->loadKey($rsaPrivateKey);
$x509 = new X509();
$x509->loadX509($keyBundle);
- $this->checker->writeCoreSignature($x509, $rsa);
+ $this->checker->writeCoreSignature($x509, $rsa, \OC::$SERVERROOT . '/tests/data/integritycheck/htaccessWithValidModifiedContent');
}
public function testVerifyCoreSignatureWithoutSignatureData() {
diff --git a/tests/lib/repair/repairmimetypes.php b/tests/lib/repair/repairmimetypes.php
index 1bdaa9a2dbf..a9ebb7bc88a 100644
--- a/tests/lib/repair/repairmimetypes.php
+++ b/tests/lib/repair/repairmimetypes.php
@@ -347,6 +347,27 @@ class RepairMimeTypes extends \Test\TestCase {
}
/**
+ * Test renaming the richdocuments additional office mime types
+ */
+ public function testRenameRichDocumentsMimeTypes() {
+ $currentMimeTypes = [
+ ['test.lwp', 'application/octet-stream'],
+ ['test.one', 'application/octet-stream'],
+ ['test.vsd', 'application/octet-stream'],
+ ['test.wpd', 'application/octet-stream'],
+ ];
+
+ $fixedMimeTypes = [
+ ['test.lwp', 'application/vnd.lotus-wordpro'],
+ ['test.one', 'application/msonenote'],
+ ['test.vsd', 'application/vnd.visio'],
+ ['test.wpd', 'application/vnd.wordperfect'],
+ ];
+
+ $this->renameMimeTypes($currentMimeTypes, $fixedMimeTypes);
+ }
+
+ /**
* Test renaming and splitting old office mime types when
* new ones already exist
*/
@@ -468,6 +489,10 @@ class RepairMimeTypes extends \Test\TestCase {
['test.hpp', 'text/x-h'],
['test.rss', 'application/rss+xml'],
['test.rtf', 'text/rtf'],
+ ['test.lwp', 'application/vnd.lotus-wordpro'],
+ ['test.one', 'application/msonenote'],
+ ['test.vsd', 'application/vnd.visio'],
+ ['test.wpd', 'application/vnd.wordperfect'],
];
$fixedMimeTypes = [
@@ -512,6 +537,10 @@ class RepairMimeTypes extends \Test\TestCase {
['test.hpp', 'text/x-h'],
['test.rss', 'application/rss+xml'],
['test.rtf', 'text/rtf'],
+ ['test.lwp', 'application/vnd.lotus-wordpro'],
+ ['test.one', 'application/msonenote'],
+ ['test.vsd', 'application/vnd.visio'],
+ ['test.wpd', 'application/vnd.wordperfect'],
];
$this->renameMimeTypes($currentMimeTypes, $fixedMimeTypes);
diff --git a/tests/lib/share/share.php b/tests/lib/share/share.php
index 5162a03f367..4519c33f9d1 100644
--- a/tests/lib/share/share.php
+++ b/tests/lib/share/share.php
@@ -1423,7 +1423,7 @@ class Test_Share extends \Test\TestCase {
$userSession->method('getUser')->willReturn($user);
- $ex = $this->getMockBuilder('\OC\DB\QueryBuilder\ExpressionBuilder')
+ $ex = $this->getMockBuilder('\OC\DB\QueryBuilder\ExpressionBuilder\ExpressionBuilder')
->disableOriginalConstructor()
->getMock();
$qb = $this->getMockBuilder('\OC\DB\QueryBuilder\QueryBuilder')
@@ -1478,7 +1478,7 @@ class Test_Share extends \Test\TestCase {
$userSession->method('getUser')->willReturn($user);
- $ex = $this->getMockBuilder('\OC\DB\QueryBuilder\ExpressionBuilder')
+ $ex = $this->getMockBuilder('\OC\DB\QueryBuilder\ExpressionBuilder\ExpressionBuilder')
->disableOriginalConstructor()
->getMock();
$qb = $this->getMockBuilder('\OC\DB\QueryBuilder\QueryBuilder')
@@ -1531,7 +1531,7 @@ class Test_Share extends \Test\TestCase {
$userSession->method('getUser')->willReturn($user);
- $ex = $this->getMockBuilder('\OC\DB\QueryBuilder\ExpressionBuilder')
+ $ex = $this->getMockBuilder('\OC\DB\QueryBuilder\ExpressionBuilder\ExpressionBuilder')
->disableOriginalConstructor()
->getMock();
$qb = $this->getMockBuilder('\OC\DB\QueryBuilder\QueryBuilder')
@@ -1584,7 +1584,7 @@ class Test_Share extends \Test\TestCase {
$userSession->method('getUser')->willReturn($user);
- $ex = $this->getMockBuilder('\OC\DB\QueryBuilder\ExpressionBuilder')
+ $ex = $this->getMockBuilder('\OC\DB\QueryBuilder\ExpressionBuilder\ExpressionBuilder')
->disableOriginalConstructor()
->getMock();
$qb = $this->getMockBuilder('\OC\DB\QueryBuilder\QueryBuilder')
diff --git a/tests/lib/share20/defaultshareprovidertest.php b/tests/lib/share20/defaultshareprovidertest.php
index 504bd776036..60024989681 100644
--- a/tests/lib/share20/defaultshareprovidertest.php
+++ b/tests/lib/share20/defaultshareprovidertest.php
@@ -110,7 +110,7 @@ class DefaultShareProviderTest extends \Test\TestCase {
/**
- * @expectedException \OC\Share20\Exception\ShareNotFound
+ * @expectedException \OCP\Share\Exceptions\ShareNotFound
*/
public function testGetShareByIdNotExist() {
$this->provider->getShareById(1);
@@ -157,21 +157,92 @@ class DefaultShareProviderTest extends \Test\TestCase {
['shareOwner', $shareOwnerFolder],
]));
- $this->userManager
- ->method('get')
- ->will($this->returnValueMap([
- ['sharedWith', $sharedWith],
- ['sharedBy', $sharedBy],
- ['shareOwner', $shareOwner],
- ]));
+ $share = $this->provider->getShareById($id);
+
+ $this->assertEquals($id, $share->getId());
+ $this->assertEquals(\OCP\Share::SHARE_TYPE_USER, $share->getShareType());
+ $this->assertEquals('sharedWith', $share->getSharedWith());
+ $this->assertEquals('sharedBy', $share->getSharedBy());
+ $this->assertEquals('shareOwner', $share->getShareOwner());
+ $this->assertEquals($ownerPath, $share->getNode());
+ $this->assertEquals(13, $share->getPermissions());
+ $this->assertEquals(null, $share->getToken());
+ $this->assertEquals(null, $share->getExpirationDate());
+ $this->assertEquals('myTarget', $share->getTarget());
+ }
+
+ public function testGetShareByIdLazy() {
+ $qb = $this->dbConn->getQueryBuilder();
+
+ $qb->insert('share')
+ ->values([
+ 'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_USER),
+ 'share_with' => $qb->expr()->literal('sharedWith'),
+ 'uid_owner' => $qb->expr()->literal('shareOwner'),
+ 'uid_initiator' => $qb->expr()->literal('sharedBy'),
+ 'item_type' => $qb->expr()->literal('file'),
+ 'file_source' => $qb->expr()->literal(42),
+ 'file_target' => $qb->expr()->literal('myTarget'),
+ 'permissions' => $qb->expr()->literal(13),
+ ]);
+ $qb->execute();
+
+ $id = $qb->getLastInsertId();
+
+ $this->rootFolder->expects($this->never())->method('getUserFolder');
$share = $this->provider->getShareById($id);
+ // We do not fetch the node so the rootfolder is never called.
+
$this->assertEquals($id, $share->getId());
$this->assertEquals(\OCP\Share::SHARE_TYPE_USER, $share->getShareType());
- $this->assertEquals($sharedWith, $share->getSharedWith());
- $this->assertEquals($sharedBy, $share->getSharedBy());
- $this->assertEquals($shareOwner, $share->getShareOwner());
+ $this->assertEquals('sharedWith', $share->getSharedWith());
+ $this->assertEquals('sharedBy', $share->getSharedBy());
+ $this->assertEquals('shareOwner', $share->getShareOwner());
+ $this->assertEquals(13, $share->getPermissions());
+ $this->assertEquals(null, $share->getToken());
+ $this->assertEquals(null, $share->getExpirationDate());
+ $this->assertEquals('myTarget', $share->getTarget());
+ }
+
+ public function testGetShareByIdLazy2() {
+ $qb = $this->dbConn->getQueryBuilder();
+
+ $qb->insert('share')
+ ->values([
+ 'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_USER),
+ 'share_with' => $qb->expr()->literal('sharedWith'),
+ 'uid_owner' => $qb->expr()->literal('shareOwner'),
+ 'uid_initiator' => $qb->expr()->literal('sharedBy'),
+ 'item_type' => $qb->expr()->literal('file'),
+ 'file_source' => $qb->expr()->literal(42),
+ 'file_target' => $qb->expr()->literal('myTarget'),
+ 'permissions' => $qb->expr()->literal(13),
+ ]);
+ $qb->execute();
+
+ $id = $qb->getLastInsertId();
+
+ $ownerPath = $this->getMock('\OCP\Files\File');
+
+ $shareOwnerFolder = $this->getMock('\OCP\Files\Folder');
+ $shareOwnerFolder->method('getById')->with(42)->willReturn([$ownerPath]);
+
+ $this->rootFolder
+ ->method('getUserFolder')
+ ->with('shareOwner')
+ ->willReturn($shareOwnerFolder);
+
+ $share = $this->provider->getShareById($id);
+
+ // We fetch the node so the root folder is eventually called
+
+ $this->assertEquals($id, $share->getId());
+ $this->assertEquals(\OCP\Share::SHARE_TYPE_USER, $share->getShareType());
+ $this->assertEquals('sharedWith', $share->getSharedWith());
+ $this->assertEquals('sharedBy', $share->getSharedBy());
+ $this->assertEquals('shareOwner', $share->getShareOwner());
$this->assertEquals($ownerPath, $share->getNode());
$this->assertEquals(13, $share->getPermissions());
$this->assertEquals(null, $share->getToken());
@@ -221,25 +292,13 @@ class DefaultShareProviderTest extends \Test\TestCase {
['shareOwner', $shareOwnerFolder],
]));
- $this->userManager
- ->method('get')
- ->will($this->returnValueMap([
- ['sharedBy', $sharedBy],
- ['shareOwner', $shareOwner],
- ]));
- $this->groupManager
- ->expects($this->once())
- ->method('get')
- ->with('sharedWith')
- ->willReturn($sharedWith);
-
$share = $this->provider->getShareById($id);
$this->assertEquals($id, $share->getId());
$this->assertEquals(\OCP\Share::SHARE_TYPE_GROUP, $share->getShareType());
- $this->assertEquals($sharedWith, $share->getSharedWith());
- $this->assertEquals($sharedBy, $share->getSharedBy());
- $this->assertEquals($shareOwner, $share->getShareOwner());
+ $this->assertEquals('sharedWith', $share->getSharedWith());
+ $this->assertEquals('sharedBy', $share->getSharedBy());
+ $this->assertEquals('shareOwner', $share->getShareOwner());
$this->assertEquals($ownerPath, $share->getNode());
$this->assertEquals(13, $share->getPermissions());
$this->assertEquals(null, $share->getToken());
@@ -271,13 +330,13 @@ class DefaultShareProviderTest extends \Test\TestCase {
]));
$this->groupManager->method('get')->with('group0')->willReturn($group0);
- $share = $this->provider->getShareById($id, $user1);
+ $share = $this->provider->getShareById($id, 'user1');
$this->assertEquals($id, $share->getId());
$this->assertEquals(\OCP\Share::SHARE_TYPE_GROUP, $share->getShareType());
- $this->assertSame($group0, $share->getSharedWith());
- $this->assertSame($user0, $share->getSharedBy());
- $this->assertSame($user0, $share->getShareOwner());
+ $this->assertSame('group0', $share->getSharedWith());
+ $this->assertSame('user0', $share->getSharedBy());
+ $this->assertSame('user0', $share->getShareOwner());
$this->assertSame($node, $share->getNode());
$this->assertEquals(0, $share->getPermissions());
$this->assertEquals(null, $share->getToken());
@@ -339,8 +398,8 @@ class DefaultShareProviderTest extends \Test\TestCase {
$this->assertEquals($id, $share->getId());
$this->assertEquals(\OCP\Share::SHARE_TYPE_LINK, $share->getShareType());
$this->assertEquals('sharedWith', $share->getPassword());
- $this->assertEquals($sharedBy, $share->getSharedBy());
- $this->assertEquals($shareOwner, $share->getShareOwner());
+ $this->assertEquals('sharedBy', $share->getSharedBy());
+ $this->assertEquals('shareOwner', $share->getShareOwner());
$this->assertEquals($ownerPath, $share->getNode());
$this->assertEquals(13, $share->getPermissions());
$this->assertEquals('token', $share->getToken());
@@ -390,6 +449,39 @@ class DefaultShareProviderTest extends \Test\TestCase {
$this->assertEmpty($result);
}
+ public function testDeleteSingleShareLazy() {
+ $qb = $this->dbConn->getQueryBuilder();
+ $qb->insert('share')
+ ->values([
+ 'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_USER),
+ 'share_with' => $qb->expr()->literal('sharedWith'),
+ 'uid_owner' => $qb->expr()->literal('shareOwner'),
+ 'uid_initiator' => $qb->expr()->literal('sharedBy'),
+ 'item_type' => $qb->expr()->literal('file'),
+ 'file_source' => $qb->expr()->literal(42),
+ 'file_target' => $qb->expr()->literal('myTarget'),
+ 'permissions' => $qb->expr()->literal(13),
+ ]);
+ $this->assertEquals(1, $qb->execute());
+
+ $id = $qb->getLastInsertId();
+
+ $this->rootFolder->expects($this->never())->method($this->anything());
+
+ $share = $this->provider->getShareById($id);
+ $this->provider->delete($share);
+
+ $qb = $this->dbConn->getQueryBuilder();
+ $qb->select('*')
+ ->from('share');
+
+ $cursor = $qb->execute();
+ $result = $cursor->fetchAll();
+ $cursor->closeCursor();
+
+ $this->assertEmpty($result);
+ }
+
public function testDeleteGroupShareWithUserGroupShares() {
$qb = $this->dbConn->getQueryBuilder();
$qb->insert('share')
@@ -559,9 +651,9 @@ class DefaultShareProviderTest extends \Test\TestCase {
//Child1
$this->assertEquals(\OCP\Share::SHARE_TYPE_USER, $children[0]->getShareType());
- $this->assertEquals($user1, $children[0]->getSharedWith());
- $this->assertEquals($user2, $children[0]->getSharedBy());
- $this->assertEquals($shareOwner, $children[0]->getShareOwner());
+ $this->assertEquals('user1', $children[0]->getSharedWith());
+ $this->assertEquals('user2', $children[0]->getSharedBy());
+ $this->assertEquals('shareOwner', $children[0]->getShareOwner());
$this->assertEquals($ownerPath, $children[0]->getNode());
$this->assertEquals(2, $children[0]->getPermissions());
$this->assertEquals(null, $children[0]->getToken());
@@ -570,9 +662,9 @@ class DefaultShareProviderTest extends \Test\TestCase {
//Child2
$this->assertEquals(\OCP\Share::SHARE_TYPE_GROUP, $children[1]->getShareType());
- $this->assertEquals($group1, $children[1]->getSharedWith());
- $this->assertEquals($user3, $children[1]->getSharedBy());
- $this->assertEquals($shareOwner, $children[1]->getShareOwner());
+ $this->assertEquals('group1', $children[1]->getSharedWith());
+ $this->assertEquals('user3', $children[1]->getSharedBy());
+ $this->assertEquals('shareOwner', $children[1]->getShareOwner());
$this->assertEquals($ownerPath, $children[1]->getNode());
$this->assertEquals(4, $children[1]->getPermissions());
$this->assertEquals(null, $children[1]->getToken());
@@ -581,23 +673,11 @@ class DefaultShareProviderTest extends \Test\TestCase {
}
public function testCreateUserShare() {
- $share = new \OC\Share20\Share();
+ $share = new \OC\Share20\Share($this->rootFolder);
- $sharedWith = $this->getMock('OCP\IUser');
- $sharedWith->method('getUID')->willReturn('sharedWith');
- $sharedBy = $this->getMock('OCP\IUser');
- $sharedBy->method('getUID')->willReturn('sharedBy');
$shareOwner = $this->getMock('OCP\IUser');
$shareOwner->method('getUID')->WillReturn('shareOwner');
- $this->userManager
- ->method('get')
- ->will($this->returnValueMap([
- ['sharedWith', $sharedWith],
- ['sharedBy', $sharedBy],
- ['shareOwner', $shareOwner],
- ]));
-
$path = $this->getMock('\OCP\Files\File');
$path->method('getId')->willReturn(100);
$path->method('getOwner')->willReturn($shareOwner);
@@ -619,9 +699,9 @@ class DefaultShareProviderTest extends \Test\TestCase {
->willReturn([$path]);
$share->setShareType(\OCP\Share::SHARE_TYPE_USER);
- $share->setSharedWith($sharedWith);
- $share->setSharedBy($sharedBy);
- $share->setShareOwner($shareOwner);
+ $share->setSharedWith('sharedWith');
+ $share->setSharedBy('sharedBy');
+ $share->setShareOwner('shareOwner');
$share->setNode($path);
$share->setPermissions(1);
$share->setTarget('/target');
@@ -631,9 +711,9 @@ class DefaultShareProviderTest extends \Test\TestCase {
$this->assertNotNull($share2->getId());
$this->assertSame('ocinternal:'.$share2->getId(), $share2->getFullId());
$this->assertSame(\OCP\Share::SHARE_TYPE_USER, $share2->getShareType());
- $this->assertSame($sharedWith, $share2->getSharedWith());
- $this->assertSame($sharedBy, $share2->getSharedBy());
- $this->assertSame($shareOwner, $share2->getShareOwner());
+ $this->assertSame('sharedWith', $share2->getSharedWith());
+ $this->assertSame('sharedBy', $share2->getSharedBy());
+ $this->assertSame('shareOwner', $share2->getShareOwner());
$this->assertSame(1, $share2->getPermissions());
$this->assertSame('/target', $share2->getTarget());
$this->assertLessThanOrEqual(new \DateTime(), $share2->getShareTime());
@@ -641,25 +721,10 @@ class DefaultShareProviderTest extends \Test\TestCase {
}
public function testCreateGroupShare() {
- $share = new \OC\Share20\Share();
+ $share = new \OC\Share20\Share($this->rootFolder);
- $sharedWith = $this->getMock('OCP\IGroup');
- $sharedWith->method('getGID')->willReturn('sharedWith');
- $sharedBy = $this->getMock('OCP\IUser');
- $sharedBy->method('getUID')->willReturn('sharedBy');
- $shareOwner = $this->getMock('OCP\IUser');
- $shareOwner->method('getUID')->WillReturn('shareOwner');
-
- $this->userManager
- ->method('get')
- ->will($this->returnValueMap([
- ['sharedBy', $sharedBy],
- ['shareOwner', $shareOwner],
- ]));
- $this->groupManager
- ->method('get')
- ->with('sharedWith')
- ->willReturn($sharedWith);
+ $shareOwner = $this->getMock('\OCP\IUser');
+ $shareOwner->method('getUID')->willReturn('shareOwner');
$path = $this->getMock('\OCP\Files\Folder');
$path->method('getId')->willReturn(100);
@@ -682,9 +747,9 @@ class DefaultShareProviderTest extends \Test\TestCase {
->willReturn([$path]);
$share->setShareType(\OCP\Share::SHARE_TYPE_GROUP);
- $share->setSharedWith($sharedWith);
- $share->setSharedBy($sharedBy);
- $share->setShareOwner($shareOwner);
+ $share->setSharedWith('sharedWith');
+ $share->setSharedBy('sharedBy');
+ $share->setShareOwner('shareOwner');
$share->setNode($path);
$share->setPermissions(1);
$share->setTarget('/target');
@@ -694,9 +759,9 @@ class DefaultShareProviderTest extends \Test\TestCase {
$this->assertNotNull($share2->getId());
$this->assertSame('ocinternal:'.$share2->getId(), $share2->getFullId());
$this->assertSame(\OCP\Share::SHARE_TYPE_GROUP, $share2->getShareType());
- $this->assertSame($sharedWith, $share2->getSharedWith());
- $this->assertSame($sharedBy, $share2->getSharedBy());
- $this->assertSame($shareOwner, $share2->getShareOwner());
+ $this->assertSame('sharedWith', $share2->getSharedWith());
+ $this->assertSame('sharedBy', $share2->getSharedBy());
+ $this->assertSame('shareOwner', $share2->getShareOwner());
$this->assertSame(1, $share2->getPermissions());
$this->assertSame('/target', $share2->getTarget());
$this->assertLessThanOrEqual(new \DateTime(), $share2->getShareTime());
@@ -704,19 +769,10 @@ class DefaultShareProviderTest extends \Test\TestCase {
}
public function testCreateLinkShare() {
- $share = new \OC\Share20\Share();
+ $share = new \OC\Share20\Share($this->rootFolder);
- $sharedBy = $this->getMock('OCP\IUser');
- $sharedBy->method('getUID')->willReturn('sharedBy');
- $shareOwner = $this->getMock('OCP\IUser');
- $shareOwner->method('getUID')->WillReturn('shareOwner');
-
- $this->userManager
- ->method('get')
- ->will($this->returnValueMap([
- ['sharedBy', $sharedBy],
- ['shareOwner', $shareOwner],
- ]));
+ $shareOwner = $this->getMock('\OCP\IUser');
+ $shareOwner->method('getUID')->willReturn('shareOwner');
$path = $this->getMock('\OCP\Files\Folder');
$path->method('getId')->willReturn(100);
@@ -739,8 +795,8 @@ class DefaultShareProviderTest extends \Test\TestCase {
->willReturn([$path]);
$share->setShareType(\OCP\Share::SHARE_TYPE_LINK);
- $share->setSharedBy($sharedBy);
- $share->setShareOwner($shareOwner);
+ $share->setSharedBy('sharedBy');
+ $share->setShareOwner('shareOwner');
$share->setNode($path);
$share->setPermissions(1);
$share->setPassword('password');
@@ -754,8 +810,8 @@ class DefaultShareProviderTest extends \Test\TestCase {
$this->assertNotNull($share2->getId());
$this->assertSame('ocinternal:'.$share2->getId(), $share2->getFullId());
$this->assertSame(\OCP\Share::SHARE_TYPE_LINK, $share2->getShareType());
- $this->assertSame($sharedBy, $share2->getSharedBy());
- $this->assertSame($shareOwner, $share2->getShareOwner());
+ $this->assertSame('sharedBy', $share2->getSharedBy());
+ $this->assertSame('shareOwner', $share2->getShareOwner());
$this->assertSame(1, $share2->getPermissions());
$this->assertSame('/target', $share2->getTarget());
$this->assertLessThanOrEqual(new \DateTime(), $share2->getShareTime());
@@ -783,17 +839,6 @@ class DefaultShareProviderTest extends \Test\TestCase {
$qb->execute();
$id = $qb->getLastInsertId();
- $owner = $this->getMock('\OCP\IUser');
- $owner->method('getUID')->willReturn('shareOwner');
- $initiator = $this->getMock('\OCP\IUser');
- $initiator->method('getUID')->willReturn('sharedBy');
-
- $this->userManager->method('get')
- ->will($this->returnValueMap([
- ['sharedBy', $initiator],
- ['shareOwner', $owner],
- ]));
-
$file = $this->getMock('\OCP\Files\File');
$this->rootFolder->method('getUserFolder')->with('shareOwner')->will($this->returnSelf());
@@ -801,15 +846,15 @@ class DefaultShareProviderTest extends \Test\TestCase {
$share = $this->provider->getShareByToken('secrettoken');
$this->assertEquals($id, $share->getId());
- $this->assertSame($owner, $share->getShareOwner());
- $this->assertSame($initiator, $share->getSharedBy());
+ $this->assertSame('shareOwner', $share->getShareOwner());
+ $this->assertSame('sharedBy', $share->getSharedBy());
$this->assertSame('secrettoken', $share->getToken());
$this->assertSame('password', $share->getPassword());
$this->assertSame(null, $share->getSharedWith());
}
/**
- * @expectedException \OC\Share20\Exception\ShareNotFound
+ * @expectedException \OCP\Share\Exceptions\ShareNotFound
*/
public function testGetShareByTokenNotFound() {
$this->provider->getShareByToken('invalidtoken');
@@ -845,31 +890,18 @@ class DefaultShareProviderTest extends \Test\TestCase {
]);
$this->assertEquals(1, $qb->execute());
- $user = $this->getMock('\OCP\IUser');
- $user->method('getUID')->willReturn('sharedWith');
- $owner = $this->getMock('\OCP\IUser');
- $owner->method('getUID')->willReturn('shareOwner');
- $initiator = $this->getMock('\OCP\IUser');
- $initiator->method('getUID')->willReturn('sharedBy');
-
- $this->userManager->method('get')->willReturnMap([
- ['sharedWith', $user],
- ['shareOwner', $owner],
- ['sharedBy', $initiator],
- ]);
-
$file = $this->getMock('\OCP\Files\File');
$this->rootFolder->method('getUserFolder')->with('shareOwner')->will($this->returnSelf());
$this->rootFolder->method('getById')->with(42)->willReturn([$file]);
- $share = $this->provider->getSharedWith($user, \OCP\Share::SHARE_TYPE_USER, null, 1 , 0);
+ $share = $this->provider->getSharedWith('sharedWith', \OCP\Share::SHARE_TYPE_USER, null, 1 , 0);
$this->assertCount(1, $share);
$share = $share[0];
$this->assertEquals($id, $share->getId());
- $this->assertEquals($user, $share->getSharedWith());
- $this->assertEquals($owner, $share->getShareOwner());
- $this->assertEquals($initiator, $share->getSharedBy());
+ $this->assertEquals('sharedWith', $share->getSharedWith());
+ $this->assertEquals('shareOwner', $share->getShareOwner());
+ $this->assertEquals('sharedBy', $share->getSharedBy());
$this->assertEquals(\OCP\Share::SHARE_TYPE_USER, $share->getShareType());
}
@@ -922,6 +954,7 @@ class DefaultShareProviderTest extends \Test\TestCase {
$initiator->method('getUID')->willReturn('sharedBy');
$this->userManager->method('get')->willReturnMap([
+ ['sharedWith', $user],
['shareOwner', $owner],
['sharedBy', $initiator],
]);
@@ -932,14 +965,14 @@ class DefaultShareProviderTest extends \Test\TestCase {
$this->rootFolder->method('getUserFolder')->with('shareOwner')->will($this->returnSelf());
$this->rootFolder->method('getById')->with(42)->willReturn([$file]);
- $share = $this->provider->getSharedWith($user, \OCP\Share::SHARE_TYPE_GROUP, null, 20 , 1);
+ $share = $this->provider->getSharedWith('sharedWith', \OCP\Share::SHARE_TYPE_GROUP, null, 20 , 1);
$this->assertCount(1, $share);
$share = $share[0];
$this->assertEquals($id, $share->getId());
- $this->assertEquals($group, $share->getSharedWith());
- $this->assertEquals($owner, $share->getShareOwner());
- $this->assertEquals($initiator, $share->getSharedBy());
+ $this->assertEquals('sharedWith', $share->getSharedWith());
+ $this->assertEquals('shareOwner', $share->getShareOwner());
+ $this->assertEquals('sharedBy', $share->getSharedBy());
$this->assertEquals(\OCP\Share::SHARE_TYPE_GROUP, $share->getShareType());
}
@@ -1007,6 +1040,7 @@ class DefaultShareProviderTest extends \Test\TestCase {
$initiator->method('getUID')->willReturn('sharedBy');
$this->userManager->method('get')->willReturnMap([
+ ['user', $user],
['shareOwner', $owner],
['sharedBy', $initiator],
]);
@@ -1017,14 +1051,14 @@ class DefaultShareProviderTest extends \Test\TestCase {
$this->rootFolder->method('getUserFolder')->with('shareOwner')->will($this->returnSelf());
$this->rootFolder->method('getById')->with(42)->willReturn([$file]);
- $share = $this->provider->getSharedWith($user, \OCP\Share::SHARE_TYPE_GROUP, null, -1, 0);
+ $share = $this->provider->getSharedWith('user', \OCP\Share::SHARE_TYPE_GROUP, null, -1, 0);
$this->assertCount(1, $share);
$share = $share[0];
$this->assertSame($id, $share->getId());
- $this->assertSame($group, $share->getSharedWith());
- $this->assertSame($owner, $share->getShareOwner());
- $this->assertSame($initiator, $share->getSharedBy());
+ $this->assertSame('sharedWith', $share->getSharedWith());
+ $this->assertSame('shareOwner', $share->getShareOwner());
+ $this->assertSame('sharedBy', $share->getSharedBy());
$this->assertSame(\OCP\Share::SHARE_TYPE_GROUP, $share->getShareType());
$this->assertSame(0, $share->getPermissions());
$this->assertSame('userTarget', $share->getTarget());
@@ -1051,14 +1085,14 @@ class DefaultShareProviderTest extends \Test\TestCase {
$this->rootFolder->method('getUserFolder')->with('user1')->will($this->returnSelf());
$this->rootFolder->method('getById')->with(43)->willReturn([$file]);
- $share = $this->provider->getSharedWith($user0, \OCP\Share::SHARE_TYPE_USER, $file, -1, 0);
+ $share = $this->provider->getSharedWith('user0', \OCP\Share::SHARE_TYPE_USER, $file, -1, 0);
$this->assertCount(1, $share);
$share = $share[0];
$this->assertEquals($id, $share->getId());
- $this->assertSame($user0, $share->getSharedWith());
- $this->assertSame($user1, $share->getShareOwner());
- $this->assertSame($user1, $share->getSharedBy());
+ $this->assertSame('user0', $share->getSharedWith());
+ $this->assertSame('user1', $share->getShareOwner());
+ $this->assertSame('user1', $share->getSharedBy());
$this->assertSame($file, $share->getNode());
$this->assertEquals(\OCP\Share::SHARE_TYPE_USER, $share->getShareType());
}
@@ -1090,14 +1124,14 @@ class DefaultShareProviderTest extends \Test\TestCase {
$this->rootFolder->method('getUserFolder')->with('user1')->will($this->returnSelf());
$this->rootFolder->method('getById')->with(43)->willReturn([$node]);
- $share = $this->provider->getSharedWith($user0, \OCP\Share::SHARE_TYPE_GROUP, $node, -1, 0);
+ $share = $this->provider->getSharedWith('user0', \OCP\Share::SHARE_TYPE_GROUP, $node, -1, 0);
$this->assertCount(1, $share);
$share = $share[0];
$this->assertEquals($id, $share->getId());
- $this->assertSame($group0, $share->getSharedWith());
- $this->assertSame($user1, $share->getShareOwner());
- $this->assertSame($user1, $share->getSharedBy());
+ $this->assertSame('group0', $share->getSharedWith());
+ $this->assertSame('user1', $share->getShareOwner());
+ $this->assertSame('user1', $share->getSharedBy());
$this->assertSame($node, $share->getNode());
$this->assertEquals(\OCP\Share::SHARE_TYPE_GROUP, $share->getShareType());
}
@@ -1133,31 +1167,18 @@ class DefaultShareProviderTest extends \Test\TestCase {
]);
$this->assertEquals(1, $qb->execute());
- $user = $this->getMock('\OCP\IUser');
- $user->method('getUID')->willReturn('sharedWith');
- $owner = $this->getMock('\OCP\IUser');
- $owner->method('getUID')->willReturn('shareOwner');
- $initiator = $this->getMock('\OCP\IUser');
- $initiator->method('getUID')->willReturn('sharedBy');
-
- $this->userManager->method('get')->willReturnMap([
- ['sharedWith', $user],
- ['shareOwner', $owner],
- ['sharedBy', $initiator],
- ]);
-
$file = $this->getMock('\OCP\Files\File');
$this->rootFolder->method('getUserFolder')->with('shareOwner')->will($this->returnSelf());
$this->rootFolder->method('getById')->with(42)->willReturn([$file]);
- $share = $this->provider->getSharesBy($initiator, \OCP\Share::SHARE_TYPE_USER, null, false, 1, 0);
+ $share = $this->provider->getSharesBy('sharedBy', \OCP\Share::SHARE_TYPE_USER, null, false, 1, 0);
$this->assertCount(1, $share);
$share = $share[0];
$this->assertEquals($id, $share->getId());
- $this->assertEquals($user, $share->getSharedWith());
- $this->assertEquals($owner, $share->getShareOwner());
- $this->assertEquals($initiator, $share->getSharedBy());
+ $this->assertEquals('sharedWith', $share->getSharedWith());
+ $this->assertEquals('shareOwner', $share->getShareOwner());
+ $this->assertEquals('sharedBy', $share->getSharedBy());
$this->assertEquals(\OCP\Share::SHARE_TYPE_USER, $share->getShareType());
$this->assertEquals(13, $share->getPermissions());
$this->assertEquals('myTarget', $share->getTarget());
@@ -1194,32 +1215,19 @@ class DefaultShareProviderTest extends \Test\TestCase {
]);
$this->assertEquals(1, $qb->execute());
- $user = $this->getMock('\OCP\IUser');
- $user->method('getUID')->willReturn('sharedWith');
- $owner = $this->getMock('\OCP\IUser');
- $owner->method('getUID')->willReturn('shareOwner');
- $initiator = $this->getMock('\OCP\IUser');
- $initiator->method('getUID')->willReturn('sharedBy');
-
- $this->userManager->method('get')->willReturnMap([
- ['sharedWith', $user],
- ['shareOwner', $owner],
- ['sharedBy', $initiator],
- ]);
-
$file = $this->getMock('\OCP\Files\File');
$file->method('getId')->willReturn(42);
$this->rootFolder->method('getUserFolder')->with('shareOwner')->will($this->returnSelf());
$this->rootFolder->method('getById')->with(42)->willReturn([$file]);
- $share = $this->provider->getSharesBy($initiator, \OCP\Share::SHARE_TYPE_USER, $file, false, 1, 0);
+ $share = $this->provider->getSharesBy('sharedBy', \OCP\Share::SHARE_TYPE_USER, $file, false, 1, 0);
$this->assertCount(1, $share);
$share = $share[0];
$this->assertEquals($id, $share->getId());
- $this->assertEquals($user, $share->getSharedWith());
- $this->assertEquals($owner, $share->getShareOwner());
- $this->assertEquals($initiator, $share->getSharedBy());
+ $this->assertEquals('sharedWith', $share->getSharedWith());
+ $this->assertEquals('shareOwner', $share->getShareOwner());
+ $this->assertEquals('sharedBy', $share->getSharedBy());
$this->assertEquals(\OCP\Share::SHARE_TYPE_USER, $share->getShareType());
$this->assertEquals(13, $share->getPermissions());
$this->assertEquals('myTarget', $share->getTarget());
@@ -1256,41 +1264,28 @@ class DefaultShareProviderTest extends \Test\TestCase {
$this->assertEquals(1, $qb->execute());
$id2 = $qb->getLastInsertId();
- $user = $this->getMock('\OCP\IUser');
- $user->method('getUID')->willReturn('sharedWith');
- $owner = $this->getMock('\OCP\IUser');
- $owner->method('getUID')->willReturn('shareOwner');
- $initiator = $this->getMock('\OCP\IUser');
- $initiator->method('getUID')->willReturn('sharedBy');
-
- $this->userManager->method('get')->willReturnMap([
- ['sharedWith', $user],
- ['shareOwner', $owner],
- ['sharedBy', $initiator],
- ]);
-
$file = $this->getMock('\OCP\Files\File');
$file->method('getId')->willReturn(42);
$this->rootFolder->method('getUserFolder')->with('shareOwner')->will($this->returnSelf());
$this->rootFolder->method('getById')->with(42)->willReturn([$file]);
- $shares = $this->provider->getSharesBy($owner, \OCP\Share::SHARE_TYPE_USER, null, true, -1, 0);
+ $shares = $this->provider->getSharesBy('shareOwner', \OCP\Share::SHARE_TYPE_USER, null, true, -1, 0);
$this->assertCount(2, $shares);
$share = $shares[0];
$this->assertEquals($id1, $share->getId());
- $this->assertSame($user, $share->getSharedWith());
- $this->assertSame($owner, $share->getShareOwner());
- $this->assertSame($owner, $share->getSharedBy());
+ $this->assertSame('sharedWith', $share->getSharedWith());
+ $this->assertSame('shareOwner', $share->getShareOwner());
+ $this->assertSame('shareOwner', $share->getSharedBy());
$this->assertEquals(\OCP\Share::SHARE_TYPE_USER, $share->getShareType());
$this->assertEquals(13, $share->getPermissions());
$this->assertEquals('myTarget', $share->getTarget());
$share = $shares[1];
$this->assertEquals($id2, $share->getId());
- $this->assertSame($user, $share->getSharedWith());
- $this->assertSame($owner, $share->getShareOwner());
- $this->assertSame($initiator, $share->getSharedBy());
+ $this->assertSame('sharedWith', $share->getSharedWith());
+ $this->assertSame('shareOwner', $share->getShareOwner());
+ $this->assertSame('sharedBy', $share->getSharedBy());
$this->assertEquals(\OCP\Share::SHARE_TYPE_USER, $share->getShareType());
$this->assertEquals(0, $share->getPermissions());
$this->assertEquals('userTarget', $share->getTarget());
@@ -1334,7 +1329,7 @@ class DefaultShareProviderTest extends \Test\TestCase {
$share = $this->provider->getShareById($id);
- $this->provider->deleteFromSelf($share, $user2);
+ $this->provider->deleteFromSelf($share, 'user2');
$qb = $this->dbConn->getQueryBuilder();
$stmt = $qb->select('*')
@@ -1405,7 +1400,7 @@ class DefaultShareProviderTest extends \Test\TestCase {
$share = $this->provider->getShareById($id);
- $this->provider->deleteFromSelf($share, $user2);
+ $this->provider->deleteFromSelf($share, 'user2');
$qb = $this->dbConn->getQueryBuilder();
$stmt = $qb->select('*')
@@ -1465,7 +1460,7 @@ class DefaultShareProviderTest extends \Test\TestCase {
$share = $this->provider->getShareById($id);
- $this->provider->deleteFromSelf($share, $user2);
+ $this->provider->deleteFromSelf($share, 'user2');
}
public function testDeleteFromSelfUser() {
@@ -1501,7 +1496,7 @@ class DefaultShareProviderTest extends \Test\TestCase {
$share = $this->provider->getShareById($id);
- $this->provider->deleteFromSelf($share, $user2);
+ $this->provider->deleteFromSelf($share, 'user2');
$qb = $this->dbConn->getQueryBuilder();
$stmt = $qb->select('*')
@@ -1627,18 +1622,18 @@ class DefaultShareProviderTest extends \Test\TestCase {
$share = $this->provider->getShareById($id);
- $share->setSharedWith($users['user3']);
- $share->setSharedBy($users['user4']);
- $share->setShareOwner($users['user5']);
+ $share->setSharedWith('user3');
+ $share->setSharedBy('user4');
+ $share->setShareOwner('user5');
$share->setNode($file2);
$share->setPermissions(1);
$share2 = $this->provider->update($share);
$this->assertEquals($id, $share2->getId());
- $this->assertSame($users['user3'], $share2->getSharedWith());
- $this->assertSame($users['user4'], $share2->getSharedBy());
- $this->assertSame($users['user5'], $share2->getShareOwner());
+ $this->assertSame('user3', $share2->getSharedWith());
+ $this->assertSame('user4', $share2->getSharedBy());
+ $this->assertSame('user5', $share2->getShareOwner());
$this->assertSame(1, $share2->getPermissions());
}
@@ -1677,8 +1672,8 @@ class DefaultShareProviderTest extends \Test\TestCase {
$share = $this->provider->getShareById($id);
$share->setPassword('password');
- $share->setSharedBy($users['user4']);
- $share->setShareOwner($users['user5']);
+ $share->setSharedBy('user4');
+ $share->setShareOwner('user5');
$share->setNode($file2);
$share->setPermissions(1);
@@ -1686,8 +1681,8 @@ class DefaultShareProviderTest extends \Test\TestCase {
$this->assertEquals($id, $share2->getId());
$this->assertEquals('password', $share->getPassword());
- $this->assertSame($users['user4'], $share2->getSharedBy());
- $this->assertSame($users['user5'], $share2->getShareOwner());
+ $this->assertSame('user4', $share2->getSharedBy());
+ $this->assertSame('user5', $share2->getShareOwner());
$this->assertSame(1, $share2->getPermissions());
}
@@ -1726,8 +1721,8 @@ class DefaultShareProviderTest extends \Test\TestCase {
$share = $this->provider->getShareById($id);
$share->setPassword(null);
- $share->setSharedBy($users['user4']);
- $share->setShareOwner($users['user5']);
+ $share->setSharedBy('user4');
+ $share->setShareOwner('user5');
$share->setNode($file2);
$share->setPermissions(1);
@@ -1735,8 +1730,8 @@ class DefaultShareProviderTest extends \Test\TestCase {
$this->assertEquals($id, $share2->getId());
$this->assertEquals(null, $share->getPassword());
- $this->assertSame($users['user4'], $share2->getSharedBy());
- $this->assertSame($users['user5'], $share2->getShareOwner());
+ $this->assertSame('user4', $share2->getSharedBy());
+ $this->assertSame('user5', $share2->getShareOwner());
$this->assertSame(1, $share2->getPermissions());
}
@@ -1787,9 +1782,9 @@ class DefaultShareProviderTest extends \Test\TestCase {
$share = $this->provider->getShareById($id);
- $share->setSharedWith($groups['group0']);
- $share->setSharedBy($users['user4']);
- $share->setShareOwner($users['user5']);
+ $share->setSharedWith('group0');
+ $share->setSharedBy('user4');
+ $share->setShareOwner('user5');
$share->setNode($file2);
$share->setPermissions(1);
@@ -1797,9 +1792,9 @@ class DefaultShareProviderTest extends \Test\TestCase {
$this->assertEquals($id, $share2->getId());
// Group shares do not allow updating the recipient
- $this->assertSame($groups['group0'], $share2->getSharedWith());
- $this->assertSame($users['user4'], $share2->getSharedBy());
- $this->assertSame($users['user5'], $share2->getShareOwner());
+ $this->assertSame('group0', $share2->getSharedWith());
+ $this->assertSame('user4', $share2->getSharedBy());
+ $this->assertSame('user5', $share2->getShareOwner());
$this->assertSame(1, $share2->getPermissions());
}
@@ -1856,9 +1851,9 @@ class DefaultShareProviderTest extends \Test\TestCase {
$share = $this->provider->getShareById($id);
- $share->setSharedWith($groups['group0']);
- $share->setSharedBy($users['user4']);
- $share->setShareOwner($users['user5']);
+ $share->setSharedWith('group0');
+ $share->setSharedBy('user4');
+ $share->setShareOwner('user5');
$share->setNode($file2);
$share->setPermissions(1);
@@ -1866,9 +1861,9 @@ class DefaultShareProviderTest extends \Test\TestCase {
$this->assertEquals($id, $share2->getId());
// Group shares do not allow updating the recipient
- $this->assertSame($groups['group0'], $share2->getSharedWith());
- $this->assertSame($users['user4'], $share2->getSharedBy());
- $this->assertSame($users['user5'], $share2->getShareOwner());
+ $this->assertSame('group0', $share2->getSharedWith());
+ $this->assertSame('user4', $share2->getSharedBy());
+ $this->assertSame('user5', $share2->getShareOwner());
$this->assertSame(1, $share2->getPermissions());
$qb = $this->dbConn->getQueryBuilder();
@@ -1949,18 +1944,18 @@ class DefaultShareProviderTest extends \Test\TestCase {
$this->rootFolder->method('getUserFolder')->with('user1')->will($this->returnSelf());
$this->rootFolder->method('getById')->willReturn([$folder]);
- $share = $this->provider->getShareById($id, $user0);
+ $share = $this->provider->getShareById($id, 'user0');
$share->setTarget('/newTarget');
- $this->provider->move($share, $user0);
+ $this->provider->move($share, 'user0');
- $share = $this->provider->getShareById($id, $user0);
+ $share = $this->provider->getShareById($id, 'user0');
$this->assertSame('/newTarget', $share->getTarget());
$share->setTarget('/ultraNewTarget');
- $this->provider->move($share, $user0);
+ $this->provider->move($share, 'user0');
- $share = $this->provider->getShareById($id, $user0);
+ $share = $this->provider->getShareById($id, 'user0');
$this->assertSame('/ultraNewTarget', $share->getTarget());
}
}
diff --git a/tests/lib/share20/managertest.php b/tests/lib/share20/managertest.php
index 6043d30a0bb..131bc7fbfd2 100644
--- a/tests/lib/share20/managertest.php
+++ b/tests/lib/share20/managertest.php
@@ -20,6 +20,8 @@
*/
namespace Test\Share20;
+use OCP\Files\IRootFolder;
+use OCP\IUserManager;
use OCP\Share\IProviderFactory;
use OCP\Share\IShare;
use OC\Share20\Manager;
@@ -34,7 +36,6 @@ use OCP\Security\ISecureRandom;
use OCP\Security\IHasher;
use OCP\Files\Mount\IMountManager;
use OCP\IGroupManager;
-use Sabre\VObject\Property\VCard\DateTime;
/**
* Class ManagerTest
@@ -46,33 +47,28 @@ class ManagerTest extends \Test\TestCase {
/** @var Manager */
protected $manager;
-
/** @var ILogger */
protected $logger;
-
/** @var IConfig */
protected $config;
-
/** @var ISecureRandom */
protected $secureRandom;
-
/** @var IHasher */
protected $hasher;
-
/** @var IShareProvider | \PHPUnit_Framework_MockObject_MockObject */
protected $defaultProvider;
-
/** @var IMountManager */
protected $mountManager;
-
/** @var IGroupManager */
protected $groupManager;
-
/** @var IL10N */
protected $l;
-
/** @var DummyFactory */
protected $factory;
+ /** @var IUserManager */
+ protected $userManager;
+ /** @var IRootFolder | \PHPUnit_Framework_MockObject_MockObject */
+ protected $rootFolder;
public function setUp() {
@@ -82,6 +78,8 @@ class ManagerTest extends \Test\TestCase {
$this->hasher = $this->getMock('\OCP\Security\IHasher');
$this->mountManager = $this->getMock('\OCP\Files\Mount\IMountManager');
$this->groupManager = $this->getMock('\OCP\IGroupManager');
+ $this->userManager = $this->getMock('\OCP\IUserManager');
+ $this->rootFolder = $this->getMock('\OCP\Files\IRootFolder');
$this->l = $this->getMock('\OCP\IL10N');
$this->l->method('t')
@@ -99,7 +97,9 @@ class ManagerTest extends \Test\TestCase {
$this->mountManager,
$this->groupManager,
$this->l,
- $this->factory
+ $this->factory,
+ $this->userManager,
+ $this->rootFolder
);
$this->defaultProvider = $this->getMockBuilder('\OC\Share20\DefaultShareProvider')
@@ -124,12 +124,14 @@ class ManagerTest extends \Test\TestCase {
$this->mountManager,
$this->groupManager,
$this->l,
- $this->factory
+ $this->factory,
+ $this->userManager,
+ $this->rootFolder
]);
}
/**
- * @expectedException \OC\Share20\Exception\ShareNotFound
+ * @expectedException \OCP\Share\Exceptions\ShareNotFound
*/
public function testDeleteNoShareId() {
$share = $this->getMock('\OCP\Share\IShare');
@@ -151,24 +153,21 @@ class ManagerTest extends \Test\TestCase {
$group->method('getGID')->willReturn('sharedWithGroup');
return [
- [\OCP\Share::SHARE_TYPE_USER, $user, 'sharedWithUser'],
- [\OCP\Share::SHARE_TYPE_GROUP, $group, 'sharedWithGroup'],
- [\OCP\Share::SHARE_TYPE_LINK, '', ''],
- [\OCP\Share::SHARE_TYPE_REMOTE, 'foo@bar.com', 'foo@bar.com'],
+ [\OCP\Share::SHARE_TYPE_USER, 'sharedWithUser'],
+ [\OCP\Share::SHARE_TYPE_GROUP, 'sharedWithGroup'],
+ [\OCP\Share::SHARE_TYPE_LINK, ''],
+ [\OCP\Share::SHARE_TYPE_REMOTE, 'foo@bar.com'],
];
}
/**
* @dataProvider dataTestDelete
*/
- public function testDelete($shareType, $sharedWith, $sharedWith_string) {
+ public function testDelete($shareType, $sharedWith) {
$manager = $this->createManagerMock()
->setMethods(['getShareById', 'deleteChildren'])
->getMock();
- $sharedBy = $this->getMock('\OCP\IUser');
- $sharedBy->method('getUID')->willReturn('sharedBy');
-
$path = $this->getMock('\OCP\Files\File');
$path->method('getId')->willReturn(1);
@@ -177,7 +176,7 @@ class ManagerTest extends \Test\TestCase {
->setProviderId('prov')
->setShareType($shareType)
->setSharedWith($sharedWith)
- ->setSharedBy($sharedBy)
+ ->setSharedBy('sharedBy')
->setNode($path)
->setTarget('myTarget');
@@ -198,7 +197,7 @@ class ManagerTest extends \Test\TestCase {
'itemType' => 'file',
'itemSource' => 1,
'shareType' => $shareType,
- 'shareWith' => $sharedWith_string,
+ 'shareWith' => $sharedWith,
'itemparent' => null,
'uidOwner' => 'sharedBy',
'fileSource' => 1,
@@ -210,7 +209,7 @@ class ManagerTest extends \Test\TestCase {
'itemType' => 'file',
'itemSource' => 1,
'shareType' => $shareType,
- 'shareWith' => $sharedWith_string,
+ 'shareWith' => $sharedWith,
'itemparent' => null,
'uidOwner' => 'sharedBy',
'fileSource' => 1,
@@ -221,7 +220,7 @@ class ManagerTest extends \Test\TestCase {
'itemType' => 'file',
'itemSource' => 1,
'shareType' => $shareType,
- 'shareWith' => $sharedWith_string,
+ 'shareWith' => $sharedWith,
'itemparent' => null,
'uidOwner' => 'sharedBy',
'fileSource' => 1,
@@ -243,22 +242,90 @@ class ManagerTest extends \Test\TestCase {
$manager->deleteShare($share);
}
- public function testDeleteNested() {
+ public function testDeleteLazyShare() {
$manager = $this->createManagerMock()
- ->setMethods(['getShareById'])
+ ->setMethods(['getShareById', 'deleteChildren'])
->getMock();
- $sharedBy1 = $this->getMock('\OCP\IUser');
- $sharedBy1->method('getUID')->willReturn('sharedBy1');
- $sharedBy2 = $this->getMock('\OCP\IUser');
- $sharedBy2->method('getUID')->willReturn('sharedBy2');
- $sharedBy3 = $this->getMock('\OCP\IUser');
- $sharedBy3->method('getUID')->willReturn('sharedBy3');
+ $share = $this->manager->newShare();
+ $share->setId(42)
+ ->setProviderId('prov')
+ ->setShareType(\OCP\Share::SHARE_TYPE_USER)
+ ->setSharedWith('sharedWith')
+ ->setSharedBy('sharedBy')
+ ->setShareOwner('shareOwner')
+ ->setTarget('myTarget')
+ ->setNodeId(1)
+ ->setNodeType('file');
+
+ $this->rootFolder->expects($this->never())->method($this->anything());
+
+ $manager->expects($this->once())->method('getShareById')->with('prov:42')->willReturn($share);
+ $manager->expects($this->once())->method('deleteChildren')->with($share);
+
+ $this->defaultProvider
+ ->expects($this->once())
+ ->method('delete')
+ ->with($share);
+
+ $hookListner = $this->getMockBuilder('Dummy')->setMethods(['pre', 'post'])->getMock();
+ \OCP\Util::connectHook('OCP\Share', 'pre_unshare', $hookListner, 'pre');
+ \OCP\Util::connectHook('OCP\Share', 'post_unshare', $hookListner, 'post');
+
+ $hookListnerExpectsPre = [
+ 'id' => 42,
+ 'itemType' => 'file',
+ 'itemSource' => 1,
+ 'shareType' => \OCP\Share::SHARE_TYPE_USER,
+ 'shareWith' => 'sharedWith',
+ 'itemparent' => null,
+ 'uidOwner' => 'sharedBy',
+ 'fileSource' => 1,
+ 'fileTarget' => 'myTarget',
+ ];
+
+ $hookListnerExpectsPost = [
+ 'id' => 42,
+ 'itemType' => 'file',
+ 'itemSource' => 1,
+ 'shareType' => \OCP\Share::SHARE_TYPE_USER,
+ 'shareWith' => 'sharedWith',
+ 'itemparent' => null,
+ 'uidOwner' => 'sharedBy',
+ 'fileSource' => 1,
+ 'fileTarget' => 'myTarget',
+ 'deletedShares' => [
+ [
+ 'id' => 42,
+ 'itemType' => 'file',
+ 'itemSource' => 1,
+ 'shareType' => \OCP\Share::SHARE_TYPE_USER,
+ 'shareWith' => 'sharedWith',
+ 'itemparent' => null,
+ 'uidOwner' => 'sharedBy',
+ 'fileSource' => 1,
+ 'fileTarget' => 'myTarget',
+ ],
+ ],
+ ];
+
- $sharedWith1 = $this->getMock('\OCP\IUser');
- $sharedWith1->method('getUID')->willReturn('sharedWith1');
- $sharedWith2 = $this->getMock('\OCP\IGroup');
- $sharedWith2->method('getGID')->willReturn('sharedWith2');
+ $hookListner
+ ->expects($this->exactly(1))
+ ->method('pre')
+ ->with($hookListnerExpectsPre);
+ $hookListner
+ ->expects($this->exactly(1))
+ ->method('post')
+ ->with($hookListnerExpectsPost);
+
+ $manager->deleteShare($share);
+ }
+
+ public function testDeleteNested() {
+ $manager = $this->createManagerMock()
+ ->setMethods(['getShareById'])
+ ->getMock();
$path = $this->getMock('\OCP\Files\File');
$path->method('getId')->willReturn(1);
@@ -267,8 +334,8 @@ class ManagerTest extends \Test\TestCase {
$share1->setId(42)
->setProviderId('prov')
->setShareType(\OCP\Share::SHARE_TYPE_USER)
- ->setSharedWith($sharedWith1)
- ->setSharedBy($sharedBy1)
+ ->setSharedWith('sharedWith1')
+ ->setSharedBy('sharedBy1')
->setNode($path)
->setTarget('myTarget1');
@@ -276,8 +343,8 @@ class ManagerTest extends \Test\TestCase {
$share2->setId(43)
->setProviderId('prov')
->setShareType(\OCP\Share::SHARE_TYPE_GROUP)
- ->setSharedWith($sharedWith2)
- ->setSharedBy($sharedBy2)
+ ->setSharedWith('sharedWith2')
+ ->setSharedBy('sharedBy2')
->setNode($path)
->setTarget('myTarget2')
->setParent(42);
@@ -286,7 +353,7 @@ class ManagerTest extends \Test\TestCase {
$share3->setId(44)
->setProviderId('prov')
->setShareType(\OCP\Share::SHARE_TYPE_LINK)
- ->setSharedBy($sharedBy3)
+ ->setSharedBy('sharedBy3')
->setNode($path)
->setTarget('myTarget3')
->setParent(43);
@@ -504,72 +571,72 @@ class ManagerTest extends \Test\TestCase {
}
public function dataGeneralChecks() {
- $user = $this->getMock('\OCP\IUser');
- $user2 = $this->getMock('\OCP\IUser');
- $group = $this->getMock('\OCP\IGroup');
+ $user0 = 'user0';
+ $user2 = 'user1';
+ $group0 = 'group0';
$file = $this->getMock('\OCP\Files\File');
$node = $this->getMock('\OCP\Files\Node');
$data = [
- [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, $file, null, $user, $user, 31, null, null), 'SharedWith should be an IUser', true],
- [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, $file, $group, $user, $user, 31, null, null), 'SharedWith should be an IUser', true],
- [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, $file, 'foo@bar.com', $user, $user, 31, null, null), 'SharedWith should be an IUser', true],
- [$this->createShare(null, \OCP\Share::SHARE_TYPE_GROUP, $file, null, $user, $user, 31, null, null), 'SharedWith should be an IGroup', true],
- [$this->createShare(null, \OCP\Share::SHARE_TYPE_GROUP, $file, $user2, $user, $user, 31, null, null), 'SharedWith should be an IGroup', true],
- [$this->createShare(null, \OCP\Share::SHARE_TYPE_GROUP, $file, 'foo@bar.com', $user, $user, 31, null, null), 'SharedWith should be an IGroup', true],
- [$this->createShare(null, \OCP\Share::SHARE_TYPE_LINK, $file, $user2, $user, $user, 31, null, null), 'SharedWith should be empty', true],
- [$this->createShare(null, \OCP\Share::SHARE_TYPE_LINK, $file, $group, $user, $user, 31, null, null), 'SharedWith should be empty', true],
- [$this->createShare(null, \OCP\Share::SHARE_TYPE_LINK, $file, 'foo@bar.com', $user, $user, 31, null, null), 'SharedWith should be empty', true],
- [$this->createShare(null, -1, $file, null, $user, $user, 31, null, null), 'unkown share type', true],
-
- [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, $file, $user2, null, $user, 31, null, null), 'SharedBy should be set', true],
- [$this->createShare(null, \OCP\Share::SHARE_TYPE_GROUP, $file, $group, null, $user, 31, null, null), 'SharedBy should be set', true],
- [$this->createShare(null, \OCP\Share::SHARE_TYPE_LINK, $file, null, null, $user, 31, null, null), 'SharedBy should be set', true],
-
- [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, $file, $user, $user, $user, 31, null, null), 'Can\'t share with yourself', true],
-
- [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, null, $user2, $user, $user, 31, null, null), 'Path should be set', true],
- [$this->createShare(null, \OCP\Share::SHARE_TYPE_GROUP, null, $group, $user, $user, 31, null, null), 'Path should be set', true],
- [$this->createShare(null, \OCP\Share::SHARE_TYPE_LINK, null, null, $user, $user, 31, null, null), 'Path should be set', true],
-
- [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, $node, $user2, $user, $user, 31, null, null), 'Path should be either a file or a folder', true],
- [$this->createShare(null, \OCP\Share::SHARE_TYPE_GROUP, $node, $group, $user, $user, 31, null, null), 'Path should be either a file or a folder', true],
- [$this->createShare(null, \OCP\Share::SHARE_TYPE_LINK, $node, null, $user, $user, 31, null, null), 'Path should be either a file or a folder', true],
+ [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, $file, null, $user0, $user0, 31, null, null), 'SharedWith is not a valid user', true],
+ [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, $file, $group0, $user0, $user0, 31, null, null), 'SharedWith is not a valid user', true],
+ [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, $file, 'foo@bar.com', $user0, $user0, 31, null, null), 'SharedWith is not a valid user', true],
+ [$this->createShare(null, \OCP\Share::SHARE_TYPE_GROUP, $file, null, $user0, $user0, 31, null, null), 'SharedWith is not a valid group', true],
+ [$this->createShare(null, \OCP\Share::SHARE_TYPE_GROUP, $file, $user2, $user0, $user0, 31, null, null), 'SharedWith is not a valid group', true],
+ [$this->createShare(null, \OCP\Share::SHARE_TYPE_GROUP, $file, 'foo@bar.com', $user0, $user0, 31, null, null), 'SharedWith is not a valid group', true],
+ [$this->createShare(null, \OCP\Share::SHARE_TYPE_LINK, $file, $user2, $user0, $user0, 31, null, null), 'SharedWith should be empty', true],
+ [$this->createShare(null, \OCP\Share::SHARE_TYPE_LINK, $file, $group0, $user0, $user0, 31, null, null), 'SharedWith should be empty', true],
+ [$this->createShare(null, \OCP\Share::SHARE_TYPE_LINK, $file, 'foo@bar.com', $user0, $user0, 31, null, null), 'SharedWith should be empty', true],
+ [$this->createShare(null, -1, $file, null, $user0, $user0, 31, null, null), 'unkown share type', true],
+
+ [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, $file, $user2, null, $user0, 31, null, null), 'SharedBy should be set', true],
+ [$this->createShare(null, \OCP\Share::SHARE_TYPE_GROUP, $file, $group0, null, $user0, 31, null, null), 'SharedBy should be set', true],
+ [$this->createShare(null, \OCP\Share::SHARE_TYPE_LINK, $file, null, null, $user0, 31, null, null), 'SharedBy should be set', true],
+
+ [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, $file, $user0, $user0, $user0, 31, null, null), 'Can\'t share with yourself', true],
+
+ [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, null, $user2, $user0, $user0, 31, null, null), 'Path should be set', true],
+ [$this->createShare(null, \OCP\Share::SHARE_TYPE_GROUP, null, $group0, $user0, $user0, 31, null, null), 'Path should be set', true],
+ [$this->createShare(null, \OCP\Share::SHARE_TYPE_LINK, null, null, $user0, $user0, 31, null, null), 'Path should be set', true],
+
+ [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, $node, $user2, $user0, $user0, 31, null, null), 'Path should be either a file or a folder', true],
+ [$this->createShare(null, \OCP\Share::SHARE_TYPE_GROUP, $node, $group0, $user0, $user0, 31, null, null), 'Path should be either a file or a folder', true],
+ [$this->createShare(null, \OCP\Share::SHARE_TYPE_LINK, $node, null, $user0, $user0, 31, null, null), 'Path should be either a file or a folder', true],
];
$nonShareAble = $this->getMock('\OCP\Files\Folder');
$nonShareAble->method('isShareable')->willReturn(false);
$nonShareAble->method('getPath')->willReturn('path');
- $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, $nonShareAble, $user2, $user, $user, 31, null, null), 'You are not allowed to share path', true];
- $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_GROUP, $nonShareAble, $group, $user, $user, 31, null, null), 'You are not allowed to share path', true];
- $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_LINK, $nonShareAble, null, $user, $user, 31, null, null), 'You are not allowed to share path', true];
+ $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, $nonShareAble, $user2, $user0, $user0, 31, null, null), 'You are not allowed to share path', true];
+ $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_GROUP, $nonShareAble, $group0, $user0, $user0, 31, null, null), 'You are not allowed to share path', true];
+ $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_LINK, $nonShareAble, null, $user0, $user0, 31, null, null), 'You are not allowed to share path', true];
$limitedPermssions = $this->getMock('\OCP\Files\File');
$limitedPermssions->method('isShareable')->willReturn(true);
$limitedPermssions->method('getPermissions')->willReturn(\OCP\Constants::PERMISSION_READ);
$limitedPermssions->method('getPath')->willReturn('path');
- $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, $limitedPermssions, $user2, $user, $user, null, null, null), 'A share requires permissions', true];
- $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_GROUP, $limitedPermssions, $group, $user, $user, null, null, null), 'A share requires permissions', true];
- $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_LINK, $limitedPermssions, null, $user, $user, null, null, null), 'A share requires permissions', true];
+ $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, $limitedPermssions, $user2, $user0, $user0, null, null, null), 'A share requires permissions', true];
+ $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_GROUP, $limitedPermssions, $group0, $user0, $user0, null, null, null), 'A share requires permissions', true];
+ $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_LINK, $limitedPermssions, null, $user0, $user0, null, null, null), 'A share requires permissions', true];
- $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, $limitedPermssions, $user2, $user, $user, 31, null, null), 'Cannot increase permissions of path', true];
- $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_GROUP, $limitedPermssions, $group, $user, $user, 17, null, null), 'Cannot increase permissions of path', true];
- $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_LINK, $limitedPermssions, null, $user, $user, 3, null, null), 'Cannot increase permissions of path', true];
+ $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, $limitedPermssions, $user2, $user0, $user0, 31, null, null), 'Cannot increase permissions of path', true];
+ $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_GROUP, $limitedPermssions, $group0, $user0, $user0, 17, null, null), 'Cannot increase permissions of path', true];
+ $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_LINK, $limitedPermssions, null, $user0, $user0, 3, null, null), 'Cannot increase permissions of path', true];
$allPermssions = $this->getMock('\OCP\Files\Folder');
$allPermssions->method('isShareable')->willReturn(true);
$allPermssions->method('getPermissions')->willReturn(\OCP\Constants::PERMISSION_ALL);
- $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, $allPermssions, $user2, $user, $user, 30, null, null), 'Shares need at least read permissions', true];
- $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_GROUP, $allPermssions, $group, $user, $user, 2, null, null), 'Shares need at least read permissions', true];
- $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_LINK, $allPermssions, null, $user, $user, 16, null, null), 'Shares need at least read permissions', true];
+ $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, $allPermssions, $user2, $user0, $user0, 30, null, null), 'Shares need at least read permissions', true];
+ $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_GROUP, $allPermssions, $group0, $user0, $user0, 2, null, null), 'Shares need at least read permissions', true];
+ $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_LINK, $allPermssions, null, $user0, $user0, 16, null, null), 'Shares need at least read permissions', true];
- $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, $allPermssions, $user2, $user, $user, 31, null, null), null, false];
- $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_GROUP, $allPermssions, $group, $user, $user, 3, null, null), null, false];
- $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_LINK, $allPermssions, null, $user, $user, 17, null, null), null, false];
+ $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_USER, $allPermssions, $user2, $user0, $user0, 31, null, null), null, false];
+ $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_GROUP, $allPermssions, $group0, $user0, $user0, 3, null, null), null, false];
+ $data[] = [$this->createShare(null, \OCP\Share::SHARE_TYPE_LINK, $allPermssions, null, $user0, $user0, 17, null, null), null, false];
return $data;
}
@@ -583,10 +650,19 @@ class ManagerTest extends \Test\TestCase {
public function testGeneralChecks($share, $exceptionMessage, $exception) {
$thrown = null;
+ $this->userManager->method('userExists')->will($this->returnValueMap([
+ ['user0', true],
+ ['user1', true],
+ ]));
+
+ $this->groupManager->method('groupExists')->will($this->returnValueMap([
+ ['group0', true],
+ ]));
+
try {
$this->invokePrivate($this->manager, 'generalCreateChecks', [$share]);
$thrown = false;
- } catch (\OC\HintException $e) {
+ } catch (\OCP\Share\Exceptions\GenericShareException $e) {
$this->assertEquals($exceptionMessage, $e->getHint());
$thrown = true;
} catch(\InvalidArgumentException $e) {
@@ -598,7 +674,7 @@ class ManagerTest extends \Test\TestCase {
}
/**
- * @expectedException \OC\HintException
+ * @expectedException \OCP\Share\Exceptions\GenericShareException
* @expectedExceptionMessage Expiration date is in the past
*/
public function testvalidateExpirationDateInPast() {
@@ -644,7 +720,7 @@ class ManagerTest extends \Test\TestCase {
try {
$this->invokePrivate($this->manager, 'validateExpirationDate', [$share]);
- } catch (\OC\HintException $e) {
+ } catch (\OCP\Share\Exceptions\GenericShareException $e) {
$this->assertEquals('Cannot set expiration date more than 3 days in the future', $e->getMessage());
$this->assertEquals('Cannot set expiration date more than 3 days in the future', $e->getHint());
$this->assertEquals(404, $e->getCode());
@@ -791,11 +867,11 @@ class ManagerTest extends \Test\TestCase {
* @expectedExceptionMessage Only sharing with group members is allowed
*/
public function testUserCreateChecksShareWithGroupMembersOnlyDifferentGroups() {
- $share = new \OC\Share20\Share();
+ $share = $this->manager->newShare();
$sharedBy = $this->getMock('\OCP\IUser');
$sharedWith = $this->getMock('\OCP\IUser');
- $share->setSharedBy($sharedBy)->setSharedWith($sharedWith);
+ $share->setSharedBy('sharedBy')->setSharedWith('sharedWith');
$this->groupManager
->method('getUserGroupIds')
@@ -806,6 +882,11 @@ class ManagerTest extends \Test\TestCase {
])
);
+ $this->userManager->method('get')->will($this->returnValueMap([
+ ['sharedBy', $sharedBy],
+ ['sharedWith', $sharedWith],
+ ]));
+
$this->config
->method('getAppValue')
->will($this->returnValueMap([
@@ -816,11 +897,11 @@ class ManagerTest extends \Test\TestCase {
}
public function testUserCreateChecksShareWithGroupMembersOnlySharedGroup() {
- $share = new \OC\Share20\Share();
+ $share = $this->manager->newShare();
$sharedBy = $this->getMock('\OCP\IUser');
$sharedWith = $this->getMock('\OCP\IUser');
- $share->setSharedBy($sharedBy)->setSharedWith($sharedWith);
+ $share->setSharedBy('sharedBy')->setSharedWith('sharedWith');
$path = $this->getMock('\OCP\Files\Node');
$share->setNode($path);
@@ -834,6 +915,11 @@ class ManagerTest extends \Test\TestCase {
])
);
+ $this->userManager->method('get')->will($this->returnValueMap([
+ ['sharedBy', $sharedBy],
+ ['sharedWith', $sharedWith],
+ ]));
+
$this->config
->method('getAppValue')
->will($this->returnValueMap([
@@ -859,10 +945,10 @@ class ManagerTest extends \Test\TestCase {
$sharedWith = $this->getMock('\OCP\IUser');
$path = $this->getMock('\OCP\Files\Node');
- $share->setSharedWith($sharedWith)->setNode($path)
+ $share->setSharedWith('sharedWith')->setNode($path)
->setProviderId('foo')->setId('bar');
- $share2->setSharedWith($sharedWith)->setNode($path)
+ $share2->setSharedWith('sharedWith')->setNode($path)
->setProviderId('foo')->setId('baz');
$this->defaultProvider
@@ -881,28 +967,31 @@ class ManagerTest extends \Test\TestCase {
$share = $this->manager->newShare();
$sharedWith = $this->getMock('\OCP\IUser');
- $owner = $this->getMock('\OCP\IUser');
+ $sharedWith->method('getUID')->willReturn('sharedWith');
+
+ $this->userManager->method('get')->with('sharedWith')->willReturn($sharedWith);
+
$path = $this->getMock('\OCP\Files\Node');
- $share->setSharedWith($sharedWith)
+ $share->setSharedWith('sharedWith')
->setNode($path)
- ->setShareOwner($owner)
+ ->setShareOwner('shareOwner')
->setProviderId('foo')
->setId('bar');
- $share2 = new \OC\Share20\Share();
- $owner2 = $this->getMock('\OCP\IUser');
+ $share2 = $this->manager->newShare();
$share2->setShareType(\OCP\Share::SHARE_TYPE_GROUP)
- ->setShareOwner($owner2)
+ ->setShareOwner('shareOwner2')
->setProviderId('foo')
- ->setId('baz');
+ ->setId('baz')
+ ->setSharedWith('group');
$group = $this->getMock('\OCP\IGroup');
$group->method('inGroup')
->with($sharedWith)
->willReturn(true);
- $share2->setSharedWith($group);
+ $this->groupManager->method('get')->with('group')->willReturn($group);
$this->defaultProvider
->method('getSharesByPath')
@@ -913,20 +1002,20 @@ class ManagerTest extends \Test\TestCase {
}
public function testUserCreateChecksIdenticalPathNotSharedWithUser() {
- $share = new \OC\Share20\Share();
+ $share = $this->manager->newShare();
$sharedWith = $this->getMock('\OCP\IUser');
- $owner = $this->getMock('\OCP\IUser');
$path = $this->getMock('\OCP\Files\Node');
- $share->setSharedWith($sharedWith)
+ $share->setSharedWith('sharedWith')
->setNode($path)
- ->setShareOwner($owner)
+ ->setShareOwner('shareOwner')
->setProviderId('foo')
->setId('bar');
- $share2 = new \OC\Share20\Share();
- $owner2 = $this->getMock('\OCP\IUser');
+ $this->userManager->method('get')->with('sharedWith')->willReturn($sharedWith);
+
+ $share2 = $this->manager->newShare();
$share2->setShareType(\OCP\Share::SHARE_TYPE_GROUP)
- ->setShareOwner($owner2)
+ ->setShareOwner('shareOwner2')
->setProviderId('foo')
->setId('baz');
@@ -935,7 +1024,9 @@ class ManagerTest extends \Test\TestCase {
->with($sharedWith)
->willReturn(false);
- $share2->setSharedWith($group);
+ $this->groupManager->method('get')->with('group')->willReturn($group);
+
+ $share2->setSharedWith('group');
$this->defaultProvider
->method('getSharesByPath')
@@ -950,13 +1041,16 @@ class ManagerTest extends \Test\TestCase {
* @expectedExceptionMessage Only sharing within your own groups is allowed
*/
public function testGroupCreateChecksShareWithGroupMembersOnlyNotInGroup() {
- $share = new \OC\Share20\Share();
+ $share = $this->manager->newShare();
- $sharedBy = $this->getMock('\OCP\IUser');
- $sharedWith = $this->getMock('\OCP\IGroup');
- $share->setSharedBy($sharedBy)->setSharedWith($sharedWith);
+ $user = $this->getMock('\OCP\IUser');
+ $group = $this->getMock('\OCP\IGroup');
+ $share->setSharedBy('user')->setSharedWith('group');
+
+ $group->method('inGroup')->with($user)->willReturn(false);
- $sharedWith->method('inGroup')->with($sharedBy)->willReturn(false);
+ $this->groupManager->method('get')->with('group')->willReturn($group);
+ $this->userManager->method('get')->with('user')->willReturn($user);
$this->config
->method('getAppValue')
@@ -968,13 +1062,16 @@ class ManagerTest extends \Test\TestCase {
}
public function testGroupCreateChecksShareWithGroupMembersOnlyInGroup() {
- $share = new \OC\Share20\Share();
+ $share = $this->manager->newShare();
- $sharedBy = $this->getMock('\OCP\IUser');
- $sharedWith = $this->getMock('\OCP\IGroup');
- $share->setSharedBy($sharedBy)->setSharedWith($sharedWith);
+ $user = $this->getMock('\OCP\IUser');
+ $group = $this->getMock('\OCP\IGroup');
+ $share->setSharedBy('user')->setSharedWith('group');
+
+ $this->userManager->method('get')->with('user')->willReturn($user);
+ $this->groupManager->method('get')->with('group')->willReturn($group);
- $sharedWith->method('inGroup')->with($sharedBy)->willReturn(true);
+ $group->method('inGroup')->with($user)->willReturn(true);
$path = $this->getMock('\OCP\Files\Node');
$share->setNode($path);
@@ -999,15 +1096,14 @@ class ManagerTest extends \Test\TestCase {
public function testGroupCreateChecksPathAlreadySharedWithSameGroup() {
$share = $this->manager->newShare();
- $sharedWith = $this->getMock('\OCP\IGroup');
$path = $this->getMock('\OCP\Files\Node');
- $share->setSharedWith($sharedWith)
+ $share->setSharedWith('sharedWith')
->setNode($path)
->setProviderId('foo')
->setId('bar');
- $share2 = new \OC\Share20\Share();
- $share2->setSharedWith($sharedWith)
+ $share2 = $this->manager->newShare();
+ $share2->setSharedWith('sharedWith')
->setProviderId('foo')
->setId('baz');
@@ -1019,17 +1115,15 @@ class ManagerTest extends \Test\TestCase {
}
public function testGroupCreateChecksPathAlreadySharedWithDifferentGroup() {
- $share = new \OC\Share20\Share();
+ $share = $this->manager->newShare();
- $sharedWith = $this->getMock('\OCP\IGroup');
- $share->setSharedWith($sharedWith);
+ $share->setSharedWith('sharedWith');
$path = $this->getMock('\OCP\Files\Node');
$share->setNode($path);
- $share2 = new \OC\Share20\Share();
- $sharedWith2 = $this->getMock('\OCP\IGroup');
- $share2->setSharedWith($sharedWith2);
+ $share2 = $this->manager->newShare();
+ $share2->setSharedWith('sharedWith2');
$this->defaultProvider->method('getSharesByPath')
->with($path)
@@ -1043,7 +1137,7 @@ class ManagerTest extends \Test\TestCase {
* @expectedExceptionMessage Link sharing not allowed
*/
public function testLinkCreateChecksNoLinkSharesAllowed() {
- $share = new \OC\Share20\Share();
+ $share = $this->manager->newShare();
$this->config
->method('getAppValue')
@@ -1059,7 +1153,7 @@ class ManagerTest extends \Test\TestCase {
* @expectedExceptionMessage Link shares can't have reshare permissions
*/
public function testLinkCreateChecksSharePermissions() {
- $share = new \OC\Share20\Share();
+ $share = $this->manager->newShare();
$share->setPermissions(\OCP\Constants::PERMISSION_SHARE);
@@ -1077,7 +1171,7 @@ class ManagerTest extends \Test\TestCase {
* @expectedExceptionMessage Link shares can't have delete permissions
*/
public function testLinkCreateChecksDeletePermissions() {
- $share = new \OC\Share20\Share();
+ $share = $this->manager->newShare();
$share->setPermissions(\OCP\Constants::PERMISSION_DELETE);
@@ -1095,7 +1189,7 @@ class ManagerTest extends \Test\TestCase {
* @expectedExceptionMessage Public upload not allowed
*/
public function testLinkCreateChecksNoPublicUpload() {
- $share = new \OC\Share20\Share();
+ $share = $this->manager->newShare();
$share->setPermissions(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE);
@@ -1110,7 +1204,7 @@ class ManagerTest extends \Test\TestCase {
}
public function testLinkCreateChecksPublicUpload() {
- $share = new \OC\Share20\Share();
+ $share = $this->manager->newShare();
$share->setPermissions(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE);
@@ -1125,7 +1219,7 @@ class ManagerTest extends \Test\TestCase {
}
public function testLinkCreateChecksReadOnly() {
- $share = new \OC\Share20\Share();
+ $share = $this->manager->newShare();
$share->setPermissions(\OCP\Constants::PERMISSION_READ);
@@ -1238,7 +1332,9 @@ class ManagerTest extends \Test\TestCase {
->with($user)
->willReturn($groupIds);
- $res = $this->manager->sharingDisabledForUser($user);
+ $this->userManager->method('get')->with('user')->willReturn($user);
+
+ $res = $this->manager->sharingDisabledForUser('user');
$this->assertEquals($expected, $res);
}
@@ -1278,7 +1374,7 @@ class ManagerTest extends \Test\TestCase {
$user = $this->getMock('\OCP\IUser');
$share = $this->manager->newShare();
- $share->setSharedBy($user);
+ $share->setSharedBy('user');
$res = $this->invokePrivate($manager, 'canShare', [$share]);
$this->assertEquals($expected, $res);
@@ -1294,7 +1390,7 @@ class ManagerTest extends \Test\TestCase {
->getMock();
$manager->expects($this->once())->method('canShare')->willReturn(false);
- $share = new \OC\Share20\Share();
+ $share = $this->manager->newShare();
$manager->createShare($share);
}
@@ -1303,9 +1399,8 @@ class ManagerTest extends \Test\TestCase {
->setMethods(['canShare', 'generalCreateChecks', 'userCreateChecks', 'pathCreateChecks'])
->getMock();
- $sharedWith = $this->getMock('\OCP\IUser');
- $sharedBy = $this->getMock('\OCP\IUser');
$shareOwner = $this->getMock('\OCP\IUser');
+ $shareOwner->method('getUID')->willReturn('shareOwner');
$path = $this->getMock('\OCP\Files\File');
$path->method('getOwner')->willReturn($shareOwner);
@@ -1315,8 +1410,8 @@ class ManagerTest extends \Test\TestCase {
null,
\OCP\Share::SHARE_TYPE_USER,
$path,
- $sharedWith,
- $sharedBy,
+ 'sharedWith',
+ 'sharedBy',
null,
\OCP\Constants::PERMISSION_ALL);
@@ -1342,7 +1437,7 @@ class ManagerTest extends \Test\TestCase {
$share->expects($this->once())
->method('setShareOwner')
- ->with($shareOwner);
+ ->with('shareOwner');
$share->expects($this->once())
->method('setTarget')
->with('/target');
@@ -1355,9 +1450,8 @@ class ManagerTest extends \Test\TestCase {
->setMethods(['canShare', 'generalCreateChecks', 'groupCreateChecks', 'pathCreateChecks'])
->getMock();
- $sharedWith = $this->getMock('\OCP\IGroup');
- $sharedBy = $this->getMock('\OCP\IUser');
$shareOwner = $this->getMock('\OCP\IUser');
+ $shareOwner->method('getUID')->willReturn('shareOwner');
$path = $this->getMock('\OCP\Files\File');
$path->method('getOwner')->willReturn($shareOwner);
@@ -1367,8 +1461,8 @@ class ManagerTest extends \Test\TestCase {
null,
\OCP\Share::SHARE_TYPE_GROUP,
$path,
- $sharedWith,
- $sharedBy,
+ 'sharedWith',
+ 'sharedBy',
null,
\OCP\Constants::PERMISSION_ALL);
@@ -1394,7 +1488,7 @@ class ManagerTest extends \Test\TestCase {
$share->expects($this->once())
->method('setShareOwner')
- ->with($shareOwner);
+ ->with('shareOwner');
$share->expects($this->once())
->method('setTarget')
->with('/target');
@@ -1414,9 +1508,8 @@ class ManagerTest extends \Test\TestCase {
])
->getMock();
- $sharedBy = $this->getMock('\OCP\IUser');
- $sharedBy->method('getUID')->willReturn('sharedBy');
$shareOwner = $this->getMock('\OCP\IUser');
+ $shareOwner->method('getUID')->willReturn('shareOwner');
$path = $this->getMock('\OCP\Files\File');
$path->method('getOwner')->willReturn($shareOwner);
@@ -1428,7 +1521,7 @@ class ManagerTest extends \Test\TestCase {
$share = $this->manager->newShare();
$share->setShareType(\OCP\Share::SHARE_TYPE_LINK)
->setNode($path)
- ->setSharedBy($sharedBy)
+ ->setSharedBy('sharedBy')
->setPermissions(\OCP\Constants::PERMISSION_ALL)
->setExpirationDate($date)
->setPassword('password');
@@ -1515,7 +1608,7 @@ class ManagerTest extends \Test\TestCase {
/** @var IShare $share */
$share = $manager->createShare($share);
- $this->assertSame($shareOwner, $share->getShareOwner());
+ $this->assertSame('shareOwner', $share->getShareOwner());
$this->assertEquals('/target', $share->getTarget());
$this->assertSame($date, $share->getExpirationDate());
$this->assertEquals('token', $share->getToken());
@@ -1536,9 +1629,8 @@ class ManagerTest extends \Test\TestCase {
])
->getMock();
- $sharedWith = $this->getMock('\OCP\IUser');
- $sharedBy = $this->getMock('\OCP\IUser');
$shareOwner = $this->getMock('\OCP\IUser');
+ $shareOwner->method('getUID')->willReturn('shareOwner');
$path = $this->getMock('\OCP\Files\File');
$path->method('getOwner')->willReturn($shareOwner);
@@ -1548,8 +1640,8 @@ class ManagerTest extends \Test\TestCase {
null,
\OCP\Share::SHARE_TYPE_USER,
$path,
- $sharedWith,
- $sharedBy,
+ 'sharedWith',
+ 'sharedBy',
null,
\OCP\Constants::PERMISSION_ALL);
@@ -1569,7 +1661,7 @@ class ManagerTest extends \Test\TestCase {
$share->expects($this->once())
->method('setShareOwner')
- ->with($shareOwner);
+ ->with('shareOwner');
$share->expects($this->once())
->method('setTarget')
->with('/target');
@@ -1591,7 +1683,9 @@ class ManagerTest extends \Test\TestCase {
$this->mountManager,
$this->groupManager,
$this->l,
- $factory
+ $factory,
+ $this->userManager,
+ $this->rootFolder
);
$share = $this->getMock('\OCP\Share\IShare');
@@ -1676,7 +1770,7 @@ class ManagerTest extends \Test\TestCase {
->getMock();
$manager->expects($this->once())->method('canShare')->willReturn(false);
- $share = new \OC\Share20\Share();
+ $share = $this->manager->newShare();
$manager->updateShare($share);
}
@@ -1692,13 +1786,13 @@ class ManagerTest extends \Test\TestCase {
])
->getMock();
- $originalShare = new \OC\Share20\Share();
+ $originalShare = $this->manager->newShare();
$originalShare->setShareType(\OCP\Share::SHARE_TYPE_GROUP);
$manager->expects($this->once())->method('canShare')->willReturn(true);
$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
- $share = new \OC\Share20\Share();
+ $share = $this->manager->newShare();
$share->setProviderId('foo')
->setId('42')
->setShareType(\OCP\Share::SHARE_TYPE_USER);
@@ -1718,21 +1812,18 @@ class ManagerTest extends \Test\TestCase {
])
->getMock();
- $origGroup = $this->getMock('\OCP\IGroup');
- $newGroup = $this->getMock('\OCP\IGroup');
-
- $originalShare = new \OC\Share20\Share();
+ $originalShare = $this->manager->newShare();
$originalShare->setShareType(\OCP\Share::SHARE_TYPE_GROUP)
- ->setSharedWith($origGroup);
+ ->setSharedWith('origGroup');
$manager->expects($this->once())->method('canShare')->willReturn(true);
$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
- $share = new \OC\Share20\Share();
+ $share = $this->manager->newShare();
$share->setProviderId('foo')
->setId('42')
->setShareType(\OCP\Share::SHARE_TYPE_GROUP)
- ->setSharedWith($newGroup);
+ ->setSharedWith('newGroup');
$manager->updateShare($share);
}
@@ -1749,22 +1840,19 @@ class ManagerTest extends \Test\TestCase {
])
->getMock();
- $origUser = $this->getMock('\OCP\IUser');
- $newUser = $this->getMock('\OCP\IUser');
-
- $originalShare = new \OC\Share20\Share();
+ $originalShare = $this->manager->newShare();
$originalShare->setShareType(\OCP\Share::SHARE_TYPE_USER)
- ->setSharedWith($origUser);
+ ->setSharedWith('sharedWith');
$manager->expects($this->once())->method('canShare')->willReturn(true);
$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
- $share = new \OC\Share20\Share();
+ $share = $this->manager->newShare();
$share->setProviderId('foo')
->setId('42')
->setShareType(\OCP\Share::SHARE_TYPE_USER)
- ->setSharedWith($newUser)
- ->setShareOwner($newUser);
+ ->setSharedWith('newUser')
+ ->setShareOwner('newUser');
$manager->updateShare($share);
}
@@ -1780,22 +1868,27 @@ class ManagerTest extends \Test\TestCase {
])
->getMock();
- $origUser = $this->getMock('\OCP\IUser');
- $newUser = $this->getMock('\OCP\IUser');
-
- $originalShare = new \OC\Share20\Share();
+ $originalShare = $this->manager->newShare();
$originalShare->setShareType(\OCP\Share::SHARE_TYPE_USER)
- ->setSharedWith($origUser);
+ ->setSharedWith('origUser')
+ ->setPermissions(1);
+
+ $node = $this->getMock('\OCP\Files\File');
+ $node->method('getId')->willReturn(100);
+ $node->method('getPath')->willReturn('/newUser/files/myPath');
$manager->expects($this->once())->method('canShare')->willReturn(true);
$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
- $share = new \OC\Share20\Share();
+ $share = $this->manager->newShare();
$share->setProviderId('foo')
->setId('42')
->setShareType(\OCP\Share::SHARE_TYPE_USER)
- ->setSharedWith($origUser)
- ->setShareOwner($newUser);
+ ->setSharedWith('origUser')
+ ->setShareOwner('newUser')
+ ->setSharedBy('sharer')
+ ->setPermissions(31)
+ ->setNode($node);
$this->defaultProvider->expects($this->once())
->method('update')
@@ -1806,6 +1899,20 @@ class ManagerTest extends \Test\TestCase {
\OCP\Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListner, 'post');
$hookListner->expects($this->never())->method('post');
+ $this->rootFolder->method('getUserFolder')->with('newUser')->will($this->returnSelf());
+ $this->rootFolder->method('getRelativePath')->with('/newUser/files/myPath')->willReturn('/myPath');
+
+ $hookListner2 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock();
+ \OCP\Util::connectHook('OCP\Share', 'post_update_permissions', $hookListner2, 'post');
+ $hookListner2->expects($this->once())->method('post')->with([
+ 'itemType' => 'file',
+ 'itemSource' => 100,
+ 'shareType' => \OCP\Share::SHARE_TYPE_USER,
+ 'shareWith' => 'origUser',
+ 'uidOwner' => 'sharer',
+ 'permissions' => 31,
+ 'path' => '/myPath',
+ ]);
$manager->updateShare($share);
}
@@ -1821,22 +1928,24 @@ class ManagerTest extends \Test\TestCase {
])
->getMock();
- $origGroup = $this->getMock('\OCP\IGroup');
- $user = $this->getMock('\OCP\IUser');
-
- $originalShare = new \OC\Share20\Share();
+ $originalShare = $this->manager->newShare();
$originalShare->setShareType(\OCP\Share::SHARE_TYPE_GROUP)
- ->setSharedWith($origGroup);
+ ->setSharedWith('origUser')
+ ->setPermissions(31);
$manager->expects($this->once())->method('canShare')->willReturn(true);
$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
- $share = new \OC\Share20\Share();
+ $node = $this->getMock('\OCP\Files\File');
+
+ $share = $this->manager->newShare();
$share->setProviderId('foo')
->setId('42')
->setShareType(\OCP\Share::SHARE_TYPE_GROUP)
- ->setSharedWith($origGroup)
- ->setShareOwner($user);
+ ->setSharedWith('origUser')
+ ->setShareOwner('owner')
+ ->setNode($node)
+ ->setPermissions(31);
$this->defaultProvider->expects($this->once())
->method('update')
@@ -1847,6 +1956,9 @@ class ManagerTest extends \Test\TestCase {
\OCP\Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListner, 'post');
$hookListner->expects($this->never())->method('post');
+ $hookListner2 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock();
+ \OCP\Util::connectHook('OCP\Share', 'post_update_permissions', $hookListner2, 'post');
+ $hookListner2->expects($this->never())->method('post');
$manager->updateShare($share);
}
@@ -1864,11 +1976,9 @@ class ManagerTest extends \Test\TestCase {
])
->getMock();
- $user = $this->getMock('\OCP\IUser');
- $user->method('getUID')->willReturn('owner');
-
- $originalShare = new \OC\Share20\Share();
- $originalShare->setShareType(\OCP\Share::SHARE_TYPE_LINK);
+ $originalShare = $this->manager->newShare();
+ $originalShare->setShareType(\OCP\Share::SHARE_TYPE_LINK)
+ ->setPermissions(15);
$tomorrow = new \DateTime();
$tomorrow->setTime(0,0,0);
@@ -1881,11 +1991,12 @@ class ManagerTest extends \Test\TestCase {
$share->setProviderId('foo')
->setId('42')
->setShareType(\OCP\Share::SHARE_TYPE_LINK)
- ->setSharedBy($user)
- ->setShareOwner($user)
+ ->setSharedBy('owner')
+ ->setShareOwner('owner')
->setPassword('password')
->setExpirationDate($tomorrow)
- ->setNode($file);
+ ->setNode($file)
+ ->setPermissions(15);
$manager->expects($this->once())->method('canShare')->willReturn(true);
$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
@@ -1905,6 +2016,10 @@ class ManagerTest extends \Test\TestCase {
'uidOwner' => 'owner',
]);
+ $hookListner2 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock();
+ \OCP\Util::connectHook('OCP\Share', 'post_update_permissions', $hookListner2, 'post');
+ $hookListner2->expects($this->never())->method('post');
+
$manager->updateShare($share);
}
@@ -1930,24 +2045,20 @@ class ManagerTest extends \Test\TestCase {
$share = $this->manager->newShare();
$share->setShareType(\OCP\Share::SHARE_TYPE_USER);
- $sharedWith = $this->getMock('\OCP\IUser');
- $share->setSharedWith($sharedWith);
+ $share->setSharedWith('sharedWith');
- $recipient = $this->getMock('\OCP\IUser');
-
- $this->manager->moveShare($share, $recipient);
+ $this->manager->moveShare($share, 'recipient');
}
public function testMoveShareUser() {
$share = $this->manager->newShare();
$share->setShareType(\OCP\Share::SHARE_TYPE_USER);
- $recipient = $this->getMock('\OCP\IUser');
- $share->setSharedWith($recipient);
+ $share->setSharedWith('recipient');
- $this->defaultProvider->method('move')->with($share, $recipient)->will($this->returnArgument(0));
+ $this->defaultProvider->method('move')->with($share, 'recipient')->will($this->returnArgument(0));
- $this->manager->moveShare($share, $recipient);
+ $this->manager->moveShare($share, 'recipient');
}
/**
@@ -1959,27 +2070,33 @@ class ManagerTest extends \Test\TestCase {
$share->setShareType(\OCP\Share::SHARE_TYPE_GROUP);
$sharedWith = $this->getMock('\OCP\IGroup');
- $share->setSharedWith($sharedWith);
+ $share->setSharedWith('shareWith');
$recipient = $this->getMock('\OCP\IUser');
$sharedWith->method('inGroup')->with($recipient)->willReturn(false);
- $this->manager->moveShare($share, $recipient);
+ $this->groupManager->method('get')->with('shareWith')->willReturn($sharedWith);
+ $this->userManager->method('get')->with('recipient')->willReturn($recipient);
+
+ $this->manager->moveShare($share, 'recipient');
}
public function testMoveShareGroup() {
$share = $this->manager->newShare();
$share->setShareType(\OCP\Share::SHARE_TYPE_GROUP);
- $sharedWith = $this->getMock('\OCP\IGroup');
- $share->setSharedWith($sharedWith);
+ $group = $this->getMock('\OCP\IGroup');
+ $share->setSharedWith('group');
$recipient = $this->getMock('\OCP\IUser');
- $sharedWith->method('inGroup')->with($recipient)->willReturn(true);
+ $group->method('inGroup')->with($recipient)->willReturn(true);
- $this->defaultProvider->method('move')->with($share, $recipient)->will($this->returnArgument(0));
+ $this->groupManager->method('get')->with('group')->willReturn($group);
+ $this->userManager->method('get')->with('recipient')->willReturn($recipient);
- $this->manager->moveShare($share, $recipient);
+ $this->defaultProvider->method('move')->with($share, 'recipient')->will($this->returnArgument(0));
+
+ $this->manager->moveShare($share, 'recipient');
}
}
diff --git a/version.php b/version.php
index f807b01d7d0..44bddca0700 100644
--- a/version.php
+++ b/version.php
@@ -25,7 +25,7 @@
// We only can count up. The 4. digit is only for the internal patchlevel to trigger DB upgrades
// between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel
// when updating major/minor version number.
-$OC_Version = array(9, 0, 0, 9);
+$OC_Version = array(9, 0, 0, 10);
// The human readable string
$OC_VersionString = '9.0 pre alpha';