Compare commits

...

631 Commits

Author SHA1 Message Date
Frank Karlitschek 927cae7efc 7.0.6 RC1 2015-05-29 13:58:39 -04:00
Vincent Petry b04d510053 Merge pull request #16608 from owncloud/fix_14588
[stable7] make sure to get the right list of users with access to the file when deleting a shared file
2015-05-28 16:53:55 +02:00
Bjoern Schiessle b4741cfa96 make sure to get the right list of users with access to the file, including the owner 2015-05-28 16:13:05 +02:00
Thomas Müller 55a122a9fe Merge pull request #13742 from owncloud/fix-12190-2-stable7
[backport #13740] backport #13740 to stable7
2015-05-26 16:06:21 +02:00
Morris Jobke 5014d2c60c Merge pull request #15402 from owncloud/response-setContentLengthHeader-stable7
[stable7] Add OC_Response::setContentLengthHeader() for Apache PHP SAPI workaround.
2015-05-20 10:15:58 +02:00
Morris Jobke 8a39256092 Merge pull request #15077 from owncloud/fix-smb-oc-admin-stable7
[stable7] Support constructing an SMB_OC without saved session credentials
2015-05-20 10:03:18 +02:00
Arthur Schiwon ae850d76ea add primary group users to resultset before caching 2015-05-14 01:09:57 +02:00
Morris Jobke 765526ec4c Merge pull request #15271 from owncloud/stable7-fix-ext-owncloud
[stable7] Fix bugs in ownCloud external storage
2015-05-13 09:40:20 +02:00
Thomas Müller 87052be76f Merge pull request #16291 from RealRancor/asset_pipe_note
Add note for asset pipeline and third-party apps on stable7
2015-05-13 00:52:20 +02:00
RealRancor 02ef384064 Add note for asset pipeline and third-party apps on stable7 2015-05-12 18:59:57 +02:00
Morris Jobke cf05d50654 Merge pull request #15863 from owncloud/public-reshare-webdav-stable7
[stable7] Fix webdav access for public reshare
2015-05-08 13:56:07 +02:00
Lukas Reschke f5a597b259 Merge pull request #16114 from owncloud/stable7-backport-15510-and-15465
[stable7] block cron.php and OCS API when in single user mode or maintenance mode
2015-05-08 12:13:24 +02:00
Thomas Müller 2c656b0e4c Fix singe user mode on public.php - take two 2015-05-06 12:14:34 +02:00
Thomas Müller 9c44e7bfb8 Fix single user check in case no user is logged in 2015-05-06 12:12:40 +02:00
Robin Appelman 0418b330d5 block ocs in single user mode 2015-05-06 12:10:02 +02:00
Robin Appelman 780530ec83 block webdav in single user mode 2015-05-06 12:08:58 +02:00
Robin Appelman 67c862c286 block cron when in single user mode 2015-05-06 11:51:14 +02:00
Joas Schilling 88006222a9 Disable OCS api when in maintenance mode 2015-05-06 11:50:08 +02:00
Lukas Reschke d01bfe3587 Merge pull request #15833 from owncloud/backport-files-external-fixes
Backport files external fixes
2015-05-05 12:22:35 +02:00
Robin Appelman 38644cffd4 fix subfolder reshares over webdav 2015-04-24 14:19:52 +02:00
Robin Appelman 2c10e31c8f resolve reshares in public webdav 2015-04-24 14:19:52 +02:00
Jörn Friedrich Dreyer e37f9c8351 use displayname lookup route in files_external settings 2015-04-23 14:23:17 +02:00
Jörn Friedrich Dreyer 79187fcb10 add lookup route for displaynames 2015-04-23 14:23:03 +02:00
Morris Jobke e72cd711ad Merge pull request #15332 from owncloud/dont_hide_exceptions
do not hide exception when ldap server has a hiccup
2015-04-22 22:48:29 +02:00
Arthur Schiwon 598f798c04 throw exception when LDAP Connection was lost 2015-04-22 15:22:11 +02:00
Jörn Friedrich Dreyer 919241cdda fix filesystem and encryption tests 2015-04-22 11:34:17 +02:00
Jörn Friedrich Dreyer f7db588e62 throw exception when backends don't provide a user instead of creating legacy local storages 2015-04-22 11:34:17 +02:00
Morris Jobke a2cc658f37 throw exception if setup is incomplete 2015-04-22 11:34:14 +02:00
Morris Jobke f830150acc more robust share dialog 2015-04-22 11:33:05 +02:00
Jörn Friedrich Dreyer 77a601c3fe fix_tests 2015-04-22 11:33:05 +02:00
Jörn Friedrich Dreyer 24037218dd do not disclose information, show generic error on login page 2015-04-22 11:33:05 +02:00
Jörn Friedrich Dreyer caae0e6f47 do not hide exception when ldap server has a hiccup 2015-04-22 11:32:58 +02:00
Arthur Schiwon 07988cf77c Fixes returns of group memberships and counting if all members have the specific groups as primary set. 2015-04-14 14:56:36 +02:00
Arthur Schiwon f3bd266787 Backport of #13740
inlcude AD primary group in user filter, if a group is selected. fixes #12190

fix counting of users in primary group

💄

adept to OC 7

and escape the search term

Conflicts:
	apps/user_ldap/lib/connection.php
2015-04-14 14:56:01 +02:00
Morris Jobke 03c9657607 Merge pull request #15559 from owncloud/backport-15541-stable7
[stable7] Add "Reply-To" support for sharing notifications
2015-04-13 08:50:22 +02:00
Lukas Reschke e6c2382a19 Add "Reply-To" support for sharing notifications
Very hacky backport of https://github.com/owncloud/core/pull/15541 - I changed the code path to use OC_Mail instead the OCP pendant since I didn't want to modify the public API. (OCP\Util::sendMail() is anyways deprecated with 8.1)
2015-04-12 23:03:32 +02:00
Morris Jobke 43b2f3c2dc Merge pull request #15435 from owncloud/dont_return_empty_groups
don't return null for not existing group id's
2015-04-10 14:23:38 +02:00
Jörn Friedrich Dreyer 1ae73f0e99 don't return null for not existing group id's 2015-04-07 13:47:10 +02:00
Andreas Fischer 3f23ae4a16 Add OC_Response::setContentLengthHeader() for Apache PHP SAPI workaround.
Do not send Content-Length headers with a value larger than PHP_INT_MAX
(2147483647) on Apache PHP SAPI 32-bit. PHP will eat them and send 2147483647
instead.

When X-Sendfile is enabled, Apache will send a correct Content-Length header,
even for files larger than 2147483647 bytes. When X-Sendfile is not enabled,
ownCloud will not send a Content-Length header. This prevents progress bars
from working, but allows the actual transfer to work properly.
2015-04-04 11:53:32 +02:00
Thomas Müller a4c0f259a5 Merge pull request #15370 from owncloud/stable7-backport-15353
Cron has to be executed with the correct user - fixes 13912 and others
2015-04-02 09:22:01 +02:00
Thomas Müller 6ebe04f8d4 Cron has to be executed with the correct user - fixes 13912 and others 2015-04-01 18:30:20 +02:00
Robin McCorkell 1c5a86a115 Fix bugs in ownCloud external storage 2015-03-27 12:31:20 +00:00
Morris Jobke 57d6c49a62 Merge pull request #15251 from owncloud/use_default_share_folder_oc7
always fall back to default share folder
2015-03-27 09:56:46 +01:00
Lukas Reschke 423311c7e8 Merge pull request #14498 from owncloud/kill-substr-mssql-stable7
[stable7] Remove hacky Substring support for MSSQL
2015-03-26 23:00:33 +01:00
Bjoern Schiessle 0cdeeec82b always fall back to default share folder 2015-03-26 22:46:43 +01:00
Morris Jobke 32bd2d15e3 Merge pull request #15072 from owncloud/fix_group_share
also call generateTarget for group shares
2015-03-26 22:24:42 +01:00
Morris Jobke ef1ddfc5db Merge pull request #14861 from owncloud/stable7-fix-sizepropagationwithshare
[stable7] Fix size propagation over shared storage boundary
2015-03-26 20:14:00 +01:00
Thomas Müller 529d45c5b2 Merge pull request #15161 from owncloud/stable7-fixcronconfig
[stable7] Fix config API usage in cron.php
2015-03-24 20:22:30 +01:00
Morris Jobke 0c72c99f04 Merge pull request #14889 from owncloud/backport-14849-stable7
[stable7] support paged results against 389ds.
2015-03-24 20:11:34 +01:00
Vincent Petry 2bb6a920e3 Fix config API usage in cron.php 2015-03-24 18:19:43 +01:00
Morris Jobke 1325649b4b Merge pull request #15141 from owncloud/backport-15123-stable7
[backport] [stable7] offset needs to be considered in computed limit
2015-03-24 11:12:16 +01:00
Arthur Schiwon bf7e2c756f offset needs to be considered in computed limit 2015-03-24 10:22:49 +01:00
Robin McCorkell 467da3c519 Support constructing an SMB_OC without saved session credentials
Conflicts:
	apps/files_external/lib/smb_oc.php
2015-03-20 16:07:19 +00:00
Bjoern Schiessle df2f85ee01 also call generateTarget for group share to add the correct prefix if share_folder is defined in config.php 2015-03-20 15:51:25 +01:00
Thomas Müller 9e52b174b1 Merge pull request #14902 from owncloud/tempmanager-fix-backport
Check directory handle before we use it
2015-03-16 09:44:52 +01:00
Robin McCorkell 03ca380815 Check directory handle before we use it 2015-03-15 18:28:01 +00:00
Arthur Schiwon db763760f1 support paged results against 389ds. 2015-03-13 23:03:47 +01:00
Robin Appelman 0ca1500330 also clear statcache in mapped local 2015-03-13 11:53:50 +01:00
Robin Appelman 92cbeefa34 Clear statcache before getting the mtime from local storage backends 2015-03-13 11:53:21 +01:00
Vincent Petry b62d20f2ee Uglify unit test to make them work on stable7 2015-03-13 11:36:31 +01:00
Vincent Petry 4f9c750a0a Add unit test for size propagation across share boundaries 2015-03-13 11:09:41 +01:00
Vincent Petry a529b2bf86 Fix size propagation over shared storage boundary 2015-03-13 11:09:36 +01:00
Thomas Müller 27ec925132 Merge pull request #14846 from owncloud/fix-14843-stable7
cron shall not operate in case we are in maintenance mode - fixes #14843
2015-03-13 09:25:18 +01:00
Thomas Müller c716776a90 cron shall not operate in case we are in maintenance mode - fixes #14843 2015-03-12 21:08:00 +01:00
Morris Jobke b588692ef4 Merge pull request #14637 from owncloud/backport-13341
[Stable7] Read version and product name from update template
2015-03-11 20:16:01 +01:00
Morris Jobke 5544509283 Merge pull request #14182 from RealRancor/update_office_preview
[stable7] Fix libre/openoffice preview on multi-user instances
2015-03-11 17:55:00 +01:00
Morris Jobke 39492eb020 Merge pull request #14707 from owncloud/ldap-reset-paged-search-on-null-limit-stable7
LDAP: reset paged search on null limit [stable7]
2015-03-09 08:15:18 +01:00
Arthur Schiwon 24eb2bcab5 set up paged search when limit is 0 2015-03-05 13:22:52 +01:00
Frank Karlitschek 8b83580af7 bump release 2015-03-02 22:45:17 +01:00
Frank Karlitschek 02757ad08e Merge pull request #14688 from owncloud/stable7-trashbin-selected-delete
[stable7] Fix deleting selected files in the trashbin
2015-03-04 08:54:56 -05:00
Robin Appelman 3bf505b566 Fix deleting selected files in the trashbin 2015-03-04 12:48:52 +01:00
Morris Jobke 1dea188fea Merge pull request #14642 from owncloud/issue/13751-only-variables-passed-by-reference
[Stable7] Fix "Only variables should be passed by reference" in stable7 template
2015-03-02 16:10:49 +01:00
Joas Schilling 86e4177914 Fix "Only variables should be passed by reference" in stable7 template 2015-03-02 14:31:38 +01:00
Vincent Petry ec71e0b4e6 Read version and product name from update template
During upgrade, the config settings aren't always available due to
base.php changes. This fix makes the update info page read the product
name and version from the update template, which already had them.
2015-03-02 11:39:23 +01:00
Lukas Reschke 51017e43a0 Remove hacky Substring support for MSSQL
Substring() is not required for the core functionality and this allows us to get rid of a huge hack...
2015-02-25 14:08:44 +01:00
Thomas Müller eb778eb2b0 Merge pull request #14425 from owncloud/backport-12313
[stable7] The class name is Movie NOT Movies
2015-02-23 15:12:57 +01:00
Olivier Paroz 45ad072c62 The class name is Movie NOT Movies
Conflicts:
	config/config.sample.php
	lib/private/preview.php
2015-02-23 11:02:46 +01:00
Frank Karlitschek 3ac33c865b 7.0.5 2015-02-16 04:56:33 +01:00
Lukas Reschke 431638742c Merge pull request #14040 from owncloud/stable7-app-upgrade-order
[Stable7] app upgrade order fix
2015-02-17 14:48:09 +01:00
Thomas Müller 7b432cbbf7 Merge pull request #12327 from owncloud/stable7l10nbport
backport some strings to stable7
2015-02-17 14:08:45 +01:00
Thomas Müller 01cede4511 Merge pull request #14254 from owncloud/console-execution-time-stable7
[backport-14243-stable7] console commands shall not be limited with respect to execution time
2015-02-16 19:44:07 +01:00
Thomas Müller 73954c44c6 console commands shall not be limited with respect to execution time - fixes #14156 2015-02-16 16:22:16 +01:00
Lukas Reschke e345ae7b53 Merge pull request #13988 from owncloud/group-share-collition-wrong-type-in-post-hook-stable7
[stable7] Do not overwrite the shareType so the post hook is still correct
2015-02-16 14:41:52 +01:00
RealRancor 9fd53ef84f Removed anchor in config.sample.php 2015-02-13 15:28:35 +01:00
RealRancor 6a46ede8b7 Fix libre/openoffice preview on multi-user instances 2015-02-12 23:20:54 +01:00
Jörn Friedrich Dreyer 3e5a1ad76b Merge pull request #14147 from owncloud/no-whitespace-from-themes-stable7
catch any whitespaces which might get written to the output buffer while...
2015-02-12 17:07:34 +01:00
Thomas Müller a45c606b96 catch any whitespaces which might get written to the output buffer while loading a theme 2015-02-12 11:28:59 +01:00
Thomas Müller fcad7252bd Merge pull request #14078 from owncloud/stable7-preview-hint
Add hint for troubleshooting MS Word previews
2015-02-11 21:17:59 +01:00
RealRancor c11edb9138 Add hint for troubleshooting MS Word previews 2015-02-11 01:14:58 +01:00
Vincent Petry 61852536fe Fix "other" app update stack 2015-02-10 11:58:25 +01:00
Arthur Schiwon d9d7774cc1 on ownCloud upgrade: upgrade all apps in order, load important ones 2015-02-10 11:58:23 +01:00
Joas Schilling 63e5282c41 Add a test for the post_shared hook shareType
Conflicts:
	tests/lib/share/share.php
2015-02-09 16:27:44 +01:00
Joas Schilling 0c3204c7a6 Do not overwrite the shareType so the post hook is still correct
Conflicts:
	lib/private/share/share.php
2015-02-09 16:26:29 +01:00
RealRancor c2a72ce6b0 external user app: Add note to enable it first 2015-02-07 20:12:15 +01:00
Lukas Reschke cbf8dd439c Normalize before processing 2015-02-06 15:09:31 +01:00
Frank Karlitschek c658ec658a 7.0.5 RC1 2015-02-06 02:46:00 +01:00
Morris Jobke 9db5323a92 Merge pull request #13927 from owncloud/fix_ghost_directories
fix creation of ghost directories
2015-02-06 00:07:43 +01:00
Bjoern Schiessle c58501ee87 for password protected link shares the password is stored in shareWith, so we need to set this manually to null for the hooks 2015-02-05 17:11:27 +01:00
Thomas Müller 3e9d8cce10 Merge pull request #13759 from owncloud/fix-12035
fix LDAP update routine to OC 7
2015-02-05 17:05:32 +01:00
Morris Jobke 6897be7a93 Merge pull request #13888 from owncloud/upload_to_root_of_mountpoint_stable7
detect root of mountpoint also if the trailing slash is missed
2015-02-04 16:21:34 +01:00
Björn Schießle f0b0e462ea Merge pull request #13796 from owncloud/issue/13490-stable7-backport
[stable7] use uid provided by setupfs hook to mount server2server shares
2015-02-04 14:59:44 +01:00
Bjoern Schiessle 2b83afdd7e detect root of mountpoint also if the trailing slash is missed 2015-02-04 14:53:17 +01:00
Morris Jobke a81b4c54d8 Merge pull request #13880 from owncloud/backport-10398-stable7
[backport #10398] Give a better error message for external shares with self-signed ssl cer...
2015-02-04 14:09:25 +01:00
Robin Appelman 7975b74816 Give a better error message for external shares with self-signed ssl certificates 2015-02-04 12:19:08 +01:00
Thomas Müller 361b70e4d7 Merge pull request #13803 from owncloud/revert-close-cursor-stable7
Revert "Close cursor early in calculateFolderSize" for now
2015-01-30 23:23:44 +01:00
Morris Jobke 8305ae6b09 Merge pull request #13798 from owncloud/update-sabre-dav-stable7
Update sabre dav to 1.8.12 on stable7
2015-01-30 16:10:34 +01:00
Joas Schilling 91fc933432 Revert "Close cursor early in calculateFolderSize"
This reverts commit 234f33e01e.
2015-01-30 15:35:54 +01:00
Joas Schilling ed60bdeac9 Update sabre dav to 1.8.12 on stable7 2015-01-30 14:43:41 +01:00
Joas Schilling bd14af5806 use uid provided by setupfs hook to mount server2server shares
otherwise mount will fail for public link shares

backport of 66f0db30b2
2015-01-30 12:57:03 +01:00
Vincent Petry 234f33e01e Close cursor early in calculateFolderSize
This method triggers additional queries in $this->update() so to avoid
potential database locks or delays, we close the cursor as soon as it is not needed any more
2015-01-29 14:53:44 +01:00
Arthur Schiwon 441f807bce fix update routine 2015-01-29 12:51:12 +01:00
Morris Jobke 80560e70b7 Merge pull request #13470 from owncloud/stable7-share-fixfindshareforuserwithmultiplegroups
[stable7] Fix getItemSharedWithUser for groups
2015-01-23 12:59:39 +01:00
Georg Ehrke 56c51d481c add config-option for an image's maximum filesize when generating previews 2015-01-22 23:23:36 +01:00
Georg Ehrke 2d2e024cfa remove insane debug-log from OC_Image 2015-01-22 23:21:40 +01:00
Morris Jobke 491c714f54 Fix undefined offset 1 for wrong user mail address
* fixes Undefined offset: 1 at lib/private/mail.php#143
2015-01-22 17:26:13 +01:00
Robin Appelman 8459b9f6fb Add unit test 2015-01-22 16:18:36 +01:00
Robin Appelman 153ff1b766 Remove duplicated slashes from the requested url 2015-01-22 16:18:32 +01:00
Morris Jobke 11efe732f9 Merge pull request #13555 from owncloud/issue/13482-stable7
Stable7 Backport Set the debugoutput channel to error_log instead of echoing it
2015-01-21 16:31:04 +01:00
Joas Schilling f03a1868ab Set the debugoutput channel to error_log instead of echoing it 2015-01-21 15:34:58 +01:00
Arthur Schiwon 1c000b799b this must be larger then (>), since buggy behaviour occurs when the parameter is a small number 2015-01-21 14:38:47 +01:00
Vincent Petry 18d46dfdeb Fix getItemSharedWithUser for groups
Fixed SQL query for whenever a user has more than one group.
Added missing $owner where clause for group lookup.
Added unit tests for the group cases.

Backport of 40931a8b0d from master
2015-01-20 22:07:21 +01:00
Thomas Müller 9d761fcaee Merge pull request #13422 from owncloud/user-mgnt-init-fix
Increase initial user count to 50
2015-01-19 15:08:16 +01:00
Carla Schroder 5f70ed188b Note in config.sample.php that certain previews are not available in ms windows 2015-01-17 09:27:27 +01:00
Morris Jobke 616fd4b54a Increase initial user count to 50
* fix initial user count if you have a big screen (or a portrait screen)
2015-01-16 18:04:29 +01:00
Thomas Müller 6d87922cea Merge pull request #13384 from owncloud/stable7-fix-13317-backport
Fix backport of #13317
2015-01-15 17:27:09 +01:00
Robin Appelman 0753514e5b Fix test 2015-01-15 14:24:54 +01:00
Robin Appelman 7ef006e1c9 php <5.4 style array 2015-01-15 14:02:36 +01:00
Robin Appelman 5a58d142e5 Proper constant for stable7 2015-01-15 14:02:11 +01:00
Robin Appelman db51d9aacb Add View::getMount() for stable7 2015-01-15 14:01:52 +01:00
Vincent Petry d534f262aa Use source storage permissions when scanning shared storage 2015-01-15 11:15:39 +01:00
Robin Appelman 0f04bfc319 Return valid fileinfo objects for part files 2015-01-15 00:22:38 +01:00
Morris Jobke 4d42485bf5 drop useless "!!! No reuse of etag" - fixes #13187
Backport of 9b49b52fc6 from master
2015-01-13 13:47:09 +01:00
Arthur Schiwon 713f2b3a52 fix retrieval of user groups
Conflicts:
	apps/user_ldap/lib/connection.php
2015-01-13 10:19:50 +01:00
Morris Jobke 0d39a63b05 Merge pull request #13186 from owncloud/no-session-for-formfactor-stable7
no need to store the form factor in the session - it's computation is ra...
2015-01-09 18:19:26 +01:00
Jan-Christoph Borchardt bd1bf9e9ac replace outdated 'shared' people icon with regular share icon as fallback 2015-01-09 17:58:45 +01:00
Thomas Müller 6552fec113 no need to store the form factor in the session - it's computation is rather cheep
Conflicts:
	lib/private/template.php
2015-01-09 10:19:28 +01:00
Morris Jobke d5190b5481 Merge pull request #12735 from owncloud/temp-handling-stable7
[stable7] Cleanup handling of temporary files
2015-01-08 18:35:00 +01:00
Robin Appelman 06bc987bd9 Use the TempManager to handle temporary files
Conflicts:
	lib/private/helper.php
2015-01-08 16:22:14 +01:00
Robin Appelman 344606b2c8 Add \OC\TempManager to handle creating and cleaning temporary files
Conflicts:
	lib/private/server.php
	lib/public/iservercontainer.php
2015-01-08 16:22:14 +01:00
Vincent Petry a5574e885c Fix source path when share is a mount point
Whenever an external storage mount point is shared directly, its path is
empty which causes a leading slash to appear in the source path.

This fix removes the bogus leading slash in such situation.

Backport of 01c83158bb from master
2015-01-08 16:07:44 +01:00
Robin Appelman bf1f9df590 Prevent leaking db connection info in the stacktrace 2015-01-07 09:48:25 +01:00
Morris Jobke 2fd2b182e7 Check for version before mounting a public link
* ownCloud 7.0.0 is needed - version of merge of server <-> server
  sharing - https://github.com/owncloud/core/pull/8399
* adjust error message
2015-01-05 13:23:53 +01:00
Byron Marohn 8778af681c Added error check to lib/private/image.php
This checks that imagecreatetruecolor actually creates an image, rather than returning FALSE.
Without this check, subsequent loop might create billions of ERROR-level log messages.

Signed-off-by: Byron Marohn <combustible@live.com>
2015-01-02 08:48:59 +01:00
blizzz fb63e75743 Merge pull request #12643 from owncloud/ldap-user-cleanup-stable7
LDAP User Cleanup - stable7
2014-12-19 19:04:50 +01:00
Morris Jobke 4c0af1b2a2 Merge pull request #12332 from owncloud/langbport2
more strings to backport
2014-12-19 14:14:03 +01:00
Morris Jobke 9c38baac9e show spinner on file upload in IE8, 9 2014-12-19 02:04:35 +01:00
Arthur Schiwon dd18f963d4 and don't forget to adjust tests 2014-12-18 12:22:34 +01:00
Arthur Schiwon 5d46dfd2b4 PHPdoc fixes, no code change 2014-12-17 16:08:01 +01:00
Arthur Schiwon 1d54735d5d forgotten file 2014-12-17 13:52:09 +01:00
Arthur Schiwon cb5f9d2164 add ldap:check-user to check user existance on the fly 2014-12-17 13:37:53 +01:00
Jan-Christoph Borchardt a26ddb33a2 Merge pull request #12798 from cyberb/stable7
fixes #12434 (stable7)
2014-12-16 14:35:11 +01:00
Arthur Schiwon dd8ba68e07 LDAP User Cleanup
background job for user clean up

adjust user backend for clean up

register background job

remove dead code

dependency injection

make Helper non-static for proper testing

check whether it is OK to run clean up job. Do not forget to pass arguments.

use correct method to get the config from server

methods can be private, proper indirect testing is given

no automatic user deletion

make limit readable for test purposes

make method less complex

add first tests

let preferences accept limit and offset for getUsersForValue

DI via constructor does not work for background jobs

after detecting, now we have retrieving deleted users and their details

we need this method to be public for now

finalize export method, add missing getter

clean up namespaces and get rid of unnecessary files

helper is not static anymore

cleanup according to scrutinizer

add cli tool to show deleted users

uses are necessary after recent namespace change

also remove user from mappings table on deletion

add occ command to delete users

fix use statement

improve output

big fixes / improvements

PHP doc

return true in userExists early for cleaning up deleted users

bump version

control state and interval with one config.php setting, now ldapUserCleanupInterval. 0 will disable it. enabled by default.

improve doc

rename cli method to be consistent with  others

introduce ldapUserCleanupInterval in sample config

don't show last login as unix epoche start when no  login happend

less log output

consistent namespace for OfflineUser

rename GarbageCollector to DeletedUsersIndex and move it to user subdir

fix unit tests

add tests for deleteUser

more test adjustements
2014-12-15 12:56:16 +01:00
Morris Jobke bfe4ee6e47 Merge pull request #12825 from d1saster/stable7-fixpcre
make regex in controllermethodreflector.php compatible with PCRE 6.x
2014-12-14 10:51:56 +01:00
Morris Jobke a429fa74d9 Merge pull request #12655 from owncloud/fix-appstore-link
fix broken link on app management page for apps without ocsid
2014-12-13 11:54:30 +01:00
Morris Jobke f0a0e44d2e fix broken link on app management page for apps without ocsid - fix #9574, fix #10461 2014-12-13 08:39:38 +01:00
Philipp Knechtges 533e8e14b6 make regex in controllermethodreflector.php compatible with PCRE 6.x
The syntax ?<...> seems to be only supported from PCRE 7.0 on. For
backwards-compability ?P<...> is used.
2014-12-13 02:16:37 +01:00
Vincent Petry 60099b91c4 Merge pull request #12624 from nazar-pc/stable7
Backport of #11524 into stable7
2014-12-12 11:34:40 +01:00
Georg Ehrke 5fd1d54607 remove ugly hack and don't use OC\Preview\Image for tiffs and svgs 2014-12-12 08:30:17 +01:00
Vincent Petry 0eb3496ab6 Return real mime type on PROPFIND
Return the real (insecure) mime type on PROPFIND
2014-12-12 08:29:44 +01:00
Robin Appelman bd06b4cf42 Ensure user mountpoints are setup when using getUserFolder 2014-12-12 08:29:15 +01:00
Vincent Petry 72c0cc2267 Do not remove dir entry if it has the same name as the parent
This fixes an issue when a subdir has the same name as its parent, it
would get exluded from the list.
2014-12-11 23:57:17 +01:00
Boris Rybalkin 43b6676d0e fixes #12434 2014-12-11 18:44:50 +00:00
Morris Jobke 36e7d3b7da Merge pull request #12663 from zinks-/l10n-fr-backport
Patched french translation (backported from master)
2014-12-10 08:59:11 +01:00
Morris Jobke 7a60651037 Merge pull request #12656 from owncloud/stable7-fix-12164
Wipe cache if there is no response from feed
2014-12-10 08:26:02 +01:00
Robin Appelman 50705cfaf8 Add js unit test 2014-12-10 08:24:35 +01:00
Robin Appelman 3720ba9318 Dont show the delete button for selected files if one of the selected files is not deletable 2014-12-10 08:24:31 +01:00
Robin Appelman a05fc9dc73 Check if files are deletable before trying to delete them 2014-12-10 08:24:27 +01:00
Morris Jobke cf0a12f999 fix placeholder fake in IE8 & 9 that brokes group listing in user management - fixes #12525 2014-12-10 08:23:26 +01:00
Volkan Gezer 5fcc3401e2 translated saved message in files external 2014-12-10 08:23:03 +01:00
Victor Dubiniuk 60b2dd6ab4 Skip headers that can not be split 2014-12-10 08:22:06 +01:00
Morris Jobke ed96f8c628 remove duplicate loaded personal.js - fixes #12674 2014-12-10 08:21:40 +01:00
Frank Karlitschek 77bcc5b2f3 7.0.4 2014-12-08 19:27:21 +01:00
Arthur Schiwon 1b1951a64f add doc 2014-12-08 19:18:28 +01:00
Arthur Schiwon a33dcd359a preserve an asterisk at the start when escaping a search term 2014-12-08 19:18:24 +01:00
Lukas Reschke 55ebf024a7 Create config if it does not exists
The codepath that is executed when executing ownCloud via CLI is different than via browser. Specifically, the config is created by the user session already in `OC_Util::getInstanceId()` by a call to `setValue`. That said, this seems to be quite a bad side-effect, but for the sake of "not breaking whatever might break if we touch this" let's keep it that way for now.

When executing the autoconfig via `php -f index.php` the said session was not setup and thus no `config/config.php` file was created resulting in an installation error.

To reproduce this try to setup ownCloud via `php -f index.php` with and without that patch. (ensure to delete all existing configs before and don't access ownCloud with a browser in the meantime)

Fixes itself.
2014-12-07 22:34:55 +01:00
Victor Dubiniuk 21f467dd36 Wipe cache if there is no response from feed 2014-12-06 15:19:34 +03:00
Thomas Imbreckx 26e504e096 Patched french translation (backported from master) 2014-12-05 19:14:08 +01:00
Lukas Reschke 5d56eba398 Add test for IPv6 without port 2014-12-05 11:29:04 +01:00
Lukas Reschke 0b80c5e18e Add workaround for older instances
To be removed with oCAdd workaround for older instances

To be removed with oC99
2014-12-05 11:29:00 +01:00
Lukas Reschke be26cccd8a Trim port from domain
Depending on the used environment the port might be appended to the host header resulting in an inaccessible instance when initially setting up on a system with a different HTTP or HTTPS port. (for example test:500)

To test this setup ownCloud under a different port with and without this patch. (heads-up: localhost is always white-listed, so use a different domain)
2014-12-05 11:28:56 +01:00
Frank Karlitschek 71bd33da98 7.0.4 RC2 2014-12-05 04:24:13 +01:00
Björn Schießle 3c673717b0 Merge pull request #12623 from owncloud/fix-s2s-oc7
password column needs to allow null (oc7 backport)
2014-12-04 22:24:57 +01:00
blizzz 01a176f2a3 Merge pull request #12309 from owncloud/ldap-cache-user-count
LDAP: cache total  user count
2014-12-04 19:08:20 +01:00
blizzz af1c47d1e8 Merge pull request #12493 from owncloud/ldap_search_perf
LDAP search behaviour modifications
2014-12-04 18:58:18 +01:00
Vincent Petry 913ad8634f Merge pull request #11524 from nazar-pc/patch-1
Page size calculation based on real page height
2014-12-04 17:07:41 +01:00
Bjoern Schiessle 79711c32b7 password column needs to allow null otherwise Oracle will break for empty passwords 2014-12-04 16:18:16 +01:00
Arthur Schiwon ddd832c2dc trim search string before passing it on 2014-12-04 15:29:16 +01:00
Thomas Müller d30059d76c Merge pull request #12528 from owncloud/backport-12419
Allow read-only configuration
2014-12-03 17:48:25 +01:00
Morris Jobke 5fe7781452 add proper description what database is supported by CE and EE 2014-12-03 13:14:58 +01:00
Frank Karlitschek 8fc4f67f14 7.0.4 RC1 2014-12-01 21:42:19 +01:00
Lukas Reschke f5d9513957 Allow read-only configuration
Workaround required for IIS setups running ownCloud to prevent dataloss.

Long-term solution would be to move some configuration settings to the database

Conflicts:
	lib/base.php
	settings/admin.php
2014-12-01 17:26:21 +01:00
Vincent Petry 3917383cef Merge pull request #11747 from owncloud/storeCredentialsOnlyInSessionIfRequired
Store credentials only in session if required
2014-12-01 11:07:57 +01:00
Thomas Müller 46a4af1dc2 Merge pull request #12496 from owncloud/check-xml-writer-for-7
Check for XMLWriter class
2014-12-01 10:53:50 +01:00
Lukas Reschke 2954169512 Adjust sample config 2014-11-28 19:20:11 +01:00
Lukas Reschke b122b285c9 Disable MSSQL for new CE installations
Since automatic schema migrations are not yet possible let's disable this for now.

Conflicts:
	lib/private/setup.php
2014-11-28 19:19:48 +01:00
Lukas Reschke 85b7ee349b Check for XMLWriter class
Backport of https://github.com/owncloud/core/pull/12321
2014-11-28 15:43:08 +01:00
Arthur Schiwon 7484c2f0d8 LDAP search filter creation changes:
1. do not prepend * wildcard to search terms. Will result in faster search, but
you don't find "foobar"  when looking for "bar"
2. advanced behaviour when search string contains a space and multiple search
attributes are present. The search string is split into single words. The
resulting filter requires that each word at least appears once in any search
attribute. This is supposed to return better results in big LDAPs.
2014-11-28 13:31:57 +01:00
Arthur Schiwon 2944f952dc add ldap-search command to occ 2014-11-28 12:32:38 +01:00
Carla Schroder 9b414d81d8 Markup corrections 2014-11-28 10:20:12 +01:00
Carla Schroder 5ac96c0a87 Add notes that SQLite is CE only 2014-11-28 10:20:08 +01:00
Georg Ehrke a60e113fa8 delete old previews 2014-11-27 12:09:56 +01:00
Carla Schroder 392e36d4e4 added comment that App Store is disabled for EE 2014-11-26 17:56:51 +01:00
Lukas Reschke 8b3728ed9b Don't show favicon to prevent iteration through subfolders
The codepath for generating the favicons iterates through subnodes and if one of those nodes is unavailable is throwing a 503 exception. Since these favicons don't have any use except of "making a tool for developers looking nicer" I consider it feasible to remove them.
2014-11-26 17:07:24 +01:00
Miguel Prokop b96b601017 Consolidate if statement, and update unit test 2014-11-26 13:04:20 +01:00
Miguel Prokop cdf37a061b fix calculation of expiration date if there is a default expiration date set (but not forced) and the user does not want the link to expire. 2014-11-26 13:03:45 +01:00
Morris Jobke b1f838814d Merge pull request #12397 from owncloud/fix-undefined-appitem
[stable7] fixes undefined appitem - fixes #12396
2014-11-26 11:18:15 +01:00
Morris Jobke 161e58b1a2 Merge pull request #12415 from owncloud/port-12262
Backport #12262
2014-11-25 15:45:27 +01:00
Lukas Reschke d815638f7b Try to read the file only instead of trying to touch
The permissions are already catched properly on the installation so we just have to check whether the file is readable to prevent fatal errors from happening.

Fixes https://github.com/owncloud/core/issues/12135

Conflicts:
	lib/private/config.php
2014-11-25 14:40:52 +01:00
Bjoern Schiessle 384d1892aa use login name to verify password 2014-11-25 14:09:22 +01:00
Lukas Reschke 32a90911b0 The "dir" key is used within the public sharing template to indicate in which directory the user currently is when sharing a directory with subdirectories. This is needed by the JS scripts.
However, when not accessing a directory then "dir" was set to the relative path of the file (from the user's home directory), meaning that for every public shared file the sharee can see the path.
(For example if you share the file "foo.txt" from "finances/topsecret/" the sharee would still see the path "finances/topsecret/" from the shared HTML template)

This is not the excpected behaviour and can be considered a privacy problem, this patch addresses this by setting "dir" to an empty key.

Port of https://github.com/owncloud/core/pull/12262, approved with https://github.com/owncloud/core/pull/12262#issuecomment-64394040
2014-11-25 13:52:44 +01:00
Morris Jobke 6967512c5f fixes undefined appitem - fixes #12396 2014-11-25 09:06:49 +01:00
Morris Jobke 8ea0187ecd Merge pull request #12373 from owncloud/backport_preview_fixes_stable7
Backport preview fixes stable7
2014-11-24 13:28:00 +01:00
Lukas Reschke abc7f143da Use / as redirect location if webroot is set to an empty value
If the webroot has been set to an empty value or ownCloud has been installed at the root location (`/``) there is a fair chance that the redirect for password resets does not work at all.

This means that while the password is getting resetted the user is not redirected to the login page.

I'm aware that it might be better to just set the webroot to `/` in those cases but this patch is better in the regard that it cannot break stuff.

Thanks to @PVince81 for helping me debugging this. (I'm a moron and assumed it couldn't be THAT easy)

Reported by @cdamken
2014-11-24 11:12:01 +01:00
Georg Ehrke d7779f9209 delete all children's previews when deleting a folder
add phpdoc

Conflicts:
	lib/private/preview.php
2014-11-23 21:45:01 +01:00
Georg Ehrke 4c5aa43079 add y to with-aspect naming schema 2014-11-23 21:43:21 +01:00
Volkan Gezer 11ca5588ea more strings to backport 2014-11-20 16:51:10 +01:00
Vincent Petry 3ff1f879e0 Merge pull request #12131 from owncloud/stable7-enc-recoverykeywithextstoragefix
[stable7] Fix file upload to ext storage when recovery key is enabled
2014-11-20 16:43:20 +01:00
Lukas Reschke 74b68e10e4 Only store user credentials when SMB_OC storage is enabled 2014-11-20 16:05:42 +01:00
Lukas Reschke ec853da5ad Backport \OC\Security\Crypto to ownCloud 7
Conflicts:
	lib/repair/repairconfig.php
2014-11-20 16:05:42 +01:00
Volkan Gezer c494887d98 backport some strings to stable7 2014-11-20 15:13:37 +01:00
Vincent Petry f64c6c9c9c Show warning when invalid user was passed
Sometimes there are bugs that cause setupFS() to be called for
non-existing users. Instead of failing hard and breaking the instance,
this fix simply logs a warning.

Backport c941c3fa51 from master
2014-11-20 13:46:19 +01:00
Arthur Schiwon 56fabf8adf cache total user count 2014-11-19 20:27:20 +01:00
Craig Morrissey 42ada6cb15 adjust autocomplete behavior for sharing menu 2014-11-19 17:01:13 +01:00
Joas Schilling 54607a2142 Merge pull request #12288 from owncloud/backport-mapper-fixes
Backport mapper fixes
2014-11-19 16:29:30 +01:00
Joas Schilling 6a6b645b83 Merge pull request #12291 from owncloud/issue/10991-stable7-backport
Issue/10991 stable7 backport
2014-11-19 16:19:06 +01:00
Clark Tomlinson 2f1270278d fixing cache routes
Conflicts:
	tests/lib/cache/file.php
	tests/lib/cache/usercache.php
2014-11-19 11:07:55 +01:00
Lukas Reschke f235e8b803 Fix mapping of relative paths 2014-11-19 10:21:14 +01:00
Joas Schilling baf8d8433f Use md5() of the original name instead of uniqid() for slugifying
Previously we used uniqid() here.
However this means that the behaviour is not reproducable, so
when uploading files into a "empty" folder, the folders name is
different.

If there would be a md5() hash collition, the deduplicate check
will spot this and append an index later, so this should not be
a problem.

Fix #6722
2014-11-19 10:17:36 +01:00
Joas Schilling f5bd8e4947 Fix code layout before fixing the function 2014-11-19 10:17:30 +01:00
Bjoern Schiessle d49e3d0ceb use the new base class for share/share.php tests 2014-11-19 10:07:03 +01:00
Joas Schilling bc76998cd2 Simple fix for the wrong Mapper reset 2014-11-19 10:06:15 +01:00
Joas Schilling f371f14fc2 Back to OC_Util::generateRandomBytes() 2014-11-19 10:06:14 +01:00
Joas Schilling 4e1799759c Correctly restore previous root mount point after testing
Conflicts:
	tests/lib/cache/file.php
	tests/lib/cache/usercache.php
2014-11-19 10:06:13 +01:00
Joas Schilling 122f3ff594 Correctly refresh the apps list after removing the mock 2014-11-19 10:06:12 +01:00
Joas Schilling a19fd8880d Fix Files\Storage\Home::testRoot() 2014-11-19 10:06:11 +01:00
Joas Schilling e3a9a19d95 Make it possible to cleanPath() absolute Windows paths 2014-11-19 10:06:10 +01:00
Joas Schilling 75e8d2ad6e Fix single run of encryption tests and usages of uniqid() and fopen()
Conflicts:
	apps/files_encryption/tests/crypt.php
	apps/files_encryption/tests/helper.php
	apps/files_encryption/tests/hooks.php
	apps/files_encryption/tests/keymanager.php
	apps/files_encryption/tests/proxy.php
	apps/files_encryption/tests/share.php
	apps/files_encryption/tests/stream.php
	apps/files_encryption/tests/trashbin.php
	apps/files_encryption/tests/webdav.php
2014-11-19 10:06:09 +01:00
Joas Schilling 2dc688dcdf Skip some more tests on Windows which just can not work at all
Conflicts:
	tests/lib/archive/tar.php
	tests/lib/files/storage/local.php
	tests/lib/files/view.php
2014-11-19 10:06:08 +01:00
Joas Schilling ce79974888 Windows does not support CHMOD, therefor we can not test not writable folders
Conflicts:
	tests/lib/tempmanager.php
2014-11-19 10:06:07 +01:00
Joas Schilling 060a40ad43 Test LargeFileHelperGetFileSize also with ascii only characters
And skip the UTF8 names on Windows as they are not supported
2014-11-19 10:06:06 +01:00
Joas Schilling ce3e5a8538 Do not use uniqid in Group and User tests as it is not unique on windows 2014-11-19 10:06:05 +01:00
Joas Schilling 9384fa65b5 Testcase base class 2014-11-19 10:06:04 +01:00
Bjoern Schiessle e6e0573756 only users can have a display name different from the id 2014-11-18 17:29:00 +01:00
Bjoern Schiessle fcde4c70a2 make sure that we only find the shares from the correct share type if users and groups with the same ID exists 2014-11-18 17:27:10 +01:00
Bjoern Schiessle b7cf8fac34 make sure that we don't find the wrong shares if a user and a group have the same ID 2014-11-18 17:26:55 +01:00
Morris Jobke 0271e7539d Merge pull request #12154 from owncloud/ignore-port-for-trusted-domain
Ignore port for trusted domains
2014-11-18 10:53:22 +01:00
Morris Jobke 3acd98f331 add newline 2014-11-18 10:48:38 +01:00
Lukas Reschke 74a625155d Merge pull request #12223 from owncloud/fix-unit-tests-s7
Backport #12181
2014-11-17 13:48:56 +01:00
Michael Roitzsch 643835e2b3 file size on non-(Linux/BSD/Windows)-installations
Determining the file size using the exec() method is implemented for Linux, BSD, and Windows. However, on systems matching neither platform name (like SunOS), the fall-through path will return a file size result constituting a zero size instead of an invalid null return value.
2014-11-17 13:42:23 +01:00
Lukas Reschke a843129a06 Backport #12181
This should fix the stable7 unit tests again since the last CI update.
2014-11-17 12:48:13 +01:00
Vincent Petry 0ab77083c6 Fix file upload to ext storage when recovery key is enabled
Fixes an issue when uploading files to external storage when recovery
keys are enabled

The Util class only works with real users, so instantiating it with the
virtual recovery key user or public key user can cause issues.
2014-11-17 11:38:40 +01:00
Lukas Reschke 32401b42f1 Check if app is enabled for user
Fixes https://github.com/owncloud/core/issues/12188 for AppFramework apps
2014-11-15 14:40:48 +01:00
Clark Tomlinson 4fbd6023f0 Hiding add to your own cloud if server2server sharing is not enabled 2014-11-13 22:45:00 +01:00
michag86 b35a5b5a85 cleanup group admin(s) on deleteGroup 2014-11-13 22:40:12 +01:00
michag86 135479cae2 removal of wrong/double implemented check
Check already implemented in core/settings/ajax/changedisplayname.php
2014-11-13 18:32:13 +01:00
michag86 29fd95967b fix for issue #10880 2014-11-13 18:30:16 +01:00
Lukas Reschke c8a48272c5 Add repair steps for legacy config files
Remove all ports from the trusted domains
2014-11-13 13:34:11 +01:00
Lukas Reschke 2b3b4272f8 Merge pull request #12109 from owncloud/add-preupdate-before-upgrade
Run preupdate before an update
2014-11-13 12:07:10 +01:00
Lukas Reschke 786007c78c Ignore port for trusted domains
This lead to a lot of confusion in the past and did not really offer any value. Let's remove the port check therefore. (it's anyways not really a part of the domain)

Fixes https://github.com/owncloud/core/issues/12150 and https://github.com/owncloud/core/issues/12123 and also a problem reported by @DeepDiver1975.
2014-11-13 11:15:47 +01:00
Andreas Fischer 1e5a39ea6c user_ldap: Reimplement convertSID2Str() without BCMath dependency.
Also explicitly format sub-id integers as unsigned, which is required for
32-bit systems.
2014-11-12 19:47:44 +01:00
Vincent Petry d859d1b6c7 Fix root path handling for WebDAV ext storage
Added missing cleanPath() call that converts "/" to "" when calling
SabreDAV. This is needed because SabreDAV will discard its base URL when
passing "/".
2014-11-12 12:09:15 +01:00
Lukas Reschke 778efcb054 Run preupdate before an update
The update routine tries to test the database migration before actually performing the update.

However, this will fail hard if the schema has changed (for example an unique key has been added). App developers can convert the DB in preupdate.php, however it is not called before and therefore the update fails.

This actually breaks ownCloud updates from ownCloud 6 to ownCloud 7 when the files_antivirus app is enabled.
2014-11-11 20:22:23 +01:00
Morris Jobke f52662ab26 Fix infinite loop if count and limit is 0
* otherwise it will always think it hits the limit and need another round to fetch additional results
2014-11-11 13:39:48 +01:00
Arthur Schiwon fea444b941 dont fail with 500 if configured display name attribute is not set 2014-11-11 13:28:48 +01:00
Frank Karlitschek 27c29c0c58 updating 7.0.3 2014-11-10 17:09:50 +01:00
Thomas Müller afc4224aff Merge pull request #12083 from owncloud/fix-occ-upgrade
Ensure there is a connection object within \OC_DB::enableCaching()
2014-11-10 17:01:53 +01:00
Thomas Müller 042bfabf64 Ensure there is a connection object within \OC_DB::enableCaching() 2014-11-10 16:17:08 +01:00
Morris Jobke e9ebbcb47e Login Name -> Username in user management 2014-11-10 11:17:18 +01:00
Lukas Reschke 35a71cc9a5 Use proper array key
Fixes https://github.com/owncloud/core/issues/12047
2014-11-08 15:47:40 +01:00
Frank Karlitschek ddccbb9530 7.0.3 2014-11-07 20:26:18 +01:00
Craig Morrissey 5ef6c4e03d logging changes 2014-11-07 12:44:18 -05:00
Vincent Petry b6c868ec88 Merge pull request #11994 from owncloud/stable7-sabre-convertstoragenotavailableexception
[stable7] Convert StorageNotAvailableException to SabreDAV exception
2014-11-07 16:25:27 +01:00
Morris Jobke 32625aff30 JS unit tests fix - use toBeUndefined() instead of toEqual(null) 2014-11-07 14:31:39 +01:00
Frank Karlitschek 2fb1ed84f2 7.0.3 RC3 2014-11-06 14:45:41 +01:00
Bjoern Schiessle 9255da9856 check if the provided password is really the current log-in password 2014-11-06 14:35:48 +01:00
Vincent Petry 2db69a5328 Convert StorageNotAvailableException to SabreDAV exception
Convert \OCP\Files\StorageNotAvailableException to
\Sabre\DAV\Exception\ServiceUnavailable for every file/directory
operation happening inside of SabreDAV.

This is necessary to avoid having the exception bubble up to remote.php
which would return an exception page instead of an appropriate response.

Conflicts:
	lib/private/connector/sabre/directory.php
	lib/private/connector/sabre/file.php
2014-11-06 11:23:20 +01:00
Morris Jobke 4c46a2f162 Merge pull request #11964 from canepan/patch-1
Fixed a typo in translation
2014-11-06 09:49:30 +01:00
Bernhard Posselt 6d7a5bf943 fix typo in content type 2014-11-05 14:35:11 +01:00
Lukas Reschke 8d87a2c4a6 Support HTML in logo claim 2014-11-05 13:55:15 +01:00
Thomas Müller 42197e2ce3 Merge pull request #11944 from owncloud/stable7backportl10n
backport some strings to stable7
2014-11-05 13:50:19 +01:00
Thomas Müller 61c802935b adjust strings - fixed #11930 2014-11-05 13:44:30 +01:00
canepan b6334a2da5 Fixed a typo in translation 2014-11-05 11:51:37 +01:00
Vincent Petry acc547c5ff Merge pull request #11950 from owncloud/stable7-s2s-fixcertcheckwhennocertfile
[stable7] Check for cert bundle existence before using it
2014-11-04 20:52:41 +01:00
Vincent Petry b509fdb30f Store curl error message directly 2014-11-04 20:06:17 +01:00
Vincent Petry 3f35822e24 Check for cert bundle existence before using it 2014-11-04 16:49:25 +01:00
Volkan Gezer d5316623dc backport some strings to stable7 2014-11-04 14:36:44 +01:00
Vincent Petry 8339aeab9a Only rescan trash folder when checking deleted versions
This fix prevents the file scanner to rescan the WHOLE storage and reset
the etags by mistake.

Backport of 97a51c46ed from master
2014-11-04 14:17:32 +01:00
Morris Jobke f718e88aa1 fix config.sample.php linebreak 2014-11-04 09:23:56 +01:00
Vincent Petry 38783b1ca3 Capitalize Checks in admin page 2014-11-03 15:46:40 +01:00
Jörn Friedrich Dreyer 56fade9a04 add driver options to config samples 2014-11-03 14:22:57 +01:00
Jörn Friedrich Dreyer 70e68280b8 allow passing driver options, fixes #11718 2014-11-03 14:22:27 +01:00
Bjoern Schiessle 840f5487aa don't move versions if only the mount point was renamed 2014-11-03 13:32:19 +01:00
Lukas Reschke 920e991c82 Fix typo 2014-11-03 13:31:58 +01:00
Bjoern Schiessle 67c3ab92cf get the source path and owner in a pre hook and the target path and owner in a
post hook
2014-11-03 13:31:45 +01:00
Lukas Reschke 3bc748d43f Merge pull request #11614 from owncloud/fix_files_external_s3_storage_id_migration
fix files_external storage id migration
2014-10-31 10:22:20 +01:00
Arthur Schiwon aeb9e172a9 on xp'ed mode and switching configurations: save raw mode instead of toggling filter mode in tabs since their status is unknown and dealt with by the Wizard. Fixes #11848
Backport of 8a48b088ed from master
2014-10-31 08:39:36 +01:00
Lukas Reschke 1025c30885 Fix stupid copy paste fail
...
2014-10-30 16:09:52 +01:00
Morris Jobke 4aae60a375 update 3rdparty to match it's stable7 branch 2014-10-30 13:44:43 +01:00
Morris Jobke 05a15a9669 Merge pull request #11865 from owncloud/stable7-fix-enc-sharingtests
Properly register sharing hooks and proxies
2014-10-30 13:39:45 +01:00
Vincent Petry 43e01439d6 Properly register sharing hooks and proxies
This will fix failing tests when shares weren't cleant up on delete due
to missing hooks.

Added login for user1 in setUp().
2014-10-30 12:17:02 +01:00
Morris Jobke 2261db62f5 fix style of generated documentation 2014-10-29 20:39:18 +01:00
Jörn Friedrich Dreyer 496b62f2eb test files external amazon s3 storage id migration 2014-10-27 13:01:48 +01:00
Jörn Friedrich Dreyer b5ab3d7fc0 fix files_external storage id migration 2014-10-27 13:01:36 +01:00
Frank Karlitschek 321a631d92 7.0.3RC1 2014-10-23 21:26:04 +02:00
Vincent Petry a1ded6e9d7 Added encryption test when moving file as non-owner 2014-10-29 16:11:15 +01:00
Vincent Petry 68dd41a4c9 Fix warning with unset extension check 2014-10-29 16:11:11 +01:00
Vincent Petry 0d02aa7910 Fix moving share keys as non-owner to subdir
This fix gathers the share keys BEFORE a file is moved to make sure that
findShareKeys() is able to find all relevant keys when the file still
exists.

After the move/copy operation the keys are moved/copied to the target
dir.

Also: refactored preRename and preCopy into a single function to avoid
duplicate code.
2014-10-29 16:11:06 +01:00
Lukas Reschke 77a533a29d Close session for search
Make search non-blocking.
2014-10-29 15:29:35 +01:00
Lukas Reschke 84e942f121 Close session for avatar get
This somehow blocked the "Users" UI for me when having a lot of users. - Shouldn't hurt here.
2014-10-29 15:08:01 +01:00
Lukas Reschke 96c092ce14 Show login again instead of JSON if CSRF check fails
Previously a JSON error page was shown to the user in-case the CSRF token was not valid. This was confusing and prevented people from login.

With this at least the login page is shown again and not a JSON error message. I consider this as sufficient since adding a new error page just for this sake would uneededly make lib/base.php even more cluttered and this is a edge-case which optimally should anyways not happen that often.

This can be tested by opening the login page, then clearing the cookies, and trying to login.
2014-10-29 14:38:24 +01:00
Lukas Reschke ec3f92e102 Merge pull request #11802 from owncloud/backport-10958
Backport #10958
2014-10-28 14:23:58 +01:00
Thomas Müller 15e357fa94 Merge pull request #11800 from owncloud/backport-MakeSupportedDBsConfigurable
Make supported DBs configurable within config.php
2014-10-28 10:05:32 +01:00
Vincent Petry 3ba1441c2d Properly catch 503 storage not available in getQuotaInfo
When doing a PROPFIND on the root and one of the mount points is not
available, the returned quota attributes will now be zero.

This fix prevents the expected exception to make the whole call fail.

Backport of 21d825ed6c from master
2014-10-28 09:53:24 +01:00
Robin Appelman 9c24dbbac7 Introduce cross-db ILIKE
adding ILIKE to AdapterSQLSrv

add test case for ILIKE with wildcard

Make sqlite LIKE case sensitive on default

Implement ILIKE for sqlite

Use ILIKE in cache search

Fix ILIKE without wildcards for oracle
2014-10-27 23:00:49 +01:00
Lukas Reschke 9b908c3d05 Make supported DBs configurable within config.php
This commit will make the supported DBs for installation configurable within config.php. By default the following databases are tested: "sqlite", "mysql", "pgsql". The reason behind this is that there might be instances where we want to prevent SQLite to be used by mistake.

To test this play around with the new configuration parameter "supportedDatabases".

Conflicts:
	lib/private/util.php
2014-10-27 22:27:57 +01:00
Lukas Reschke dbfe5ef28a Make files non executable
There is not much sense in having these files marked executable, we should avoid that.
2014-10-24 14:16:37 +02:00
Vincent Petry a3c33585e1 Merge pull request #11719 from owncloud/stable7-fix-s3-regression
[stable7] Fix S3 connection regression
2014-10-23 12:36:35 +02:00
Vincent Petry 6a8c41754f Fix S3 connection 2014-10-22 21:48:22 +02:00
Arthur Schiwon 3399930355 Backport of #11702
set up FS by username, not login name\!

better variable name
2014-10-22 17:58:09 +02:00
Vincent Petry 09d80ac9fc Lazy initialize external storages
Backport of 075e8d8e86 from master
2014-10-22 14:50:22 +02:00
Jörn Friedrich Dreyer 6995b96589 guess mimetype on touch
Conflicts:
	apps/files_external/lib/amazons3.php
2014-10-22 12:35:59 +02:00
Vincent Petry 5624968d1e Merge pull request #11691 from owncloud/fix_pub_link_creation
fix target creation for public links
2014-10-22 11:06:12 +02:00
Bjoern Schiessle a5d6e6eb28 if it is not a folder share the path already points to the correct file 2014-10-21 16:20:28 +02:00
Bjoern Schiessle 098b4e9e81 always use the correct share type 2014-10-21 16:19:54 +02:00
Lukas Reschke d0b3fe2414 Merge pull request #11673 from owncloud/backport-11593
Backport #11593
2014-10-20 20:09:27 +02:00
Vincent Petry 3e02e79154 Add proper setup and teardown
Properly restore REQUEST_URI and SCRIPT_NAME after test runs
2014-10-20 19:15:50 +02:00
Lukas Reschke 841998bdcb Add "$_SERVER['REQUEST_URI']" to fix the unit tests
Let's hope that works
2014-10-20 19:15:45 +02:00
Lukas Reschke ff93c5859b Refer to relative path instead of absolute path
There is no need to refer to the absolute path here if we can use the relative one.

Conflicts:
	lib/private/templatelayout.php

Conflicts:
	lib/private/templatelayout.php
2014-10-20 19:15:23 +02:00
Lukas Reschke 7ffe80cf25 Add unit tests for convertToRelativePath 2014-10-20 19:09:47 +02:00
Arthur Schiwon 86daab2800 backport of #11494
fix retrievel of group members and cache group members

fix changed variable name

with several backends, more than limit can be returned

make performance less bad. Still far from good, but at least it works

add one simple cache test

adjust group manager tests
2014-10-18 00:17:43 +02:00
macjohnny 174ab07a4b backport of #9104
Update manager.php

add caching to getUserGroupIds

Update manager.php

added description and blank lines in getUserGroupIds

Update manager.php

defined $uid in getUserGroupIds

Update manager.php

Update manager.php

Update manager.php

clean up function getUserGroupIds

clean up of function getUserGroupIds and improved caching mechanism of cachedUserGroupIds

modified caching mechanism in getUserGroupIds

removed cachedUserGroupIds, instead changed indexing in getUserGroups to groupId

adapted tests for a groupId indexed group array
2014-10-17 21:14:01 +02:00
Vincent Petry 9998861402 Encapsulate require_once to avoid name space bleedind
The script required by require_once might use variable names like $app
which will conflict with the code that follows.

This fix encapsulates require_once into its own function to avoid such
issues.
2014-10-17 15:03:53 +02:00
Thomas Müller 5b6ba39734 fixing usage of EncryptionException 2014-10-17 14:18:46 +02:00
Thomas Müller fb9c2b5362 Merge pull request #11610 from owncloud/fix-svg-s7
Fix SVG icons
2014-10-17 12:02:03 +02:00
Bjoern Schiessle a93e424738 set password field placeholder back if passward was disabled 2014-10-17 11:34:26 +02:00
Morris Jobke d27db8cc61 fix the RST syntax of config.sample.php 2014-10-17 10:13:37 +02:00
Jörn Friedrich Dreyer 0c6a58a883 Merge pull request #11550 from owncloud/fix_flickering_users
fix flickering users in files external
2014-10-17 09:50:06 +02:00
Morris Jobke d2b766ddee read config.sample.php options and whitespace fixes 2014-10-17 00:37:02 +02:00
Carla Schroder da10518278 commented out instanceid and passwordsalt 2014-10-17 00:36:53 +02:00
Carla Schroder 9ed35a377f some small tweaks 2014-10-17 00:36:49 +02:00
Carla Schroder c8c182b36e small corrections to config.sample.php 2014-10-17 00:36:38 +02:00
Lukas Reschke f2dadc7104 Add a try catch block
This function might also be called before ownCloud is setup which results in a PHP fatal error. We therefore should gracefully catch errors in there.
2014-10-16 22:28:12 +02:00
Arthur Schiwon ada93bab0c backport of #11478
add checkbox for experienced users to server tab

must be empty not auto

sets user filters to raw mode when marking user as experienced

Objectlasses, Groups and Attributes are now loaded only in assisted mode and only once

user and group counts are only upated on demand in experienced mode

confirmation before switching to assisted mode when admin is experienced

rename internal var name to avoid collision

more beautiful white spaces

smaller corrections to make scruitinizer happier, no effective changes

bump version

fix triggering of group update counts. improves the basic code which is also responsible for user counts. i did not find regressions, please doublecheck

remove debug output

coding style, no effective code changes

always abort running ajax request when the method is fired up again

show a spinner next to test filter button when the test is running

show Spinner when stuff is being saved

show busy cursor and lock tabs on save

instead of dis/enabling tabs on save, cancel tab change. avoids noisy ui

remove debug output

rephrase xp'ed user mode label

left-align checkbox on server tab
2014-10-16 16:24:04 +02:00
Jörn Friedrich Dreyer b3acb2a1e7 Merge pull request #10732 from owncloud/make_skeleton_compatible_with_objectstore_minimal_stable7
make skeleton compatible with objectstore
2014-10-16 16:05:56 +02:00
Thomas Müller af72528570 include the apps' versions hash to invalidate the cached assets 2014-10-16 15:55:33 +02:00
Lukas Reschke 5f69b2095a Add app version to JS and CSS
This leads to the regeneration of the hash in case a single application is updated.

Fixes https://github.com/owncloud/core/issues/11374
2014-10-16 15:55:27 +02:00
Bjoern Schiessle 6e3a7ea140 strip whitespace from the beginning and end of the display name to avoid empty display names 2014-10-16 14:55:07 +02:00
Lukas Reschke 38c817c7dd Merge pull request #11613 from owncloud/external-share-self-signed-stable7
[stable7] Use certificate bundle from files_external for external shares
2014-10-16 14:33:32 +02:00
Jörn Friedrich Dreyer 61873e4e21 throw exception in writeBack, the returned boolean is checked nowhere 2014-10-16 14:10:28 +02:00
Jörn Friedrich Dreyer 6d4d5400d7 make tests compatible with hook based skeleton generation 2014-10-16 14:10:28 +02:00
Jörn Friedrich Dreyer 92d069ab6c make skeleton compatible with objectstore
suspend encryption proxy when copying skeleton
2014-10-16 14:10:15 +02:00
Robin Appelman d0101668ce Use certificate bundle from files_external for external shares 2014-10-16 13:42:42 +02:00
Lukas Reschke 73a5e3810f Remove insane comment 2014-10-16 12:40:09 +02:00
Lukas Reschke 6d81789a66 Fix SVG icons
FIXME: Ugly hack to prevent SVG of being returned if the SVG
provider is not enabled.
This is required because the preview system is designed in a
bad way and relies on opt-in with asterisks (i.e. image/*)
which will lead to the fact that a SVG will also match the image
provider.

Conflicts:
	lib/private/preview.php
2014-10-16 12:31:40 +02:00
Frank Karlitschek e1e501b17f 7.0.3 RC1 2014-10-16 08:26:55 +02:00
Lukas Reschke f53ecea372 Add darwin to if block
Otherwise it would fall into the 'win' else block because strpos($os, 'win') does also match 'darwin' what is the `php_uname` for OS X.
2014-10-15 22:26:03 +02:00
Lukas Reschke 15b39a6566 Merge pull request #11520 from owncloud/make-trash-objectstore-compatible
make trashbin compatible with objectstore
2014-10-15 22:24:59 +02:00
Lukas Reschke 508ef23486 Use rawurlencode since this seems to be expected by cURL
Fixes https://github.com/owncloud/core/pull/11501#issuecomment-58794405

Conflicts:
	tests/lib/largefilehelpergetfilesize.php
2014-10-15 20:00:51 +02:00
Robin Appelman ff8d755702 Merge pull request #11567 from owncloud/cache-updater-refactor-stable7
[stable7] Refactor cache updater to work outside of the users home
2014-10-15 17:00:01 +02:00
Clark Tomlinson 9159598d32 Adding test helper to test private methods 2014-10-15 14:43:09 +02:00
Vincent Petry 361d6892c9 Allow specifying protocol in ext storage OC config
Allow specifying a protocol in the host field when mounting another
ownCloud instance. Note that this was already possible with the WebDAV
config but this bug made it inconsistent.
2014-10-15 14:17:49 +02:00
Vincent Petry 149b55f8ae Use body element when animating scroll in public page
In the public page the scroll container is the window instead of a div.
The $(window) object doesn't support animating the scroll property, so
the $('body') element is used instead.

Backport of 704ffaa6a3 from master
2014-10-15 10:53:25 +02:00
Thomas Müller e7a46ed9e7 Merge pull request #11408 from owncloud/refactor-mailsettings-controller
Refactor MailSettings controller
2014-10-14 15:34:13 +02:00
Robin Appelman ad06cd4b1f Remove explicit propagate calls 2014-10-14 14:38:31 +02:00
Robin Appelman f03142f3d6 remove unstable test 2014-10-14 14:38:25 +02:00
Robin Appelman 0497136d29 Update cache before post hooks 2014-10-14 14:38:11 +02:00
Robin Appelman c7f26fa969 Fix warning in homecache 2014-10-14 14:37:37 +02:00
Robin Appelman ad6e281586 Fix unit test 2014-10-14 14:37:31 +02:00
Robin Appelman 595d43ab35 Improve unit tests for Cache\Updater 2014-10-14 14:37:22 +02:00
Robin Appelman 45738b6b7a Refactor Cache\Updater to work outside of the users home 2014-10-14 14:37:10 +02:00
Joas Schilling ba33fd6a07 Set overwritemailurl* configs on setup
Correctly use overwritemailurl value when generating absolute urls in CLI

Fix #11500

Rename the config to *cli

Add overwrite.cli.url to the sample config

Revert separator fix, fixes unit test

Backport of 0407bc0978 from master
2014-10-14 09:20:23 +02:00
Thomas Müller 19585f9c3b fixing typos 2014-10-14 04:49:29 +02:00
Lukas Reschke da150afcc5 Close session when loading apps
Otherwise the session is blocked while all remote apps are loaded. This can be very annoying especially when apps.owncloud.com is down or not reachable.
2014-10-13 18:00:38 +02:00
Jörn Friedrich Dreyer 496b68e2ad fix flickering users 2014-10-13 17:51:38 +02:00
Vincent Petry d6a380613f Retrieve storage numeric id earlier when still available
The numeric id is only available before the storage entry is deleted, so
get it at that time.

Backport of d485c0098d from master
2014-10-13 17:37:33 +02:00
Vincent Petry c38454a5b2 Revert "Set overwrite.cli.url configs on setup"
This reverts commit 48a1e69f5e.

This was backported too quickly.
2014-10-13 17:30:53 +02:00
Bjoern Schiessle e4fa642e54 improved unit tests 2014-10-13 17:27:02 +02:00
Bjoern Schiessle 697f461ded always take unencrypted size 2014-10-13 17:26:38 +02:00
Joas Schilling 48a1e69f5e Set overwrite.cli.url configs on setup
Correctly use overwrite.cli.url value when generating absolute urls in CLI

Fix #11500

Backport and squash of the following from master, in order:
- f0fcaff9b957f1e6c04f9bfd9b8e0eb84f78bbf8
- 923de0afd9a7e717a5e1d25747caf4840633db25
- a487ce76e86940c94801da6157bcf70ed4005c1f
- bd3ebdbd135b30946fdf55b41b5e96497d0c3e4a
2014-10-13 17:21:33 +02:00
Bjoern Schiessle d71fae51f8 distinguish between file dependent shares and other shares 2014-10-13 17:01:19 +02:00
Vincent Petry 372676ee17 Fixed array detection on public download
When downloading a folder called "0001" PHP should fallback to parsing
it as string and properly detect that it is not a JSON array.

Backport of 6cbabdf217 from master
2014-10-13 16:56:37 +02:00
Lukas Reschke 686a43ccf3 force loading of encryption app 2014-10-13 11:52:16 +02:00
Jörn Friedrich Dreyer 3ce828b4b7 make trashbin compatible with objectstore, replace glob with search in cache, make unknown free space work like unlimited free space 2014-10-10 18:26:43 +02:00
Vincent Petry b297ddf349 Log warning when no uid was found for user
In some incomplete setups (like mine) it can happen that the uid
attribute of users is missing.

To be able to find out that something is wrong, a debug message is now
logged when it has not been found.

Backport of 59f9107dd9 from master
2014-10-10 17:59:05 +02:00
Bjoern Schiessle ecc7161611 make sure that we always delete oldest first 2014-10-10 17:31:27 +02:00
Bjoern Schiessle f4c91f0e82 try to get path from filesystem 2014-10-10 15:58:13 +02:00
Bjoern Schiessle 5a37703b3f fix performance issues 2014-10-10 15:58:00 +02:00
Vincent Petry 088879c4ec Prevent button click when enter key is pressed in LDAP wizard
Pressing enter in the LDAP wizard will trigger a click on the first
button. In the main page it would trigger the delete dialog, which is
quite inconvenient.

Added a type attribute to suppress this behavior.

Backport of bb424802c8 from master
2014-10-10 14:58:06 +02:00
Lukas Reschke 7097201eab Merge pull request #11503 from owncloud/stable7-9753
Stable7 9753
2014-10-10 13:02:28 +02:00
Lukas Reschke b089b85753 Refactor MailSettings controller
- Do not store the password (fixes https://github.com/owncloud/core/issues/11385)
- Refactor to AppFramework
- Add unit tests
2014-10-10 12:34:43 +02:00
Tony Zelenoff 34c1760e9f Urlencode file name before passing it to cURL
Large file helper use cURL to determine file sizes. Thus filenames must be
urlencoded in case special symbols like '#' can cause BadRequest errors.

Signed-off-by: Tony Zelenoff <antonz@parallels.com>

Backport of 2d03019c91 from master
2014-10-10 10:58:26 +02:00
Vincent Petry 140f3a7aa9 Merge pull request #11505 from owncloud/stable7-ext-updateetagmount
Stable7 ext updateetagmount
2014-10-10 09:54:33 +02:00
Morris Jobke f1a99ebb6d Additional changes to config.sample.php and typo fixes 2014-10-10 01:51:57 +02:00
Morris Jobke bd205c58c7 apply @carlaschroder's changes from owncloud/documentation#594 2014-10-10 01:50:56 +02:00
Vincent Petry a036cc56c4 Added PHP docs for etag propagator 2014-10-09 18:20:25 +02:00
Robin Appelman 1203580848 More phpdoc 2014-10-09 18:20:20 +02:00
Robin Appelman f534574b30 Hookup the etag propagator 2014-10-09 18:20:15 +02:00
Robin Appelman a11a75faba Add EtagPropagator to handle etag changes when external storages are changed 2014-10-09 18:20:11 +02:00
Robin Appelman 0d8d5cb3e6 Fix add/remove mountpoint hooks 2014-10-09 18:20:07 +02:00
Robin Appelman 4858b5e94a Expose getAppKeys trough \OCP\IConfig 2014-10-09 18:19:59 +02:00
Vincent Petry 3d68d172af Added failing unit tests for mount config hooks 2014-10-09 18:18:50 +02:00
Vincent Petry fe652258be Added filesystem hooks for mount/unmount ext storage 2014-10-09 18:18:46 +02:00
Vincent Petry 24dbdd2b8e Clear enabled apps cache after loading authentication app
Since getEnabledApps() depends on an authentication app to be loaded,
especially in the case of LDAP, the cache from getEnabledApps() is now
cleared to make sure that subsequent calls will properly return apps
that were enabled for groups.
This is because getEnabledApps() uses the inGroups() function from the
group manager provided by LDAP or any other authentication app.

Backport of 36d22825e0 from master
2014-10-09 17:19:34 +02:00
Lukas Reschke f8675f60e8 Add beforeeach and aftereach 2014-10-09 18:04:56 +03:00
Lukas Reschke d6ee378564 Add support for keys in the info.xml
This allows to have links to different doc base URLs
2014-10-09 17:00:06 +02:00
Lukas Reschke 335ad56ff8 Add unittest for filePath 2014-10-09 17:59:58 +03:00
Robin Appelman 7479a6ebf9 Remove special case for css in OC.filePath 2014-10-09 17:59:35 +03:00
Arthur Schiwon f0c4347330 Backport of #10527
properly cancel a Paginated Results operation in order to avoid protocol errors, fixes #10526

abandon ongoing paged search before starting a new one

abandond paged search only if PHP supports them

init a new paged search on read operations to satisfy OpenLDAP

make scrutinizer happy, very minor changes
2014-10-09 14:29:00 +02:00
Bjoern Schiessle d222d2b73f check if I can create a file at the location 2014-10-09 13:30:11 +02:00
MTRichards 5b6f866756 Updated info.xml app description
Made description consistent with other apps
2014-10-08 22:34:10 -04:00
MTRichards cdeb7cb9b3 Updated info.xml app description
Updated description
2014-10-08 22:33:02 -04:00
MTRichards a7398bcfa8 Updated info.xml app description
Updated app description
2014-10-08 22:28:11 -04:00
MTRichards f4e1e5f414 Updated info.xml app description
Backported to stable 7
2014-10-08 22:15:33 -04:00
MTRichards c9875e3959 Updated info.xml app description
Updated documentation. Removed doc links as this has two packages, need to not hard link.
2014-10-08 22:14:07 -04:00
MTRichards a3c6b7a662 Updated info.xml app description
Backporting to stable 7. Removed doc links as this is packaged in 2 different setups, links are different.
2014-10-08 22:10:32 -04:00
Morris Jobke 063d2032a7 style fixes in config.sample.php 2014-10-08 23:27:57 +02:00
Morris Jobke 47c05e048f Fixes in config.sample.php
* owncloud -> ownCloud
* add default value
* proper comment style
* fix line wrapping and minor typo
* remove duplication
* add Vincents proposals
* drop master config switches while backporting
2014-10-08 23:24:34 +02:00
Morris Jobke c83a17e6c8 re-arrange the config options and sort them in a semantical way
Conflicts:
	config/config.sample.php
2014-10-08 23:21:58 +02:00
Morris Jobke 3e7bc72281 unify style of config.sample.php
* use ' instead of " for config option
* place default parameters where useful into sample
* use proper comment block
* limit line size to 80 characters
2014-10-08 23:20:31 +02:00
brumsoel 251e4d78b8 Fix file size comparator return value 2014-10-08 23:09:01 +02:00
Vincent Petry 6b89f4b44d Merge pull request #11375 from owncloud/fix_files_external_amazon_s3_stat_call
Fix files external amazon s3
2014-10-08 18:49:41 +02:00
Bjoern Schiessle a766f5b633 improved visual feedback if user enabled recovery key 2014-10-08 16:20:21 +02:00
Bjoern Schiessle 7ee3ad411c improved visual feedback if recovery key password gets changed 2014-10-08 16:19:28 +02:00
Bjoern Schiessle bdfd3ca2bf improved visual feedback if recovery key gets enabled/disabled 2014-10-08 16:18:59 +02:00
Bjoern Schiessle 4dcd1ed34f make sure that the notification gets shown again after a second try 2014-10-08 16:13:35 +02:00
michag86 a045f8cd3a restrict $div to local scope 2014-10-07 16:30:21 +02:00
michag86 4e74983676 variable for found avatar div 2014-10-07 16:30:21 +02:00
michag86 aedd64b5a6 fix for issue #10483 2014-10-07 16:30:21 +02:00
Vincent Petry b6e81b517f Merge pull request #11457 from owncloud/stable7-fix-rename-position
fix position of rename field, fix #10867
2014-10-07 16:00:41 +02:00
Jan-Christoph Borchardt 77b5e2e661 fix position of rename field, fix #10867 2014-10-07 14:58:01 +02:00
Jan-Christoph Borchardt 9411a6ea53 reduce bottom padding in filelist, fix perceived glitching, fix #11213 2014-10-07 14:52:22 +02:00
Victor Dubiniuk e0d1fa554f Add CssImportFilter. More elegant fix for documents#348 2014-10-07 14:33:42 +02:00
Jan-Christoph Borchardt 532f65116a fix position and style of sort indicator 2014-10-07 14:23:27 +02:00
Bjoern Schiessle 30398370b8 we also encrypt/decrypt files in the versions folder for previews and if encryption is enabled/disabled 2014-10-06 13:11:09 +02:00
Jörn Friedrich Dreyer 413bd5406c extract batchDelete(), better comments 2014-10-06 11:08:21 +02:00
André Gaul 056b97834d files_extern: remove empty Body and ContentLength in Amazon S3 mount
fixes #10501

Conflicts:
	apps/files_external/lib/amazons3.php
2014-10-02 12:00:50 +02:00
Lukas Reschke 1f5f278501 Merge pull request #11299 from owncloud/barkport-10934
[stable7] Don't complain about non-writable datadirs before we're installed
2014-10-02 10:38:15 +02:00
Jörn Friedrich Dreyer 2b91e628f5 fix amazon s3 issues
folder size and mtime is always unknown in s3

more s3 fixes

make rescanDelay of root dir configurable, add on the fly update of legacy storage ids, !isset -> empty when checking strings

reduce number of http calls on remove and rmdir

fix typo
2014-10-01 14:38:50 +02:00
Jörn Friedrich Dreyer c8dab5829c make some storage tests explain what went wrong 2014-10-01 14:38:50 +02:00
Jörn Friedrich Dreyer 8089e0f9b8 strict comparison 2014-10-01 14:38:50 +02:00
Jörn Friedrich Dreyer 7fd925e96d log exceptions when listing files 2014-10-01 13:17:28 +02:00
Robin Appelman 3a4ac2caa1 Skip test for unsuported feature for amazon s3 2014-10-01 13:15:20 +02:00
Robin Appelman 67b9edeeb7 Fix copy overwrite for amazon s3 2014-10-01 13:15:13 +02:00
Robin Appelman 25d003a52d Fix amazon s3 rename overwrite 2014-10-01 13:15:06 +02:00
Robin Appelman a47f965b87 Fix AmazonS3 rmdir on the root 2014-10-01 13:14:56 +02:00
Lukas Reschke 0484939fe0 Redirect only to absolute URL
We do not want to redirect to other domains using the "?redirect_url=" feature. Please notice, that the ownCloud project does not consider open redirectors as security issue.
2014-10-01 12:49:54 +02:00
Lukas Reschke 69296befa6 Use SVG previews for public sharing
Fixes https://github.com/owncloud/core/pull/11367#issuecomment-57306037 and https://github.com/owncloud/core/issues/9218
2014-10-01 11:16:10 +02:00
Lukas Reschke bc5c608e4e Add flock to config
This adds a file lock to the config in hope that this prevents race conditions as reported in https://github.com/owncloud/core/issues/11070

Testplan:

- [ ] Delete config.php and make it read-only => Error is thrown that it is not writeable
- [ ] Installation still works
- [ ] Changing config settings works (i.e. using the SMTP config switches in the administration menu)
- [ ] Your PC didn't blow up
- [ ] Installing the news app and the "Disable AppCode checker" app did not destroy your installation

Only skip the main config

Otherwise read only additional configs might not be processed

Test on tmpdir
2014-10-01 11:14:15 +02:00
Bjoern Schiessle 02374e595a don't clean up the test environment if a data provider was finished 2014-09-30 12:50:21 +02:00
Lukas Reschke f788dffce8 Try to create datadirectory to test whether the .htaccess works
Fixes https://github.com/owncloud/core/pull/11299#issuecomment-56968588 and also https://github.com/owncloud/core/issues/10628 together with https://github.com/owncloud/core/pull/11299#issuecomment-56968588 when backported.
2014-09-30 10:24:52 +02:00
Robin Appelman d102cb4ffa Don't test for htaccess if we cant write into the datadir anyway 2014-09-30 10:24:52 +02:00
Robin Appelman 83a06950f4 Check for writable datadir during setup 2014-09-30 10:24:52 +02:00
Robin Appelman 6c09c0e082 Don't complain about non-writable datadirs before we're installed
Conflicts:
	lib/private/util.php
2014-09-30 10:24:52 +02:00
Robin Appelman 2376d69115 Inject config into checkserver and cleanup tests
Conflicts:
	lib/private/util.php
2014-09-30 10:24:52 +02:00
Lukas Reschke 7eb0d6866c Close the session for preview generation
Without closing the session every preview image generation is locking the session which makes the webinterface unresponsive.
2014-09-29 22:03:58 +02:00
Arthur Schiwon 5ddacaed7f dn needs to be fetched to be able to detect memberOf support 2014-09-29 15:17:34 +02:00
Dan Bartram bd74ab2886 Clear up confusion of log_rotate_size config value
Remove the second comment which could be confused with suggesting an invalid value: `// 100 MiB`.

To keep the easily readable example value, it has been moved into the comment header for the config item.
2014-09-29 09:39:55 +02:00
Frank Karlitschek 424cc31fd6 increase version 2014-09-28 13:19:53 +02:00
Björn Schießle d388ef5c0a Merge pull request #11363 from owncloud/sharing_group_shares_stable7
Sharing group shares stable7
2014-10-01 23:35:33 +02:00
Thomas Müller 7d389b26f9 catch and log exception in OC_Helper::cleanTmp() 2014-10-01 15:57:30 +02:00
Bjoern Schiessle 9254073786 some small fixed, suggested by scrutinizer 2014-10-01 15:13:48 +02:00
Bjoern Schiessle bb703006da throw a exception if we can't handle the provided path 2014-10-01 15:13:48 +02:00
Bjoern Schiessle 1371fecf26 on unshare only unshare childrens if there is no other parent available 2014-10-01 15:13:48 +02:00
Bjoern Schiessle 1e5c786392 only create a new share entry, if the user needs a different target name than the group share 2014-10-01 15:13:48 +02:00
Bjoern Schiessle 6d85cf2a0b for group shares we don't need a extra db entry of groupTarget equals itemTarget 2014-10-01 15:13:48 +02:00
Bjoern Schiessle 3b1715c3fc for group shares only the parent has the up-to-date permission. Make sure that we always use this permission, except if the user permission is '0' because in this case the user unshared the group share from self 2014-10-01 15:13:48 +02:00
Bjoern Schiessle 6d747e9721 call \OCP\Share::getItemsSharedWithUser() to get exclude list, this way all checks are executed, e.g. to check if the share is really visible 2014-10-01 15:13:48 +02:00
Bjoern Schiessle c5db1ef3cc always select permissions, used in getItems() 2014-10-01 15:13:48 +02:00
Bjoern Schiessle 27a630b0bc some small fixes 2014-10-01 15:13:48 +02:00
Bjoern Schiessle e25593db4e clear share table after each test run 2014-10-01 15:13:47 +02:00
Bjoern Schiessle 7edf912ef8 only add a new row if it isn't a unique share, otherwise update the existing row 2014-10-01 15:13:47 +02:00
Bjoern Schiessle aab44694ad fix unit tests 2014-10-01 15:13:47 +02:00
Bjoern Schiessle 98268078c0 mark exclude list as deprecated. It neither used by the files app nor by the
calendar or contacts app. It doesn't make sense to build a exclude list by the
share API, the apps knows best which are valid targets.
2014-10-01 15:13:47 +02:00
Bjoern Schiessle df97d8299a fix add user to group to work with grouped shares 2014-10-01 15:13:47 +02:00
Bjoern Schiessle 97dba2e022 generateTarget() will always find a unique target 2014-10-01 15:13:47 +02:00
Bjoern Schiessle b52154b306 unit tests for grouping of shares pointing to the same source 2014-10-01 15:13:47 +02:00
Bjoern Schiessle 64a9315b4a group shares and combine permissions 2014-10-01 15:13:47 +02:00
Lukas Reschke 3fb55d9d2e Merge pull request #11364 from owncloud/fix_unit_test_oc7
make sure that the users file system is initialized before we emit the post hook
2014-10-01 15:07:16 +02:00
Bjoern Schiessle 094f5bcc78 make sure that we re-load the file system after the quota was set 2014-10-01 09:42:50 +02:00
Bjoern Schiessle 79f5346105 make sure that the users file system is initialized before we emit the post hook 2014-09-30 13:14:04 +02:00
Vincent Petry 5c0139fdff Prevent monkey clicking on labels
Clicking on labels while the spinner is there will not trigger the
hidden checkbox any more.
2014-09-27 10:42:00 +02:00
Lukas Reschke c1c70b306e Add ID to markup to have the checkboxes in the right position 2014-09-27 10:41:51 +02:00
Vincent Petry 4d261d9e15 Added spinners in share dropdown
Added spinners for the following actions:
- adding user
- removing user
- changing password
- toggling allowing upload
- setting a password
2014-09-27 10:41:45 +02:00
Jan-Christoph Borchardt 257dbe61e2 for whitelabeled edition, show branding name (e.g. 'ownCloud') instead of appname in header bar 2014-09-27 10:29:20 +02:00
Robin Appelman d660aab116 Fix dav permissions for folders without create permissions 2014-09-26 09:24:24 +02:00
Robin Appelman e37f44e56a Expose creatable permissions trough fileinfo 2014-09-26 09:24:23 +02:00
Robin Appelman bdc26c6749 Don't keep the full info of all children in memory 2014-09-25 20:04:02 +02:00
Lukas Reschke 6d8fdcd7d2 Clarify possible preview providers for type Office
a

Conflicts:
	lib/private/preview.php
2014-09-25 00:00:40 +02:00
Morris Jobke 0044c3bb6b Merge pull request #11245 from owncloud/backport-11211
Add a configuration switch for enabled preview mimetypes
2014-09-24 23:57:23 +02:00
Robin Appelman 1ec756d125 Show a proper error message when trying to scan the filesystem for a non existing user 2014-09-24 23:21:26 +02:00
Thomas Müller c31990e936 Updating 3rdparty - contains updated tar archive and getid3 2014-09-24 14:30:00 +02:00
Jan-Christoph Borchardt 4e850128e6 fix filepicker home icon being partly hidden, fix #10169 2014-09-24 02:14:20 +02:00
Lukas Reschke 00bb0e122f Check for blacklisted characters
Fixes https://github.com/owncloud/core/issues/11264

(This should in future get moved to the mountpoint class - but that is something for @icewind1991 ;-))
2014-09-24 00:38:18 +02:00
Vincent Petry 2013404e0a Moved WebDAV and internet checks to client side JS
- Added setup checks in JavaScript
- Moved isWebDAVWorking to JS using SetupChecks
- Moved internet connection checks to an ajax call that goes through the
  server

Backport of e65ceb08fc from master
2014-09-23 16:58:19 +02:00
Lukas Reschke 734112a5c1 Merge branch 'stable7' into backport-11211
Conflicts:
	config/config.sample.php
2014-09-23 14:48:16 +02:00
Remco Brenninkmeijer fbcd80ac08 Previous commit was not based on master, retry. Removed broken tar cutter, double extensions are not possible in temp files. Added tar support. Fixed extension switch. 2014-09-23 14:45:56 +02:00
Thomas Müller 435b9c3028 using flush() here is pointless as we render the layout into a memory buffer and actually transmit the data later 2014-09-23 13:41:45 +02:00
Thomas Müller 838c849a5a remove post setup check
Backport of 21412559df from master
2014-09-23 13:00:55 +02:00
Vincent Petry 85d7492398 Fix share key finding algorithm in various cases
Instead of inaccurate pattern matching, use the list of users who we
know have access to the file to build the list of share keys.

This covers the following cases:

- Move/copy files into a subfolder within a share
- Unsharing from a user
- Deleting files directlry / moving share keys to trashbin

Backport of 1e631754d7 from master
2014-09-23 12:54:07 +02:00
Victor Dubiniuk a6eb638380 Use non-empty defaults 2014-09-23 12:53:11 +02:00
Lukas Reschke cb3bc5ad31 Do only follow HTTP and HTTPS redirects
We do not want to follow redirects to other protocols since they might allow an adversary to bypass network restrictions. (i.e. a redirect to ftp:// might be used to access files of a FTP server which might be in a secure zone and not be reachable from the net but from the ownCloud server)

Get final redirect manually using get_headers()

Migrate to HTTPHelper class and add unit tests

Conflicts:
	apps/files/ajax/newfile.php
	lib/private/files/storage/dav.php
	lib/private/server.php
	lib/private/util.php
	lib/public/iservercontainer.php
2014-09-23 11:51:18 +02:00
Lukas Reschke d9384cd959 Append port to trusted domain in case it's not 80 or 443
Ref https://github.com/owncloud/core/pull/10584#issuecomment-54677059

Backport of 2590a4dc85 from master
2014-09-23 11:20:52 +02:00
Bjoern Schiessle bd7f6c9e18 first check if a private key exists, if not it is always a recovery szenario 2014-09-23 10:42:56 +02:00
Lukas Reschke bb69eebde4 Add a configuration switch for enabled preview mimetypes
Backport of https://github.com/owncloud/core/pull/11211 to stable7
2014-09-23 10:42:45 +02:00
Vincent Petry cb39c55073 WebDAV now throws 403 when deletion did not work
Assume a permission issue whenever a file could not be deleted.

This is because some storages are not able to return permissions, so a
permission denied situation can only be triggered during direct
deletion.
2014-09-23 00:50:28 +02:00
Morris Jobke 33737f9526 Merge pull request #11230 from owncloud/fix-failing-mountconfig-tests-stable7
Load apps in test situations
2014-09-23 00:45:35 +02:00
Victor Dubiniuk b3ddd39438 Log unsuccessful temp file creation and return false 2014-09-22 18:57:03 +03:00
Vincent Petry 2b297567b5 Added extra check to avoid deleting key folders
Whenever a delete operation is called twice in a row, it could happen
that the first call already deleted the file.

The second call would return an empty $ownerPath because the file does
not exist. That empty $ownerPath would run the key deletion operation on
the wrong path.

This fix adds checks in many places to make sure we don't use $ownerPath
when it's empty or null.

Backport of 8aca127e52 from master
2014-09-22 17:06:46 +02:00
Thomas Müller d6276beac0 date printed in the admin section regarding last execution time is already displayed in the users timezone - no need to append UTC 2014-09-22 16:58:17 +02:00
Vincent Petry 03bb3d2bdc Reenable file proxy when renaming between mount points
When moving a folder into another mount point, $renamedFiles is empty
because that goes over a different mechanism.

In such case, this fix makes sure that the file proxy is reenable to
avoid breaking the subsequent files that are being moved.
2014-09-22 16:30:37 +02:00
Jörn Friedrich Dreyer 44c7562c7b in quota wrapper use === instead of ! for better readability and as in other wrappers 2014-09-22 16:26:20 +02:00
Jörn Friedrich Dreyer e556698db7 return boolean in Ciose::stream_seek 2014-09-22 16:26:14 +02:00
Jörn Friedrich Dreyer 2bdf5a8b1a return boolean in OC::stream_seek 2014-09-22 16:26:01 +02:00
Jörn Friedrich Dreyer dfc6bfe131 add seek and tell to streamwrapper test 2014-09-22 16:25:50 +02:00
Robin McCorkell c0d1b6bfb2 Load apps in test situations 2014-09-22 15:39:16 +02:00
Vincent Petry 387638e317 Use afterBind to send fileId header for files and directories
afterBind is called for both files and directories and is now used to
send the OC-FileId headers.
2014-09-22 14:12:52 +02:00
Morris Jobke 2d3ea08e19 update 3rdparty submodule to its stable7 commit 2014-09-22 13:05:36 +02:00
voxsim 3ebd0b8983 Backport of #9225
fix in displayNamesInGroup: when specified limit N, we did complex search only in the first N users

change logic in displayNamesInGroup and add some unit tests

add more logic in displayNamesInGroup for big user bases

1. remove sizeof($filteredUsers) > 0 as condition
2. use count instead of sizeof. Latter is an alias to first one, practically we stick to count everywhere. Having it consistent helps with readability.
3. move whitespace so we have $groupUsers[] = $filteredUser; instead of $groupUsers []= $filteredUser;
2014-09-22 12:21:34 +02:00
Robin Appelman 984b6a28ac Also setup the filesystem when matching routes 2014-09-22 10:34:40 +02:00
Robin Appelman 744b20bc0d Remove unneeded file initialization in encryption, already handled in a hook 2014-09-22 10:34:37 +02:00
Robin Appelman 8905e77d60 Don't automatically setup the filesystem the moment we load OC\Files\FileSystem 2014-09-22 10:34:32 +02:00
Vincent Petry c16c680e32 Add select2 cache for complete group list
To avoid making a server request every time the dropdown opens, the
whole list of groups are cached (from the last request):

Whenever the user types in a search term it will still send server
requests.
2014-09-22 10:14:25 +02:00
Jan-Christoph Borchardt 13cee302f7 fit select2 to ownCloud input style 2014-09-22 10:14:22 +02:00
Vincent Petry 2aaad09062 Fixed select2 for admin and apps page
Added explicit escaping.
Now internally using a pipe symbol as separator for select2, to make it
possible to use group names containing commas.
2014-09-22 10:14:18 +02:00
Vincent Petry 996c68aa2e Added select2 on the apps page
Moved setupGroupsSelect() from admin.js to a common settings.js
as OC.Settings.setupGoupsSelect().

Now using select2 as well on the apps page.
2014-09-22 10:14:15 +02:00
Vincent Petry 7f030eedde Remove excludegroup.php
The ajax call is now using ajax/appconfig.php instead
2014-09-22 10:14:11 +02:00
Vincent Petry 2e93300313 Load select2 on admin page 2014-09-22 10:14:08 +02:00
Vincent Petry a385a367b0 Now using select2 for the groups excluded from sharing 2014-09-22 10:14:05 +02:00
Vincent Petry 97b83b9098 Move select2 from files_external to core
Backport of 412da87e65 from master
2014-09-22 10:13:46 +02:00
Bjoern Schiessle ce69e83b33 make sure that we really catch the files folder only 2014-09-22 10:00:47 +02:00
Bjoern Schiessle a2e9056832 create backup from all keys before recovery 2014-09-22 10:00:37 +02:00
Thomas Müller 260229b027 Merge pull request #11202 from owncloud/stable_l10n_backport
backport server2server strings
2014-09-22 09:16:34 +02:00
Thomas Müller 0c014409e6 Merge pull request #11201 from owncloud/fix-button-text
fix button text l10n
2014-09-22 09:16:00 +02:00
Georg Ehrke 2068eaf16b make sure preview prop is instanceof OC_Image before using it in showPreview 2014-09-22 00:48:01 +02:00
Georg Ehrke 645e7a0c9e delete old previews 2014-09-21 22:49:22 +02:00
Volkan Gezer 0afd79a22c backport server2server strings 2014-09-21 17:34:39 +02:00
Volkan Gezer 6946962609 fix button text l10n 2014-09-21 17:32:37 +02:00
Morris Jobke f8ecef2917 Merge pull request #11195 from owncloud/stable_l10n_backport
backport stable translations
2014-09-21 11:16:08 +02:00
Thomas Müller 6c544b95e8 adding 'smallint unsigned' to type mapping for sqlite 2014-09-21 11:14:14 +02:00
Volkan Gezer 5637a581d2 backport stable translations 2014-09-20 18:50:17 +02:00
Robin McCorkell 83b9a89569 Merge pull request #11190 from owncloud/fix-unit-test-sort-order-stable7
Don't rely on the sorting the database gives us for tests
2014-09-20 12:09:50 +01:00
Robin Appelman 8580e2a697 Don't rely on the sorting the database gives us for tests 2014-09-20 09:17:18 +02:00
Lukas Reschke 7f45226b8e Prevent updates between multiple major versions
Ref https://github.com/owncloud/core/issues/11078
2014-09-19 17:00:50 +02:00
Lukas Reschke 37632e428d Move BasicAuth check to "isLoggedIn()"
Ensures that Basic Auth works properly for APIs and removes the need for some even uglier lines of code.
2014-09-19 13:41:55 +02:00
Volkan Gezer 7930440b31 update encryption doc link
I don't know how we missed to update this :/

update ldap doc link
2014-09-18 18:20:20 +02:00
Lukas Reschke 749c519759 Move basic auth check
At the previous point not all apps were initialized. Now the basic auth check happens together at the same location as all others.

Fixes https://github.com/owncloud/core/issues/11129
2014-09-18 14:41:43 +02:00
Vincent Petry 35cb14c95f Add timeout to user and group deletion notification
Added timeout in DeleteHandler to auto-delete after a delay.

Fixed issue where OC.Notification.hide() was called twice in a row when
deleting multiple entries, causing the second notification to disappear.
Fixed issue where "undo" click event handler was registered multiple
times when calling setNotifications() twice.
Added JS unit tests for the DeleteHandler class.

Refix undo users, groups feature

Timeout is now cleared in cancel().

Fixed click handler name for "undo" to be able to work with multiple
DeleteHandler instances (in our case one for users and one for groups)
so that there is no conflict.

Backport of 0d9f24a0ef from master
2014-09-18 10:22:10 +02:00
Lukas Reschke 28f462095d Make 404 page easier to understand
Fixes https://github.com/owncloud/core/issues/11133
2014-09-18 09:10:56 +02:00
Frank Karlitschek 19a7aa081e version bump 2014-09-13 22:56:07 +02:00
Thomas Müller 82ccb04182 adding unit test to truncate the table 2014-09-17 14:28:31 +02:00
Andreas Fischer ebbd40385a Use Doctrine Platform to generate SQL query for table truncation. 2014-09-17 14:28:31 +02:00
Vincent Petry 03f9b14a23 Merge pull request #11053 from owncloud/baskport-11041-stable7
content size checks are not valid for LOCK
2014-09-16 16:46:47 +02:00
Lukas Reschke 8ed1762dfb Reword the description
The old one was just horrible wrong.
2014-09-16 16:01:35 +02:00
Thomas Müller 76ff7ab007 Disable database migrations for MSSQL - scripts have to be applied manually 2014-09-16 14:03:24 +02:00
Bjoern Schiessle 9bf1a18512 also expire file if timestamp = limit, happens if trashbin_retention_obligation is set to zero 2014-09-16 13:58:56 +02:00
kondou 86400ea4c8 Preserve transparency when loading from a file
Fix #7148 - again :)
2014-09-16 08:34:18 +02:00
Lukas Reschke ff6deb809a Use secure mimetype for content delivery
Adds some hardening against potential CSP bypassed.
2014-09-15 12:50:35 +02:00
Vincent Petry 7f1416e62a Remove passing by reference to allow for proper GC
The garbage collector in PHP 5.3.10 does not properly release the file
handle when calling fclose() due to the fact that it is passed by
reference.
This has the side-effect of preventing file locks to be released as well
when the files_locking app is enabled.

This fix removes the useless passing by reference and now the file
handle and file lock are freed properly.
2014-09-15 11:58:18 +02:00
Joas Schilling a23396452f Set overwritewebroot when installing owncloud to avoid problems
Backport of 249558966e to stable7
2014-09-15 11:06:47 +02:00
Arthur Schiwon 1981d220c5 if only one attribute is requested, the returned array has 0 as key instead of attribute name. fixes #10888 2014-09-15 11:01:21 +02:00
Lukas Reschke 572720fb7a Do not double decode values
Fixes https://github.com/owncloud/core/issues/11012
2014-09-15 07:59:04 +02:00
Thomas Müller 0732131cd9 content size checks are not valid for LOCK 2014-09-12 22:06:28 +02:00
Thomas Müller 2ffcff228c content size checks are not valid for LOCK 2014-09-12 21:53:28 +02:00
Jan-Christoph Borchardt bec08955b2 fix nojavascript message alignment 2014-09-11 23:06:45 +02:00
Johan Björk f040529e6d Converted an array to PHP5.3 compatible version 2014-09-11 18:01:11 +02:00
Johan Björk 5ac620cb04 Fixes #8326: deletion of directories on S3 2014-09-11 18:01:01 +02:00
Jan-Christoph Borchardt e26a5ff715 fix folder icon alignment, fix #10866 2014-09-11 17:07:52 +02:00
Jan-Christoph Borchardt b7c7ec26c7 fix svg of calendar filetype icon 2014-09-11 17:07:46 +02:00
Jan-Christoph Borchardt 7f1e32764d fix size of toggle icon, make container square 2014-09-11 17:07:40 +02:00
Jan-Christoph Borchardt 3f5cefb07f improve style of checkmark icon, less bold, fitting ownCloud style 2014-09-11 17:07:34 +02:00
Jörn Friedrich Dreyer 463ad5a50d repair search lucene before installing 2014-09-11 14:24:11 +02:00
Lukas Reschke ec9517f98b Add X-UA-Compatible to all templates
Replaces https://github.com/owncloud/core/pull/10850
2014-09-11 12:39:45 +02:00
Vincent Petry 36680a5a81 Merge pull request #10998 from owncloud/use-section-in-form
Use section in first element in user_ldap
2014-09-11 12:07:31 +02:00
Lukas Reschke 04597aedcb Use section in first element 2014-09-10 18:47:29 +02:00
Vincent Petry 1a9e08ae4d Merge pull request #10973 from owncloud/stable7-issue/10847
[Stable7] Use correct language package so the subject is correctly translated
2014-09-10 14:57:32 +02:00
Vincent Petry dedb47390b Do not load extra user backends when an upgrade is due
Whenever an upgrade is due, do not load extra user backends

Backport of d6bfd90bf8 from master
2014-09-10 10:42:56 +02:00
Lukas Reschke 95eb9bf8ae Merge pull request #10884 from owncloud/stable7_backport_issue_10674
Backport issue 10764
2014-09-10 10:31:26 +02:00
Joas Schilling cc0a855103 Use correct language package so the subject is correctly translated
Fix #10847

Conflicts:
	lib/private/share/mailnotifications.php
2014-09-09 23:44:15 +03:00
Joas Schilling 19dd866c7e Fix broken new lines in plain text mail template 2014-09-09 23:40:56 +03:00
Bernhard Posselt 8e89c51e87 more sugar for including lists of templates 2014-09-09 19:40:56 +02:00
Bernhard Posselt 2a859f84a8 append .html since componets always use html files 2014-09-09 19:40:39 +02:00
Bernhard Posselt 8869dcf1af add template functions for html imports 2014-09-09 19:40:18 +02:00
Bernhard Posselt ca121d8438 add shortcut functions for style and script 2014-09-09 19:40:02 +02:00
Jörn Friedrich Dreyer f5bac5fb2d make objectstore tests check fileid on rename 2014-09-09 10:27:34 +02:00
Jörn Friedrich Dreyer c52f66cc73 Keep fileid on move in objectstore, fixes #10848 2014-09-09 10:27:21 +02:00
Jörn Friedrich Dreyer 5e5d9e0a80 allow . in dbname on web install 2014-09-09 09:43:58 +02:00
Lukas Reschke b98c22d39b Don't show warning when has_internet_connection is set to false
Revert

Add disabled
2014-09-09 09:20:03 +02:00
Jan-Christoph Borchardt b609d36e3c also add no-JavaScript notice to log in and sharing pages because they do not work without JS either 2014-09-08 22:01:56 +02:00
Jan-Christoph Borchardt a7968604d8 fix styling and wording of no-JavaScript message 2014-09-08 22:01:49 +02:00
Clark Tomlinson 9b99c81a9d Using countUsers method to return true count of users 2014-09-08 18:52:14 +02:00
Lukas Reschke 96bb1f7f45 Check for admin user instead of subadmin 2014-09-08 18:25:23 +02:00
Vincent Petry 85cde16feb Catch exceptions when moving files
When moving files on storages that don't expose permissions, the storage
itself might throw an exception when the permission is denied.

This fix ensures that exceptions are caught and forwarded to the client
instead of just hanging.

Backport of e43c9b84c4 from master
2014-09-08 16:26:01 +02:00
Oliver Kohl D.Sc 1e4431ba01 Update cron.php 2014-09-08 09:54:23 +02:00
Oliver Kohl D.Sc 994f36e498 CRON call ends in null exception
[error] 4461#0: *186285 FastCGI sent in stderr: "PHP message
: PHP Fatal error:  Call to a member function execute() on null in /var/www/ownc
loud/cron.php on line 125" while reading response header from upstream, client:
217.13.183.252, server: cloud.mycloud.com, request: "GET /cron.php HTTP/1.1", upstre
am: "fastcgi://unix:/var/run/php5-fpm.sock:", host: "cloud.mycloud.com", referrer: "
https://cloud.mycloud.com/"
2014-09-08 09:54:18 +02:00
Lukas Reschke 640abbe099 Move trusted domain check to init()
handleRequest() is not called from remote.php or public.php which made these files party available but all included apps in there produced errors.

As the expected behaviour is anyways that a trusted domain warning is shown I moved this to init()

Fixes https://github.com/owncloud/core/issues/10064
2014-09-05 18:20:40 +02:00
Jörn Friedrich Dreyer 1f2550e3da add / to url to match route 2014-09-05 16:55:36 +02:00
Vincent Petry cfca88f20e Scroll to new file/folder after adding
When creating a new file from the menu, the list now scrolls to that
file.
2014-09-05 16:55:36 +02:00
Vincent Petry 8e77ca6201 Fixed scrollto for search results
Now passing the "scrollto" URL argument to the file list class which
will also automatically scroll and highlight the matching element.

This code is triggered by the search box when in a different folder and
also by the activity app.
2014-09-05 16:55:36 +02:00
Lukas Reschke 41d8157937 Add isAppstoreEnabled instead of hijacking the URL 2014-09-05 15:14:29 +02:00
Lukas Reschke 6534304196 Remove different URL for EE
This can now be achieved by setting `appstoreenabled` to `false` in config.php
2014-09-05 15:14:19 +02:00
Jesus Macias 7bd4f6cac5 Backport issue 10764 2014-09-05 13:23:09 +02:00
Vincent Petry 69cc2044f0 Added permission check for drag and drop
When dropping files onto a read-only folder, a notification
is now shown instead of attempting to upload.

This for both the drag for upload and drag from inside the file list
cases.

Backport of f1bfe35cda from master
2014-09-05 12:21:42 +02:00
Jörn Friedrich Dreyer eb682a3022 Merge pull request #10878 from owncloud/remove_leftover
remove a left over that uselessly fetches all users
2014-09-05 11:59:12 +02:00
Arthur Schiwon e638a9a444 remove a left over that uselessly fetches all users 2014-09-05 10:27:34 +02:00
Vincent Petry f268eee86c Added unit tests for cache of enabled apps 2014-09-04 18:02:58 +02:00
Vincent Petry 28e1480d1c Added test for needUpgrade for core 2014-09-04 18:02:54 +02:00
Vincent Petry 81c4043d61 Fix upgrade process when apps enabled for specific groups
Fix issue where the currently logged user was causing side-effects when
upgrading.
Now setting incognito mode (no user) on update to make sure the whole
apps list is taken into account with getEnabledApps() or isEnabled().
2014-09-04 18:02:49 +02:00
Lukas Reschke bd5796a0d1 Merge pull request #10558 from owncloud/ajaxify_user_list_for_files_external_stable7
Ajaxify user list for files external stable7
2014-09-04 13:16:52 +02:00
pdessauw 919d19c906 Highlight every uploaded files and scroll down to the last one
Backport of 0d078e48ce from master
2014-09-04 10:45:41 +02:00
Vincent Petry 459c78106d Merge pull request #10823 from oparoz/patch-1
Typo in whichOpenOffice test
2014-09-04 10:20:50 +02:00
Olivier Paroz 444e21ab15 Typ in whichOpenOffice test 2014-09-02 22:11:49 +02:00
Raghu Nayyar b59d58fdc1 Merge pull request #10789 from owncloud/fix-z-index
fix z-index of navigation sidebar for mobile devices
2014-09-03 01:03:51 +05:30
Volkan Gezer b26dd3c76b russian translation backport. closes #10759 2014-09-02 17:53:52 +02:00
Morris Jobke 3d35c7edcc fix z-index of navigation sidebar for mobile devices 2014-08-31 19:41:58 +02:00
Morris Jobke 6eb1f7a474 update public interface for getUserFolder 2014-08-31 13:27:53 +02:00
Morris Jobke f3f1d1ee73 Add optional user ID parameter for getUseFolder 2014-08-31 13:27:53 +02:00
Arthur Schiwon 11b2835cc3 retrieve local users, groups and group members in a sorted way 2014-08-31 11:56:54 +02:00
Jörn Friedrich Dreyer 8b86df308b allow empty hostname and dots in service name for oracle autosetup 2014-08-29 17:11:38 +02:00
Arthur Schiwon 98ac45fa78 Backport of #9214
Wizad: email attribute detection

remove Access as hard dependency, inject it instead

add unit test for mail detection

write log message, if original value was changed

undo falsely changed log file

trigger email detection by Wizard upon any user filter filter change. before it happenend only upon user automatic list filter creation, but not on manual editing

adjust static method vars as well
2014-08-29 15:02:08 +02:00
Robin McCorkell 617636d5a7 Add missing 'personal' mount configuration option 2014-08-29 13:12:36 +01:00
Jan-Christoph Borchardt 4d9fd199ef user mgmt: move 'Show storage location' and 'Show last log in' to settings area 2014-08-29 12:53:17 +02:00
Stephane V cc820eb824 Adds 2 checkboxes at the top of userlist in the settings, to display/hide optional columns
This fixes #9367.
2014-08-29 12:53:11 +02:00
Jan-Christoph Borchardt 135d40203c define min height/width for icon classes to make sure they show 2014-08-29 12:51:57 +02:00
Jan-Christoph Borchardt 30cc4b9293 allow horizontal scrollbar for personal and admin settings 2014-08-29 10:33:43 +02:00
raghunayyar 04e14ab5a6 Enhancement: Adds input styles to input type dates too. 2014-08-28 17:56:24 +02:00
Arthur Schiwon a133833fb9 fix wizard test, adjust to changed parameters of the tested method, introduced by 9caa354cfc 2014-08-28 11:39:16 +02:00
Arthur Schiwon 2b001adce0 backport of #8623
set result entry identifier earlier, i.e. before a continue for the same level can happen. otherwise  will always get the same value and we end up in an infinite loop

add unit test to make sure the infinite loop never comes back

Conflicts:
	apps/user_ldap/tests/wizard.php
2014-08-28 11:38:31 +02:00
Lukas Reschke 5a8db83c48 Escape error messages 2014-08-28 09:37:11 +02:00
Jörn Friedrich Dreyer af17de9467 fix deletion of shares 2014-08-21 15:12:06 +02:00
Jörn Friedrich Dreyer 992bd6dbf2 replace chosen with select2 to provide ajaxified user and group selection for files_external, fixes #7499
remove minified select2 js

show avatars for users, simpler results

remove unneeded users and groups from settings template

fix css, escape user and group names
2014-08-20 19:25:23 +02:00
Jörn Friedrich Dreyer f74bf923ca add select2 to app specific thirdparty 2014-08-20 19:25:10 +02:00
579 changed files with 21524 additions and 5168 deletions
+3 -1
View File
@@ -27,7 +27,9 @@ $success = true;
//Now delete
foreach ($files as $file) {
if (\OC\Files\Filesystem::file_exists($dir . '/' . $file) &&
!\OC\Files\Filesystem::unlink($dir . '/' . $file)) {
!(\OC\Files\Filesystem::isDeletable($dir . '/' . $file) &&
\OC\Files\Filesystem::unlink($dir . '/' . $file))
) {
$filesWithError .= $file . "\n";
$success = false;
}
+3
View File
@@ -32,6 +32,7 @@ try {
OCP\JSON::success(array('data' => $data));
} catch (\OCP\Files\StorageNotAvailableException $e) {
\OCP\Util::logException('files', $e);
OCP\JSON::error(array(
'data' => array(
'exception' => '\OCP\Files\StorageNotAvailableException',
@@ -39,6 +40,7 @@ try {
)
));
} catch (\OCP\Files\StorageInvalidException $e) {
\OCP\Util::logException('files', $e);
OCP\JSON::error(array(
'data' => array(
'exception' => '\OCP\Files\StorageInvalidException',
@@ -46,6 +48,7 @@ try {
)
));
} catch (\Exception $e) {
\OCP\Util::logException('files', $e);
OCP\JSON::error(array(
'data' => array(
'exception' => '\Exception',
+10 -4
View File
@@ -19,10 +19,16 @@ if(\OC\Files\Filesystem::file_exists($target . '/' . $file)) {
if ($target != '' || strtolower($file) != 'shared') {
$targetFile = \OC\Files\Filesystem::normalizePath($target . '/' . $file);
$sourceFile = \OC\Files\Filesystem::normalizePath($dir . '/' . $file);
if(\OC\Files\Filesystem::rename($sourceFile, $targetFile)) {
OCP\JSON::success(array("data" => array( "dir" => $dir, "files" => $file )));
} else {
OCP\JSON::error(array("data" => array( "message" => $l->t("Could not move %s", array($file)) )));
try {
if(\OC\Files\Filesystem::rename($sourceFile, $targetFile)) {
OCP\JSON::success(array("data" => array( "dir" => $dir, "files" => $file )));
} else {
OCP\JSON::error(array("data" => array( "message" => $l->t("Could not move %s", array($file)) )));
}
} catch (\OCP\Files\NotPermittedException $e) {
OCP\JSON::error(array("data" => array( "message" => $l->t("Permission denied") )));
} catch (\Exception $e) {
OCP\JSON::error(array("data" => array( "message" => $e->getMessage())));
}
}else{
OCP\JSON::error(array("data" => array( "message" => $l->t("Could not move %s", array($file)) )));
+9 -2
View File
@@ -93,7 +93,8 @@ if (\OC\Files\Filesystem::file_exists($target)) {
}
if($source) {
if(substr($source, 0, 8)!='https://' and substr($source, 0, 7)!='http://') {
$httpHelper = \OC::$server->getHTTPHelper();
if(!$httpHelper->isHTTPURL($source)) {
OCP\JSON::error(array('data' => array('message' => $l10n->t('Not a valid source'))));
exit();
}
@@ -104,7 +105,10 @@ if($source) {
exit();
}
$ctx = stream_context_create(null, array('notification' =>'progress'));
$source = $httpHelper->getFinalLocationOfURL($source);
$ctx = stream_context_create(\OC::$server->getHTTPHelper()->getDefaultContextArray(), array('notification' =>'progress'));
$sourceStream=@fopen($source, 'rb', false, $ctx);
$result = 0;
if (is_resource($sourceStream)) {
@@ -115,6 +119,9 @@ if($source) {
$freeSpace = $storageStats['freeSpace'];
foreach($meta['wrapper_data'] as $header) {
if (strpos($header, ':') === false){
continue;
}
list($name, $value) = explode(':', $header);
if ('content-length' === strtolower(trim($name))) {
$length = (int) trim($value);
+3
View File
@@ -17,4 +17,7 @@
<webdav>appinfo/remote.php</webdav>
<filesync>appinfo/filesync.php</filesync>
</remote>
<documentation>
<user>user-files</user>
</documentation>
</info>
+1 -1
View File
@@ -38,7 +38,7 @@ $server->setBaseUri($baseuri);
$defaults = new OC_Defaults();
$server->addPlugin(new \Sabre\DAV\Auth\Plugin($authBackend, $defaults->getName()));
$server->addPlugin(new \Sabre\DAV\Locks\Plugin($lockBackend));
$server->addPlugin(new \Sabre\DAV\Browser\Plugin(false)); // Show something in the Browser, but no upload
$server->addPlugin(new \Sabre\DAV\Browser\Plugin(false, false)); // Show something in the Browser, but no upload
$server->addPlugin(new OC_Connector_Sabre_FilesPlugin());
$server->addPlugin(new OC_Connector_Sabre_MaintenancePlugin());
$server->addPlugin(new OC_Connector_Sabre_ExceptionLoggerPlugin('webdav'));
+5 -1
View File
@@ -77,7 +77,11 @@ class Scan extends Command {
if (is_object($user)) {
$user = $user->getUID();
}
$this->scanFiles($user, $output);
if ($this->userManager->userExists($user)) {
$this->scanFiles($user, $output);
} else {
$output->writeln("<error>Unknown user $user</error>");
}
}
}
}
+12 -8
View File
@@ -153,19 +153,23 @@ table th .columntitle.name {
margin-left: 50px;
}
.sort-indicator.hidden { visibility: hidden; }
table th .sort-indicator {
width: 10px;
height: 8px;
margin-left: 10px;
margin-left: 5px;
display: inline-block;
vertical-align: text-bottom;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=30)";
filter: alpha(opacity=30);
opacity: .3;
}
.sort-indicator.hidden {
visibility: hidden;
}
table th:hover .sort-indicator.hidden {
width: 10px;
height: 8px;
margin-left: 10px;
visibility: visible;
}
table th, table td { border-bottom:1px solid #ddd; text-align:left; font-weight:normal; }
table td {
padding: 0 15px;
@@ -235,8 +239,8 @@ table td.filename a.name {
table tr[data-type="dir"] td.filename a.name span.nametext {font-weight:bold; }
table td.filename input.filename {
width: 70%;
margin-top: 1px;
margin-left: 48px;
margin-top: 6px;
margin-left: 7px;
cursor: text;
}
table td.filename a, table td.login, table td.logout, table td.download, table td.upload, table td.create, table td.delete { padding:3px 8px 8px 3px; }
@@ -475,7 +479,7 @@ a.action>img {
.summary td {
padding-top: 20px;
padding-bottom: 250px;
padding-bottom: 150px;
border-bottom: none;
}
.summary .info {
+24
View File
@@ -137,3 +137,27 @@
.oc-dialog .oc-dialog-buttonrow .cancel {
float:left;
}
.highlightUploaded {
-webkit-animation: highlightAnimation 2s 1;
-moz-animation: highlightAnimation 2s 1;
-o-animation: highlightAnimation 2s 1;
animation: highlightAnimation 2s 1;
}
@-webkit-keyframes highlightAnimation {
0% { background-color: rgba(255, 255, 140, 1); }
100% { background-color: rgba(0, 0, 0, 0); }
}
@-moz-keyframes highlightAnimation {
0% { background-color: rgba(255, 255, 140, 1); }
100% { background-color: rgba(0, 0, 0, 0); }
}
@-o-keyframes highlightAnimation {
0% { background-color: rgba(255, 255, 140, 1); }
100% { background-color: rgba(0, 0, 0, 0); }
}
@keyframes highlightAnimation {
0% { background-color: rgba(255, 255, 140, 1); }
100% { background-color: rgba(0, 0, 0, 0); }
}
+2 -2
View File
@@ -34,12 +34,12 @@ if(!\OC\Files\Filesystem::file_exists($filename)) {
exit;
}
$ftype=\OC\Files\Filesystem::getMimeType( $filename );
$ftype=\OC_Helper::getSecureMimeType(\OC\Files\Filesystem::getMimeType( $filename ));
header('Content-Type:'.$ftype);
OCP\Response::setContentDispositionHeader(basename($filename), 'attachment');
OCP\Response::disableCaching();
header('Content-Length: '.\OC\Files\Filesystem::filesize($filename));
OCP\Response::setContentLengthHeader(\OC\Files\Filesystem::filesize($filename));
OC_Util::obEnd();
\OC\Files\Filesystem::readfile( $filename );
+4 -2
View File
@@ -24,6 +24,7 @@
initialize: function() {
this.navigation = new OCA.Files.Navigation($('#app-navigation'));
var urlParams = OC.Util.History.parseUrlQuery();
var fileActions = new OCA.Files.FileActions();
// default actions
fileActions.registerDefaultActions();
@@ -47,7 +48,8 @@
dragOptions: dragOptions,
folderDropOptions: folderDropOptions,
fileActions: fileActions,
allowLegacyActions: true
allowLegacyActions: true,
scrollTo: urlParams.scrollto
}
);
this.files.initialize();
@@ -58,7 +60,7 @@
this._setupEvents();
// trigger URL change event handlers
this._onPopState(OC.Util.History.parseUrlQuery());
this._onPopState(urlParams);
},
/**
+25 -2
View File
@@ -427,6 +427,14 @@ OC.Upload = {
data.textStatus = 'servererror';
data.errorThrown = result[0].data.message; // error message has been translated on server
fu._trigger('fail', e, data);
} else { // Successful upload
// Checking that the uploaded file is the last one and contained in the current directory
if (data.files[0] === data.originalFiles[data.originalFiles.length - 1] &&
result[0].directory === FileList.getCurrentDirectory()) {
// Scroll to the last uploaded file and highlight all of them
var fileList = _.pluck(data.originalFiles, 'name');
FileList.highlightFiles(fileList);
}
}
},
/**
@@ -482,6 +490,21 @@ OC.Upload = {
}
});
} else {
// for all browsers that don't support the progress bar
// IE 8 & 9
// show a spinner
fileupload.on('fileuploadstart', function() {
$('#upload').addClass('icon-loading');
$('#upload .icon-upload').hide();
});
// hide a spinner
fileupload.on('fileuploadstop fileuploadfail', function() {
$('#upload').removeClass('icon-loading');
$('#upload .icon-upload').show();
});
}
}
@@ -621,7 +644,7 @@ OC.Upload = {
},
function(result) {
if (result.status === 'success') {
FileList.add(result.data, {hidden: hidden, animate: true});
FileList.add(result.data, {hidden: hidden, animate: true, scrollTo: true});
} else {
OC.dialogs.alert(result.data.message, t('core', 'Could not create file'));
}
@@ -637,7 +660,7 @@ OC.Upload = {
},
function(result) {
if (result.status === 'success') {
FileList.add(result.data, {hidden: hidden, animate: true});
FileList.add(result.data, {hidden: hidden, animate: true, scrollTo: true});
} else {
OC.dialogs.alert(result.data.message, t('core', 'Could not create folder'));
}
+125 -21
View File
@@ -49,8 +49,10 @@
fileSummary: null,
initialized: false,
// number of files per page
pageSize: 20,
// number of files per page, calculated dynamically
pageSize: function() {
return Math.ceil(this.$container.height() / 50);
},
/**
* Array of files in the current folder.
@@ -103,9 +105,10 @@
* @param $el container element with existing markup for the #controls
* and a table
* @param options map of options, see other parameters
* @param scrollContainer scrollable container, defaults to $(window)
* @param dragOptions drag options, disabled by default
* @param folderDropOptions folder drop options, disabled by default
* @param options.scrollContainer scrollable container, defaults to $(window)
* @param options.dragOptions drag options, disabled by default
* @param options.folderDropOptions folder drop options, disabled by default
* @param options.scrollTo name of file to scroll to after the first load
*/
initialize: function($el, options) {
var self = this;
@@ -165,6 +168,12 @@
this.setupUploadEvents();
this.$container.on('scroll', _.bind(this._onScroll, this));
if (options.scrollTo) {
this.$fileList.one('updated', function() {
self.scrollTo(options.scrollTo);
});
}
},
/**
@@ -472,7 +481,8 @@
mimetype: $el.attr('data-mime'),
type: $el.attr('data-type'),
size: parseInt($el.attr('data-size'), 10),
etag: $el.attr('data-etag')
etag: $el.attr('data-etag'),
permissions: parseInt($el.attr('data-permissions'), 10)
};
},
@@ -483,7 +493,7 @@
*/
_nextPage: function(animate) {
var index = this.$fileList.children().length,
count = this.pageSize,
count = this.pageSize(),
tr,
fileData,
newTrs = [],
@@ -709,9 +719,10 @@
*
* @param fileData map of file attributes
* @param options map of attributes:
* - "updateSummary": true to update the summary after adding (default), false otherwise
* - "silent": true to prevent firing events like "fileActionsReady"
* - "animate": true to animate preview loading (defaults to true here)
* @param options.updateSummary true to update the summary after adding (default), false otherwise
* @param options.silent true to prevent firing events like "fileActionsReady"
* @param options.animate true to animate preview loading (defaults to true here)
* @param options.scrollTo true to automatically scroll to the file's location
* @return new tr element (not appended to the table)
*/
add: function(fileData, options) {
@@ -760,6 +771,10 @@
});
}
if (options.scrollTo) {
this.scrollTo(fileData.name);
}
// defaults to true if not defined
if (typeof(options.updateSummary) === 'undefined' || !!options.updateSummary) {
this.fileSummary.add(fileData, true);
@@ -1155,7 +1170,7 @@
// if there are less elements visible than one page
// but there are still pending elements in the array,
// then directly append the next page
if (lastIndex < this.files.length && lastIndex < this.pageSize) {
if (lastIndex < this.files.length && lastIndex < this.pageSize()) {
this._nextPage(true);
}
@@ -1507,16 +1522,15 @@
this.$table.removeClass('hidden');
},
scrollTo:function(file) {
//scroll to and highlight preselected file
var $scrollToRow = this.findFileEl(file);
if ($scrollToRow.exists()) {
$scrollToRow.addClass('searchresult');
$(window).scrollTop($scrollToRow.position().top);
//remove highlight when hovered over
$scrollToRow.one('hover', function() {
$scrollToRow.removeClass('searchresult');
});
if (!_.isArray(file)) {
file = [file];
}
this.highlightFiles(file, function($tr) {
$tr.addClass('searchresult');
$tr.one('hover', function() {
$tr.removeClass('searchresult');
});
});
},
filter:function(query) {
this.$fileList.find('tr').each(function(i,e) {
@@ -1551,7 +1565,7 @@
this.$el.find('.selectedActions').addClass('hidden');
}
else {
canDelete = (this.getDirectoryPermissions() & OC.PERMISSION_DELETE);
canDelete = (this.getDirectoryPermissions() & OC.PERMISSION_DELETE) && this.isSelectedDeletable();
this.$el.find('.selectedActions').removeClass('hidden');
this.$el.find('#headerSize a>span:first').text(OC.Util.humanFileSize(summary.totalSize));
var selection = '';
@@ -1571,6 +1585,15 @@
}
},
/**
* Check whether all selected files are deletable
*/
isSelectedDeletable: function() {
return _.reduce(this.getSelectedFiles(), function(deletable, file) {
return deletable && (file.permissions & OC.PERMISSION_DELETE);
}, true);
},
/**
* Returns whether all files are selected
* @return true if all files are selected, false otherwise
@@ -1615,6 +1638,18 @@
return name;
},
/**
* Shows a "permission denied" notification
*/
_showPermissionDeniedNotification: function() {
var message = t('core', 'You dont have permission to upload or create files here');
OC.Notification.show(message);
//hide notification after 10 sec
setTimeout(function() {
OC.Notification.hide();
}, 5000);
},
/**
* Setup file upload events related to the file-upload plugin
*/
@@ -1646,6 +1681,12 @@
// remember as context
data.context = dropTarget;
// if permissions are specified, only allow if create permission is there
var permissions = dropTarget.data('permissions');
if (!_.isUndefined(permissions) && (permissions & OC.PERMISSION_CREATE) === 0) {
self._showPermissionDeniedNotification();
return false;
}
var dir = dropTarget.data('file');
// if from file list, need to prepend parent dir
if (dir) {
@@ -1670,6 +1711,7 @@
// cancel uploads to current dir if no permission
var isCreatable = (self.getDirectoryPermissions() & OC.PERMISSION_CREATE) !== 0;
if (!isCreatable) {
self._showPermissionDeniedNotification();
return false;
}
}
@@ -1840,6 +1882,68 @@
self.updateStorageStatistics();
});
},
/**
* Scroll to the last file of the given list
* Highlight the list of files
* @param files array of filenames,
* @param {Function} [highlightFunction] optional function
* to be called after the scrolling is finished
*/
highlightFiles: function(files, highlightFunction) {
// Detection of the uploaded element
var filename = files[files.length - 1];
var $fileRow = this.findFileEl(filename);
while(!$fileRow.exists() && this._nextPage(false) !== false) { // Checking element existence
$fileRow = this.findFileEl(filename);
}
if (!$fileRow.exists()) { // Element not present in the file list
return;
}
var currentOffset = this.$container.scrollTop();
var additionalOffset = this.$el.find("#controls").height()+this.$el.find("#controls").offset().top;
// Animation
var _this = this;
var $scrollContainer = this.$container;
if ($scrollContainer[0] === window) {
// need to use "body" to animate scrolling
// when the scroll container is the window
$scrollContainer = $('body');
}
$scrollContainer.animate({
// Scrolling to the top of the new element
scrollTop: currentOffset + $fileRow.offset().top - $fileRow.height() * 2 - additionalOffset
}, {
duration: 500,
complete: function() {
// Highlighting function
var highlightRow = highlightFunction;
if (!highlightRow) {
highlightRow = function($fileRow) {
$fileRow.addClass("highlightUploaded");
setTimeout(function() {
$fileRow.removeClass("highlightUploaded");
}, 2500);
};
}
// Loop over uploaded files
for(var i=0; i<files.length; i++) {
var $fileRow = _this.findFileEl(files[i]);
if($fileRow.length !== 0) { // Checking element existence
highlightRow($fileRow);
}
}
}
});
}
};
+7 -2
View File
@@ -350,7 +350,7 @@ var createDragShadow = function(event) {
}
// do not show drag shadow for too many files
var selectedFiles = _.first(FileList.getSelectedFiles(), FileList.pageSize);
var selectedFiles = _.first(FileList.getSelectedFiles(), FileList.pageSize());
selectedFiles = _.sortBy(selectedFiles, FileList._fileInfoCompare);
if (!isDragSelected && selectedFiles.length === 1) {
@@ -433,7 +433,12 @@ var folderDropOptions = {
return false;
}
var targetPath = FileList.getCurrentDirectory() + '/' + $(this).closest('tr').data('file');
var $tr = $(this).closest('tr');
if (($tr.data('permissions') & OC.PERMISSION_CREATE) === 0) {
FileList._showPermissionDeniedNotification();
return false;
}
var targetPath = FileList.getCurrentDirectory() + '/' + $tr.data('file');
var files = FileList.getSelectedFiles();
if (files.length === 0) {
+4 -4
View File
@@ -17,7 +17,7 @@ $TRANSLATIONS = array(
"Invalid Token" => "Jeton non valide",
"No file was uploaded. Unknown error" => "Aucun fichier n'a été envoyé. Erreur inconnue",
"There is no error, the file uploaded with success" => "Aucune erreur, le fichier a été envoyé avec succès.",
"The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Le fichier envoyé dépasse l'instruction upload_max_filesize située dans le fichier php.ini:",
"The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Le fichier envoyé dépasse l'instruction upload_max_filesize située dans le fichier php.ini :",
"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Le fichier envoyé dépasse l'instruction MAX_FILE_SIZE qui est spécifiée dans le formulaire HTML.",
"The uploaded file was only partially uploaded" => "Le fichier n'a été que partiellement envoyé.",
"No file was uploaded" => "Pas de fichier envoyé.",
@@ -62,7 +62,7 @@ $TRANSLATIONS = array(
"Your storage is almost full ({usedSpacePercent}%)" => "Votre espace de stockage est presque plein ({usedSpacePercent}%)",
"Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "L'application de chiffrement est activée mais vos clés ne sont pas initialisées, veuillez vous déconnecter et ensuite vous reconnecter.",
"Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "Votre clef privée pour l'application de chiffrement est invalide ! Veuillez mettre à jour le mot de passe de votre clef privée dans vos paramètres personnels pour récupérer l'accès à vos fichiers chiffrés.",
"Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Le chiffrement était désactivé mais vos fichiers sont toujours chiffrés. Veuillez vous rendre sur vos Paramètres personnels pour déchiffrer vos fichiers.",
"Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Le chiffrement a été désactivé mais vos fichiers sont toujours chiffrés. Veuillez vous rendre sur vos paramètres personnels pour déchiffrer vos fichiers.",
"{dirs} and {files}" => "{dirs} et {files}",
"%s could not be renamed" => "%s ne peut être renommé",
"Upload (max. %s)" => "Envoi (max. %s)",
@@ -77,13 +77,13 @@ $TRANSLATIONS = array(
"Text file" => "Fichier texte",
"New folder" => "Nouveau dossier",
"Folder" => "Dossier",
"From link" => "Depuis le lien",
"From link" => "Depuis un lien",
"You dont have permission to upload or create files here" => "Vous n'avez pas la permission de téléverser ou de créer des fichiers ici",
"Nothing in here. Upload something!" => "Il n'y a rien ici ! Envoyez donc quelque chose :)",
"Download" => "Télécharger",
"Upload too large" => "Téléversement trop volumineux",
"The files you are trying to upload exceed the maximum size for file uploads on this server." => "Les fichiers que vous essayez d'envoyer dépassent la taille maximale permise par ce serveur.",
"Files are being scanned, please wait." => "Les fichiers sont en cours d'analyse, veuillez patienter.",
"Currently scanning" => "Analyse en cours de traitement"
"Currently scanning" => "Analyse en cours",
);
$PLURAL_FORMS = "nplurals=2; plural=(n > 1);";
+1 -1
View File
@@ -93,7 +93,7 @@ class Helper
public static function compareSize($a, $b) {
$aSize = $a->getSize();
$bSize = $b->getSize();
return $aSize - $bSize;
return ($aSize < $bSize) ? -1 : 1;
}
/**
+12 -2
View File
@@ -34,7 +34,14 @@ class Test_OC_Files_App_Rename extends \PHPUnit_Framework_TestCase {
*/
private $files;
function setUp() {
/** @var \OC\Files\Storage\Storage */
private $originalStorage;
protected function setUp() {
parent::setUp();
$this->originalStorage = \OC\Files\Filesystem::getStorage('/');
// mock OC_L10n
if (!self::$user) {
self::$user = uniqid();
@@ -59,10 +66,13 @@ class Test_OC_Files_App_Rename extends \PHPUnit_Framework_TestCase {
$this->files = new \OCA\Files\App($viewMock, $l10nMock);
}
function tearDown() {
protected function tearDown() {
$result = \OC_User::deleteUser(self::$user);
$this->assertTrue($result);
\OC\Files\Filesystem::tearDown();
\OC\Files\Filesystem::mount($this->originalStorage, array(), '/');
parent::tearDown();
}
/**
+48 -18
View File
@@ -20,7 +20,7 @@
*/
describe('OCA.Files.FileList tests', function() {
var testFiles, alertStub, notificationStub, fileList;
var testFiles, alertStub, notificationStub, fileList, pageSizeStub;
var bcResizeStub;
/**
@@ -97,7 +97,8 @@ describe('OCA.Files.FileList tests', function() {
name: 'One.txt',
mimetype: 'text/plain',
size: 12,
etag: 'abc'
etag: 'abc',
permissions: OC.PERMISSION_ALL
}, {
id: 2,
type: 'file',
@@ -105,6 +106,7 @@ describe('OCA.Files.FileList tests', function() {
mimetype: 'image/jpeg',
size: 12049,
etag: 'def',
permissions: OC.PERMISSION_ALL
}, {
id: 3,
type: 'file',
@@ -112,15 +114,17 @@ describe('OCA.Files.FileList tests', function() {
mimetype: 'application/pdf',
size: 58009,
etag: '123',
permissions: OC.PERMISSION_ALL
}, {
id: 4,
type: 'dir',
name: 'somedir',
mimetype: 'httpd/unix-directory',
size: 250,
etag: '456'
etag: '456',
permissions: OC.PERMISSION_ALL
}];
pageSizeStub = sinon.stub(OCA.Files.FileList.prototype, 'pageSize').returns(20);
fileList = new OCA.Files.FileList($('#app-content-files'));
});
afterEach(function() {
@@ -130,6 +134,7 @@ describe('OCA.Files.FileList tests', function() {
notificationStub.restore();
alertStub.restore();
bcResizeStub.restore();
pageSizeStub.restore();
});
describe('Getters', function() {
it('Returns the current directory', function() {
@@ -218,13 +223,13 @@ describe('OCA.Files.FileList tests', function() {
expect($tr).toBeDefined();
expect($tr[0].tagName.toLowerCase()).toEqual('tr');
expect($tr.attr('data-id')).toEqual(null);
expect($tr.attr('data-id')).toBeUndefined();
expect($tr.attr('data-type')).toEqual('file');
expect($tr.attr('data-file')).toEqual('testFile.txt');
expect($tr.attr('data-size')).toEqual(null);
expect($tr.attr('data-etag')).toEqual(null);
expect($tr.attr('data-size')).toBeUndefined();
expect($tr.attr('data-etag')).toBeUndefined();
expect($tr.attr('data-permissions')).toEqual('31');
expect($tr.attr('data-mime')).toEqual(null);
expect($tr.attr('data-mime')).toBeUndefined();
expect($tr.attr('data-mtime')).toEqual('123456');
expect($tr.find('.filesize').text()).toEqual('Pending');
@@ -239,11 +244,11 @@ describe('OCA.Files.FileList tests', function() {
expect($tr).toBeDefined();
expect($tr[0].tagName.toLowerCase()).toEqual('tr');
expect($tr.attr('data-id')).toEqual(null);
expect($tr.attr('data-id')).toBeUndefined();
expect($tr.attr('data-type')).toEqual('dir');
expect($tr.attr('data-file')).toEqual('testFolder');
expect($tr.attr('data-size')).toEqual(null);
expect($tr.attr('data-etag')).toEqual(null);
expect($tr.attr('data-size')).toBeUndefined();
expect($tr.attr('data-etag')).toBeUndefined();
expect($tr.attr('data-permissions')).toEqual('31');
expect($tr.attr('data-mime')).toEqual('httpd/unix-directory');
expect($tr.attr('data-mtime')).toEqual('123456');
@@ -814,7 +819,7 @@ describe('OCA.Files.FileList tests', function() {
fileList.$fileList.on('fileActionsReady', handler);
fileList._nextPage();
expect(handler.calledOnce).toEqual(true);
expect(handler.getCall(0).args[0].$files.length).toEqual(fileList.pageSize);
expect(handler.getCall(0).args[0].$files.length).toEqual(fileList.pageSize());
});
it('does not trigger "fileActionsReady" event after single add with silent argument', function() {
var handler = sinon.stub();
@@ -1478,6 +1483,17 @@ describe('OCA.Files.FileList tests', function() {
$('.select-all').click();
expect(fileList.$el.find('.delete-selected').hasClass('hidden')).toEqual(true);
});
it('show doesnt show the delete action if one or more files are not deletable', function () {
fileList.setFiles(testFiles);
$('#permissions').val(OC.PERMISSION_READ | OC.PERMISSION_DELETE);
$('.select-all').click();
expect(fileList.$el.find('.delete-selected').hasClass('hidden')).toEqual(false);
testFiles[0].permissions = OC.PERMISSION_READ;
$('.select-all').click();
fileList.setFiles(testFiles);
$('.select-all').click();
expect(fileList.$el.find('.delete-selected').hasClass('hidden')).toEqual(true);
});
});
describe('Actions', function() {
beforeEach(function() {
@@ -1494,7 +1510,8 @@ describe('OCA.Files.FileList tests', function() {
mimetype: 'text/plain',
type: 'file',
size: 12,
etag: 'abc'
etag: 'abc',
permissions: OC.PERMISSION_ALL
});
expect(files[1]).toEqual({
id: 3,
@@ -1502,7 +1519,8 @@ describe('OCA.Files.FileList tests', function() {
name: 'Three.pdf',
mimetype: 'application/pdf',
size: 58009,
etag: '123'
etag: '123',
permissions: OC.PERMISSION_ALL
});
expect(files[2]).toEqual({
id: 4,
@@ -1510,7 +1528,8 @@ describe('OCA.Files.FileList tests', function() {
name: 'somedir',
mimetype: 'httpd/unix-directory',
size: 250,
etag: '456'
etag: '456',
permissions: OC.PERMISSION_ALL
});
});
it('Removing a file removes it from the selection', function() {
@@ -1523,7 +1542,8 @@ describe('OCA.Files.FileList tests', function() {
mimetype: 'text/plain',
type: 'file',
size: 12,
etag: 'abc'
etag: 'abc',
permissions: OC.PERMISSION_ALL
});
expect(files[1]).toEqual({
id: 4,
@@ -1531,7 +1551,8 @@ describe('OCA.Files.FileList tests', function() {
name: 'somedir',
mimetype: 'httpd/unix-directory',
size: 250,
etag: '456'
etag: '456',
permissions: OC.PERMISSION_ALL
});
});
describe('Download', function() {
@@ -1835,7 +1856,6 @@ describe('OCA.Files.FileList tests', function() {
// but it makes it possible to simulate the event triggering to
// test the response of the handlers
$uploader = $('#file_upload_start');
fileList.setupUploadEvents();
fileList.setFiles(testFiles);
});
@@ -1912,6 +1932,16 @@ describe('OCA.Files.FileList tests', function() {
ev = dropOn(fileList.$fileList.find('th:first'));
expect(ev.result).toEqual(false);
expect(notificationStub.calledOnce).toEqual(true);
});
it('drop on an folder does not trigger upload if no upload permission on that folder', function() {
var $tr = fileList.findFileEl('somedir');
var ev;
$tr.data('permissions', OC.PERMISSION_READ);
ev = dropOn($tr);
expect(ev.result).toEqual(false);
expect(notificationStub.calledOnce).toEqual(true);
});
it('drop on a file row inside the table triggers upload to current folder', function() {
var ev;
+31 -17
View File
@@ -16,8 +16,28 @@ use OCA\Encryption;
$l = OC_L10N::get('files_encryption');
$return = false;
// Enable recoveryAdmin
$errorMessage = $l->t("Unknown error");
//check if both passwords are the same
if (empty($_POST['recoveryPassword'])) {
$errorMessage = $l->t('Missing recovery key password');
\OCP\JSON::error(array('data' => array('message' => $errorMessage)));
exit();
}
if (empty($_POST['confirmPassword'])) {
$errorMessage = $l->t('Please repeat the recovery key password');
\OCP\JSON::error(array('data' => array('message' => $errorMessage)));
exit();
}
if ($_POST['recoveryPassword'] !== $_POST['confirmPassword']) {
$errorMessage = $l->t('Repeated recovery key password does not match the provided recovery key password');
\OCP\JSON::error(array('data' => array('message' => $errorMessage)));
exit();
}
// Enable recoveryAdmin
$recoveryKeyId = \OC::$server->getAppConfig()->getValue('files_encryption', 'recoveryKeyId');
if (isset($_POST['adminEnableRecovery']) && $_POST['adminEnableRecovery'] === '1') {
@@ -26,14 +46,9 @@ if (isset($_POST['adminEnableRecovery']) && $_POST['adminEnableRecovery'] === '1
// Return success or failure
if ($return) {
\OCP\JSON::success(array('data' => array('message' => $l->t('Recovery key successfully enabled'))));
$successMessage = $l->t('Recovery key successfully enabled');
} else {
\OCP\JSON::error(array(
'data' => array(
'message' => $l->t(
'Could not enable recovery key. Please check your recovery key password!')
)
));
$errorMessage = $l->t('Could not disable recovery key. Please check your recovery key password!');
}
// Disable recoveryAdmin
@@ -43,17 +58,16 @@ if (isset($_POST['adminEnableRecovery']) && $_POST['adminEnableRecovery'] === '1
) {
$return = \OCA\Encryption\Helper::adminDisableRecovery($_POST['recoveryPassword']);
// Return success or failure
if ($return) {
\OCP\JSON::success(array('data' => array('message' => $l->t('Recovery key successfully disabled'))));
$successMessage = $l->t('Recovery key successfully disabled');
} else {
\OCP\JSON::error(array(
'data' => array(
'message' => $l->t(
'Could not disable recovery key. Please check your recovery key password!')
)
));
$errorMessage = $l->t('Could not disable recovery key. Please check your recovery key password!');
}
}
// Return success or failure
if ($return) {
\OCP\JSON::success(array('data' => array('message' => $successMessage)));
} else {
\OCP\JSON::error(array('data' => array('message' => $errorMessage)));
}
@@ -21,6 +21,32 @@ $return = false;
$oldPassword = $_POST['oldPassword'];
$newPassword = $_POST['newPassword'];
$confirmPassword = $_POST['confirmPassword'];
//check if both passwords are the same
if (empty($_POST['oldPassword'])) {
$errorMessage = $l->t('Please provide the old recovery password');
\OCP\JSON::error(array('data' => array('message' => $errorMessage)));
exit();
}
if (empty($_POST['newPassword'])) {
$errorMessage = $l->t('Please provide a new recovery password');
\OCP\JSON::error(array('data' => array('message' => $errorMessage)));
exit();
}
if (empty($_POST['confirmPassword'])) {
$errorMessage = $l->t('Please repeat the new recovery password');
\OCP\JSON::error(array('data' => array('message' => $errorMessage)));
exit();
}
if ($_POST['newPassword'] !== $_POST['confirmPassword']) {
$errorMessage = $l->t('Repeated recovery key password does not match the provided recovery key password');
\OCP\JSON::error(array('data' => array('message' => $errorMessage)));
exit();
}
$view = new \OC\Files\View('/');
$util = new \OCA\Encryption\Util(new \OC\Files\View('/'), \OCP\User::getUser());
@@ -18,6 +18,7 @@ use OCA\Encryption;
$l = OC_L10N::get('core');
$return = false;
$errorMessage = $l->t('Could not update the private key password.');
$oldPassword = $_POST['oldPassword'];
$newPassword = $_POST['newPassword'];
@@ -25,31 +26,45 @@ $newPassword = $_POST['newPassword'];
$view = new \OC\Files\View('/');
$session = new \OCA\Encryption\Session($view);
$user = \OCP\User::getUser();
$loginName = \OC::$server->getUserSession()->getLoginName();
$proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false;
// check new password
$passwordCorrect = \OCP\User::checkPassword($loginName, $newPassword);
$keyPath = '/' . $user . '/files_encryption/' . $user . '.private.key';
if ($passwordCorrect !== false) {
$encryptedKey = $view->file_get_contents($keyPath);
$decryptedKey = \OCA\Encryption\Crypt::decryptPrivateKey($encryptedKey, $oldPassword);
$proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false;
if ($decryptedKey) {
$cipher = \OCA\Encryption\Helper::getCipher();
$encryptedKey = \OCA\Encryption\Crypt::symmetricEncryptFileContent($decryptedKey, $newPassword, $cipher);
if ($encryptedKey) {
\OCA\Encryption\Keymanager::setPrivateKey($encryptedKey, $user);
$session->setPrivateKey($decryptedKey);
$return = true;
$keyPath = '/' . $user . '/files_encryption/' . $user . '.private.key';
$encryptedKey = $view->file_get_contents($keyPath);
$decryptedKey = \OCA\Encryption\Crypt::decryptPrivateKey($encryptedKey, $oldPassword);
if ($decryptedKey) {
$cipher = \OCA\Encryption\Helper::getCipher();
$encryptedKey = \OCA\Encryption\Crypt::symmetricEncryptFileContent($decryptedKey, $newPassword, $cipher);
if ($encryptedKey) {
\OCA\Encryption\Keymanager::setPrivateKey($encryptedKey, $user);
$session->setPrivateKey($decryptedKey);
$return = true;
}
} else {
$result = false;
$errorMessage = $l->t('The old password was not correct, please try again.');
}
}
\OC_FileProxy::$enabled = $proxyStatus;
\OC_FileProxy::$enabled = $proxyStatus;
} else {
$result = false;
$errorMessage = $l->t('The current log-in password was not correct, please try again.');
}
// success or failure
if ($return) {
$session->setInitialized(\OCA\Encryption\Session::INIT_SUCCESSFUL);
\OCP\JSON::success(array('data' => array('message' => $l->t('Private key password successfully updated.'))));
} else {
\OCP\JSON::error(array('data' => array('message' => $l->t('Could not update the private key password. Maybe the old password was not correct.'))));
\OCP\JSON::error(array('data' => array('message' => $errorMessage)));
}
+7 -1
View File
@@ -13,6 +13,8 @@ use OCA\Encryption;
\OCP\JSON::checkAppEnabled('files_encryption');
\OCP\JSON::callCheck();
$l = \OC::$server->getL10N('files_encryption');
if (
isset($_POST['userEnableRecovery'])
&& (0 == $_POST['userEnableRecovery'] || '1' === $_POST['userEnableRecovery'])
@@ -38,4 +40,8 @@ if (
}
// Return success or failure
($return) ? \OCP\JSON::success() : \OCP\JSON::error();
if ($return) {
\OCP\JSON::success(array('data' => array('message' => $l->t('File recovery settings updated'))));
} else {
\OCP\JSON::error(array('data' => array('message' => $l->t('Could not update file recovery'))));
}
-16
View File
@@ -35,22 +35,6 @@ if (!OC_Config::getValue('maintenance', false)) {
if(!in_array('crypt', stream_get_wrappers())) {
stream_wrapper_register('crypt', 'OCA\Encryption\Stream');
}
// check if we are logged in
if (OCP\User::isLoggedIn()) {
// ensure filesystem is loaded
if (!\OC\Files\Filesystem::$loaded) {
\OC_Util::setupFS();
}
$view = new OC\Files\View('/');
$sessionReady = OCA\Encryption\Helper::checkRequirements();
if($sessionReady) {
$session = new \OCA\Encryption\Session($view);
}
}
} else {
// logout user if we are in maintenance to force re-login
OCP\User::logout();
+7 -3
View File
@@ -2,14 +2,18 @@
<info>
<id>files_encryption</id>
<name>Encryption</name>
<description>The ownCloud files encryption system provides server side-encryption. After the app is enabled you need to re-login to initialize your encryption keys. Please note that server side encryption requires that the ownCloud server admin can be trusted. The main purpose of this app is the encryption of files that are stored on externally mounted storages.</description>
<description>
This application encrypts all files accessed by ownCloud at rest, wherever they are stored. As an example, with this application enabled, external cloud based Amazon S3 storage will be encrypted, protecting this data on storage outside of the control of the Admin. When this application is enabled for the first time, all files are encrypted as users log in and are prompted for their password. The recommended recovery key option enables recovery of files in case the key is lost.
Note that this app encrypts all files that are touched by ownCloud, so external storage providers and applications such as SharePoint will see new files encrypted when they are accessed. Encryption is based on AES 128 or 256 bit keys. More information is available in the Encryption documentation.
</description>
<licence>AGPL</licence>
<author>Sam Tuke, Bjoern Schiessle, Florin Peter</author>
<requiremin>4</requiremin>
<shipped>true</shipped>
<documentation>
<user>http://doc.owncloud.org/server/6.0/user_manual/files/encryption.html</user>
<admin>http://doc.owncloud.org/server/6.0/admin_manual/configuration/configuration_encryption.html</admin>
<user>user-encryption</user>
<admin>admin-encryption</admin>
</documentation>
<rememberlogin>false</rememberlogin>
<types>
+3
View File
@@ -6,6 +6,9 @@ if (!isset($_)) { //also provide standalone error page
$l = OC_L10N::get('files_encryption');
OC_JSON::checkAppEnabled('files_encryption');
OC_App::loadApp('files_encryption');
if (isset($_GET['errorCode'])) {
$errorCode = $_GET['errorCode'];
switch ($errorCode) {
+34 -31
View File
@@ -205,13 +205,12 @@ class Hooks {
if (Crypt::mode() === 'server') {
$view = new \OC\Files\View('/');
$session = new \OCA\Encryption\Session($view);
if ($params['uid'] === \OCP\User::getUser()) {
// Get existing decrypted private key
$privateKey = $session->getPrivateKey();
$session = new \OCA\Encryption\Session($view);
// Get existing decrypted private key
$privateKey = $session->getPrivateKey();
if ($params['uid'] === \OCP\User::getUser() && $privateKey) {
// Encrypt private key with new user pwd as passphrase
$encryptedPrivateKey = Crypt::symmetricEncryptFileContent($privateKey, $params['password'], Helper::getCipher());
@@ -242,6 +241,9 @@ class Hooks {
|| !$util->userKeysExists()
|| !$view->file_exists($user . '/files')) {
// backup old keys
$util->backupAllKeys('recovery');
$newUserPassword = $params['password'];
// make sure that the users home is mounted
@@ -421,34 +423,18 @@ class Hooks {
* @param array $params with the old path and the new path
*/
public static function preRename($params) {
$user = \OCP\User::getUser();
$view = new \OC\Files\View('/');
$util = new Util($view, $user);
list($ownerOld, $pathOld) = $util->getUidAndFilename($params['oldpath']);
// we only need to rename the keys if the rename happens on the same mountpoint
// otherwise we perform a stream copy, so we get a new set of keys
$mp1 = $view->getMountPoint('/' . $user . '/files/' . $params['oldpath']);
$mp2 = $view->getMountPoint('/' . $user . '/files/' . $params['newpath']);
$type = $view->is_dir('/' . $user . '/files/' . $params['oldpath']) ? 'folder' : 'file';
if ($mp1 === $mp2) {
self::$renamedFiles[$params['oldpath']] = array(
'uid' => $ownerOld,
'path' => $pathOld,
'type' => $type,
'operation' => 'rename',
);
}
self::preRenameOrCopy($params, 'rename');
}
/**
* mark file as renamed so that we know the original source after the file was renamed
* mark file as copied so that we know the original source after the file was copied
* @param array $params with the old path and the new path
*/
public static function preCopy($params) {
self::preRenameOrCopy($params, 'copy');
}
private static function preRenameOrCopy($params, $operation) {
$user = \OCP\User::getUser();
$view = new \OC\Files\View('/');
$util = new Util($view, $user);
@@ -462,11 +448,27 @@ class Hooks {
$type = $view->is_dir('/' . $user . '/files/' . $params['oldpath']) ? 'folder' : 'file';
if ($mp1 === $mp2) {
if ($util->isSystemWideMountPoint($pathOld)) {
$oldShareKeyPath = 'files_encryption/share-keys/' . $pathOld;
} else {
$oldShareKeyPath = $ownerOld . '/' . 'files_encryption/share-keys/' . $pathOld;
}
// gather share keys here because in postRename() the file will be moved already
$oldShareKeys = Helper::findShareKeys($pathOld, $oldShareKeyPath, $view);
if (count($oldShareKeys) === 0) {
\OC_Log::write(
'Encryption library', 'No share keys found for "' . $pathOld . '"',
\OC_Log::WARN
);
}
self::$renamedFiles[$params['oldpath']] = array(
'uid' => $ownerOld,
'path' => $pathOld,
'type' => $type,
'operation' => 'copy');
'operation' => $operation,
'sharekeys' => $oldShareKeys
);
}
}
@@ -488,6 +490,7 @@ class Hooks {
$view = new \OC\Files\View('/');
$userId = \OCP\User::getUser();
$util = new Util($view, $userId);
$oldShareKeys = null;
if (isset(self::$renamedFiles[$params['oldpath']]['uid']) &&
isset(self::$renamedFiles[$params['oldpath']]['path'])) {
@@ -495,9 +498,11 @@ class Hooks {
$pathOld = self::$renamedFiles[$params['oldpath']]['path'];
$type = self::$renamedFiles[$params['oldpath']]['type'];
$operation = self::$renamedFiles[$params['oldpath']]['operation'];
$oldShareKeys = self::$renamedFiles[$params['oldpath']]['sharekeys'];
unset(self::$renamedFiles[$params['oldpath']]);
} else {
\OCP\Util::writeLog('Encryption library', "can't get path and owner from the file before it was renamed", \OCP\Util::DEBUG);
\OC_FileProxy::$enabled = $proxyStatus;
return false;
}
@@ -533,9 +538,7 @@ class Hooks {
$oldKeyfilePath .= '.key';
$newKeyfilePath .= '.key';
// handle share-keys
$matches = Helper::findShareKeys($oldShareKeyPath, $view);
foreach ($matches as $src) {
foreach ($oldShareKeys as $src) {
$dst = \OC\Files\Filesystem::normalizePath(str_replace($pathOld, $pathNew, $src));
$view->$operation($src, $dst);
}
+8 -35
View File
@@ -9,32 +9,21 @@
$(document).ready(function(){
$('input:password[name="encryptionRecoveryPassword"]').keyup(function(event) {
var recoveryPassword = $( '#encryptionRecoveryPassword' ).val();
var recoveryPasswordRepeated = $( '#repeatEncryptionRecoveryPassword' ).val();
var checkedButton = $('input:radio[name="adminEnableRecovery"]:checked').val();
var uncheckedValue = (1+parseInt(checkedButton)) % 2;
if (recoveryPassword !== '' && recoveryPassword === recoveryPasswordRepeated) {
$('input:radio[name="adminEnableRecovery"][value="'+uncheckedValue.toString()+'"]').removeAttr("disabled");
} else {
$('input:radio[name="adminEnableRecovery"][value="'+uncheckedValue.toString()+'"]').attr("disabled", "true");
}
});
$( 'input:radio[name="adminEnableRecovery"]' ).change(
function() {
var recoveryStatus = $( this ).val();
var oldStatus = (1+parseInt(recoveryStatus)) % 2;
var recoveryPassword = $( '#encryptionRecoveryPassword' ).val();
var confirmPassword = $( '#repeatEncryptionRecoveryPassword' ).val();
OC.msg.startSaving('#encryptionSetRecoveryKey .msg');
$.post(
OC.filePath( 'files_encryption', 'ajax', 'adminrecovery.php' )
, { adminEnableRecovery: recoveryStatus, recoveryPassword: recoveryPassword }
, { adminEnableRecovery: recoveryStatus, recoveryPassword: recoveryPassword, confirmPassword: confirmPassword }
, function( result ) {
OC.msg.finishedSaving('#encryptionSetRecoveryKey .msg', result);
if (result.status === "error") {
OC.Notification.show(t('admin', result.data.message));
$('input:radio[name="adminEnableRecovery"][value="'+oldStatus.toString()+'"]').attr("checked", "true");
} else {
OC.Notification.hide();
if (recoveryStatus === "0") {
$('p[name="changeRecoveryPasswordBlock"]').addClass("hidden");
} else {
@@ -49,33 +38,17 @@ $(document).ready(function(){
// change recovery password
$('input:password[name="changeRecoveryPassword"]').keyup(function(event) {
var oldRecoveryPassword = $('#oldEncryptionRecoveryPassword').val();
var newRecoveryPassword = $('#newEncryptionRecoveryPassword').val();
var newRecoveryPasswordRepeated = $('#repeatedNewEncryptionRecoveryPassword').val();
if (newRecoveryPassword !== '' && oldRecoveryPassword !== '' && newRecoveryPassword === newRecoveryPasswordRepeated) {
$('button:button[name="submitChangeRecoveryKey"]').removeAttr("disabled");
} else {
$('button:button[name="submitChangeRecoveryKey"]').attr("disabled", "true");
}
});
$('button:button[name="submitChangeRecoveryKey"]').click(function() {
var oldRecoveryPassword = $('#oldEncryptionRecoveryPassword').val();
var newRecoveryPassword = $('#newEncryptionRecoveryPassword').val();
OC.msg.startSaving('#encryption .msg');
var confirmNewPassword = $('#repeatedNewEncryptionRecoveryPassword').val();
OC.msg.startSaving('#encryptionChangeRecoveryKey .msg');
$.post(
OC.filePath( 'files_encryption', 'ajax', 'changeRecoveryPassword.php' )
, { oldPassword: oldRecoveryPassword, newPassword: newRecoveryPassword }
, { oldPassword: oldRecoveryPassword, newPassword: newRecoveryPassword, confirmPassword: confirmNewPassword }
, function( data ) {
if (data.status == "error") {
OC.msg.finishedSaving('#encryption .msg', data);
} else {
OC.msg.finishedSaving('#encryption .msg', data);
OC.msg.finishedSaving('#encryptionChangeRecoveryKey .msg', data);
}
}
);
});
+6 -15
View File
@@ -26,36 +26,27 @@ $(document).ready(function(){
// Trigger ajax on recoveryAdmin status change
$( 'input:radio[name="userEnableRecovery"]' ).change(
function() {
// Hide feedback messages in case they're already visible
$('#recoveryEnabledSuccess').hide();
$('#recoveryEnabledError').hide();
var recoveryStatus = $( this ).val();
OC.msg.startAction('#userEnableRecovery .msg', 'Updating recovery keys. This can take some time...');
$.post(
OC.filePath( 'files_encryption', 'ajax', 'userrecovery.php' )
, { userEnableRecovery: recoveryStatus }
, function( data ) {
if ( data.status == "success" ) {
$('#recoveryEnabledSuccess').show();
} else {
$('#recoveryEnabledError').show();
}
OC.msg.finishedAction('#userEnableRecovery .msg', data);
}
);
// Ensure page is not reloaded on form submit
return false;
}
);
$("#encryptAll").click(
function(){
// Hide feedback messages in case they're already visible
$('#encryptAllSuccess').hide();
$('#encryptAllError').hide();
var userPassword = $( '#userPassword' ).val();
var encryptAll = $( '#encryptAll' ).val();
@@ -73,7 +64,7 @@ $(document).ready(function(){
// Ensure page is not reloaded on form submit
return false;
}
);
// update private key password
+4 -4
View File
@@ -4,8 +4,8 @@ $TRANSLATIONS = array(
"Could not enable recovery key. Please check your recovery key password!" => "Impossible d'activer la clé de récupération. Veuillez vérifier votre mot de passe de clé de récupération !",
"Recovery key successfully disabled" => "Clé de récupération désactivée avec succès",
"Could not disable recovery key. Please check your recovery key password!" => "Impossible de désactiver la clé de récupération. Veuillez vérifier votre mot de passe de clé de récupération !",
"Password successfully changed." => "Mot de passe changé avec succès ",
"Could not change the password. Maybe the old password was not correct." => "Ne peut pas changer le mot de passe. L'ancien mot de passe est peut-être incorrect.",
"Password successfully changed." => "Mot de passe changé avec succès.",
"Could not change the password. Maybe the old password was not correct." => "Erreur lors du changement de mot de passe. L'ancien mot de passe est peut-être incorrect.",
"Private key password successfully updated." => "Mot de passe de la clé privé mis à jour avec succès.",
"Could not update the private key password. Maybe the old password was not correct." => "Impossible de mettre à jour le mot de passe de la clé privé. Peut-être que l'ancien mot de passe n'était pas correcte.",
"Encryption app not initialized! Maybe the encryption app was re-enabled during your session. Please try to log out and log back in to initialize the encryption app." => "L'application de chiffrement n'est pas initialisée ! Peut-être que cette application a été réactivée pendant votre session. Veuillez essayer de vous déconnecter et ensuite de vous reconnecter pour initialiser l'application de chiffrement.",
@@ -22,8 +22,8 @@ $TRANSLATIONS = array(
"Enable recovery key (allow to recover users files in case of password loss):" => "Activer la clef de récupération (permet de récupérer les fichiers des utilisateurs en cas de perte de mot de passe).",
"Recovery key password" => "Mot de passe de la clef de récupération",
"Repeat Recovery key password" => "Répétez le mot de passe de la clé de récupération",
"Enabled" => "Activer",
"Disabled" => "Désactiver",
"Enabled" => "Activé",
"Disabled" => "Désactivé",
"Change recovery key password:" => "Modifier le mot de passe de la clef de récupération :",
"Old Recovery key password" => "Ancien mot de passe de la clef de récupération",
"New Recovery key password" => "Nouveau mot de passe de la clef de récupération",
+4 -3
View File
@@ -24,6 +24,7 @@
*/
namespace OCA\Encryption;
use OCA\Encryption\Exceptions\EncryptionException;
require_once __DIR__ . '/../3rdparty/Crypt_Blowfish/Blowfish.php';
@@ -321,9 +322,9 @@ class Crypt {
$padded = self::addPadding($catfile);
return $padded;
} catch (OCA\Encryption\Exceptions\EncryptionException $e) {
$message = 'Could not encrypt file content (code: ' . $e->getCode . '): ';
\OCP\Util::writeLog('files_encryption', $message . $e->getMessage, \OCP\Util::ERROR);
} catch (EncryptionException $e) {
$message = 'Could not encrypt file content (code: ' . $e->getCode() . '): ';
\OCP\Util::writeLog('files_encryption', $message . $e->getMessage(), \OCP\Util::ERROR);
return false;
}
+30 -14
View File
@@ -431,24 +431,40 @@ class Helper {
/**
* find all share keys for a given file
* @param string $path to the file
* @param \OC\Files\View $view view, relative to data/
* @return array list of files, path relative to data/
*
* @param string $filePath path to the file name relative to the user's files dir
* for example "subdir/filename.txt"
* @param string $shareKeyPath share key prefix path relative to the user's data dir
* for example "user1/files_encryption/share-keys/subdir/filename.txt"
* @param \OC\Files\View $rootView root view, relative to data/
* @return array list of share key files, path relative to data/$user
*/
public static function findShareKeys($path, $view) {
public static function findShareKeys($filePath, $shareKeyPath, $rootView) {
$result = array();
$pathinfo = pathinfo($path);
$dirContent = $view->opendir($pathinfo['dirname']);
if (is_resource($dirContent)) {
while (($file = readdir($dirContent)) !== false) {
if (!\OC\Files\Filesystem::isIgnoredDir($file)) {
if (preg_match("/" . $pathinfo['filename'] . ".(.*).shareKey/", $file)) {
$result[] = $pathinfo['dirname'] . '/' . $file;
}
}
$user = \OCP\User::getUser();
$util = new Util($rootView, $user);
// get current sharing state
$sharingEnabled = \OCP\Share::isEnabled();
// get users sharing this file
$usersSharing = $util->getSharingUsersArray($sharingEnabled, $filePath);
$pathinfo = pathinfo($shareKeyPath);
$baseDir = $pathinfo['dirname'] . '/';
$fileName = $pathinfo['basename'];
foreach ($usersSharing as $user) {
$keyName = $fileName . '.' . $user . '.shareKey';
if ($rootView->file_exists($baseDir . $keyName)) {
$result[] = $baseDir . $keyName;
} else {
\OC_Log::write(
'Encryption library',
'No share key found for user "' . $user . '" for file "' . $fileName . '"',
\OC_Log::WARN
);
}
closedir($dirContent);
}
return $result;
+32 -22
View File
@@ -459,13 +459,17 @@ class Keymanager {
\OCP\Util::writeLog('files_encryption', 'delAllShareKeys: delete share keys: ' . $baseDir . $filePath, \OCP\Util::DEBUG);
$result = $view->unlink($baseDir . $filePath);
} else {
$parentDir = dirname($baseDir . $filePath);
$filename = pathinfo($filePath, PATHINFO_BASENAME);
foreach($view->getDirectoryContent($parentDir) as $content) {
$path = $content['path'];
if (self::getFilenameFromShareKey($content['name']) === $filename) {
\OCP\Util::writeLog('files_encryption', 'dellAllShareKeys: delete share keys: ' . '/' . $userId . '/' . $path, \OCP\Util::DEBUG);
$result &= $view->unlink('/' . $userId . '/' . $path);
$sharingEnabled = \OCP\Share::isEnabled();
$users = $util->getSharingUsersArray($sharingEnabled, $filePath);
foreach($users as $user) {
$keyName = $baseDir . $filePath . '.' . $user . '.shareKey';
if ($view->file_exists($keyName)) {
\OCP\Util::writeLog(
'files_encryption',
'dellAllShareKeys: delete share keys: "' . $keyName . '"',
\OCP\Util::DEBUG
);
$result &= $view->unlink($keyName);
}
}
}
@@ -539,17 +543,20 @@ class Keymanager {
if ($view->is_dir($dir . '/' . $file)) {
self::recursiveDelShareKeys($dir . '/' . $file, $userIds, $owner, $view);
} else {
$realFile = $realFileDir . self::getFilenameFromShareKey($file);
foreach ($userIds as $userId) {
if (preg_match("/(.*)." . $userId . ".shareKey/", $file)) {
if ($userId === $owner &&
$view->file_exists($realFile)) {
\OCP\Util::writeLog('files_encryption', 'original file still exists, keep owners share key!', \OCP\Util::ERROR);
continue;
}
\OCP\Util::writeLog('files_encryption', 'recursiveDelShareKey: delete share key: ' . $file, \OCP\Util::DEBUG);
$view->unlink($dir . '/' . $file);
$fileNameFromShareKey = self::getFilenameFromShareKey($file, $userId);
if (!$fileNameFromShareKey) {
continue;
}
$realFile = $realFileDir . $fileNameFromShareKey;
if ($userId === $owner &&
$view->file_exists($realFile)) {
\OCP\Util::writeLog('files_encryption', 'original file still exists, keep owners share key!', \OCP\Util::ERROR);
continue;
}
\OCP\Util::writeLog('files_encryption', 'recursiveDelShareKey: delete share key: ' . $file, \OCP\Util::DEBUG);
$view->unlink($dir . '/' . $file);
}
}
}
@@ -591,16 +598,19 @@ class Keymanager {
/**
* extract filename from share key name
* @param string $shareKey (filename.userid.sharekey)
* @param string $userId
* @return string|false filename or false
*/
protected static function getFilenameFromShareKey($shareKey) {
$parts = explode('.', $shareKey);
protected static function getFilenameFromShareKey($shareKey, $userId) {
$expectedSuffix = '.' . $userId . '.' . 'shareKey';
$suffixLen = strlen($expectedSuffix);
$filename = false;
if(count($parts) > 2) {
$filename = implode('.', array_slice($parts, 0, count($parts)-2));
$suffix = substr($shareKey, -$suffixLen);
if ($suffix !== $expectedSuffix) {
return false;
}
return $filename;
return substr($shareKey, 0, -$suffixLen);
}
}
+11 -6
View File
@@ -49,12 +49,17 @@ class Proxy extends \OC_FileProxy {
* @param string $uid user
* @return boolean
*/
private function isExcludedPath($path, $uid) {
protected function isExcludedPath($path, $uid) {
$view = new \OC\Files\View();
// files outside of the files-folder are excluded
if(strpos($path, '/' . $uid . '/files') !== 0) {
$path = \OC\Files\Filesystem::normalizePath($path);
// we only encrypt/decrypt files in the files and files_versions folder
if(
strpos($path, '/' . $uid . '/files/') !== 0 &&
strpos($path, '/' . $uid . '/files_versions/') !== 0) {
return true;
}
@@ -157,8 +162,8 @@ class Proxy extends \OC_FileProxy {
// store new unenecrypted size so that it can be updated
// in the post proxy
$tmpFileInfo = $view->getFileInfo($tmpPath);
if ( isset($tmpFileInfo['size']) ) {
self::$unencryptedSizes[\OC\Files\Filesystem::normalizePath($path)] = $tmpFileInfo['size'];
if ( isset($tmpFileInfo['unencrypted_size']) ) {
self::$unencryptedSizes[\OC\Files\Filesystem::normalizePath($path)] = $tmpFileInfo['unencrypted_size'];
}
// remove our temp file
@@ -262,7 +267,7 @@ class Proxy extends \OC_FileProxy {
* @param resource $result
* @return resource
*/
public function postFopen($path, &$result) {
public function postFopen($path, $result) {
$path = \OC\Files\Filesystem::normalizePath($path);
+1
View File
@@ -573,6 +573,7 @@ class Stream {
\OC_FileProxy::$enabled = false;
if ($this->rootView->file_exists($this->rawPath) && $this->size === 0) {
fclose($this->handle);
$this->rootView->unlink($this->rawPath);
}
+44 -9
View File
@@ -23,6 +23,7 @@
*/
namespace OCA\Encryption;
use OC\User\NoUserException;
/**
* Class for utilities relating to encrypted file storage system
@@ -888,6 +889,31 @@ class Util {
}
/**
* Returns whether the given user is ready for encryption.
* Also returns true if the given user is the public user
* or the recovery key user.
*
* @param string $user user to check
*
* @return boolean true if the user is ready, false otherwise
*/
private function isUserReady($user) {
if ($user === $this->publicShareKeyId
|| $user === $this->recoveryKeyId
) {
return true;
}
try {
$util = new Util($this->view, $user);
return $util->ready();
} catch (NoUserException $e) {
\OCP\Util::writeLog('Encryption library',
'No User object for '.$user, \OCP\Util::DEBUG);
return false;
}
}
/**
* Filter an array of UIDs to return only ones ready for sharing
* @param array $unfilteredUsers users to be checked for sharing readiness
@@ -900,16 +926,9 @@ class Util {
// Loop through users and create array of UIDs that need new keyfiles
foreach ($unfilteredUsers as $user) {
$util = new Util($this->view, $user);
// Check that the user is encryption capable, or is the
// public system user 'ownCloud' (for public shares)
if (
$user === $this->publicShareKeyId
or $user === $this->recoveryKeyId
or $util->ready()
) {
// public system user (for public shares)
if ($this->isUserReady($user)) {
// Construct array of ready UIDs for Keymanager{}
$readyIds[] = $user;
@@ -1525,6 +1544,22 @@ class Util {
$this->recoverAllFiles('/', $privateKey);
}
/**
* create a backup of all keys from the user
*
* @param string $purpose (optional) define the purpose of the backup, will be part of the backup folder
*/
public function backupAllKeys($purpose = '') {
$this->userId;
$backupDir = $this->encryptionDir . '/backup.';
$backupDir .= ($purpose === '') ? date("Y-m-d_H-i-s") . '/' : $purpose . '.' . date("Y-m-d_H-i-s") . '/';
$this->view->mkdir($backupDir);
$this->view->copy($this->shareKeysPath, $backupDir . 'share-keys/');
$this->view->copy($this->keyfilesPath, $backupDir . 'keyfiles/');
$this->view->copy($this->privateKeyPath, $backupDir . $this->userId . '.private.key');
$this->view->copy($this->publicKeyPath, $backupDir . $this->userId . '.public.key');
}
/**
* check if the file is stored on a system wide mount point
* @param string $path relative to /data/user with leading '/'
@@ -28,7 +28,6 @@ $result = false;
if ($recoveryAdminEnabled || !$privateKeySet) {
\OCP\Util::addscript('files_encryption', 'settings-personal');
\OCP\Util::addScript('settings', 'personal');
$tmpl->assign('recoveryEnabled', $recoveryAdminEnabled);
$tmpl->assign('recoveryEnabledForUser', $recoveryEnabledForUser);
@@ -4,8 +4,9 @@
<?php if($_["initStatus"] === \OCA\Encryption\Session::NOT_INITIALIZED): ?>
<?php p($l->t("Encryption App is enabled but your keys are not initialized, please log-out and log-in again")); ?>
<?php else: ?>
<p>
<p id="encryptionSetRecoveryKey">
<?php p($l->t("Enable recovery key (allow to recover users files in case of password loss):")); ?>
<span class="msg"></span>
<br/>
<br/>
<input type="password" name="encryptionRecoveryPassword" id="encryptionRecoveryPassword"/>
@@ -18,7 +19,7 @@
type='radio'
name='adminEnableRecovery'
value='1'
<?php echo($_["recoveryEnabled"] === '1' ? 'checked="checked"' : 'disabled'); ?> />
<?php echo($_["recoveryEnabled"] === '1' ? 'checked="checked"' : ''); ?> />
<?php p($l->t("Enabled")); ?>
<br/>
@@ -26,13 +27,14 @@
type='radio'
name='adminEnableRecovery'
value='0'
<?php echo($_["recoveryEnabled"] === '0' ? 'checked="checked"' : 'disabled'); ?> />
<?php echo($_["recoveryEnabled"] === '0' ? 'checked="checked"' : ''); ?> />
<?php p($l->t("Disabled")); ?>
</p>
<br/><br/>
<p name="changeRecoveryPasswordBlock" <?php if ($_['recoveryEnabled'] === '0') print_unescaped('class="hidden"');?>>
<p name="changeRecoveryPasswordBlock" id="encryptionChangeRecoveryKey" <?php if ($_['recoveryEnabled'] === '0') print_unescaped('class="hidden"');?>>
<strong><?php p($l->t("Change recovery key password:")); ?></strong>
<span class="msg"></span>
<br/><br/>
<input
type="password"
@@ -55,10 +57,9 @@
<br/>
<button
type="button"
name="submitChangeRecoveryKey"
disabled><?php p($l->t("Change Password")); ?>
name="submitChangeRecoveryKey">
<?php p($l->t("Change Password")); ?>
</button>
<span class="msg"></span>
</p>
<?php endif; ?>
</form>
@@ -39,8 +39,9 @@
<?php elseif ( $_["recoveryEnabled"] && $_["privateKeySet"] && $_["initialized"] === \OCA\Encryption\Session::INIT_SUCCESSFUL ): ?>
<br />
<p>
<p id="userEnableRecovery">
<label for="userEnableRecovery"><?php p( $l->t( "Enable password recovery:" ) ); ?></label>
<span class="msg"></span>
<br />
<em><?php p( $l->t( "Enabling this option will allow you to reobtain access to your encrypted files in case of password loss" ) ); ?></em>
<br />
@@ -58,8 +59,6 @@
value='0'
<?php echo ( $_["recoveryEnabledForUser"] === false ? 'checked="checked"' : '' ); ?> />
<?php p( $l->t( "Disabled" ) ); ?>
<div id="recoveryEnabledSuccess"><?php p( $l->t( 'File recovery settings updated' ) ); ?></div>
<div id="recoveryEnabledError"><?php p( $l->t( 'Could not update file recovery' ) ); ?></div>
</p>
<?php endif; ?>
</form>
+58 -41
View File
@@ -23,7 +23,7 @@ use OCA\Encryption;
/**
* Class Test_Encryption_Crypt
*/
class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
class Test_Encryption_Crypt extends \OCA\Files_Encryption\Tests\TestCase {
const TEST_ENCRYPTION_CRYPT_USER1 = "test-crypt-user1";
@@ -42,6 +42,8 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
public $genPublicKey;
public static function setUpBeforeClass() {
parent::setUpBeforeClass();
// reset backend
\OC_User::clearBackends();
\OC_User::useBackend('database');
@@ -57,10 +59,12 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
\OC_FileProxy::register(new OCA\Encryption\Proxy());
// create test user
\Test_Encryption_Util::loginHelper(\Test_Encryption_Crypt::TEST_ENCRYPTION_CRYPT_USER1, true);
self::loginHelper(\Test_Encryption_Crypt::TEST_ENCRYPTION_CRYPT_USER1, true);
}
function setUp() {
protected function setUp() {
parent::setUp();
// set user id
\OC_User::setUserId(\Test_Encryption_Crypt::TEST_ENCRYPTION_CRYPT_USER1);
$this->userId = \Test_Encryption_Crypt::TEST_ENCRYPTION_CRYPT_USER1;
@@ -88,7 +92,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
\OC_App::disable('files_trashbin');
}
function tearDown() {
protected function tearDown() {
// reset app files_trashbin
if ($this->stateFilesTrashbin) {
OC_App::enable('files_trashbin');
@@ -98,17 +102,29 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
$this->assertTrue(\OC_FileProxy::$enabled);
\OCP\Config::deleteSystemValue('cipher');
parent::tearDown();
}
public static function tearDownAfterClass() {
// cleanup test user
\OC_User::deleteUser(\Test_Encryption_Crypt::TEST_ENCRYPTION_CRYPT_USER1);
\OC_Hook::clear();
\OC_FileProxy::clearProxies();
// Delete keys in /data/
$view = new \OC\Files\View('/');
$view->rmdir('public-keys');
$view->rmdir('owncloud_private_key');
parent::tearDownAfterClass();
}
/**
* @medium
*/
function testGenerateKey() {
public function testGenerateKey() {
# TODO: use more accurate (larger) string length for test confirmation
@@ -118,7 +134,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
}
function testDecryptPrivateKey() {
public function testDecryptPrivateKey() {
// test successful decrypt
$crypted = Encryption\Crypt::symmetricEncryptFileContent($this->genPrivateKey, 'hat');
@@ -140,7 +156,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
/**
* @medium
*/
function testSymmetricEncryptFileContent() {
public function testSymmetricEncryptFileContent() {
# TODO: search in keyfile for actual content as IV will ensure this test always passes
@@ -158,7 +174,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
/**
* @medium
*/
function testSymmetricEncryptFileContentAes128() {
public function testSymmetricEncryptFileContentAes128() {
# TODO: search in keyfile for actual content as IV will ensure this test always passes
@@ -176,9 +192,9 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
/**
* @medium
*/
function testSymmetricStreamEncryptShortFileContent() {
public function testSymmetricStreamEncryptShortFileContent() {
$filename = 'tmp-' . uniqid() . '.test';
$filename = 'tmp-' . $this->getUniqueID() . '.test';
$cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/'. $filename, $this->dataShort);
@@ -213,9 +229,9 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
/**
* @medium
*/
function testSymmetricStreamEncryptShortFileContentAes128() {
public function testSymmetricStreamEncryptShortFileContentAes128() {
$filename = 'tmp-' . uniqid() . '.test';
$filename = 'tmp-' . $this->getUniqueID() . '.test';
\OCP\Config::setSystemValue('cipher', 'AES-128-CFB');
@@ -258,10 +274,10 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
* @note If this test fails with truncate content, check that enough array slices are being rejoined to form $e, as the crypt.php file may have gotten longer and broken the manual
* reassembly of its data
*/
function testSymmetricStreamEncryptLongFileContent() {
public function testSymmetricStreamEncryptLongFileContent() {
// Generate a a random filename
$filename = 'tmp-' . uniqid() . '.test';
$filename = 'tmp-' . $this->getUniqueID() . '.test';
// Save long data as encrypted file using stream wrapper
$cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/' . $filename, $this->dataLong . $this->dataLong);
@@ -302,10 +318,10 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
* @note If this test fails with truncate content, check that enough array slices are being rejoined to form $e, as the crypt.php file may have gotten longer and broken the manual
* reassembly of its data
*/
function testSymmetricStreamEncryptLongFileContentAes128() {
public function testSymmetricStreamEncryptLongFileContentAes128() {
// Generate a a random filename
$filename = 'tmp-' . uniqid() . '.test';
$filename = 'tmp-' . $this->getUniqueID() . '.test';
\OCP\Config::setSystemValue('cipher', 'AES-128-CFB');
@@ -350,10 +366,10 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
* @note If this test fails with truncate content, check that enough array slices are being rejoined to form $e, as the crypt.php file may have gotten longer and broken the manual
* reassembly of its data
*/
function testStreamDecryptLongFileContentWithoutHeader() {
public function testStreamDecryptLongFileContentWithoutHeader() {
// Generate a a random filename
$filename = 'tmp-' . uniqid() . '.test';
$filename = 'tmp-' . $this->getUniqueID() . '.test';
\OCP\Config::setSystemValue('cipher', 'AES-128-CFB');
@@ -398,7 +414,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
/**
* @medium
*/
function testIsEncryptedContent() {
public function testIsEncryptedContent() {
$this->assertFalse(Encryption\Crypt::isCatfileContent($this->dataUrl));
@@ -413,7 +429,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
/**
* @large
*/
function testMultiKeyEncrypt() {
public function testMultiKeyEncrypt() {
# TODO: search in keyfile for actual content as IV will ensure this test always passes
@@ -467,9 +483,9 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
/**
* @medium
*/
function testRenameFile() {
public function testRenameFile() {
$filename = 'tmp-' . uniqid();
$filename = 'tmp-' . $this->getUniqueID();
// Save long data as encrypted file using stream wrapper
$cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/' . $filename, $this->dataLong);
@@ -482,7 +498,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
$this->assertEquals($this->dataLong, $decrypt);
$newFilename = 'tmp-new-' . uniqid();
$newFilename = 'tmp-new-' . $this->getUniqueID();
$view = new \OC\Files\View('/' . $this->userId . '/files');
$view->rename($filename, $newFilename);
@@ -498,9 +514,9 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
/**
* @medium
*/
function testMoveFileIntoFolder() {
public function testMoveFileIntoFolder() {
$filename = 'tmp-' . uniqid();
$filename = 'tmp-' . $this->getUniqueID();
// Save long data as encrypted file using stream wrapper
$cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/' . $filename, $this->dataLong);
@@ -513,8 +529,8 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
$this->assertEquals($this->dataLong, $decrypt);
$newFolder = '/newfolder' . uniqid();
$newFilename = 'tmp-new-' . uniqid();
$newFolder = '/newfolder' . $this->getUniqueID();
$newFilename = 'tmp-new-' . $this->getUniqueID();
$view = new \OC\Files\View('/' . $this->userId . '/files');
$view->mkdir($newFolder);
$view->rename($filename, $newFolder . '/' . $newFilename);
@@ -531,12 +547,12 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
/**
* @medium
*/
function testMoveFolder() {
public function testMoveFolder() {
$view = new \OC\Files\View('/' . $this->userId . '/files');
$filename = '/tmp-' . uniqid();
$folder = '/folder' . uniqid();
$filename = '/tmp-' . $this->getUniqueID();
$folder = '/folder' . $this->getUniqueID();
$view->mkdir($folder);
@@ -551,7 +567,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
$this->assertEquals($this->dataLong, $decrypt);
$newFolder = '/newfolder/subfolder' . uniqid();
$newFolder = '/newfolder/subfolder' . $this->getUniqueID();
$view->mkdir('/newfolder');
$view->rename($folder, $newFolder);
@@ -569,8 +585,8 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
/**
* @medium
*/
function testChangePassphrase() {
$filename = 'tmp-' . uniqid();
public function testChangePassphrase() {
$filename = 'tmp-' . $this->getUniqueID();
// Save long data as encrypted file using stream wrapper
$cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/' . $filename, $this->dataLong);
@@ -606,9 +622,9 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
/**
* @medium
*/
function testViewFilePutAndGetContents() {
public function testViewFilePutAndGetContents() {
$filename = '/tmp-' . uniqid();
$filename = '/tmp-' . $this->getUniqueID();
$view = new \OC\Files\View('/' . $this->userId . '/files');
// Save short data as encrypted file using stream wrapper
@@ -640,8 +656,8 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
/**
* @large
*/
function testTouchExistingFile() {
$filename = '/tmp-' . uniqid();
public function testTouchExistingFile() {
$filename = '/tmp-' . $this->getUniqueID();
$view = new \OC\Files\View('/' . $this->userId . '/files');
// Save short data as encrypted file using stream wrapper
@@ -664,8 +680,8 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
/**
* @medium
*/
function testTouchFile() {
$filename = '/tmp-' . uniqid();
public function testTouchFile() {
$filename = '/tmp-' . $this->getUniqueID();
$view = new \OC\Files\View('/' . $this->userId . '/files');
$view->touch($filename);
@@ -688,8 +704,8 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
/**
* @medium
*/
function testFopenFile() {
$filename = '/tmp-' . uniqid();
public function testFopenFile() {
$filename = '/tmp-' . $this->getUniqueID();
$view = new \OC\Files\View('/' . $this->userId . '/files');
// Save short data as encrypted file using stream wrapper
@@ -706,6 +722,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
$this->assertEquals($this->dataShort, $decrypt);
// tear down
fclose($handle);
$view->unlink($filename);
}
+81 -11
View File
@@ -5,33 +5,49 @@
* later.
* See the COPYING-README file.
*/
require_once __DIR__ . '/../lib/helper.php';
require_once __DIR__ . '/util.php';
use OCA\Encryption;
/**
* Class Test_Encryption_Helper
*/
class Test_Encryption_Helper extends \PHPUnit_Framework_TestCase {
class Test_Encryption_Helper extends \OCA\Files_Encryption\Tests\TestCase {
const TEST_ENCRYPTION_HELPER_USER1 = "test-helper-user1";
const TEST_ENCRYPTION_HELPER_USER2 = "test-helper-user2";
public static function setUpBeforeClass() {
protected function setUpUsers() {
// create test user
\Test_Encryption_Util::loginHelper(\Test_Encryption_Helper::TEST_ENCRYPTION_HELPER_USER2, true);
\Test_Encryption_Util::loginHelper(\Test_Encryption_Helper::TEST_ENCRYPTION_HELPER_USER1, true);
self::loginHelper(\Test_Encryption_Helper::TEST_ENCRYPTION_HELPER_USER2, true);
self::loginHelper(\Test_Encryption_Helper::TEST_ENCRYPTION_HELPER_USER1, true);
}
public static function tearDownAfterClass() {
protected function cleanUpUsers() {
// cleanup test user
\OC_User::deleteUser(\Test_Encryption_Helper::TEST_ENCRYPTION_HELPER_USER1);
\OC_User::deleteUser(\Test_Encryption_Helper::TEST_ENCRYPTION_HELPER_USER2);
}
public static function setupHooks() {
// Filesystem related hooks
\OCA\Encryption\Helper::registerFilesystemHooks();
// clear and register hooks
\OC_FileProxy::clearProxies();
\OC_FileProxy::register(new OCA\Encryption\Proxy());
}
public static function tearDownAfterClass() {
\OC_Hook::clear();
\OC_FileProxy::clearProxies();
// Delete keys in /data/
$view = new \OC\Files\View('/');
$view->rmdir('public-keys');
$view->rmdir('owncloud_private_key');
parent::tearDownAfterClass();
}
/**
@@ -83,19 +99,20 @@ class Test_Encryption_Helper extends \PHPUnit_Framework_TestCase {
}
function testGetUser() {
self::setUpUsers();
$path1 = "/" . self::TEST_ENCRYPTION_HELPER_USER1 . "/files/foo/bar.txt";
$path2 = "/" . self::TEST_ENCRYPTION_HELPER_USER1 . "/cache/foo/bar.txt";
$path3 = "/" . self::TEST_ENCRYPTION_HELPER_USER2 . "/thumbnails/foo";
$path4 ="/" . "/" . self::TEST_ENCRYPTION_HELPER_USER1;
\Test_Encryption_Util::loginHelper(self::TEST_ENCRYPTION_HELPER_USER1);
self::loginHelper(self::TEST_ENCRYPTION_HELPER_USER1);
// if we are logged-in every path should return the currently logged-in user
$this->assertEquals(self::TEST_ENCRYPTION_HELPER_USER1, Encryption\Helper::getUser($path3));
// now log out
\Test_Encryption_Util::logoutHelper();
self::logoutHelper();
// now we should only get the user from /user/files and user/cache paths
$this->assertEquals(self::TEST_ENCRYPTION_HELPER_USER1, Encryption\Helper::getUser($path1));
@@ -105,7 +122,60 @@ class Test_Encryption_Helper extends \PHPUnit_Framework_TestCase {
$this->assertFalse(Encryption\Helper::getUser($path4));
// Log-in again
\Test_Encryption_Util::loginHelper(\Test_Encryption_Helper::TEST_ENCRYPTION_HELPER_USER1);
self::loginHelper(\Test_Encryption_Helper::TEST_ENCRYPTION_HELPER_USER1);
self::cleanUpUsers();
}
function userNamesProvider() {
return array(
array('testuser' . $this->getUniqueID()),
array('user.name.with.dots'),
);
}
/**
* Tests whether share keys can be found
*
* @dataProvider userNamesProvider
*/
function testFindShareKeys($userName) {
self::setUpUsers();
// note: not using dataProvider as we want to make
// sure that the correct keys are match and not any
// other ones that might happen to have similar names
self::setupHooks();
self::loginHelper($userName, true);
$testDir = 'testFindShareKeys' . $this->getUniqueID() . '/';
$baseDir = $userName . '/files/' . $testDir;
$fileList = array(
't est.txt',
't est_.txt',
't est.doc.txt',
't est(.*).txt', // make sure the regexp is escaped
'multiple.dots.can.happen.too.txt',
't est.' . $userName . '.txt',
't est_.' . $userName . '.shareKey.txt',
'who would upload their.shareKey',
'user ones file.txt',
'user ones file.txt.backup',
'.t est.txt'
);
$rootView = new \OC\Files\View('/');
$rootView->mkdir($baseDir);
foreach ($fileList as $fileName) {
$rootView->file_put_contents($baseDir . $fileName, 'dummy');
}
$shareKeysDir = $userName . '/files_encryption/share-keys/' . $testDir;
foreach ($fileList as $fileName) {
// make sure that every file only gets its correct respective keys
$result = Encryption\Helper::findShareKeys($baseDir . $fileName, $shareKeysDir . $fileName, $rootView);
$this->assertEquals(
array($shareKeysDir . $fileName . '.' . $userName . '.shareKey'),
$result
);
}
self::cleanUpUsers();
}
}
+120 -66
View File
@@ -26,7 +26,6 @@ require_once __DIR__ . '/../lib/keymanager.php';
require_once __DIR__ . '/../lib/stream.php';
require_once __DIR__ . '/../lib/util.php';
require_once __DIR__ . '/../appinfo/app.php';
require_once __DIR__ . '/util.php';
use OCA\Encryption;
@@ -34,22 +33,44 @@ use OCA\Encryption;
* Class Test_Encryption_Hooks
* this class provide basic hook app tests
*/
class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase {
class Test_Encryption_Hooks extends \OCA\Files_Encryption\Tests\TestCase {
const TEST_ENCRYPTION_HOOKS_USER1 = "test-encryption-hooks-user1";
const TEST_ENCRYPTION_HOOKS_USER2 = "test-encryption-hooks-user2";
const TEST_ENCRYPTION_HOOKS_USER1 = "test-encryption-hooks-user1.dot";
const TEST_ENCRYPTION_HOOKS_USER2 = "test-encryption-hooks-user2.dot";
const TEST_ENCRYPTION_HOOKS_USER3 = "test-encryption-hooks-user3.dot";
/**
* @var \OC\Files\View
*/
/** @var \OC\Files\View */
public $user1View; // view on /data/user1/files
/** @var \OC\Files\View */
public $user2View; // view on /data/user2/files
/** @var \OC\Files\View */
public $rootView; // view on /data/user
public $data;
public $filename;
public $folder;
private static $testFiles;
public static function setUpBeforeClass() {
parent::setUpBeforeClass();
// note: not using a data provider because these
// files all need to coexist to make sure the
// share keys are found properly (pattern matching)
self::$testFiles = array(
't est.txt',
't est_.txt',
't est.doc.txt',
't est(.*).txt', // make sure the regexp is escaped
'multiple.dots.can.happen.too.txt',
't est.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.txt',
't est_.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey.txt',
'who would upload their.shareKey',
'user ones file.txt',
'user ones file.txt.backup',
'.t est.txt'
);
// reset backend
\OC_User::clearBackends();
\OC_User::useBackend('database');
@@ -73,13 +94,15 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase {
\OC_FileProxy::register(new OCA\Encryption\Proxy());
// create test user
\Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1, true);
\Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2, true);
self::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1, true);
self::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2, true);
}
function setUp() {
protected function setUp() {
parent::setUp();
// set user id
\Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
self::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
\OC_User::setUserId(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
// init filesystem view
@@ -89,8 +112,8 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase {
// init short data
$this->data = 'hats';
$this->filename = 'enc_hooks_tests-' . uniqid() . '.txt';
$this->folder = 'enc_hooks_tests_folder-' . uniqid();
$this->filename = 'enc_hooks_tests-' . $this->getUniqueID() . '.txt';
$this->folder = 'enc_hooks_tests_folder-' . $this->getUniqueID();
}
@@ -98,6 +121,17 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase {
// cleanup test user
\OC_User::deleteUser(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
\OC_User::deleteUser(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2);
\OC_User::deleteUser(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER3);
\OC_Hook::clear();
\OC_FileProxy::clearProxies();
// Delete keys in /data/
$view = new \OC\Files\View('/');
$view->rmdir('public-keys');
$view->rmdir('owncloud_private_key');
parent::tearDownAfterClass();
}
function testDisableHook() {
@@ -119,7 +153,7 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase {
// relogin user to initialize the encryption again
$user = \OCP\User::getUser();
\Test_Encryption_Util::loginHelper($user);
self::loginHelper($user);
}
@@ -144,8 +178,8 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase {
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
\Test_Encryption_Util::logoutHelper();
\Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2);
self::logoutHelper();
self::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2);
\OC_User::setUserId(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2);
@@ -202,8 +236,8 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase {
function testDeleteHooksForSharedFiles() {
\Test_Encryption_Util::logoutHelper();
\Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
self::logoutHelper();
self::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
\OC_User::setUserId(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
// remember files_trashbin state
@@ -238,8 +272,8 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase {
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey'));
\Test_Encryption_Util::logoutHelper();
\Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2);
self::logoutHelper();
self::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2);
\OC_User::setUserId(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2);
// user2 update the shared file
@@ -269,8 +303,8 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase {
// cleanup
\Test_Encryption_Util::logoutHelper();
\Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
self::logoutHelper();
self::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
\OC_User::setUserId(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
if ($stateFilesTrashbin) {
@@ -281,25 +315,33 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase {
}
}
function testRenameHook() {
// create all files to make sure all keys can coexist properly
foreach (self::$testFiles as $file) {
// save file with content
$cryptedFile = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $file, $this->data);
// test that data was successfully written
$this->assertTrue(is_int($cryptedFile));
}
foreach (self::$testFiles as $file) {
$this->doTestRenameHook($file);
}
}
/**
* test rename operation
*/
function testRenameHook() {
// save file with content
$cryptedFile = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->filename, $this->data);
// test that data was successfully written
$this->assertTrue(is_int($cryptedFile));
function doTestRenameHook($filename) {
// check if keys exists
$this->assertTrue($this->rootView->file_exists(
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
. $this->filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
. $filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
$this->assertTrue($this->rootView->file_exists(
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/'
. $this->filename . '.key'));
. $filename . '.key'));
// make subfolder and sub-subfolder
$this->rootView->mkdir('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder);
@@ -310,50 +352,58 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase {
// move the file to the sub-subfolder
$root = $this->rootView->getRoot();
$this->rootView->chroot('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/');
$this->rootView->rename($this->filename, '/' . $this->folder . '/' . $this->folder . '/' . $this->filename);
$this->rootView->rename($filename, '/' . $this->folder . '/' . $this->folder . '/' . $filename);
$this->rootView->chroot($root);
$this->assertFalse($this->rootView->file_exists('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->filename));
$this->assertTrue($this->rootView->file_exists('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder . '/' . $this->folder . '/' . $this->filename));
$this->assertFalse($this->rootView->file_exists('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $filename));
$this->assertTrue($this->rootView->file_exists('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder . '/' . $this->folder . '/' . $filename));
// keys should be renamed too
$this->assertFalse($this->rootView->file_exists(
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
. $this->filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
. $filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
$this->assertFalse($this->rootView->file_exists(
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/'
. $this->filename . '.key'));
. $filename . '.key'));
$this->assertTrue($this->rootView->file_exists(
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/' . $this->folder . '/' . $this->folder . '/'
. $this->filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
. $filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
$this->assertTrue($this->rootView->file_exists(
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $this->folder . '/' . $this->folder . '/'
. $this->filename . '.key'));
. $filename . '.key'));
// cleanup
$this->rootView->unlink('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder);
}
function testCopyHook() {
// create all files to make sure all keys can coexist properly
foreach (self::$testFiles as $file) {
// save file with content
$cryptedFile = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $file, $this->data);
// test that data was successfully written
$this->assertTrue(is_int($cryptedFile));
}
foreach (self::$testFiles as $file) {
$this->doTestCopyHook($file);
}
}
/**
* test rename operation
*/
function testCopyHook() {
// save file with content
$cryptedFile = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->filename, $this->data);
// test that data was successfully written
$this->assertTrue(is_int($cryptedFile));
function doTestCopyHook($filename) {
// check if keys exists
$this->assertTrue($this->rootView->file_exists(
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
. $this->filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
. $filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
$this->assertTrue($this->rootView->file_exists(
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/'
. $this->filename . '.key'));
. $filename . '.key'));
// make subfolder and sub-subfolder
$this->rootView->mkdir('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder);
@@ -362,29 +412,29 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase {
$this->assertTrue($this->rootView->is_dir('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder . '/' . $this->folder));
// copy the file to the sub-subfolder
\OC\Files\Filesystem::copy($this->filename, '/' . $this->folder . '/' . $this->folder . '/' . $this->filename);
\OC\Files\Filesystem::copy($filename, '/' . $this->folder . '/' . $this->folder . '/' . $filename);
$this->assertTrue($this->rootView->file_exists('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->filename));
$this->assertTrue($this->rootView->file_exists('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder . '/' . $this->folder . '/' . $this->filename));
$this->assertTrue($this->rootView->file_exists('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $filename));
$this->assertTrue($this->rootView->file_exists('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder . '/' . $this->folder . '/' . $filename));
// keys should be copied too
$this->assertTrue($this->rootView->file_exists(
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
. $this->filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
. $filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
$this->assertTrue($this->rootView->file_exists(
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/'
. $this->filename . '.key'));
. $filename . '.key'));
$this->assertTrue($this->rootView->file_exists(
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/' . $this->folder . '/' . $this->folder . '/'
. $this->filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
. $filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
$this->assertTrue($this->rootView->file_exists(
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $this->folder . '/' . $this->folder . '/'
. $this->filename . '.key'));
. $filename . '.key'));
// cleanup
$this->rootView->unlink('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder);
$this->rootView->unlink('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->filename);
$this->rootView->unlink('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $filename);
}
/**
@@ -396,31 +446,35 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase {
$view = new \OC\Files\View();
// set user password for the first time
\OCA\Encryption\Hooks::postCreateUser(array('uid' => 'newUser', 'password' => 'newUserPassword'));
\OC_User::createUser(self::TEST_ENCRYPTION_HOOKS_USER3, 'newUserPassword');
\OCA\Encryption\Hooks::postCreateUser(array(
'uid' => self::TEST_ENCRYPTION_HOOKS_USER3,
'password' => 'newUserPassword')
);
$this->assertTrue($view->file_exists('public-keys/newUser.public.key'));
$this->assertTrue($view->file_exists('newUser/files_encryption/newUser.private.key'));
$this->assertTrue($view->file_exists('public-keys/'.self::TEST_ENCRYPTION_HOOKS_USER3.'.public.key'));
$this->assertTrue($view->file_exists(self::TEST_ENCRYPTION_HOOKS_USER3.'/files_encryption/'.self::TEST_ENCRYPTION_HOOKS_USER3.'.private.key'));
// check if we are able to decrypt the private key
$encryptedKey = \OCA\Encryption\Keymanager::getPrivateKey($view, 'newUser');
$encryptedKey = \OCA\Encryption\Keymanager::getPrivateKey($view, self::TEST_ENCRYPTION_HOOKS_USER3);
$privateKey = \OCA\Encryption\Crypt::decryptPrivateKey($encryptedKey, 'newUserPassword');
$this->assertTrue(is_string($privateKey));
// change the password before the user logged-in for the first time,
// we can replace the encryption keys
\OCA\Encryption\Hooks::setPassphrase(array('uid' => 'newUser', 'password' => 'passwordChanged'));
\OCA\Encryption\Hooks::setPassphrase(array('uid' => self::TEST_ENCRYPTION_HOOKS_USER3, 'password' => 'passwordChanged'));
$encryptedKey = \OCA\Encryption\Keymanager::getPrivateKey($view, 'newUser');
$encryptedKey = \OCA\Encryption\Keymanager::getPrivateKey($view, self::TEST_ENCRYPTION_HOOKS_USER3);
$privateKey = \OCA\Encryption\Crypt::decryptPrivateKey($encryptedKey, 'passwordChanged');
$this->assertTrue(is_string($privateKey));
// now create a files folder to simulate a already used account
$view->mkdir('/newUser/files');
$view->mkdir('/'.self::TEST_ENCRYPTION_HOOKS_USER3.'/files');
// change the password after the user logged in, now the password should not change
\OCA\Encryption\Hooks::setPassphrase(array('uid' => 'newUser', 'password' => 'passwordChanged2'));
\OCA\Encryption\Hooks::setPassphrase(array('uid' => self::TEST_ENCRYPTION_HOOKS_USER3, 'password' => 'passwordChanged2'));
$encryptedKey = \OCA\Encryption\Keymanager::getPrivateKey($view, 'newUser');
$encryptedKey = \OCA\Encryption\Keymanager::getPrivateKey($view, self::TEST_ENCRYPTION_HOOKS_USER3);
$privateKey = \OCA\Encryption\Crypt::decryptPrivateKey($encryptedKey, 'passwordChanged2');
$this->assertFalse($privateKey);
+67 -19
View File
@@ -14,16 +14,15 @@ require_once __DIR__ . '/../lib/stream.php';
require_once __DIR__ . '/../lib/util.php';
require_once __DIR__ . '/../lib/helper.php';
require_once __DIR__ . '/../appinfo/app.php';
require_once __DIR__ . '/util.php';
use OCA\Encryption;
/**
* Class Test_Encryption_Keymanager
*/
class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
class Test_Encryption_Keymanager extends \OCA\Files_Encryption\Tests\TestCase {
const TEST_USER = "test-keymanager-user";
const TEST_USER = "test-keymanager-user.dot";
public $userId;
public $pass;
@@ -36,6 +35,8 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
public $dataShort;
public static function setUpBeforeClass() {
parent::setUpBeforeClass();
// reset backend
\OC_User::clearBackends();
\OC_User::useBackend('database');
@@ -58,10 +59,11 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
// create test user
\OC_User::deleteUser(\Test_Encryption_Keymanager::TEST_USER);
\Test_Encryption_Util::loginHelper(\Test_Encryption_Keymanager::TEST_USER, true);
parent::loginHelper(\Test_Encryption_Keymanager::TEST_USER, true);
}
function setUp() {
protected function setUp() {
parent::setUp();
// set content for encrypting / decrypting in tests
$this->dataLong = file_get_contents(__DIR__ . '/../lib/crypt.php');
$this->dataShort = 'hats';
@@ -76,7 +78,7 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
$this->view = new \OC\Files\View('/');
\Test_Encryption_Util::loginHelper(Test_Encryption_Keymanager::TEST_USER);
self::loginHelper(Test_Encryption_Keymanager::TEST_USER);
$this->userId = \Test_Encryption_Keymanager::TEST_USER;
$this->pass = \Test_Encryption_Keymanager::TEST_USER;
@@ -87,6 +89,8 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
function tearDown() {
$this->view->deleteAll('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys');
$this->view->deleteAll('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/keyfiles');
parent::tearDown();
}
public static function tearDownAfterClass() {
@@ -98,6 +102,16 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
if (self::$stateFilesTrashbin) {
OC_App::enable('files_trashbin');
}
\OC_Hook::clear();
\OC_FileProxy::clearProxies();
// Delete keys in /data/
$view = new \OC\Files\View('/');
$view->rmdir('public-keys');
$view->rmdir('owncloud_private_key');
parent::tearDownAfterClass();
}
/**
@@ -135,15 +149,25 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
$this->assertArrayHasKey('key', $sslInfo);
}
function fileNameFromShareKeyProvider() {
return array(
array('file.user.shareKey', 'user', 'file'),
array('file.name.with.dots.user.shareKey', 'user', 'file.name.with.dots'),
array('file.name.user.with.dots.shareKey', 'user.with.dots', 'file.name'),
array('file.txt', 'user', false),
array('user.shareKey', 'user', false),
);
}
/**
* @small
*
* @dataProvider fileNameFromShareKeyProvider
*/
function testGetFilenameFromShareKey() {
$this->assertEquals("file",
\TestProtectedKeymanagerMethods::testGetFilenameFromShareKey("file.user.shareKey"));
$this->assertEquals("file.name.with.dots",
\TestProtectedKeymanagerMethods::testGetFilenameFromShareKey("file.name.with.dots.user.shareKey"));
$this->assertFalse(\TestProtectedKeymanagerMethods::testGetFilenameFromShareKey("file.txt"));
function testGetFilenameFromShareKey($fileName, $user, $expectedFileName) {
$this->assertEquals($expectedFileName,
\TestProtectedKeymanagerMethods::testGetFilenameFromShareKey($fileName, $user)
);
}
/**
@@ -153,7 +177,7 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
$key = $this->randomKey;
$file = 'unittest-' . uniqid() . '.txt';
$file = 'unittest-' . $this->getUniqueID() . '.txt';
$util = new Encryption\Util($this->view, $this->userId);
@@ -249,6 +273,12 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/existingFile.txt.user1.shareKey', 'data');
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/existingFile.txt.' . Test_Encryption_Keymanager::TEST_USER . '.shareKey', 'data');
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.user1.shareKey', 'data');
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.user1.test.shareKey', 'data');
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.test-keymanager-userxdot.shareKey', 'data');
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.userx.' . Test_Encryption_Keymanager::TEST_USER . '.shareKey', 'data');
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.' . Test_Encryption_Keymanager::TEST_USER . '.userx.shareKey', 'data');
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.user1.' . Test_Encryption_Keymanager::TEST_USER . '.shareKey', 'data');
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.' . Test_Encryption_Keymanager::TEST_USER . '.user1.shareKey', 'data');
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file2.user2.shareKey', 'data');
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file2.user3.shareKey', 'data');
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/subfolder/file2.user3.shareKey', 'data');
@@ -279,6 +309,23 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
$this->assertTrue($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/subfolder/file2.user3.shareKey'));
// check if share keys for user or file with similar name
$this->assertTrue($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.user1.test.shareKey'));
$this->assertTrue($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.test-keymanager-userxdot.shareKey'));
$this->assertTrue($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.' . Test_Encryption_Keymanager::TEST_USER . '.userx.shareKey'));
// FIXME: this case currently cannot be distinguished, needs further fixing
/*
$this->assertTrue($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.userx.' . Test_Encryption_Keymanager::TEST_USER . '.shareKey'));
$this->assertTrue($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.user1.' . Test_Encryption_Keymanager::TEST_USER . '.shareKey'));
$this->assertTrue($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.' . Test_Encryption_Keymanager::TEST_USER . '.user1.shareKey'));
*/
// owner key from existing file should still exists because the file is still there
$this->assertTrue($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/existingFile.txt.' . Test_Encryption_Keymanager::TEST_USER . '.shareKey'));
@@ -432,18 +479,19 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
$this->assertTrue($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/existingFile.txt.user3.shareKey'));
// try to del all share keys froma file, should fail because the file still exists
// try to del all share keys from file, should succeed because the does not exist any more
$result2 = Encryption\Keymanager::delAllShareKeys($this->view, Test_Encryption_Keymanager::TEST_USER, 'folder1/nonexistingFile.txt');
$this->assertTrue($result2);
// check if share keys are really gone
$this->assertFalse($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/nonexistingFile.txt.' . Test_Encryption_Keymanager::TEST_USER . '.shareKey'));
$this->assertFalse($this->view->file_exists(
// check that it only deleted keys or users who had access, others remain
$this->assertTrue($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/nonexistingFile.txt.user1.shareKey'));
$this->assertFalse($this->view->file_exists(
$this->assertTrue($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/nonexistingFile.txt.user2.shareKey'));
$this->assertFalse($this->view->file_exists(
$this->assertTrue($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/nonexistingFile.txt.user3.shareKey'));
// cleanup
@@ -479,8 +527,8 @@ class TestProtectedKeymanagerMethods extends \OCA\Encryption\Keymanager {
/**
* @param string $sharekey
*/
public static function testGetFilenameFromShareKey($sharekey) {
return self::getFilenameFromShareKey($sharekey);
public static function testGetFilenameFromShareKey($sharekey, $user) {
return self::getFilenameFromShareKey($sharekey, $user);
}
/**
+64 -9
View File
@@ -27,7 +27,6 @@ require_once __DIR__ . '/../lib/proxy.php';
require_once __DIR__ . '/../lib/stream.php';
require_once __DIR__ . '/../lib/util.php';
require_once __DIR__ . '/../appinfo/app.php';
require_once __DIR__ . '/util.php';
use OCA\Encryption;
@@ -35,7 +34,7 @@ use OCA\Encryption;
* Class Test_Encryption_Proxy
* this class provide basic proxy app tests
*/
class Test_Encryption_Proxy extends \PHPUnit_Framework_TestCase {
class Test_Encryption_Proxy extends \OCA\Files_Encryption\Tests\TestCase {
const TEST_ENCRYPTION_PROXY_USER1 = "test-proxy-user1";
@@ -47,9 +46,12 @@ class Test_Encryption_Proxy extends \PHPUnit_Framework_TestCase {
public $view; // view in /data/user/files
public $rootView; // view on /data/user
public $data;
public $dataLong;
public $filename;
public static function setUpBeforeClass() {
parent::setUpBeforeClass();
// reset backend
\OC_User::clearBackends();
\OC_User::useBackend('database');
@@ -65,10 +67,12 @@ class Test_Encryption_Proxy extends \PHPUnit_Framework_TestCase {
\OC_FileProxy::register(new OCA\Encryption\Proxy());
// create test user
\Test_Encryption_Util::loginHelper(\Test_Encryption_Proxy::TEST_ENCRYPTION_PROXY_USER1, true);
self::loginHelper(\Test_Encryption_Proxy::TEST_ENCRYPTION_PROXY_USER1, true);
}
function setUp() {
protected function setUp() {
parent::setUp();
// set user id
\OC_User::setUserId(\Test_Encryption_Proxy::TEST_ENCRYPTION_PROXY_USER1);
$this->userId = \Test_Encryption_Proxy::TEST_ENCRYPTION_PROXY_USER1;
@@ -80,13 +84,24 @@ class Test_Encryption_Proxy extends \PHPUnit_Framework_TestCase {
// init short data
$this->data = 'hats';
$this->filename = 'enc_proxy_tests-' . uniqid() . '.txt';
$this->dataLong = file_get_contents(__DIR__ . '/../lib/crypt.php');
$this->filename = 'enc_proxy_tests-' . $this->getUniqueID() . '.txt';
}
public static function tearDownAfterClass() {
// cleanup test user
\OC_User::deleteUser(\Test_Encryption_Proxy::TEST_ENCRYPTION_PROXY_USER1);
\OC_Hook::clear();
\OC_FileProxy::clearProxies();
// Delete keys in /data/
$view = new \OC\Files\View('/');
$view->rmdir('public-keys');
$view->rmdir('owncloud_private_key');
parent::tearDownAfterClass();
}
/**
@@ -95,17 +110,19 @@ class Test_Encryption_Proxy extends \PHPUnit_Framework_TestCase {
*/
function testPostFileSize() {
$this->view->file_put_contents($this->filename, $this->data);
$this->view->file_put_contents($this->filename, $this->dataLong);
$size = strlen($this->dataLong);
\OC_FileProxy::$enabled = false;
$unencryptedSize = $this->view->filesize($this->filename);
$encryptedSize = $this->view->filesize($this->filename);
\OC_FileProxy::$enabled = true;
$encryptedSize = $this->view->filesize($this->filename);
$unencryptedSize = $this->view->filesize($this->filename);
$this->assertTrue($encryptedSize !== $unencryptedSize);
$this->assertTrue($encryptedSize > $unencryptedSize);
$this->assertSame($size, $unencryptedSize);
// cleanup
$this->view->unlink($this->filename);
@@ -132,4 +149,42 @@ class Test_Encryption_Proxy extends \PHPUnit_Framework_TestCase {
}
/**
* @dataProvider isExcludedPathProvider
*/
function testIsExcludedPath($path, $expected) {
$this->view->mkdir(dirname($path));
$this->view->file_put_contents($path, "test");
$testClass = new DummyProxy();
$result = $testClass->isExcludedPathTesting($path, $this->userId);
$this->assertSame($expected, $result);
$this->view->deleteAll(dirname($path));
}
public function isExcludedPathProvider() {
return array(
array ('/' . \Test_Encryption_Proxy::TEST_ENCRYPTION_PROXY_USER1 . '/files/test.txt', false),
array (\Test_Encryption_Proxy::TEST_ENCRYPTION_PROXY_USER1 . '/files/test.txt', false),
array ('/files/test.txt', true),
array ('/' . \Test_Encryption_Proxy::TEST_ENCRYPTION_PROXY_USER1 . '/files/versions/test.txt', false),
array ('/' . \Test_Encryption_Proxy::TEST_ENCRYPTION_PROXY_USER1 . '/files_versions/test.txt', false),
array ('/' . \Test_Encryption_Proxy::TEST_ENCRYPTION_PROXY_USER1 . '/files_trashbin/test.txt', true),
array ('/' . \Test_Encryption_Proxy::TEST_ENCRYPTION_PROXY_USER1 . '/file/test.txt', true),
);
}
}
/**
* Dummy class to make protected methods available for testing
*/
class DummyProxy extends \OCA\Encryption\Proxy {
public function isExcludedPathTesting($path, $uid) {
return $this->isExcludedPath($path, $uid);
}
}
+143 -52
View File
@@ -29,14 +29,13 @@ require_once __DIR__ . '/../lib/stream.php';
require_once __DIR__ . '/../lib/util.php';
require_once __DIR__ . '/../lib/helper.php';
require_once __DIR__ . '/../appinfo/app.php';
require_once __DIR__ . '/util.php';
use OCA\Encryption;
/**
* Class Test_Encryption_Share
*/
class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
class Test_Encryption_Share extends \OCA\Files_Encryption\Tests\TestCase {
const TEST_ENCRYPTION_SHARE_USER1 = "test-share-user1";
const TEST_ENCRYPTION_SHARE_USER2 = "test-share-user2";
@@ -56,6 +55,8 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
public $subsubfolder;
public static function setUpBeforeClass() {
parent::setUpBeforeClass();
// reset backend
\OC_User::clearBackends();
\OC_User::useBackend('database');
@@ -65,8 +66,10 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
// clear share hooks
\OC_Hook::clear('OCP\\Share');
// register share hooks
\OC::registerShareHooks();
\OCP\Util::connectHook('OC_Filesystem', 'setup', '\OC\Files\Storage\Shared', 'setup');
\OCA\Files_Sharing\Helper::registerHooks();
// Sharing related hooks
\OCA\Encryption\Helper::registerShareHooks();
@@ -76,13 +79,14 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
// clear and register hooks
\OC_FileProxy::clearProxies();
\OC_FileProxy::register(new OCA\Files\Share\Proxy());
\OC_FileProxy::register(new OCA\Encryption\Proxy());
// create users
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1, true);
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, true);
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3, true);
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4, true);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1, true);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, true);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3, true);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4, true);
// create group and assign users
\OC_Group::createGroup(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_GROUP1);
@@ -90,7 +94,9 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
\OC_Group::addToGroup(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_GROUP1);
}
function setUp() {
protected function setUp() {
parent::setUp();
$this->dataShort = 'hats';
$this->view = new \OC\Files\View('/');
@@ -105,15 +111,20 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
// we don't want to tests with app files_trashbin enabled
\OC_App::disable('files_trashbin');
// login as first user
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
}
function tearDown() {
protected function tearDown() {
// reset app files_trashbin
if ($this->stateFilesTrashbin) {
OC_App::enable('files_trashbin');
} else {
OC_App::disable('files_trashbin');
}
parent::tearDown();
}
public static function tearDownAfterClass() {
@@ -125,6 +136,16 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
\OC_User::deleteUser(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
\OC_User::deleteUser(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3);
\OC_User::deleteUser(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4);
\OC_Hook::clear();
\OC_FileProxy::clearProxies();
// Delete keys in /data/
$view = new \OC\Files\View('/');
$view->rmdir('public-keys');
$view->rmdir('owncloud_private_key');
parent::tearDownAfterClass();
}
@@ -134,7 +155,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
*/
function testShareFile($withTeardown = true) {
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
// save file with content
$cryptedFile = file_put_contents('crypt:///' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename, $this->dataShort);
@@ -163,7 +184,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
\OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, OCP\PERMISSION_ALL);
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
// check if share key for user1 exists
$this->assertTrue($this->view->file_exists(
@@ -171,7 +192,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
// login as user1
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
// get file contents
$retrievedCryptedFile = $this->view->file_get_contents(
@@ -184,7 +205,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
if ($withTeardown) {
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
// unshare the file
\OCP\Share::unshare('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
@@ -214,7 +235,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
$this->testShareFile(false);
// login as user2
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
// get the file info
$fileInfo = $this->view->getFileInfo(
@@ -224,7 +245,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
\OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3, OCP\PERMISSION_ALL);
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
// check if share key for user2 exists
$this->assertTrue($this->view->file_exists(
@@ -232,7 +253,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '.shareKey'));
// login as user2
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3);
// get file contents
$retrievedCryptedFile = $this->view->file_get_contents(
@@ -245,13 +266,13 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
if ($withTeardown) {
// login as user1
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
// unshare the file with user2
\OCP\Share::unshare('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3);
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
// check if share key not exists
$this->assertFalse($this->view->file_exists(
@@ -285,7 +306,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
*/
function testShareFolder($withTeardown = true) {
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
// create folder structure
$this->view->mkdir('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files' . $this->folder1);
@@ -320,7 +341,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
\OCP\Share::shareItem('folder', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, OCP\PERMISSION_ALL);
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
// check if share key for user1 exists
$this->assertTrue($this->view->file_exists(
@@ -329,7 +350,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
// login as user1
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
// get file contents
$retrievedCryptedFile = $this->view->file_get_contents(
@@ -343,7 +364,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
if ($withTeardown) {
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
// unshare the folder with user1
\OCP\Share::unshare('folder', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
@@ -377,7 +398,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
$fileInfoFolder1 = $this->testShareFolder(false);
// login as user2
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
// disable encryption proxy to prevent recursive calls
$proxyStatus = \OC_FileProxy::$enabled;
@@ -398,7 +419,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
\OCP\Share::shareItem('folder', $fileInfoSubFolder['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3, OCP\PERMISSION_ALL);
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
// check if share key for user3 exists
$this->assertTrue($this->view->file_exists(
@@ -407,7 +428,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '.shareKey'));
// login as user3
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3);
// get file contents
$retrievedCryptedFile = $this->view->file_get_contents(
@@ -429,7 +450,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
\OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4, OCP\PERMISSION_ALL);
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
// check if share key for user3 exists
$this->assertTrue($this->view->file_exists(
@@ -438,7 +459,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4 . '.shareKey'));
// login as user3
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4);
// get file contents
$retrievedCryptedFile = $this->view->file_get_contents(
@@ -451,7 +472,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
if ($withTeardown) {
// login as user2
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3);
// unshare the file with user3
\OCP\Share::unshare('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4);
@@ -463,7 +484,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4 . '.shareKey'));
// login as user1
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
// unshare the folder with user2
\OCP\Share::unshare('folder', $fileInfoSubFolder['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3);
@@ -475,7 +496,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '.shareKey'));
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
// unshare the folder1 with user1
\OCP\Share::unshare('folder', $fileInfoFolder1['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
@@ -502,7 +523,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
function testPublicShareFile() {
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
// save file with content
$cryptedFile = file_put_contents('crypt:///' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename, $this->dataShort);
@@ -531,7 +552,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
\OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_LINK, false, OCP\PERMISSION_ALL);
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
$publicShareKeyId = \OC::$server->getAppConfig()->getValue('files_encryption', 'publicShareKeyId');
@@ -543,7 +564,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
// some hacking to simulate public link
//$GLOBALS['app'] = 'files_sharing';
//$GLOBALS['fileOwner'] = \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1;
\Test_Encryption_Util::logoutHelper();
self::logoutHelper();
// get file contents
$retrievedCryptedFile = file_get_contents('crypt:///' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
@@ -554,7 +575,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
// tear down
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
// unshare the file
\OCP\Share::unshare('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_LINK, null);
@@ -580,7 +601,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
*/
function testShareFileWithGroup() {
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
// save file with content
$cryptedFile = file_put_contents('crypt:///' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename, $this->dataShort);
@@ -609,7 +630,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
\OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_GROUP, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_GROUP1, OCP\PERMISSION_ALL);
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
// check if share key for user2 and user3 exists
$this->assertTrue($this->view->file_exists(
@@ -620,7 +641,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4 . '.shareKey'));
// login as user1
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3);
// get file contents
$retrievedCryptedFile = $this->view->file_get_contents(
@@ -630,7 +651,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
$this->assertEquals($this->dataShort, $retrievedCryptedFile);
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
// unshare the file
\OCP\Share::unshare('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_GROUP, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_GROUP1);
@@ -661,13 +682,13 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
function testRecoveryFile() {
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
\OCA\Encryption\Helper::adminEnableRecovery(null, 'test123');
$recoveryKeyId = \OC::$server->getAppConfig()->getValue('files_encryption', 'recoveryKeyId');
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
$util = new \OCA\Encryption\Util(new \OC\Files\View('/'), \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
@@ -767,7 +788,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
function testRecoveryForUser() {
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
$result = \OCA\Encryption\Helper::adminEnableRecovery(null, 'test123');
$this->assertTrue($result);
@@ -775,7 +796,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
$recoveryKeyId = \OC::$server->getAppConfig()->getValue('files_encryption', 'recoveryKeyId');
// login as user2
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
$util = new \OCA\Encryption\Util(new \OC\Files\View('/'), \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
@@ -819,7 +840,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->filename . '.' . $recoveryKeyId . '.shareKey'));
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
// change password
\OC_User::setPassword(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, 'test', 'test123');
@@ -829,7 +850,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
\OCA\Encryption\Hooks::setPassphrase($params);
// login as user2
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, false, 'test');
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, false, 'test');
// get file contents
$retrievedCryptedFile1 = file_get_contents('crypt:///' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->filename);
@@ -881,7 +902,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
*/
function testFailShareFile() {
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
// save file with content
$cryptedFile = file_put_contents('crypt:///' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename, $this->dataShort);
@@ -919,7 +940,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
// check if share key for user1 not exists
$this->assertFalse($this->view->file_exists(
@@ -964,7 +985,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
function testRename() {
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
// save file with content
$cryptedFile = file_put_contents('crypt:///' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename, $this->dataShort);
@@ -989,7 +1010,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
// login as user2
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
$this->assertTrue($this->view->file_exists('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->filename));
@@ -1012,7 +1033,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
$this->assertEquals($this->dataShort, $retrievedRenamedFile);
// cleanup
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
$this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
}
@@ -1024,8 +1045,8 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
$view = new \OC\Files\View('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
$filename = '/tmp-' . uniqid();
$folder = '/folder' . uniqid();
$filename = '/tmp-' . $this->getUniqueID();
$folder = '/folder' . $this->getUniqueID();
\OC\Files\Filesystem::mkdir($folder);
@@ -1040,7 +1061,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
$this->assertEquals($this->dataShort, $decrypt);
$newFolder = '/newfolder/subfolder' . uniqid();
$newFolder = '/newfolder/subfolder' . $this->getUniqueID();
\OC\Files\Filesystem::mkdir('/newfolder');
// get the file info from previous created file
@@ -1059,9 +1080,79 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
// check if additional share key for user2 exists
$this->assertTrue($view->file_exists('files_encryption/share-keys' . $newFolder . '/' . $filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
// check that old keys were removed/moved properly
$this->assertFalse($view->file_exists('files_encryption/share-keys' . $folder . '/' . $filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
// tear down
\OC\Files\Filesystem::unlink($newFolder);
\OC\Files\Filesystem::unlink('/newfolder');
}
function usersProvider() {
return array(
// test as owner
array(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1),
// test as share receiver
array(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2),
);
}
/**
* @dataProvider usersProvider
*/
function testMoveFileToFolder($userId) {
$view = new \OC\Files\View('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
$filename = '/tmp-' . $this->getUniqueID();
$folder = '/folder' . $this->getUniqueID();
\OC\Files\Filesystem::mkdir($folder);
// Save long data as encrypted file using stream wrapper
$cryptedFile = \OC\Files\Filesystem::file_put_contents($folder . $filename, $this->dataShort);
// Test that data was successfully written
$this->assertTrue(is_int($cryptedFile));
// Get file decrypted contents
$decrypt = \OC\Files\Filesystem::file_get_contents($folder . $filename);
$this->assertEquals($this->dataShort, $decrypt);
$subFolder = $folder . '/subfolder' . $this->getUniqueID();
\OC\Files\Filesystem::mkdir($subFolder);
// get the file info from previous created file
$fileInfo = \OC\Files\Filesystem::getFileInfo($folder);
$this->assertTrue($fileInfo instanceof \OC\Files\FileInfo);
// share the folder
\OCP\Share::shareItem('folder', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, OCP\PERMISSION_ALL);
// check that the share keys exist
$this->assertTrue($view->file_exists('files_encryption/share-keys' . $folder . '/' . $filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '.shareKey'));
$this->assertTrue($view->file_exists('files_encryption/share-keys' . $folder . '/' . $filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
// move the file into the subfolder as the test user
self::loginHelper($userId);
\OC\Files\Filesystem::rename($folder . $filename, $subFolder . $filename);
self::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
// Get file decrypted contents
$newDecrypt = \OC\Files\Filesystem::file_get_contents($subFolder . $filename);
$this->assertEquals($this->dataShort, $newDecrypt);
// check if additional share key for user2 exists
$this->assertTrue($view->file_exists('files_encryption/share-keys' . $subFolder . '/' . $filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '.shareKey'));
$this->assertTrue($view->file_exists('files_encryption/share-keys' . $subFolder . '/' . $filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
// check that old keys were removed/moved properly
$this->assertFalse($view->file_exists('files_encryption/share-keys' . $folder . '/' . $filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '.shareKey'));
$this->assertFalse($view->file_exists('files_encryption/share-keys' . $folder . '/' . $filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
// tear down
\OC\Files\Filesystem::unlink($subFolder);
\OC\Files\Filesystem::unlink($folder);
}
}
+37 -11
View File
@@ -27,7 +27,6 @@ require_once __DIR__ . '/../lib/proxy.php';
require_once __DIR__ . '/../lib/stream.php';
require_once __DIR__ . '/../lib/util.php';
require_once __DIR__ . '/../appinfo/app.php';
require_once __DIR__ . '/util.php';
use OCA\Encryption;
@@ -35,7 +34,7 @@ use OCA\Encryption;
* Class Test_Encryption_Stream
* this class provide basic stream tests
*/
class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase {
class Test_Encryption_Stream extends \OCA\Files_Encryption\Tests\TestCase {
const TEST_ENCRYPTION_STREAM_USER1 = "test-stream-user1";
@@ -49,6 +48,8 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase {
public $stateFilesTrashbin;
public static function setUpBeforeClass() {
parent::setUpBeforeClass();
// reset backend
\OC_User::clearBackends();
\OC_User::useBackend('database');
@@ -61,10 +62,12 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase {
\OC_FileProxy::register(new OCA\Encryption\Proxy());
// create test user
\Test_Encryption_Util::loginHelper(\Test_Encryption_Stream::TEST_ENCRYPTION_STREAM_USER1, true);
self::loginHelper(\Test_Encryption_Stream::TEST_ENCRYPTION_STREAM_USER1, true);
}
function setUp() {
protected function setUp() {
parent::setUp();
// set user id
\OC_User::setUserId(\Test_Encryption_Stream::TEST_ENCRYPTION_STREAM_USER1);
$this->userId = \Test_Encryption_Stream::TEST_ENCRYPTION_STREAM_USER1;
@@ -83,7 +86,7 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase {
\OC_App::disable('files_trashbin');
}
function tearDown() {
protected function tearDown() {
// reset app files_trashbin
if ($this->stateFilesTrashbin) {
OC_App::enable('files_trashbin');
@@ -91,15 +94,27 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase {
else {
OC_App::disable('files_trashbin');
}
parent::tearDown();
}
public static function tearDownAfterClass() {
// cleanup test user
\OC_User::deleteUser(\Test_Encryption_Stream::TEST_ENCRYPTION_STREAM_USER1);
\OC_Hook::clear();
\OC_FileProxy::clearProxies();
// Delete keys in /data/
$view = new \OC\Files\View('/');
$view->rmdir('public-keys');
$view->rmdir('owncloud_private_key');
parent::tearDownAfterClass();
}
function testStreamOptions() {
$filename = '/tmp-' . uniqid();
$filename = '/tmp-' . $this->getUniqueID();
$view = new \OC\Files\View('/' . $this->userId . '/files');
// Save short data as encrypted file using stream wrapper
@@ -117,12 +132,14 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase {
$this->assertTrue(flock($handle, LOCK_SH));
$this->assertTrue(flock($handle, LOCK_UN));
fclose($handle);
// tear down
$view->unlink($filename);
}
function testStreamSetBlocking() {
$filename = '/tmp-' . uniqid();
$filename = '/tmp-' . $this->getUniqueID();
$view = new \OC\Files\View('/' . $this->userId . '/files');
// Save short data as encrypted file using stream wrapper
@@ -133,6 +150,13 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase {
$handle = $view->fopen($filename, 'r');
if (\OC_Util::runningOnWindows()) {
fclose($handle);
$view->unlink($filename);
$this->markTestSkipped('[Windows] stream_set_blocking() does not work as expected on Windows.');
}
// set stream options
$this->assertTrue(stream_set_blocking($handle, 1));
@@ -146,7 +170,7 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase {
* @medium
*/
function testStreamSetTimeout() {
$filename = '/tmp-' . uniqid();
$filename = '/tmp-' . $this->getUniqueID();
$view = new \OC\Files\View('/' . $this->userId . '/files');
// Save short data as encrypted file using stream wrapper
@@ -167,7 +191,7 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase {
}
function testStreamSetWriteBuffer() {
$filename = '/tmp-' . uniqid();
$filename = '/tmp-' . $this->getUniqueID();
$view = new \OC\Files\View('/' . $this->userId . '/files');
// Save short data as encrypted file using stream wrapper
@@ -193,9 +217,9 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase {
*/
function testStreamFromLocalFile() {
$filename = '/' . $this->userId . '/files/' . 'tmp-' . uniqid().'.txt';
$filename = '/' . $this->userId . '/files/' . 'tmp-' . $this->getUniqueID().'.txt';
$tmpFilename = "/tmp/" . uniqid() . ".txt";
$tmpFilename = "/tmp/" . $this->getUniqueID() . ".txt";
// write an encrypted file
$cryptedFile = $this->view->file_put_contents($filename, $this->dataShort);
@@ -220,6 +244,8 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase {
// check if it was successful
$this->assertEquals($this->dataShort, $contentFromTmpFile);
fclose($handle);
// clean up
unlink($tmpFilename);
$this->view->unlink($filename);
+53
View File
@@ -0,0 +1,53 @@
<?php
/**
* Copyright (c) 2012 Sam Tuke <samtuke@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OCA\Files_Encryption\Tests;
use OCA\Encryption;
/**
* Class Test_Encryption_TestCase
*/
abstract class TestCase extends \Test\TestCase {
/**
* @param string $user
* @param bool $create
* @param bool $password
*/
public static function loginHelper($user, $create = false, $password = false, $loadEncryption = true) {
if ($create) {
try {
\OC_User::createUser($user, $user);
} catch (\Exception $e) {
// catch username is already being used from previous aborted runs
}
}
if ($password === false) {
$password = $user;
}
\OC_Util::tearDownFS();
\OC_User::setUserId('');
\OC\Files\Filesystem::tearDown();
\OC_User::setUserId($user);
\OC_Util::setupFS($user);
if ($loadEncryption) {
$params['uid'] = $user;
$params['password'] = $password;
\OCA\Encryption\Hooks::login($params);
}
}
public static function logoutHelper() {
\OC_Util::tearDownFS();
\OC_User::setUserId(false);
\OC\Files\Filesystem::tearDown();
}
}
+195 -56
View File
@@ -28,7 +28,6 @@ require_once __DIR__ . '/../lib/stream.php';
require_once __DIR__ . '/../lib/util.php';
require_once __DIR__ . '/../appinfo/app.php';
require_once __DIR__ . '/../../files_trashbin/appinfo/app.php';
require_once __DIR__ . '/util.php';
use OCA\Encryption;
@@ -36,9 +35,10 @@ use OCA\Encryption;
* Class Test_Encryption_Trashbin
* this class provide basic trashbin app tests
*/
class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase {
class Test_Encryption_Trashbin extends \OCA\Files_Encryption\Tests\TestCase {
const TEST_ENCRYPTION_TRASHBIN_USER1 = "test-trashbin-user1";
const TEST_ENCRYPTION_TRASHBIN_USER2 = "test-trashbin-user2";
public $userId;
public $pass;
@@ -53,12 +53,15 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase {
public $subsubfolder;
public static function setUpBeforeClass() {
parent::setUpBeforeClass();
// reset backend
\OC_User::clearBackends();
\OC_User::useBackend('database');
\OC_Hook::clear('OC_Filesystem');
\OC_Hook::clear('OC_User');
\OC_Hook::clear('OCP\\Share');
// trashbin hooks
\OCA\Files_Trashbin\Trashbin::registerHooks();
@@ -66,19 +69,34 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase {
// Filesystem related hooks
\OCA\Encryption\Helper::registerFilesystemHooks();
// register share hooks
\OC::registerShareHooks();
\OCA\Files_Sharing\Helper::registerHooks();
// Sharing related hooks
\OCA\Encryption\Helper::registerShareHooks();
// Filesystem related hooks
\OCA\Encryption\Helper::registerFilesystemHooks();
// clear and register hooks
\OC_FileProxy::clearProxies();
\OC_FileProxy::register(new OCA\Files\Share\Proxy());
\OC_FileProxy::register(new OCA\Encryption\Proxy());
// create test user
\Test_Encryption_Util::loginHelper(\Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1, true);
self::loginHelper(self::TEST_ENCRYPTION_TRASHBIN_USER2, true);
self::loginHelper(self::TEST_ENCRYPTION_TRASHBIN_USER1, true);
}
function setUp() {
protected function setUp() {
parent::setUp();
// set user id
\OC_User::setUserId(\Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1);
$this->userId = \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1;
$this->pass = \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1;
\OC_User::setUserId(self::TEST_ENCRYPTION_TRASHBIN_USER1);
$this->userId = self::TEST_ENCRYPTION_TRASHBIN_USER1;
$this->pass = self::TEST_ENCRYPTION_TRASHBIN_USER1;
// init filesystem view
$this->view = new \OC\Files\View('/');
@@ -93,11 +111,14 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase {
// remember files_trashbin state
$this->stateFilesTrashbin = OC_App::isEnabled('files_trashbin');
$this->view->deleteAll('/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin');
$this->view->deleteAll('/' . self::TEST_ENCRYPTION_TRASHBIN_USER2 . '/files_trashbin');
// we want to tests with app files_trashbin enabled
\OC_App::enable('files_trashbin');
}
function tearDown() {
protected function tearDown() {
// reset app files_trashbin
if ($this->stateFilesTrashbin) {
OC_App::enable('files_trashbin');
@@ -105,11 +126,23 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase {
else {
OC_App::disable('files_trashbin');
}
parent::tearDown();
}
public static function tearDownAfterClass() {
// cleanup test user
\OC_User::deleteUser(\Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1);
\OC_User::deleteUser(self::TEST_ENCRYPTION_TRASHBIN_USER1);
\OC_Hook::clear();
\OC_FileProxy::clearProxies();
// Delete keys in /data/
$view = new \OC\Files\View('/');
$view->rmdir('public-keys');
$view->rmdir('owncloud_private_key');
parent::tearDownAfterClass();
}
/**
@@ -119,49 +152,72 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase {
function testDeleteFile() {
// generate filename
$filename = 'tmp-' . uniqid() . '.txt';
$filename = 'tmp-' . $this->getUniqueID() . '.txt';
$filename2 = $filename . '.backup'; // a second file with similar name
// save file with content
$cryptedFile = file_put_contents('crypt:///' .\Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1. '/files/'. $filename, $this->dataShort);
$cryptedFile = file_put_contents('crypt:///' .self::TEST_ENCRYPTION_TRASHBIN_USER1. '/files/'. $filename, $this->dataShort);
$cryptedFile2 = file_put_contents('crypt:///' .self::TEST_ENCRYPTION_TRASHBIN_USER1. '/files/'. $filename2, $this->dataShort);
// test that data was successfully written
$this->assertTrue(is_int($cryptedFile));
$this->assertTrue(is_int($cryptedFile2));
// check if key for admin exists
$this->assertTrue($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/keyfiles/' . $filename
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/keyfiles/' . $filename
. '.key'));
$this->assertTrue($this->view->file_exists(
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/keyfiles/' . $filename2
. '.key'));
// check if share key for admin exists
$this->assertTrue($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/'
. $filename . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey'));
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/'
. $filename . '.' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey'));
$this->assertTrue($this->view->file_exists(
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/'
. $filename2 . '.' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey'));
// delete file
// delete first file
\OC\FIles\Filesystem::unlink($filename);
// check if file not exists
$this->assertFalse($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files/' . $filename));
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files/' . $filename));
// check if key for admin not exists
$this->assertFalse($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/keyfiles/' . $filename
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/keyfiles/' . $filename
. '.key'));
// check if share key for admin not exists
$this->assertFalse($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/'
. $filename . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey'));
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/'
. $filename . '.' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey'));
// check that second file still exists
$this->assertTrue($this->view->file_exists(
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files/' . $filename2));
// check that key for second file still exists
$this->assertTrue($this->view->file_exists(
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/keyfiles/' . $filename2
. '.key'));
// check that share key for second file still exists
$this->assertTrue($this->view->file_exists(
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/'
. $filename2 . '.' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey'));
// get files
$trashFiles = $this->view->getDirectoryContent(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/files/');
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/files/');
$trashFileSuffix = null;
// find created file with timestamp
foreach ($trashFiles as $file) {
if (strncmp($file['path'], $filename, strlen($filename))) {
if (strpos($file['path'], $filename . '.d') !== false) {
$path_parts = pathinfo($file['name']);
$trashFileSuffix = $path_parts['extension'];
}
@@ -172,48 +228,77 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase {
// check if key for admin not exists
$this->assertTrue($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/keyfiles/' . $filename
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/keyfiles/' . $filename
. '.key.' . $trashFileSuffix));
// check if share key for admin not exists
$this->assertTrue($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/share-keys/' . $filename
. '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey.' . $trashFileSuffix));
// return filename for next test
return $filename . '.' . $trashFileSuffix;
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/share-keys/' . $filename
. '.' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey.' . $trashFileSuffix));
}
/**
* @medium
* test restore file
*
* @depends testDeleteFile
*/
function testRestoreFile($filename) {
function testRestoreFile() {
// generate filename
$filename = 'tmp-' . $this->getUniqueID() . '.txt';
$filename2 = $filename . '.backup'; // a second file with similar name
// save file with content
$cryptedFile = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_TRASHBIN_USER1. '/files/'. $filename, $this->dataShort);
$cryptedFile2 = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_TRASHBIN_USER1. '/files/'. $filename2, $this->dataShort);
// delete both files
\OC\Files\Filesystem::unlink($filename);
\OC\Files\Filesystem::unlink($filename2);
$trashFiles = $this->view->getDirectoryContent('/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/files/');
$trashFileSuffix = null;
$trashFileSuffix2 = null;
// find created file with timestamp
foreach ($trashFiles as $file) {
if (strpos($file['path'], $filename . '.d') !== false) {
$path_parts = pathinfo($file['name']);
$trashFileSuffix = $path_parts['extension'];
}
}
// prepare file information
$path_parts = pathinfo($filename);
$trashFileSuffix = $path_parts['extension'];
$timestamp = str_replace('d', '', $trashFileSuffix);
$fileNameWithoutSuffix = str_replace('.' . $trashFileSuffix, '', $filename);
// restore file
$this->assertTrue(\OCA\Files_Trashbin\Trashbin::restore($filename, $fileNameWithoutSuffix, $timestamp));
// restore first file
$this->assertTrue(\OCA\Files_Trashbin\Trashbin::restore($filename . '.' . $trashFileSuffix, $filename, $timestamp));
// check if file exists
$this->assertTrue($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files/' . $fileNameWithoutSuffix));
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files/' . $filename));
// check if key for admin exists
$this->assertTrue($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/keyfiles/'
. $fileNameWithoutSuffix . '.key'));
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/keyfiles/'
. $filename . '.key'));
// check if share key for admin exists
$this->assertTrue($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/'
. $fileNameWithoutSuffix . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey'));
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/'
. $filename . '.' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey'));
// check that second file was NOT restored
$this->assertFalse($this->view->file_exists(
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files/' . $filename2));
// check if key for admin exists
$this->assertFalse($this->view->file_exists(
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/keyfiles/'
. $filename2 . '.key'));
// check if share key for admin exists
$this->assertFalse($this->view->file_exists(
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/'
. $filename2 . '.' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey'));
}
/**
@@ -223,7 +308,7 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase {
function testPermanentDeleteFile() {
// generate filename
$filename = 'tmp-' . uniqid() . '.txt';
$filename = 'tmp-' . $this->getUniqueID() . '.txt';
// save file with content
$cryptedFile = file_put_contents('crypt:///' .$this->userId. '/files/' . $filename, $this->dataShort);
@@ -233,30 +318,30 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase {
// check if key for admin exists
$this->assertTrue($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/keyfiles/' . $filename
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/keyfiles/' . $filename
. '.key'));
// check if share key for admin exists
$this->assertTrue($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/'
. $filename . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey'));
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/'
. $filename . '.' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey'));
// delete file
\OC\FIles\Filesystem::unlink($filename);
\OC\Files\Filesystem::unlink($filename);
// check if file not exists
$this->assertFalse($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files/' . $filename));
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files/' . $filename));
// check if key for admin not exists
$this->assertFalse($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/keyfiles/' . $filename
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/keyfiles/' . $filename
. '.key'));
// check if share key for admin not exists
$this->assertFalse($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/'
. $filename . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey'));
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/'
. $filename . '.' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey'));
// find created file with timestamp
$query = \OC_DB::prepare('SELECT `timestamp`,`type` FROM `*PREFIX*files_trash`'
@@ -270,13 +355,13 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase {
// check if key for admin exists
$this->assertTrue($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/keyfiles/' . $filename
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/keyfiles/' . $filename
. '.key.' . $trashFileSuffix));
// check if share key for admin exists
$this->assertTrue($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/share-keys/' . $filename
. '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey.' . $trashFileSuffix));
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/share-keys/' . $filename
. '.' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey.' . $trashFileSuffix));
// get timestamp from file
$timestamp = str_replace('d', '', $trashFileSuffix);
@@ -286,18 +371,72 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase {
// check if key for admin not exists
$this->assertFalse($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/files/' . $filename . '.'
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/files/' . $filename . '.'
. $trashFileSuffix));
// check if key for admin not exists
$this->assertFalse($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/keyfiles/' . $filename
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/keyfiles/' . $filename
. '.key.' . $trashFileSuffix));
// check if share key for admin not exists
$this->assertFalse($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/share-keys/' . $filename
. '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey.' . $trashFileSuffix));
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/share-keys/' . $filename
. '.' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey.' . $trashFileSuffix));
}
function testDeleteSharedFile() {
// generate filename
$filename = 'tmp-' . $this->getUniqueID() . '.txt';
// save file with content
$cryptedFile = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files/' . $filename, $this->dataShort);
// test that data was successfully written
$this->assertTrue(is_int($cryptedFile));
// get the file info from previous created file
$fileInfo = $this->view->getFileInfo(
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files/' . $filename);
// check if we have a valid file info
$this->assertTrue($fileInfo instanceof \OC\Files\FileInfo);
// share the file
$this->assertTrue(
\OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, self::TEST_ENCRYPTION_TRASHBIN_USER2, OCP\PERMISSION_ALL)
);
self::loginHelper(self::TEST_ENCRYPTION_TRASHBIN_USER2);
$this->assertTrue(\OC\Files\Filesystem::file_exists($filename));
\OCA\Files_Trashbin\Trashbin::move2trash($filename);
$query = \OC_DB::prepare('SELECT `timestamp` FROM `*PREFIX*files_trash`'
. ' WHERE `id`=?');
$result = $query->execute(array($filename))->fetchRow();
$this->assertNotEmpty($result);
$timestamp = $result['timestamp'];
// check if key for both users exists
$this->assertTrue($this->view->file_exists(
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/keyfiles/' . $filename
. '.key.d'. $timestamp));
// check if key for admin exists
$this->assertTrue($this->view->file_exists(
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER2 . '/files_trashbin/keyfiles/' . $filename
. '.key.d' . $timestamp));
// check if share key for both users exists
$this->assertTrue($this->view->file_exists(
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/share-keys/'
. $filename . '.' . self::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey.d' . $timestamp));
$this->assertTrue($this->view->file_exists(
'/' . self::TEST_ENCRYPTION_TRASHBIN_USER2 . '/files_trashbin/share-keys/'
. $filename . '.' . self::TEST_ENCRYPTION_TRASHBIN_USER2 . '.shareKey.d' . $timestamp));
}
}
+129 -30
View File
@@ -19,7 +19,7 @@ use OCA\Encryption;
/**
* Class Test_Encryption_Util
*/
class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
class Test_Encryption_Util extends \OCA\Files_Encryption\Tests\TestCase {
const TEST_ENCRYPTION_UTIL_USER1 = "test-util-user1";
const TEST_ENCRYPTION_UTIL_USER2 = "test-util-user2";
@@ -49,21 +49,18 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
public $stateFilesTrashbin;
public static function setUpBeforeClass() {
parent::setUpBeforeClass();
// reset backend
\OC_User::clearBackends();
\OC_User::useBackend('database');
// Filesystem related hooks
\OCA\Encryption\Helper::registerFilesystemHooks();
// clear and register hooks
\OC_FileProxy::clearProxies();
\OC_FileProxy::register(new OCA\Encryption\Proxy());
self::setupHooks();
// create test user
\Test_Encryption_Util::loginHelper(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1, true);
\Test_Encryption_Util::loginHelper(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER2, true);
\Test_Encryption_Util::loginHelper(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER, true);
self::loginHelper(self::TEST_ENCRYPTION_UTIL_USER1, true);
self::loginHelper(self::TEST_ENCRYPTION_UTIL_USER2, true);
self::loginHelper(self::TEST_ENCRYPTION_UTIL_LEGACY_USER, true);
// create groups
\OC_Group::createGroup(self::TEST_ENCRYPTION_UTIL_GROUP1);
@@ -73,13 +70,14 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
\OC_Group::addToGroup(self::TEST_ENCRYPTION_UTIL_USER1, self::TEST_ENCRYPTION_UTIL_GROUP1);
}
protected function setUp() {
parent::setUp();
function setUp() {
// login user
\Test_Encryption_Util::loginHelper(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1);
\OC_User::setUserId(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1);
$this->userId = \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1;
$this->pass = \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1;
self::loginHelper(self::TEST_ENCRYPTION_UTIL_USER1);
\OC_User::setUserId(self::TEST_ENCRYPTION_UTIL_USER1);
$this->userId = self::TEST_ENCRYPTION_UTIL_USER1;
$this->pass = self::TEST_ENCRYPTION_UTIL_USER1;
// set content for encrypting / decrypting in tests
$this->dataUrl = __DIR__ . '/../lib/crypt.php';
@@ -114,7 +112,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
\OC_App::disable('files_trashbin');
}
function tearDown() {
protected function tearDown() {
// reset app files_trashbin
if ($this->stateFilesTrashbin) {
OC_App::enable('files_trashbin');
@@ -122,16 +120,38 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
else {
OC_App::disable('files_trashbin');
}
parent::tearDown();
}
public static function tearDownAfterClass() {
// cleanup test user
\OC_User::deleteUser(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1);
\OC_User::deleteUser(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER2);
\OC_User::deleteUser(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER);
\OC_User::deleteUser(self::TEST_ENCRYPTION_UTIL_USER1);
\OC_User::deleteUser(self::TEST_ENCRYPTION_UTIL_USER2);
\OC_User::deleteUser(self::TEST_ENCRYPTION_UTIL_LEGACY_USER);
//cleanup groups
\OC_Group::deleteGroup(self::TEST_ENCRYPTION_UTIL_GROUP1);
\OC_Group::deleteGroup(self::TEST_ENCRYPTION_UTIL_GROUP2);
\OC_Hook::clear();
\OC_FileProxy::clearProxies();
// Delete keys in /data/
$view = new \OC\Files\View('/');
$view->rmdir('public-keys');
$view->rmdir('owncloud_private_key');
parent::tearDownAfterClass();
}
public static function setupHooks() {
// Filesystem related hooks
\OCA\Encryption\Helper::registerFilesystemHooks();
// clear and register hooks
\OC_FileProxy::clearProxies();
\OC_FileProxy::register(new OCA\Encryption\Proxy());
}
/**
@@ -159,8 +179,8 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
self::loginHelper($this->userId);
$unencryptedFile = '/tmpUnencrypted-' . uniqid() . '.txt';
$encryptedFile = '/tmpEncrypted-' . uniqid() . '.txt';
$unencryptedFile = '/tmpUnencrypted-' . $this->getUniqueID() . '.txt';
$encryptedFile = '/tmpEncrypted-' . $this->getUniqueID() . '.txt';
// Disable encryption proxy to write a unencrypted file
$proxyStatus = \OC_FileProxy::$enabled;
@@ -267,9 +287,9 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
*/
function testGetUidAndFilename() {
\OC_User::setUserId(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1);
\OC_User::setUserId(self::TEST_ENCRYPTION_UTIL_USER1);
$filename = '/tmp-' . uniqid() . '.test';
$filename = '/tmp-' . $this->getUniqueID() . '.test';
// Disable encryption proxy to prevent recursive calls
$proxyStatus = \OC_FileProxy::$enabled;
@@ -284,7 +304,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
list($fileOwnerUid, $file) = $util->getUidAndFilename($filename);
$this->assertEquals(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1, $fileOwnerUid);
$this->assertEquals(self::TEST_ENCRYPTION_UTIL_USER1, $fileOwnerUid);
$this->assertEquals($file, $filename);
@@ -295,9 +315,9 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
< * Test that data that is read by the crypto stream wrapper
*/
function testGetFileSize() {
\Test_Encryption_Util::loginHelper(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1);
self::loginHelper(self::TEST_ENCRYPTION_UTIL_USER1);
$filename = 'tmp-' . uniqid();
$filename = 'tmp-' . $this->getUniqueID();
$externalFilename = '/' . $this->userId . '/files/' . $filename;
// Test for 0 byte files
@@ -321,7 +341,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
function testEncryptAll() {
$filename = "/encryptAll" . uniqid() . ".txt";
$filename = "/encryptAll" . $this->getUniqueID() . ".txt";
$util = new Encryption\Util($this->view, $this->userId);
// disable encryption to upload a unencrypted file
@@ -352,7 +372,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
function testDecryptAll() {
$filename = "/decryptAll" . uniqid() . ".txt";
$filename = "/decryptAll" . $this->getUniqueID() . ".txt";
$datadir = \OC_Config::getValue('datadirectory', \OC::$SERVERROOT . '/data/');
$userdir = $datadir . '/' . $this->userId . '/files/';
@@ -426,11 +446,53 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
}
/**
* test if all keys get moved to the backup folder correctly
*/
function testBackupAllKeys() {
self::loginHelper(self::TEST_ENCRYPTION_UTIL_USER1);
// create some dummy key files
$encPath = '/' . self::TEST_ENCRYPTION_UTIL_USER1 . '/files_encryption';
$this->view->file_put_contents($encPath . '/keyfiles/foo.key', 'key');
$this->view->file_put_contents($encPath . '/share-keys/foo.user1.shareKey', 'share key');
$util = new \OCA\Encryption\Util($this->view, self::TEST_ENCRYPTION_UTIL_USER1);
$util->backupAllKeys('testing');
$encFolderContent = $this->view->getDirectoryContent($encPath);
$backupPath = '';
foreach ($encFolderContent as $c) {
$name = $c['name'];
if (substr($name, 0, strlen('backup')) === 'backup') {
$backupPath = $encPath . '/'. $c['name'];
break;
}
}
$this->assertTrue($backupPath !== '');
// check backupDir Content
$this->assertTrue($this->view->is_dir($backupPath . '/keyfiles'));
$this->assertTrue($this->view->is_dir($backupPath . '/share-keys'));
$this->assertTrue($this->view->file_exists($backupPath . '/keyfiles/foo.key'));
$this->assertTrue($this->view->file_exists($backupPath . '/share-keys/foo.user1.shareKey'));
$this->assertTrue($this->view->file_exists($backupPath . '/' . self::TEST_ENCRYPTION_UTIL_USER1 . '.private.key'));
$this->assertTrue($this->view->file_exists($backupPath . '/' . self::TEST_ENCRYPTION_UTIL_USER1 . '.public.key'));
//cleanup
$this->view->deleteAll($backupPath);
$this->view->unlink($encPath . '/keyfiles/foo.key', 'key');
$this->view->unlink($encPath . '/share-keys/foo.user1.shareKey', 'share key');
}
function testDescryptAllWithBrokenFiles() {
$file1 = "/decryptAll1" . uniqid() . ".txt";
$file2 = "/decryptAll2" . uniqid() . ".txt";
$file1 = "/decryptAll1" . $this->getUniqueID() . ".txt";
$file2 = "/decryptAll2" . $this->getUniqueID() . ".txt";
$util = new Encryption\Util($this->view, $this->userId);
@@ -575,6 +637,43 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
);
}
/**
* Tests that filterShareReadyUsers() returns the correct list of
* users that are ready or not ready for encryption
*/
public function testFilterShareReadyUsers() {
$appConfig = \OC::$server->getAppConfig();
$publicShareKeyId = $appConfig->getValue('files_encryption', 'publicShareKeyId');
$recoveryKeyId = $appConfig->getValue('files_encryption', 'recoveryKeyId');
$usersToTest = array(
'readyUser',
'notReadyUser',
'nonExistingUser',
$publicShareKeyId,
$recoveryKeyId,
);
\Test_Encryption_Util::loginHelper('readyUser', true);
\Test_Encryption_Util::loginHelper('notReadyUser', true);
// delete encryption dir to make it not ready
$this->view->unlink('notReadyUser/files_encryption/');
// login as user1
\Test_Encryption_Util::loginHelper(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1);
$result = $this->util->filterShareReadyUsers($usersToTest);
$this->assertEquals(
array('readyUser', $publicShareKeyId, $recoveryKeyId),
$result['ready']
);
$this->assertEquals(
array('notReadyUser', 'nonExistingUser'),
$result['unready']
);
\OC_User::deleteUser('readyUser');
}
/**
* @param string $user
* @param bool $create
+22 -7
View File
@@ -27,7 +27,6 @@ require_once __DIR__ . '/../lib/proxy.php';
require_once __DIR__ . '/../lib/stream.php';
require_once __DIR__ . '/../lib/util.php';
require_once __DIR__ . '/../appinfo/app.php';
require_once __DIR__ . '/util.php';
use OCA\Encryption;
@@ -36,7 +35,7 @@ use OCA\Encryption;
*
* this class provide basic webdav tests for PUT,GET and DELETE
*/
class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase {
class Test_Encryption_Webdav extends \OCA\Files_Encryption\Tests\TestCase {
const TEST_ENCRYPTION_WEBDAV_USER1 = "test-webdav-user1";
@@ -52,6 +51,8 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase {
private $storage;
public static function setUpBeforeClass() {
parent::setUpBeforeClass();
// reset backend
\OC_User::clearBackends();
\OC_User::useBackend('database');
@@ -67,11 +68,13 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase {
\OC_FileProxy::register(new OCA\Encryption\Proxy());
// create test user
\Test_Encryption_Util::loginHelper(\Test_Encryption_Webdav::TEST_ENCRYPTION_WEBDAV_USER1, true);
self::loginHelper(\Test_Encryption_Webdav::TEST_ENCRYPTION_WEBDAV_USER1, true);
}
function setUp() {
protected function setUp() {
parent::setUp();
// reset backend
\OC_User::useBackend('database');
@@ -93,21 +96,33 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase {
\OC_App::disable('files_trashbin');
// create test user
\Test_Encryption_Util::loginHelper(\Test_Encryption_Webdav::TEST_ENCRYPTION_WEBDAV_USER1);
self::loginHelper(\Test_Encryption_Webdav::TEST_ENCRYPTION_WEBDAV_USER1);
}
function tearDown() {
protected function tearDown() {
// reset app files_trashbin
if ($this->stateFilesTrashbin) {
OC_App::enable('files_trashbin');
} else {
OC_App::disable('files_trashbin');
}
parent::tearDown();
}
public static function tearDownAfterClass() {
// cleanup test user
\OC_User::deleteUser(\Test_Encryption_Webdav::TEST_ENCRYPTION_WEBDAV_USER1);
\OC_Hook::clear();
\OC_FileProxy::clearProxies();
// Delete keys in /data/
$view = new \OC\Files\View('/');
$view->rmdir('public-keys');
$view->rmdir('owncloud_private_key');
parent::tearDownAfterClass();
}
/**
@@ -116,7 +131,7 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase {
function testWebdavPUT() {
// generate filename
$filename = '/tmp-' . uniqid() . '.txt';
$filename = '/tmp-' . $this->getUniqueID() . '.txt';
// set server vars
$_SERVER['REQUEST_METHOD'] = 'OPTIONS';
+26
View File
@@ -0,0 +1,26 @@
<?php
OCP\JSON::checkAppEnabled('files_external');
OCP\JSON::callCheck();
OCP\JSON::checkAdminUser();
$pattern = '';
$limit = null;
$offset = null;
if (isset($_GET['pattern'])) {
$pattern = $_GET['pattern'];
}
if (isset($_GET['limit'])) {
$limit = $_GET['limit'];
}
if (isset($_GET['offset'])) {
$offset = $_GET['offset'];
}
$groups = \OC_Group::getGroups($pattern, $limit, $offset);
$users = \OCP\User::getDisplayNames($pattern, $limit, $offset);
$results = array('groups' => $groups, 'users' => $users);
\OCP\JSON::success($results);
+8 -1
View File
@@ -2,11 +2,18 @@
<info>
<id>files_external</id>
<name>External storage support</name>
<description>Mount external storage sources</description>
<description>
This application enables administrators to configure connections to external storage providers, such as FTP servers, S3 or SWIFT object stores, Google Drive, Dropbox, other ownCloud servers, WebDAV servers and more. Administrators can choose in the GUI which type of storage to enable, and can mount these storage locations for a user, a group, or the entire system. Users will see a new folder appear in their root ownCloud directory, and then can then access and use it like any other ownCloud folder. External Storage also allows users to share files stored in these external location. In these cases, the credentials for the owner of the file are used then the recipient requests the file from external storage, thereby ensuring that the recipient can get at the file that was shared.
In addition to the GUI, it is possible to configure external storage manually at the command line. This option provides the advanced user with more flexibility for configuring bulk external storage mounts, as well as setting mount priorities. More information is available in the External Storage GUI documentation and the External Storage Configuration File documentation.
</description>
<licence>AGPL</licence>
<author>Robin Appelman, Michael Gapczynski, Vincent Petry</author>
<requiremin>4.93</requiremin>
<shipped>true</shipped>
<documentation>
<admin>admin-external-storage</admin>
</documentation>
<types>
<filesystem/>
</types>
+6 -4
View File
@@ -20,8 +20,10 @@
*
*/
OC_API::register('get',
'/apps/files_external/api/v1/mounts',
array('\OCA\Files\External\Api', 'getUserMounts'),
'files_external');
$this->create('files_external_list_applicable', '/applicable')->actionInclude('files_external/ajax/applicable.php');
OC_API::register('get',
'/apps/files_external/api/v1/mounts',
array('\OCA\Files\External\Api', 'getUserMounts'),
'files_external');
+1 -1
View File
@@ -1 +1 @@
0.2.1
0.2.2
+16
View File
@@ -42,3 +42,19 @@ tr:hover>td.remove>img { visibility:visible; cursor:pointer; }
#userMountingBackends {
padding-left: 25px;
}
#body-settings .select2-results .select2-result-label {
height: 32px;
padding: 3px;
}
.select2-results .select2-result-label .avatardiv {
display:inline-block;
}
.select2-results .select2-result-label .avatardiv + span {
margin-left: 10px;
}
.select2-results .select2-result-label .avatardiv[data-type="group"] + span {
vertical-align: top;
top: 6px;
position: relative;
}
+141 -28
View File
@@ -11,6 +11,14 @@ function updateStatus(statusEl, result){
}
}
function getSelection($row) {
var values = $row.find('.applicableUsers').select2('val');
if (!values || values.length === 0) {
values = ['all'];
}
return values;
}
OC.MountConfig={
saveStorage:function(tr, callback) {
var mountPoint = $(tr).find('.mountPoint input').val();
@@ -42,10 +50,7 @@ OC.MountConfig={
}
});
if ($('#externalStorage').data('admin') === true) {
var multiselect = $(tr).find('.chzn-select').val();
if (multiselect == null) {
return false;
}
var multiselect = getSelection($(tr));
}
if (addMountPoint) {
var status = false;
@@ -166,8 +171,122 @@ OC.MountConfig={
};
$(document).ready(function() {
$('.chzn-select').chosen();
//initialize hidden input field with list of users and groups
$('#externalStorage').find('tr:not(#addMountPoint)').each(function(i,tr) {
var applicable = $(tr).find('.applicable');
if (applicable.length > 0) {
var groups = applicable.data('applicable-groups');
var groupsId = [];
$.each(groups, function () {
groupsId.push(this+"(group)");
});
var users = applicable.data('applicable-users');
if (users.indexOf('all') > -1) {
$(tr).find('.applicableUsers').val('');
} else {
$(tr).find('.applicableUsers').val(groupsId.concat(users).join(','));
}
}
});
var userListLimit = 30;
function addSelect2 ($elements) {
if ($elements.length > 0) {
$elements.select2({
placeholder: t('files_external', 'All users. Type to select user or group.'),
allowClear: true,
multiple: true,
//minimumInputLength: 1,
ajax: {
url: OC.generateUrl('apps/files_external/applicable'),
dataType: 'json',
quietMillis: 100,
data: function (term, page) { // page is the one-based page number tracked by Select2
return {
pattern: term, //search term
limit: userListLimit, // page size
offset: userListLimit*(page-1) // page number starts with 0
};
},
results: function (data, page) {
if (data.status === "success") {
var results = [];
var userCount = 0; // users is an object
// add groups
$.each(data.groups, function(i, group) {
results.push({name:group+'(group)', displayname:group, type:'group' });
});
// add users
$.each(data.users, function(id, user) {
userCount++;
results.push({name:id, displayname:user, type:'user' });
});
var more = (userCount >= userListLimit) || (data.groups.length >= userListLimit);
return {results: results, more: more};
} else {
//FIXME add error handling
}
}
},
initSelection: function(element, callback) {
$.ajax(OC.generateUrl('displaynames'), {
data: {
users: element.val().split(",")
},
dataType: "json"
}).done(function(data) {
var results = [];
if (data.status === "success") {
$.each(data.users, function(user, displayname) {
if (displayname !== false) {
results.push({name:user, displayname:displayname, type:'user'});
}
});
callback(results);
} else {
//FIXME add error handling
}
});
},
id: function(element) {
return element.name;
},
formatResult: function (element) {
var $result = $('<span><div class="avatardiv"/><span>'+escapeHTML(element.displayname)+'</span></span>');
var $div = $result.find('.avatardiv')
.attr('data-type', element.type)
.attr('data-name', element.name)
.attr('data-displayname', element.displayname);
if (element.type === 'group') {
var url = OC.imagePath('core','places/contacts-dark'); // TODO better group icon
$div.html('<img width="32" height="32" src="'+url+'">');
}
return $result.get(0).outerHTML;
},
formatSelection: function (element) {
if (element.type === 'group') {
return '<span title="'+escapeHTML(element.name)+'" class="group">'+escapeHTML(element.displayname+' '+t('files_external', '(group)'))+'</span>';
} else {
return '<span title="'+escapeHTML(element.name)+'" class="user">'+escapeHTML(element.displayname)+'</span>';
}
},
escapeMarkup: function (m) { return m; } // we escape the markup in formatResult and formatSelection
}).on("select2-loaded", function() {
$.each($(".avatardiv"), function(i, div) {
$div = $(div);
if ($div.data('type') === 'user') {
$div.avatar($div.data('name'),32);
}
})
});
}
}
addSelect2($('tr:not(#addMountPoint) .applicableUsers'));
$('#externalStorage').on('change', '#selectBackend', function() {
var tr = $(this).parent().parent();
$('#externalStorage tbody').append($(tr).clone());
@@ -209,15 +328,11 @@ $(document).ready(function() {
return false;
}
});
// Reset chosen
var chosen = $(tr).find('.applicable select');
chosen.parent().find('div').remove();
chosen.removeAttr('id').removeClass('chzn-done').css({display:'inline-block'});
chosen.chosen();
$(tr).find('td').last().attr('class', 'remove');
$(tr).find('td').last().removeAttr('style');
$(tr).removeAttr('id');
$(this).remove();
addSelect2(tr.find('.applicableUsers'));
});
function suggestMountPoint(defaultMountPoint) {
@@ -270,8 +385,8 @@ $(document).ready(function() {
OC.MountConfig.saveStorage($(this).parent().parent().parent());
});
$('#externalStorage').on('change', '.applicable .chzn-select', function() {
OC.MountConfig.saveStorage($(this).parent().parent());
$('#externalStorage').on('change', '.applicable', function() {
OC.MountConfig.saveStorage($(this).parent());
});
$('#sslCertificate').on('click', 'td.remove>img', function() {
@@ -288,20 +403,18 @@ $(document).ready(function() {
if ($('#externalStorage').data('admin') === true) {
var isPersonal = false;
var multiselect = $(tr).find('.chzn-select').val();
if (multiselect != null) {
$.each(multiselect, function(index, value) {
var pos = value.indexOf('(group)');
if (pos != -1) {
var mountType = 'group';
var applicable = value.substr(0, pos);
} else {
var mountType = 'user';
var applicable = value;
}
$.post(OC.filePath('files_external', 'ajax', 'removeMountPoint.php'), { mountPoint: mountPoint, mountType: mountType, applicable: applicable, isPersonal: isPersonal });
});
}
var multiselect = getSelection($(tr));
$.each(multiselect, function(index, value) {
var pos = value.indexOf('(group)');
if (pos != -1) {
var mountType = 'group';
var applicable = value.substr(0, pos);
} else {
var mountType = 'user';
var applicable = value;
}
$.post(OC.filePath('files_external', 'ajax', 'removeMountPoint.php'), { mountPoint: mountPoint, mountType: mountType, applicable: applicable, isPersonal: isPersonal });
});
} else {
var mountType = 'user';
var applicable = OC.currentUser;
@@ -322,14 +435,14 @@ $(document).ready(function() {
OC.AppConfig.setValue('files_external', 'allow_user_mounting', 'no');
$('#userMountingBackends').addClass('hidden');
}
OC.msg.finishedSaving('#userMountingMsg', {status: 'success', data: {message: t('settings', 'Saved')}});
OC.msg.finishedSaving('#userMountingMsg', {status: 'success', data: {message: t('files_external', 'Saved')}});
});
$('input[name="allowUserMountingBackends\\[\\]"]').bind('change', function() {
OC.msg.startSaving('#userMountingMsg');
var userMountingBackends = $('input[name="allowUserMountingBackends\\[\\]"]:checked').map(function(){return $(this).val();}).get();
OC.AppConfig.setValue('files_external', 'user_mounting_backends', userMountingBackends.join());
OC.msg.finishedSaving('#userMountingMsg', {status: 'success', data: {message: t('settings', 'Saved')}});
OC.msg.finishedSaving('#userMountingMsg', {status: 'success', data: {message: t('files_external', 'Saved')}});
// disable allowUserMounting
if(userMountingBackends.length === 0) {
+8 -8
View File
@@ -1,10 +1,10 @@
<?php
$TRANSLATIONS = array(
"Fetching request tokens failed. Verify that your Dropbox app key and secret are correct." => "La requête de récupération des jetons dauthentification a échoué. Veuillez vérifier votre App-Key Dropbox ainsi que le mot de passe.",
"Fetching request tokens failed. Verify that your Dropbox app key and secret are correct." => "La récupération des jetons dauthentification a échoué. Veuillez vérifier votre clé d'application Dropbox ainsi que le mot de passe.",
"Fetching access tokens failed. Verify that your Dropbox app key and secret are correct." => "La requête daccès aux jetons dauthentification a échoué. Veuillez vérifier votre App-Key Dropbox ainsi que le mot de passe.",
"Please provide a valid Dropbox app key and secret." => "Veuillez fournir une clé d'application (app key) ainsi qu'un mot de passe valides.",
"Step 1 failed. Exception: %s" => "L’étape 1 a échoué. Erreur: %s",
"Step 2 failed. Exception: %s" => "L’étape 2 a échoué. Erreur: %s",
"Step 1 failed. Exception: %s" => "L’étape 1 a échoué. Erreur : %s",
"Step 2 failed. Exception: %s" => "L’étape 2 a échoué. Erreur : %s",
"External storage" => "Stockage externe",
"Local" => "Local",
"Location" => "Emplacement",
@@ -26,7 +26,7 @@ $TRANSLATIONS = array(
"Username" => "Nom d'utilisateur",
"Password" => "Mot de passe",
"Root" => "Root",
"Secure ftps://" => "Sécuriser via ftps://",
"Secure ftps://" => "Sécurisation ftps://",
"Client ID" => "ID Client",
"Client secret" => "Secret client",
"OpenStack Object Storage" => "Object de Stockage OpenStack",
@@ -40,7 +40,7 @@ $TRANSLATIONS = array(
"URL of identity endpoint (required for OpenStack Object Storage)" => "URL du point d'accès d'identité (requis pour le stockage OpenStack)",
"Timeout of HTTP requests in seconds (optional)" => "Temps maximal de requête HTTP en seconde (facultatif)",
"Share" => "Partager",
"SMB / CIFS using OC login" => "SMB / CIFS utilise le nom d'utilisateur OC",
"SMB / CIFS using OC login" => "SMB / CIFS en utilisant les identifiants OC",
"Username as share" => "Nom d'utilisateur du partage",
"URL" => "URL",
"Secure https://" => "Sécurisation https://",
@@ -54,8 +54,8 @@ $TRANSLATIONS = array(
"Saved" => "Sauvegarder",
"<b>Note:</b> " => "<b>Attention :</b>",
" and " => "et",
"<b>Note:</b> The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "<b>Attention :</b> Le support de cURL de PHP n'est pas activé ou installé. Le montage de %s n'est pas possible. Contactez votre administrateur système pour l'installer.",
"<b>Note:</b> The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "<b>Attention : </b> Le support FTP de PHP n'est pas activé ou installé. Le montage de %s n'est pas possible. Contactez votre administrateur système pour l'installer.",
"<b>Note:</b> The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "<b>Attention :</b> La prise en charge de cURL par PHP n'est pas activée ou installée. Le montage de %s n'est pas possible. Contactez votre administrateur système pour l'installer.",
"<b>Note:</b> The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "<b>Attention : </b> La prise en charge du FTP par PHP n'est pas activée ou installée. Le montage de %s n'est pas possible. Contactez votre administrateur système pour l'installer.",
"<b>Note:</b> \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "<b>Attention : </b> \"%s\" n'est pas installé. Le montage de %s n'est pas possible. Contactez votre administrateur système pour l'installer.",
"You don't have any external storages" => "Vous n'avez pas de support de stockage externe",
"Name" => "Nom",
@@ -72,7 +72,7 @@ $TRANSLATIONS = array(
"Groups" => "Groupes",
"Users" => "Utilisateurs",
"Delete" => "Supprimer",
"Enable User External Storage" => "Activer le stockage externe pour les utilisateurs",
"Enable User External Storage" => "Autoriser les utilisateurs à ajouter des stockages externes",
"Allow users to mount the following external storage" => "Autorise les utilisateurs à monter les stockage externes suivants",
"SSL root certificates" => "Certificats racine SSL",
"Import Root Certificate" => "Importer un certificat racine"
+212 -145
View File
@@ -45,6 +45,10 @@ class AmazonS3 extends \OC\Files\Storage\Common {
* @var array
*/
private static $tmpFiles = array();
/**
* @var array
*/
private $params;
/**
* @var bool
*/
@@ -53,6 +57,10 @@ class AmazonS3 extends \OC\Files\Storage\Common {
* @var int
*/
private $timeout = 15;
/**
* @var int in seconds
*/
private $rescanDelay = 10;
/**
* @param string $path
@@ -68,72 +76,92 @@ class AmazonS3 extends \OC\Files\Storage\Common {
return $path;
}
/**
* when running the tests wait to let the buckets catch up
*/
private function testTimeout() {
if ($this->test) {
sleep($this->timeout);
}
}
private function isRoot($path) {
return $path === '.';
}
private function cleanKey($path) {
if ($path === '.') {
if ($this->isRoot($path)) {
return '/';
}
return $path;
}
public function __construct($params) {
if (!isset($params['key']) || !isset($params['secret']) || !isset($params['bucket'])) {
if (empty($params['key']) || empty($params['secret']) || empty($params['bucket'])) {
throw new \Exception("Access Key, Secret and Bucket have to be configured.");
}
$this->id = 'amazon::' . $params['key'] . md5($params['secret']);
$this->id = 'amazon::' . $params['bucket'];
$this->updateLegacyId($params);
$this->bucket = $params['bucket'];
$scheme = ($params['use_ssl'] === 'false') ? 'http' : 'https';
$this->test = isset($params['test']);
$this->timeout = ( ! isset($params['timeout'])) ? 15 : $params['timeout'];
$params['region'] = ( ! isset($params['region']) || $params['region'] === '' ) ? 'eu-west-1' : $params['region'];
$params['hostname'] = ( !isset($params['hostname']) || $params['hostname'] === '' ) ? 's3.amazonaws.com' : $params['hostname'];
$this->timeout = (!isset($params['timeout'])) ? 15 : $params['timeout'];
$this->rescanDelay = (!isset($params['rescanDelay'])) ? 10 : $params['rescanDelay'];
$params['region'] = empty($params['region']) ? 'eu-west-1' : $params['region'];
$params['hostname'] = empty($params['hostname']) ? 's3.amazonaws.com' : $params['hostname'];
if (!isset($params['port']) || $params['port'] === '') {
$params['port'] = ($params['use_ssl'] === 'false') ? 80 : 443;
}
$base_url = $scheme.'://'.$params['hostname'].':'.$params['port'].'/';
$this->params = $params;
}
$this->connection = S3Client::factory(array(
'key' => $params['key'],
'secret' => $params['secret'],
'base_url' => $base_url,
'region' => $params['region']
));
/**
* Updates old storage ids (v0.2.1 and older) that are based on key and secret to new ones based on the bucket name.
* TODO Do this in an update.php. requires iterating over all users and loading the mount.json from their home
*
* @param array $params
*/
public function updateLegacyId (array $params) {
$oldId = 'amazon::' . $params['key'] . md5($params['secret']);
if (!$this->connection->isValidBucketName($this->bucket)) {
throw new \Exception("The configured bucket name is invalid.");
// find by old id or bucket
$stmt = \OC::$server->getDatabaseConnection()->prepare(
'SELECT `numeric_id`, `id` FROM `*PREFIX*storages` WHERE `id` IN (?, ?)'
);
$stmt->execute(array($oldId, $this->id));
while ($row = $stmt->fetch()) {
$storages[$row['id']] = $row['numeric_id'];
}
if (!$this->connection->doesBucketExist($this->bucket)) {
try {
$result = $this->connection->createBucket(array(
'Bucket' => $this->bucket
));
$this->connection->waitUntilBucketExists(array(
'Bucket' => $this->bucket,
'waiter.interval' => 1,
'waiter.max_attempts' => 15
));
$this->testTimeout();
} catch (S3Exception $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
throw new \Exception("Creation of bucket failed.");
}
if (isset($storages[$this->id]) && isset($storages[$oldId])) {
// if both ids exist, delete the old storage and corresponding filecache entries
\OC\Files\Cache\Storage::remove($oldId);
} else if (isset($storages[$oldId])) {
// if only the old id exists do an update
$stmt = \OC::$server->getDatabaseConnection()->prepare(
'UPDATE `*PREFIX*storages` SET `id` = ? WHERE `id` = ?'
);
$stmt->execute(array($this->id, $oldId));
}
if (!$this->file_exists('.')) {
$result = $this->connection->putObject(array(
'Bucket' => $this->bucket,
'Key' => $this->cleanKey('.'),
'Body' => '',
'ContentType' => 'httpd/unix-directory',
'ContentLength' => 0
));
$this->testTimeout();
// only the bucket based id may exist, do nothing
}
/**
* Remove a file or folder
*
* @param string $path
* @return bool
*/
protected function remove($path) {
// remember fileType to reduce http calls
$fileType = $this->filetype($path);
if ($fileType === 'dir') {
return $this->rmdir($path);
} else if ($fileType === 'file') {
return $this->unlink($path);
} else {
return false;
}
}
@@ -145,16 +173,14 @@ class AmazonS3 extends \OC\Files\Storage\Common {
}
try {
$result = $this->connection->putObject(array(
$this->getConnection()->putObject(array(
'Bucket' => $this->bucket,
'Key' => $path . '/',
'Body' => '',
'ContentType' => 'httpd/unix-directory',
'ContentLength' => 0
'Key' => $path . '/',
'ContentType' => 'httpd/unix-directory'
));
$this->testTimeout();
} catch (S3Exception $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
\OCP\Util::logException('files_external', $e);
return false;
}
@@ -162,77 +188,75 @@ class AmazonS3 extends \OC\Files\Storage\Common {
}
public function file_exists($path) {
$path = $this->normalizePath($path);
if (!$path) {
$path = '.';
} else if ($path != '.' && $this->is_dir($path)) {
$path .= '/';
}
try {
$result = $this->connection->doesObjectExist(
$this->bucket,
$this->cleanKey($path)
);
} catch (S3Exception $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
return false;
}
return $result;
return $this->filetype($path) !== false;
}
public function rmdir($path) {
$path = $this->normalizePath($path);
if ($this->isRoot($path)) {
return $this->clearBucket();
}
if (!$this->file_exists($path)) {
return false;
}
$dh = $this->opendir($path);
if(is_resource($dh)) {
while (($file = readdir($dh)) !== false) {
if ($file === '.' || $file === '..') {
continue;
}
if ($this->is_dir($path . '/' . $file)) {
$this->rmdir($path . '/' . $file);
} else {
$this->unlink($path . '/' . $file);
}
}
}
return $this->batchDelete($path);
}
protected function clearBucket() {
try {
$result = $this->connection->deleteObject(array(
'Bucket' => $this->bucket,
'Key' => $path . '/'
));
$this->testTimeout();
$this->getConnection()->clearBucket($this->bucket);
return true;
// clearBucket() is not working with Ceph, so if it fails we try the slower approach
} catch (\Exception $e) {
return $this->batchDelete();
}
return false;
}
private function batchDelete ($path = null) {
$params = array(
'Bucket' => $this->bucket
);
if ($path !== null) {
$params['Prefix'] = $path . '/';
}
try {
// Since there are no real directories on S3, we need
// to delete all objects prefixed with the path.
do {
// instead of the iterator, manually loop over the list ...
$objects = $this->getConnection()->listObjects($params);
// ... so we can delete the files in batches
$this->getConnection()->deleteObjects(array(
'Bucket' => $this->bucket,
'Objects' => $objects['Contents']
));
$this->testTimeout();
// we reached the end when the list is no longer truncated
} while ($objects['IsTruncated']);
} catch (S3Exception $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
\OCP\Util::logException('files_external', $e);
return false;
}
return true;
}
public function opendir($path) {
$path = $this->normalizePath($path);
if ($path === '.') {
if ($this->isRoot($path)) {
$path = '';
} else if ($path) {
} else {
$path .= '/';
}
try {
$files = array();
$result = $this->connection->getIterator('ListObjects', array(
$result = $this->getConnection()->getIterator('ListObjects', array(
'Bucket' => $this->bucket,
'Delimiter' => '/',
'Prefix' => $path
@@ -242,17 +266,14 @@ class AmazonS3 extends \OC\Files\Storage\Common {
$file = basename(
isset($object['Key']) ? $object['Key'] : $object['Prefix']
);
if ($file != basename($path)) {
$files[] = $file;
}
$files[] = $file;
}
\OC\Files\Stream\Dir::register('amazons3' . $path, $files);
return opendir('fakedir://amazons3' . $path);
} catch (S3Exception $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
\OCP\Util::logException('files_external', $e);
return false;
}
}
@@ -261,27 +282,29 @@ class AmazonS3 extends \OC\Files\Storage\Common {
$path = $this->normalizePath($path);
try {
if ($this->is_dir($path) && $path != '.') {
$path .= '/';
}
$result = $this->connection->headObject(array(
'Bucket' => $this->bucket,
'Key' => $this->cleanKey($path)
));
$stat = array();
$stat['size'] = $result['ContentLength'] ? $result['ContentLength'] : 0;
if ($result['Metadata']['lastmodified']) {
$stat['mtime'] = strtotime($result['Metadata']['lastmodified']);
if ($this->is_dir($path)) {
//folders don't really exist
$stat['size'] = -1; //unknown
$stat['mtime'] = time() - $this->rescanDelay * 1000;
} else {
$stat['mtime'] = strtotime($result['LastModified']);
$result = $this->getConnection()->headObject(array(
'Bucket' => $this->bucket,
'Key' => $path
));
$stat['size'] = $result['ContentLength'] ? $result['ContentLength'] : 0;
if ($result['Metadata']['lastmodified']) {
$stat['mtime'] = strtotime($result['Metadata']['lastmodified']);
} else {
$stat['mtime'] = strtotime($result['LastModified']);
}
}
$stat['atime'] = time();
return $stat;
} catch(S3Exception $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
\OCP\Util::logException('files_external', $e);
return false;
}
}
@@ -289,19 +312,19 @@ class AmazonS3 extends \OC\Files\Storage\Common {
public function filetype($path) {
$path = $this->normalizePath($path);
if ($this->isRoot($path)) {
return 'dir';
}
try {
if ($path != '.' && $this->connection->doesObjectExist($this->bucket, $path)) {
if ($this->getConnection()->doesObjectExist($this->bucket, $path)) {
return 'file';
}
if ($path != '.') {
$path .= '/';
}
if ($this->connection->doesObjectExist($this->bucket, $this->cleanKey($path))) {
if ($this->getConnection()->doesObjectExist($this->bucket, $path.'/')) {
return 'dir';
}
} catch (S3Exception $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
\OCP\Util::logException('files_external', $e);
return false;
}
@@ -311,14 +334,18 @@ class AmazonS3 extends \OC\Files\Storage\Common {
public function unlink($path) {
$path = $this->normalizePath($path);
if ($this->is_dir($path)) {
return $this->rmdir($path);
}
try {
$result = $this->connection->deleteObject(array(
$this->getConnection()->deleteObject(array(
'Bucket' => $this->bucket,
'Key' => $this->cleanKey($path)
'Key' => $path
));
$this->testTimeout();
} catch (S3Exception $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
\OCP\Util::logException('files_external', $e);
return false;
}
@@ -335,13 +362,13 @@ class AmazonS3 extends \OC\Files\Storage\Common {
self::$tmpFiles[$tmpFile] = $path;
try {
$result = $this->connection->getObject(array(
$this->getConnection()->getObject(array(
'Bucket' => $this->bucket,
'Key' => $this->cleanKey($path),
'Key' => $path,
'SaveAs' => $tmpFile
));
} catch (S3Exception $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
\OCP\Util::logException('files_external', $e);
return false;
}
@@ -383,12 +410,12 @@ class AmazonS3 extends \OC\Files\Storage\Common {
return 'httpd/unix-directory';
} else if ($this->file_exists($path)) {
try {
$result = $this->connection->headObject(array(
$result = $this->getConnection()->headObject(array(
'Bucket' => $this->bucket,
'Key' => $this->cleanKey($path)
'Key' => $path
));
} catch (S3Exception $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
\OCP\Util::logException('files_external', $e);
return false;
}
@@ -405,12 +432,13 @@ class AmazonS3 extends \OC\Files\Storage\Common {
$metadata = array('lastmodified' => $mtime);
}
$fileType = $this->filetype($path);
try {
if ($this->file_exists($path)) {
if ($this->is_dir($path) && $path != '.') {
if ($fileType !== false) {
if ($fileType === 'dir' && ! $this->isRoot($path)) {
$path .= '/';
}
$result = $this->connection->copyObject(array(
$this->getConnection()->copyObject(array(
'Bucket' => $this->bucket,
'Key' => $this->cleanKey($path),
'Metadata' => $metadata,
@@ -418,15 +446,17 @@ class AmazonS3 extends \OC\Files\Storage\Common {
));
$this->testTimeout();
} else {
$result = $this->connection->putObject(array(
$mimeType = \OC_Helper::getMimetypeDetector()->detectPath($path);
$this->getConnection()->putObject(array(
'Bucket' => $this->bucket,
'Key' => $this->cleanKey($path),
'Metadata' => $metadata
'Metadata' => $metadata,
'ContentType' => $mimeType
));
$this->testTimeout();
}
} catch (S3Exception $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
\OCP\Util::logException('files_external', $e);
return false;
}
@@ -439,35 +469,33 @@ class AmazonS3 extends \OC\Files\Storage\Common {
if ($this->is_file($path1)) {
try {
$result = $this->connection->copyObject(array(
$this->getConnection()->copyObject(array(
'Bucket' => $this->bucket,
'Key' => $this->cleanKey($path2),
'CopySource' => S3Client::encodeKey($this->bucket . '/' . $path1)
));
$this->testTimeout();
} catch (S3Exception $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
\OCP\Util::logException('files_external', $e);
return false;
}
} else {
if ($this->file_exists($path2)) {
return false;
}
$this->remove($path2);
try {
$result = $this->connection->copyObject(array(
$this->getConnection()->copyObject(array(
'Bucket' => $this->bucket,
'Key' => $path2 . '/',
'CopySource' => S3Client::encodeKey($this->bucket . '/' . $path1 . '/')
));
$this->testTimeout();
} catch (S3Exception $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
\OCP\Util::logException('files_external', $e);
return false;
}
$dh = $this->opendir($path1);
if(is_resource($dh)) {
if (is_resource($dh)) {
while (($file = readdir($dh)) !== false) {
if ($file === '.' || $file === '..') {
continue;
@@ -488,6 +516,7 @@ class AmazonS3 extends \OC\Files\Storage\Common {
$path2 = $this->normalizePath($path2);
if ($this->is_file($path1)) {
if ($this->copy($path1, $path2) === false) {
return false;
}
@@ -497,9 +526,6 @@ class AmazonS3 extends \OC\Files\Storage\Common {
return false;
}
} else {
if ($this->file_exists($path2)) {
return false;
}
if ($this->copy($path1, $path2) === false) {
return false;
@@ -515,7 +541,7 @@ class AmazonS3 extends \OC\Files\Storage\Common {
}
public function test() {
$test = $this->connection->getBucketAcl(array(
$test = $this->getConnection()->getBucketAcl(array(
'Bucket' => $this->bucket,
));
if (isset($test) && !is_null($test->getPath('Owner/ID'))) {
@@ -528,7 +554,48 @@ class AmazonS3 extends \OC\Files\Storage\Common {
return $this->id;
}
/**
* Returns the connection
*
* @return S3Client connected client
* @throws \Exception if connection could not be made
*/
public function getConnection() {
if (!is_null($this->connection)) {
return $this->connection;
}
$scheme = ($this->params['use_ssl'] === 'false') ? 'http' : 'https';
$base_url = $scheme . '://' . $this->params['hostname'] . ':' . $this->params['port'] . '/';
$this->connection = S3Client::factory(array(
'key' => $this->params['key'],
'secret' => $this->params['secret'],
'base_url' => $base_url,
'region' => $this->params['region']
));
if (!$this->connection->isValidBucketName($this->bucket)) {
throw new \Exception("The configured bucket name is invalid.");
}
if (!$this->connection->doesBucketExist($this->bucket)) {
try {
$this->connection->createBucket(array(
'Bucket' => $this->bucket
));
$this->connection->waitUntilBucketExists(array(
'Bucket' => $this->bucket,
'waiter.interval' => 1,
'waiter.max_attempts' => 15
));
$this->testTimeout();
} catch (S3Exception $e) {
\OCP\Util::logException('files_external', $e);
throw new \Exception('Creation of bucket failed. '.$e->getMessage());
}
}
return $this->connection;
}
@@ -538,7 +605,7 @@ class AmazonS3 extends \OC\Files\Storage\Common {
}
try {
$result= $this->connection->putObject(array(
$this->getConnection()->putObject(array(
'Bucket' => $this->bucket,
'Key' => $this->cleanKey(self::$tmpFiles[$tmpFile]),
'SourceFile' => $tmpFile,
@@ -549,7 +616,7 @@ class AmazonS3 extends \OC\Files\Storage\Common {
unlink($tmpFile);
} catch (S3Exception $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
\OCP\Util::logException('files_external', $e);
return false;
}
}
+53 -1
View File
@@ -118,6 +118,30 @@ class OC_Mount_Config {
}
$manager->addMount($mount);
}
if ($data['user']) {
$user = \OC::$server->getUserManager()->get($data['user']);
if (!$user) {
\OC_Log::write(
'files_external',
'Cannot init external mount points for non-existant user "' . $data['user'] . '".',
\OC_Log::WARN
);
return;
}
$userView = new \OC\Files\View('/' . $user->getUID() . '/files');
$changePropagator = new \OC\Files\Cache\ChangePropagator($userView);
$etagPropagator = new \OCA\Files_External\EtagPropagator($user, $changePropagator, \OC::$server->getConfig());
$etagPropagator->propagateDirtyMountPoints();
\OCP\Util::connectHook(
\OC\Files\Filesystem::CLASSNAME,
\OC\Files\Filesystem::signal_create_mount,
$etagPropagator, 'updateHook');
\OCP\Util::connectHook(
\OC\Files\Filesystem::CLASSNAME,
\OC\Files\Filesystem::signal_delete_mount,
$etagPropagator, 'updateHook');
}
}
/**
@@ -169,6 +193,7 @@ class OC_Mount_Config {
foreach ($options as &$option) {
$option = self::setUserVars($user, $option);
}
$options['personal'] = false;
$options['options'] = self::decryptPasswords($options['options']);
if (!isset($options['priority'])) {
$options['priority'] = $backends[$options['class']]['priority'];
@@ -458,6 +483,7 @@ class OC_Mount_Config {
$priority = null) {
$backends = self::getBackends();
$mountPoint = OC\Files\Filesystem::normalizePath($mountPoint);
$relMountPoint = $mountPoint;
if ($mountPoint === '' || $mountPoint === '/') {
// can't mount at root folder
return false;
@@ -490,6 +516,10 @@ class OC_Mount_Config {
}
$mountPoints = self::readData($isPersonal ? OCP\User::getUser() : NULL);
// who else loves multi-dimensional array ?
$isNew = !isset($mountPoints[$mountType]) ||
!isset($mountPoints[$mountType][$applicable]) ||
!isset($mountPoints[$mountType][$applicable][$mountPoint]);
$mountPoints = self::mergeMountPoints($mountPoints, $mount, $mountType);
// Set default priority if none set
@@ -505,7 +535,19 @@ class OC_Mount_Config {
self::writeData($isPersonal ? OCP\User::getUser() : NULL, $mountPoints);
return self::getBackendStatus($class, $classOptions, $isPersonal);
$result = self::getBackendStatus($class, $classOptions, $isPersonal);
if ($result && $isNew) {
\OC_Hook::emit(
\OC\Files\Filesystem::CLASSNAME,
\OC\Files\Filesystem::signal_create_mount,
array(
\OC\Files\Filesystem::signal_param_path => $relMountPoint,
\OC\Files\Filesystem::signal_param_mount_type => $mountType,
\OC\Files\Filesystem::signal_param_users => $applicable,
)
);
}
return $result;
}
/**
@@ -518,6 +560,7 @@ class OC_Mount_Config {
*/
public static function removeMountPoint($mountPoint, $mountType, $applicable, $isPersonal = false) {
// Verify that the mount point applies for the current user
$relMountPoints = $mountPoint;
if ($isPersonal) {
if ($applicable != OCP\User::getUser()) {
return false;
@@ -538,6 +581,15 @@ class OC_Mount_Config {
}
}
self::writeData($isPersonal ? OCP\User::getUser() : NULL, $mountPoints);
\OC_Hook::emit(
\OC\Files\Filesystem::CLASSNAME,
\OC\Files\Filesystem::signal_delete_mount,
array(
\OC\Files\Filesystem::signal_param_path => $relMountPoints,
\OC\Files\Filesystem::signal_param_mount_type => $mountType,
\OC\Files\Filesystem::signal_param_users => $applicable,
)
);
return true;
}
+1
View File
@@ -44,6 +44,7 @@ class Dropbox extends \OC\Files\Storage\Common {
$this->id = 'dropbox::'.$params['app_key'] . $params['token']. '/' . $this->root;
$oauth = new \Dropbox_OAuth_Curl($params['app_key'], $params['app_secret']);
$oauth->setToken($params['token'], $params['token_secret']);
// note: Dropbox_API connection is lazy
$this->dropbox = new \Dropbox_API($oauth, 'auto');
} else {
throw new \Exception('Creating \OC\Files\Storage\Dropbox storage failed');
+126
View File
@@ -0,0 +1,126 @@
<?php
/**
* Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OCA\Files_External;
use OC\Files\Filesystem;
/**
* Updates the etag of parent folders whenever a new external storage mount
* point has been created or deleted. Updates need to be triggered using
* the updateHook() method.
*
* There are two modes of operation:
* - for personal mount points, the etag is propagated directly
* - for system mount points, a dirty flag is saved in the configuration and
* the etag will be updated the next time propagateDirtyMountPoints() is called
*/
class EtagPropagator {
/**
* @var \OCP\IUser
*/
protected $user;
/**
* @var \OC\Files\Cache\ChangePropagator
*/
protected $changePropagator;
/**
* @var \OCP\IConfig
*/
protected $config;
/**
* @param \OCP\IUser $user current user, must match the propagator's
* user
* @param \OC\Files\Cache\ChangePropagator $changePropagator change propagator
* initialized with a view for $user
* @param \OCP\IConfig $config
*/
public function __construct($user, $changePropagator, $config) {
$this->user = $user;
$this->changePropagator = $changePropagator;
$this->config = $config;
}
/**
* Propagate the etag changes for all mountpoints marked as dirty and mark the mountpoints as clean
*
* @param int $time
*/
public function propagateDirtyMountPoints($time = null) {
if ($time === null) {
$time = time();
}
$mountPoints = $this->getDirtyMountPoints();
foreach ($mountPoints as $mountPoint) {
$this->changePropagator->addChange($mountPoint);
$this->config->setUserValue($this->user->getUID(), 'files_external', $mountPoint, $time);
}
if (count($mountPoints)) {
$this->changePropagator->propagateChanges($time);
}
}
/**
* Get all mountpoints we need to update the etag for
*
* @return string[]
*/
protected function getDirtyMountPoints() {
$dirty = array();
$mountPoints = $this->config->getAppKeys('files_external');
foreach ($mountPoints as $mountPoint) {
if (substr($mountPoint, 0, 1) === '/') {
$updateTime = $this->config->getAppValue('files_external', $mountPoint);
$userTime = $this->config->getUserValue($this->user->getUID(), 'files_external', $mountPoint);
if ($updateTime > $userTime) {
$dirty[] = $mountPoint;
}
}
}
return $dirty;
}
/**
* @param string $mountPoint
* @param int $time
*/
protected function markDirty($mountPoint, $time = null) {
if ($time === null) {
$time = time();
}
$this->config->setAppValue('files_external', $mountPoint, $time);
}
/**
* Update etags for mount points for known user
* For global or group mount points, updating the etag for every user is not feasible
* instead we mark the mount point as dirty and update the etag when the filesystem is loaded for the user
* For personal mount points, the change is propagated directly
*
* @param array $params hook parameters
* @param int $time update time to use when marking a mount point as dirty
*/
public function updateHook($params, $time = null) {
if ($time === null) {
$time = time();
}
$users = $params[Filesystem::signal_param_users];
$type = $params[Filesystem::signal_param_mount_type];
$mountPoint = $params[Filesystem::signal_param_path];
$mountPoint = Filesystem::normalizePath($mountPoint);
if ($type === \OC_Mount_Config::MOUNT_TYPE_GROUP or $users === 'all') {
$this->markDirty($mountPoint, $time);
} else {
$this->changePropagator->addChange($mountPoint);
$this->changePropagator->propagateChanges($time);
}
}
}
+1 -1
View File
@@ -39,7 +39,7 @@ class FTP extends \OC\Files\Storage\StreamWrapper{
$this->root .= '/';
}
} else {
throw new \Exception();
throw new \Exception('Creating \OC\Files\Storage\FTP storage failed');
}
}
+1
View File
@@ -52,6 +52,7 @@ class Google extends \OC\Files\Storage\Common {
$client->setScopes(array('https://www.googleapis.com/auth/drive'));
$client->setUseObjects(true);
$client->setAccessToken($params['token']);
// note: API connection is lazy
$this->service = new \Google_DriveService($client);
$token = json_decode($params['token'], true);
$this->id = 'google::'.substr($params['client_id'], 0, 30).$token['created'];
+10 -2
View File
@@ -22,6 +22,14 @@ class OwnCloud extends \OC\Files\Storage\DAV{
// extract context path from host if specified
// (owncloud install path on host)
$host = $params['host'];
// strip protocol
if (substr($host, 0, 8) == "https://") {
$host = substr($host, 8);
$params['secure'] = true;
} else if (substr($host, 0, 7) == "http://") {
$host = substr($host, 7);
$params['secure'] = false;
}
$contextPath = '';
$hostSlashPos = strpos($host, '/');
if ($hostSlashPos !== false){
@@ -29,13 +37,13 @@ class OwnCloud extends \OC\Files\Storage\DAV{
$host = substr($host, 0, $hostSlashPos);
}
if (substr($contextPath , 1) !== '/'){
if (substr($contextPath, -1) !== '/'){
$contextPath .= '/';
}
if (isset($params['root'])){
$root = $params['root'];
if (substr($root, 1) !== '/'){
if (substr($root, 0, 1) !== '/'){
$root = '/' . $root;
}
}
+26 -13
View File
@@ -53,6 +53,18 @@ class SFTP extends \OC\Files\Storage\Common {
if (substr($this->root, -1, 1) != '/') {
$this->root .= '/';
}
}
/**
* Returns the connection.
*
* @return \Net_SFTP connected client instance
* @throws \Exception when the connection failed
*/
public function getConnection() {
if (!is_null($this->client)) {
return $this->client;
}
$hostKeys = $this->readHostKeys();
$this->client = new \Net_SFTP($this->host);
@@ -71,6 +83,7 @@ class SFTP extends \OC\Files\Storage\Common {
if (!$this->client->login($this->user, $this->password)) {
throw new \Exception('Login failed');
}
return $this->client;
}
public function test() {
@@ -81,7 +94,7 @@ class SFTP extends \OC\Files\Storage\Common {
) {
return false;
}
return $this->client->nlist() !== false;
return $this->getConnection()->nlist() !== false;
}
public function getId(){
@@ -149,7 +162,7 @@ class SFTP extends \OC\Files\Storage\Common {
public function mkdir($path) {
try {
return $this->client->mkdir($this->absPath($path));
return $this->getConnection()->mkdir($this->absPath($path));
} catch (\Exception $e) {
return false;
}
@@ -157,7 +170,7 @@ class SFTP extends \OC\Files\Storage\Common {
public function rmdir($path) {
try {
return $this->client->delete($this->absPath($path), true);
return $this->getConnection()->delete($this->absPath($path), true);
} catch (\Exception $e) {
return false;
}
@@ -165,7 +178,7 @@ class SFTP extends \OC\Files\Storage\Common {
public function opendir($path) {
try {
$list = $this->client->nlist($this->absPath($path));
$list = $this->getConnection()->nlist($this->absPath($path));
$id = md5('sftp:' . $path);
$dirStream = array();
@@ -183,7 +196,7 @@ class SFTP extends \OC\Files\Storage\Common {
public function filetype($path) {
try {
$stat = $this->client->stat($this->absPath($path));
$stat = $this->getConnection()->stat($this->absPath($path));
if ($stat['type'] == NET_SFTP_TYPE_REGULAR) {
return 'file';
}
@@ -199,7 +212,7 @@ class SFTP extends \OC\Files\Storage\Common {
public function file_exists($path) {
try {
return $this->client->stat($this->absPath($path)) !== false;
return $this->getConnection()->stat($this->absPath($path)) !== false;
} catch (\Exception $e) {
return false;
}
@@ -207,7 +220,7 @@ class SFTP extends \OC\Files\Storage\Common {
public function unlink($path) {
try {
return $this->client->delete($this->absPath($path), true);
return $this->getConnection()->delete($this->absPath($path), true);
} catch (\Exception $e) {
return false;
}
@@ -234,7 +247,7 @@ class SFTP extends \OC\Files\Storage\Common {
case 'x+':
case 'c':
case 'c+':
$context = stream_context_create(array('sftp' => array('session' => $this->client)));
$context = stream_context_create(array('sftp' => array('session' => $this->getConnection())));
return fopen($this->constructUrl($path), $mode, false, $context);
}
} catch (\Exception $e) {
@@ -248,7 +261,7 @@ class SFTP extends \OC\Files\Storage\Common {
return false;
}
if (!$this->file_exists($path)) {
$this->client->put($this->absPath($path), '');
$this->getConnection()->put($this->absPath($path), '');
} else {
return false;
}
@@ -259,11 +272,11 @@ class SFTP extends \OC\Files\Storage\Common {
}
public function getFile($path, $target) {
$this->client->get($path, $target);
$this->getConnection()->get($path, $target);
}
public function uploadFile($path, $target) {
$this->client->put($target, $path, NET_SFTP_LOCAL_FILE);
$this->getConnection()->put($target, $path, NET_SFTP_LOCAL_FILE);
}
public function rename($source, $target) {
@@ -271,7 +284,7 @@ class SFTP extends \OC\Files\Storage\Common {
if (!$this->is_dir($target) && $this->file_exists($target)) {
$this->unlink($target);
}
return $this->client->rename(
return $this->getConnection()->rename(
$this->absPath($source),
$this->absPath($target)
);
@@ -282,7 +295,7 @@ class SFTP extends \OC\Files\Storage\Common {
public function stat($path) {
try {
$stat = $this->client->stat($this->absPath($path));
$stat = $this->getConnection()->stat($this->absPath($path));
$mtime = $stat ? $stat['mtime'] : -1;
$size = $stat ? $stat['size'] : 0;
+36 -6
View File
@@ -13,14 +13,24 @@ require_once __DIR__ . '/../3rdparty/smb4php/smb.php';
class SMB_OC extends \OC\Files\Storage\SMB {
private $username_as_share;
/**
* @param array $params
* @throws \Exception
*/
public function __construct($params) {
if (isset($params['host']) && \OC::$session->exists('smb-credentials')) {
if (isset($params['host'])) {
$host=$params['host'];
$this->username_as_share = ($params['username_as_share'] === 'true');
$params_auth = \OC::$session->get('smb-credentials');
$user = \OC::$session->get('loginname');
$password = $params_auth['password'];
$user = 'foo';
$password = 'bar';
if (\OC::$session->exists('smb-credentials')) {
$params_auth = json_decode(\OC::$server->getCrypto()->decrypt(\OC::$session->get('smb-credentials')), true);
$user = \OC::$session->get('loginname');
$password = $params_auth['password'];
} else {
// assume we are testing from the admin section
}
$root=isset($params['root'])?$params['root']:'/';
$share = '';
@@ -44,14 +54,34 @@ class SMB_OC extends \OC\Files\Storage\SMB {
}
}
public static function login( $params ) {
\OC::$session->set('smb-credentials', $params);
/**
* Intercepts the user credentials on login and stores them
* encrypted inside the session if SMB_OC storage is enabled.
* @param array $params
*/
public static function login($params) {
$mountpoints = \OC_Mount_Config::getAbsoluteMountPoints($params['uid']);
$mountpointClasses = array();
foreach($mountpoints as $mountpoint) {
$mountpointClasses[$mountpoint['class']] = true;
}
if(isset($mountpointClasses['\OC\Files\Storage\SMB_OC'])) {
\OC::$session->set('smb-credentials', \OC::$server->getCrypto()->encrypt(json_encode($params)));
}
}
/**
* @param string $path
* @return boolean
*/
public function isSharable($path) {
return false;
}
/**
* @param bool $isPersonal
* @return bool
*/
public function test($isPersonal = true) {
if ($isPersonal) {
if ($this->stat('')) {
+77 -45
View File
@@ -47,6 +47,12 @@ class Swift extends \OC\Files\Storage\Common {
* @var string
*/
private $bucket;
/**
* Connection parameters
*
* @var array
*/
private $params;
/**
* @var array
*/
@@ -84,7 +90,7 @@ class Swift extends \OC\Files\Storage\Common {
*/
private function doesObjectExist($path) {
try {
$this->container->getPartialObject($path);
$this->getContainer()->getPartialObject($path);
return true;
} catch (ClientErrorResponseException $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
@@ -110,37 +116,7 @@ class Swift extends \OC\Files\Storage\Common {
$params['service_name'] = 'cloudFiles';
}
$settings = array(
'username' => $params['user'],
);
if (isset($params['password'])) {
$settings['password'] = $params['password'];
} else if (isset($params['key'])) {
$settings['apiKey'] = $params['key'];
}
if (isset($params['tenant'])) {
$settings['tenantName'] = $params['tenant'];
}
if (isset($params['timeout'])) {
$settings['timeout'] = $params['timeout'];
}
$this->anchor = new OpenStack($params['url'], $settings);
$this->connection = $this->anchor->objectStoreService($params['service_name'], $params['region']);
try {
$this->container = $this->connection->getContainer($this->bucket);
} catch (ClientErrorResponseException $e) {
$this->container = $this->connection->createContainer($this->bucket);
}
if (!$this->file_exists('.')) {
$this->mkdir('.');
}
$this->params = $params;
}
public function mkdir($path) {
@@ -158,7 +134,7 @@ class Swift extends \OC\Files\Storage\Common {
$customHeaders = array('content-type' => 'httpd/unix-directory');
$metadataHeaders = DataObject::stockHeaders(array());
$allHeaders = $customHeaders + $metadataHeaders;
$this->container->uploadObject($path, '', $allHeaders);
$this->getContainer()->uploadObject($path, '', $allHeaders);
} catch (Exceptions\CreateUpdateError $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
return false;
@@ -198,7 +174,7 @@ class Swift extends \OC\Files\Storage\Common {
}
try {
$this->container->dataObject()->setName($path . '/')->delete();
$this->getContainer()->dataObject()->setName($path . '/')->delete();
} catch (Exceptions\DeleteError $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
return false;
@@ -221,7 +197,7 @@ class Swift extends \OC\Files\Storage\Common {
try {
$files = array();
/** @var OpenCloud\Common\Collection $objects */
$objects = $this->container->objectList(array(
$objects = $this->getContainer()->objectList(array(
'prefix' => $path,
'delimiter' => '/'
));
@@ -251,7 +227,7 @@ class Swift extends \OC\Files\Storage\Common {
}
try {
$object = $this->container->getPartialObject($path);
$object = $this->getContainer()->getPartialObject($path);
} catch (ClientErrorResponseException $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
return false;
@@ -304,7 +280,7 @@ class Swift extends \OC\Files\Storage\Common {
}
try {
$this->container->dataObject()->setName($path)->delete();
$this->getContainer()->dataObject()->setName($path)->delete();
} catch (ClientErrorResponseException $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
return false;
@@ -322,7 +298,7 @@ class Swift extends \OC\Files\Storage\Common {
$tmpFile = \OC_Helper::tmpFile();
self::$tmpFiles[$tmpFile] = $path;
try {
$object = $this->container->getObject($path);
$object = $this->getContainer()->getObject($path);
} catch (ClientErrorResponseException $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
return false;
@@ -375,7 +351,7 @@ class Swift extends \OC\Files\Storage\Common {
if ($this->is_dir($path)) {
return 'httpd/unix-directory';
} else if ($this->file_exists($path)) {
$object = $this->container->getPartialObject($path);
$object = $this->getContainer()->getPartialObject($path);
return $object->getContentType();
}
return false;
@@ -392,14 +368,15 @@ class Swift extends \OC\Files\Storage\Common {
$path .= '/';
}
$object = $this->container->getPartialObject($path);
$object = $this->getContainer()->getPartialObject($path);
$object->saveMetadata($metadata);
return true;
} else {
$customHeaders = array('content-type' => 'text/plain');
$mimeType = \OC_Helper::getMimetypeDetector()->detectPath($path);
$customHeaders = array('content-type' => $mimeType);
$metadataHeaders = DataObject::stockHeaders($metadata);
$allHeaders = $customHeaders + $metadataHeaders;
$this->container->uploadObject($path, '', $allHeaders);
$this->getContainer()->uploadObject($path, '', $allHeaders);
return true;
}
}
@@ -415,7 +392,7 @@ class Swift extends \OC\Files\Storage\Common {
$this->unlink($path2);
try {
$source = $this->container->getPartialObject($path1);
$source = $this->getContainer()->getPartialObject($path1);
$source->copy($this->bucket.'/'.$path2);
} catch (ClientErrorResponseException $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
@@ -428,7 +405,7 @@ class Swift extends \OC\Files\Storage\Common {
$this->unlink($path2);
try {
$source = $this->container->getPartialObject($path1 . '/');
$source = $this->getContainer()->getPartialObject($path1 . '/');
$source->copy($this->bucket.'/'.$path2 . '/');
} catch (ClientErrorResponseException $e) {
\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
@@ -486,16 +463,71 @@ class Swift extends \OC\Files\Storage\Common {
return $this->id;
}
/**
* Returns the connection
*
* @return OpenCloud\ObjectStore\Service connected client
* @throws \Exception if connection could not be made
*/
public function getConnection() {
if (!is_null($this->connection)) {
return $this->connection;
}
$settings = array(
'username' => $this->params['user'],
);
if (!empty($this->params['password'])) {
$settings['password'] = $this->params['password'];
} else if (!empty($this->params['key'])) {
$settings['apiKey'] = $this->params['key'];
}
if (!empty($this->params['tenant'])) {
$settings['tenantName'] = $this->params['tenant'];
}
if (!empty($this->params['timeout'])) {
$settings['timeout'] = $this->params['timeout'];
}
$this->anchor = new OpenStack($this->params['url'], $settings);
$this->connection = $this->anchor->objectStoreService($this->params['service_name'], $this->params['region']);
return $this->connection;
}
/**
* Returns the initialized object store container.
*
* @return OpenCloud\ObjectStore\Resource\Container
*/
public function getContainer() {
if (!is_null($this->container)) {
return $this->container;
}
try {
$this->container = $this->getConnection()->getContainer($this->bucket);
} catch (ClientErrorResponseException $e) {
$this->container = $this->getConnection()->createContainer($this->bucket);
}
if (!$this->file_exists('.')) {
$this->mkdir('.');
}
return $this->container;
}
public function writeBack($tmpFile) {
if (!isset(self::$tmpFiles[$tmpFile])) {
return false;
}
$fileData = fopen($tmpFile, 'r');
$this->container->uploadObject(self::$tmpFiles[$tmpFile], $fileData);
$this->getContainer()->uploadObject(self::$tmpFiles[$tmpFile], $fileData);
unlink($tmpFile);
}
Executable → Regular
View File
+3 -5
View File
@@ -23,9 +23,10 @@
OC_Util::checkAdminUser();
OCP\Util::addScript('files_external', 'settings');
OCP\Util::addscript('3rdparty', 'chosen/chosen.jquery.min');
OCP\Util::addStyle('files_external', 'settings');
OCP\Util::addStyle('3rdparty', 'chosen/chosen');
OCP\Util::addScript('core', 'select2/select2');
OCP\Util::addStyle('core', 'select2/select2');
$backends = OC_Mount_Config::getBackends();
$personal_backends = array();
@@ -46,9 +47,6 @@ $tmpl->assign('isAdminPage', true);
$tmpl->assign('mounts', OC_Mount_Config::getSystemMountPoints());
$tmpl->assign('backends', $backends);
$tmpl->assign('personal_backends', $personal_backends);
$tmpl->assign('groups', OC_Group::getGroups());
$tmpl->assign('users', OCP\User::getUsers());
$tmpl->assign('userDisplayNames', OC_User::getDisplayNames());
$tmpl->assign('dependencies', OC_Mount_Config::checkDependencies());
$tmpl->assign('allowUserMounting', OCP\Config::getAppValue('files_external', 'allow_user_mounting', 'yes'));
return $tmpl->fetchPage();
+2 -25
View File
@@ -88,31 +88,8 @@
print_unescaped(json_encode($mount['applicable']['groups'])); ?>'
data-applicable-users='<?php if (isset($mount['applicable']['users']))
print_unescaped(json_encode($mount['applicable']['users'])); ?>'>
<select class="chzn-select"
multiple style="width:20em;"
data-placeholder="<?php p($l->t('No user or group')); ?>">
<option value="all"
<?php if (empty($mount['class']) || (isset($mount['applicable']['users']) && in_array('all', $mount['applicable']['users']))) print_unescaped('selected="selected"');?> >
<?php p($l->t('All Users')); ?>
</option>
<optgroup label="<?php p($l->t('Groups')); ?>">
<?php foreach ($_['groups'] as $group): ?>
<option value="<?php p($group); ?>(group)"
<?php if (isset($mount['applicable']['groups']) && in_array($group, $mount['applicable']['groups'])): ?>
selected="selected"
<?php endif; ?>><?php p($group); ?></option>
<?php endforeach; ?>
</optgroup>
<optgroup label="<?php p($l->t('Users')); ?>">
<?php foreach ($_['users'] as $user): ?>
<option value="<?php p($user); ?>"
<?php if (isset($mount['applicable']['users']) && in_array($user, $mount['applicable']['users'])): ?>
selected="selected"
<?php endif; ?>><?php p($_['userDisplayNames'][$user]); ?></option>
<?php endforeach; ?>
</optgroup>
</select>
</td>
<input type="hidden" class="applicableUsers" style="width:20em;" value=""/>
</td>
<?php endif; ?>
<td <?php if (isset($mount['mountpoint'])): ?>class="remove"
<?php else: ?>style="visibility:hidden;"
+5 -23
View File
@@ -38,29 +38,11 @@ class AmazonS3 extends Storage {
public function tearDown() {
if ($this->instance) {
$connection = $this->instance->getConnection();
try {
// NOTE(berendt): clearBucket() is not working with Ceph
$iterator = $connection->getIterator('ListObjects', array(
'Bucket' => $this->config['amazons3']['bucket']
));
foreach ($iterator as $object) {
$connection->deleteObject(array(
'Bucket' => $this->config['amazons3']['bucket'],
'Key' => $object['Key']
));
}
} catch (S3Exception $e) {
}
$connection->deleteBucket(array(
'Bucket' => $this->config['amazons3']['bucket']
));
//wait some seconds for completing the replication
sleep(30);
$this->instance->rmdir('');
}
}
public function testStat() {
$this->markTestSkipped('S3 doesn\'t update the parents folder mtime');
}
}
@@ -0,0 +1,117 @@
<?php
/**
* ownCloud
*
* @author Jörn Friedrich Dreyer
* @copyright 2012 Jörn Friedrich Dreyer jfd@owncloud.com
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Test\Files\Storage;
class AmazonS3Migration extends \PHPUnit_Framework_TestCase {
/**
* @var \OC\Files\Storage\Storage instance
*/
protected $instance;
public function setUp () {
$uuid = uniqid();
$this->params['key'] = 'key'.$uuid;
$this->params['secret'] = 'secret'.$uuid;
$this->params['bucket'] = 'bucket'.$uuid;
$this->oldId = 'amazon::' . $this->params['key'] . md5($this->params['secret']);
$this->newId = 'amazon::' . $this->params['bucket'];
}
public function tearDown () {
$this->deleteStorage($this->oldId);
$this->deleteStorage($this->newId);
}
public function testUpdateLegacyOnlyId () {
// add storage ids
$oldCache = new \OC\Files\Cache\Cache($this->oldId);
// add file to old cache
$fileId = $oldCache->put('/', array('size' => 0, 'mtime' => time(), 'mimetype' => 'httpd/directory'));
try {
$this->instance = new \OC\Files\Storage\AmazonS3($this->params);
} catch (\Exception $e) {
//ignore
}
$storages = $this->getStorages();
$this->assertTrue(isset($storages[$this->newId]));
$this->assertFalse(isset($storages[$this->oldId]));
$this->assertSame((int)$oldCache->getNumericStorageId(), (int)$storages[$this->newId]);
list($storageId, $path) = \OC\Files\Cache\Cache::getById($fileId);
$this->assertSame($this->newId, $storageId);
$this->assertSame('/', $path);
}
public function testUpdateLegacyAndNewId () {
// add storage ids
$oldCache = new \OC\Files\Cache\Cache($this->oldId);
new \OC\Files\Cache\Cache($this->newId);
// add file to old cache
$fileId = $oldCache->put('/', array('size' => 0, 'mtime' => time(), 'mimetype' => 'httpd/directory'));
try {
$this->instance = new \OC\Files\Storage\AmazonS3($this->params);
} catch (\Exception $e) {
//ignore
}
$storages = $this->getStorages();
$this->assertTrue(isset($storages[$this->newId]));
$this->assertFalse(isset($storages[$this->oldId]));
$this->assertNull(\OC\Files\Cache\Cache::getById($fileId), 'old filecache has not been cleared');
}
/**
* @param $storages
* @return array
*/
public function getStorages() {
$storages = array();
$stmt = \OC::$server->getDatabaseConnection()->prepare(
'SELECT `numeric_id`, `id` FROM `*PREFIX*storages` WHERE `id` IN (?, ?)'
);
$stmt->execute(array($this->oldId, $this->newId));
while ($row = $stmt->fetch()) {
$storages[$row['id']] = $row['numeric_id'];
}
return $storages;
}
public function deleteStorage($id) {
$stmt = \OC::$server->getDatabaseConnection()->prepare(
'DELETE FROM `*PREFIX*storages` WHERE `id` = ?'
);
$stmt->execute(array($id));
}
}
@@ -0,0 +1,328 @@
<?php
/**
* Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace Tests\Files_External;
use OC\Files\Filesystem;
use OC\User\User;
class EtagPropagator extends \PHPUnit_Framework_TestCase {
protected function getUser() {
return new User(uniqid(), null);
}
/**
* @return \PHPUnit_Framework_MockObject_MockObject | \OC\Files\Cache\ChangePropagator
*/
protected function getChangePropagator() {
return $this->getMockBuilder('\OC\Files\Cache\ChangePropagator')
->disableOriginalConstructor()
->getMock();
}
/**
* @return \PHPUnit_Framework_MockObject_MockObject | \OCP\IConfig
*/
protected function getConfig() {
$appConfig = array();
$userConfig = array();
$mock = $this->getMockBuilder('\OCP\IConfig')
->disableOriginalConstructor()
->getMock();
$mock->expects($this->any())
->method('getAppValue')
->will($this->returnCallback(function ($appId, $key, $default = null) use (&$appConfig) {
if (isset($appConfig[$appId]) and isset($appConfig[$appId][$key])) {
return $appConfig[$appId][$key];
} else {
return $default;
}
}));
$mock->expects($this->any())
->method('setAppValue')
->will($this->returnCallback(function ($appId, $key, $value) use (&$appConfig) {
if (!isset($appConfig[$appId])) {
$appConfig[$appId] = array();
}
$appConfig[$appId][$key] = $value;
}));
$mock->expects($this->any())
->method('getAppKeys')
->will($this->returnCallback(function ($appId) use (&$appConfig) {
if (!isset($appConfig[$appId])) {
$appConfig[$appId] = array();
}
return array_keys($appConfig[$appId]);
}));
$mock->expects($this->any())
->method('getUserValue')
->will($this->returnCallback(function ($userId, $appId, $key, $default = null) use (&$userConfig) {
if (isset($userConfig[$userId]) and isset($userConfig[$userId][$appId]) and isset($userConfig[$userId][$appId][$key])) {
return $userConfig[$userId][$appId][$key];
} else {
return $default;
}
}));
$mock->expects($this->any())
->method('setUserValue')
->will($this->returnCallback(function ($userId, $appId, $key, $value) use (&$userConfig) {
if (!isset($userConfig[$userId])) {
$userConfig[$userId] = array();
}
if (!isset($userConfig[$userId][$appId])) {
$userConfig[$userId][$appId] = array();
}
$userConfig[$userId][$appId][$key] = $value;
}));
return $mock;
}
public function testSingleUserMount() {
$time = time();
$user = $this->getUser();
$config = $this->getConfig();
$changePropagator = $this->getChangePropagator();
$propagator = new \OCA\Files_External\EtagPropagator($user, $changePropagator, $config);
$changePropagator->expects($this->once())
->method('addChange')
->with('/test');
$changePropagator->expects($this->once())
->method('propagateChanges')
->with($time);
$propagator->updateHook(array(
Filesystem::signal_param_path => '/test',
Filesystem::signal_param_mount_type => \OC_Mount_Config::MOUNT_TYPE_USER,
Filesystem::signal_param_users => $user->getUID(),
), $time);
}
public function testGlobalMountNoDirectUpdate() {
$time = time();
$user = $this->getUser();
$config = $this->getConfig();
$changePropagator = $this->getChangePropagator();
$propagator = new \OCA\Files_External\EtagPropagator($user, $changePropagator, $config);
// not updated directly
$changePropagator->expects($this->never())
->method('addChange');
$changePropagator->expects($this->never())
->method('propagateChanges');
$propagator->updateHook(array(
Filesystem::signal_param_path => '/test',
Filesystem::signal_param_mount_type => \OC_Mount_Config::MOUNT_TYPE_USER,
Filesystem::signal_param_users => 'all',
), $time);
// mount point marked as dirty
$this->assertEquals(array('/test'), $config->getAppKeys('files_external'));
$this->assertEquals($time, $config->getAppValue('files_external', '/test'));
}
public function testGroupMountNoDirectUpdate() {
$time = time();
$user = $this->getUser();
$config = $this->getConfig();
$changePropagator = $this->getChangePropagator();
$propagator = new \OCA\Files_External\EtagPropagator($user, $changePropagator, $config);
// not updated directly
$changePropagator->expects($this->never())
->method('addChange');
$changePropagator->expects($this->never())
->method('propagateChanges');
$propagator->updateHook(array(
Filesystem::signal_param_path => '/test',
Filesystem::signal_param_mount_type => \OC_Mount_Config::MOUNT_TYPE_GROUP,
Filesystem::signal_param_users => 'test',
), $time);
// mount point marked as dirty
$this->assertEquals(array('/test'), $config->getAppKeys('files_external'));
$this->assertEquals($time, $config->getAppValue('files_external', '/test'));
}
public function testGlobalMountNoDirtyMountPoint() {
$time = time();
$user = $this->getUser();
$config = $this->getConfig();
$changePropagator = $this->getChangePropagator();
$propagator = new \OCA\Files_External\EtagPropagator($user, $changePropagator, $config);
$changePropagator->expects($this->never())
->method('addChange');
$changePropagator->expects($this->never())
->method('propagateChanges');
$propagator->propagateDirtyMountPoints($time);
$this->assertEquals(0, $config->getUserValue($user->getUID(), 'files_external', '/test', 0));
}
public function testGlobalMountDirtyMountPointFirstTime() {
$time = time();
$user = $this->getUser();
$config = $this->getConfig();
$changePropagator = $this->getChangePropagator();
$propagator = new \OCA\Files_External\EtagPropagator($user, $changePropagator, $config);
$config->setAppValue('files_external', '/test', $time - 10);
$changePropagator->expects($this->once())
->method('addChange')
->with('/test');
$changePropagator->expects($this->once())
->method('propagateChanges')
->with($time);
$propagator->propagateDirtyMountPoints($time);
$this->assertEquals($time, $config->getUserValue($user->getUID(), 'files_external', '/test'));
}
public function testGlobalMountNonDirtyMountPoint() {
$time = time();
$user = $this->getUser();
$config = $this->getConfig();
$changePropagator = $this->getChangePropagator();
$propagator = new \OCA\Files_External\EtagPropagator($user, $changePropagator, $config);
$config->setAppValue('files_external', '/test', $time - 10);
$config->setUserValue($user->getUID(), 'files_external', '/test', $time - 10);
$changePropagator->expects($this->never())
->method('addChange');
$changePropagator->expects($this->never())
->method('propagateChanges');
$propagator->propagateDirtyMountPoints($time);
$this->assertEquals($time - 10, $config->getUserValue($user->getUID(), 'files_external', '/test'));
}
public function testGlobalMountNonDirtyMountPointOtherUser() {
$time = time();
$user = $this->getUser();
$user2 = $this->getUser();
$config = $this->getConfig();
$changePropagator = $this->getChangePropagator();
$propagator = new \OCA\Files_External\EtagPropagator($user, $changePropagator, $config);
$config->setAppValue('files_external', '/test', $time - 10);
$config->setUserValue($user2->getUID(), 'files_external', '/test', $time - 10);
$changePropagator->expects($this->once())
->method('addChange')
->with('/test');
$changePropagator->expects($this->once())
->method('propagateChanges')
->with($time);
$propagator->propagateDirtyMountPoints($time);
$this->assertEquals($time, $config->getUserValue($user->getUID(), 'files_external', '/test'));
}
public function testGlobalMountDirtyMountPointSecondTime() {
$time = time();
$user = $this->getUser();
$config = $this->getConfig();
$changePropagator = $this->getChangePropagator();
$propagator = new \OCA\Files_External\EtagPropagator($user, $changePropagator, $config);
$config->setAppValue('files_external', '/test', $time - 10);
$config->setUserValue($user->getUID(), 'files_external', '/test', $time - 20);
$changePropagator->expects($this->once())
->method('addChange')
->with('/test');
$changePropagator->expects($this->once())
->method('propagateChanges')
->with($time);
$propagator->propagateDirtyMountPoints($time);
$this->assertEquals($time, $config->getUserValue($user->getUID(), 'files_external', '/test'));
}
public function testGlobalMountMultipleUsers() {
$time = time();
$config = $this->getConfig();
$user1 = $this->getUser();
$user2 = $this->getUser();
$user3 = $this->getUser();
$changePropagator1 = $this->getChangePropagator();
$changePropagator2 = $this->getChangePropagator();
$changePropagator3 = $this->getChangePropagator();
$propagator1 = new \OCA\Files_External\EtagPropagator($user1, $changePropagator1, $config);
$propagator2 = new \OCA\Files_External\EtagPropagator($user2, $changePropagator2, $config);
$propagator3 = new \OCA\Files_External\EtagPropagator($user3, $changePropagator3, $config);
$config->setAppValue('files_external', '/test', $time - 10);
$changePropagator1->expects($this->once())
->method('addChange')
->with('/test');
$changePropagator1->expects($this->once())
->method('propagateChanges')
->with($time);
$propagator1->propagateDirtyMountPoints($time);
$this->assertEquals($time, $config->getUserValue($user1->getUID(), 'files_external', '/test'));
$this->assertEquals(0, $config->getUserValue($user2->getUID(), 'files_external', '/test', 0));
$this->assertEquals(0, $config->getUserValue($user3->getUID(), 'files_external', '/test', 0));
$changePropagator2->expects($this->once())
->method('addChange')
->with('/test');
$changePropagator2->expects($this->once())
->method('propagateChanges')
->with($time);
$propagator2->propagateDirtyMountPoints($time);
$this->assertEquals($time, $config->getUserValue($user1->getUID(), 'files_external', '/test'));
$this->assertEquals($time, $config->getUserValue($user2->getUID(), 'files_external', '/test', 0));
$this->assertEquals(0, $config->getUserValue($user3->getUID(), 'files_external', '/test', 0));
}
public function testGlobalMountMultipleDirtyMountPoints() {
$time = time();
$user = $this->getUser();
$config = $this->getConfig();
$changePropagator = $this->getChangePropagator();
$propagator = new \OCA\Files_External\EtagPropagator($user, $changePropagator, $config);
$config->setAppValue('files_external', '/test', $time - 10);
$config->setAppValue('files_external', '/foo', $time - 50);
$config->setAppValue('files_external', '/bar', $time - 70);
$config->setUserValue($user->getUID(), 'files_external', '/foo', $time - 70);
$config->setUserValue($user->getUID(), 'files_external', '/bar', $time - 70);
$changePropagator->expects($this->exactly(2))
->method('addChange');
$changePropagator->expects($this->once())
->method('propagateChanges')
->with($time);
$propagator->propagateDirtyMountPoints($time);
$this->assertEquals($time, $config->getUserValue($user->getUID(), 'files_external', '/test'));
$this->assertEquals($time, $config->getUserValue($user->getUID(), 'files_external', '/foo'));
$this->assertEquals($time - 70, $config->getUserValue($user->getUID(), 'files_external', '/bar'));
}
}
+134 -2
View File
@@ -20,14 +20,48 @@
*
*/
require_once __DIR__ . '/../../../lib/base.php';
class Test_Mount_Config_Dummy_Storage {
public function test() {
return true;
}
}
class Test_Mount_Config_Hook_Test {
static $signal;
static $params;
public static function setUpHooks() {
self::clear();
\OCP\Util::connectHook(
\OC\Files\Filesystem::CLASSNAME,
\OC\Files\Filesystem::signal_create_mount,
'\Test_Mount_Config_Hook_Test', 'createHookCallback');
\OCP\Util::connectHook(
\OC\Files\Filesystem::CLASSNAME,
\OC\Files\Filesystem::signal_delete_mount,
'\Test_Mount_Config_Hook_Test', 'deleteHookCallback');
}
public static function clear() {
self::$signal = null;
self::$params = null;
}
public static function createHookCallback($params) {
self::$signal = \OC\Files\Filesystem::signal_create_mount;
self::$params = $params;
}
public static function deleteHookCallback($params) {
self::$signal = \OC\Files\Filesystem::signal_delete_mount;
self::$params = $params;
}
public static function getLastCall() {
return array(self::$signal, self::$params);
}
}
/**
* Class Test_Mount_Config
*/
@@ -79,9 +113,11 @@ class Test_Mount_Config extends \PHPUnit_Framework_TestCase {
);
OC_Mount_Config::$skipTest = true;
Test_Mount_Config_Hook_Test::setupHooks();
}
public function tearDown() {
Test_Mount_Config_Hook_Test::clear();
OC_Mount_Config::$skipTest = false;
\OC_User::deleteUser(self::TEST_USER2);
@@ -329,6 +365,102 @@ class Test_Mount_Config extends \PHPUnit_Framework_TestCase {
$this->assertEquals(array_keys($options), array_keys($savedOptions));
}
public function testHooks() {
$mountPoint = '/test';
$mountType = 'user';
$applicable = 'all';
$isPersonal = false;
$mountConfig = array(
'host' => 'smbhost',
'user' => 'smbuser',
'password' => 'smbpassword',
'share' => 'smbshare',
'root' => 'smbroot'
);
// write config
$this->assertTrue(
OC_Mount_Config::addMountPoint(
$mountPoint,
'\OC\Files\Storage\SMB',
$mountConfig,
$mountType,
$applicable,
$isPersonal
)
);
list($hookName, $params) = Test_Mount_Config_Hook_Test::getLastCall();
$this->assertEquals(
\OC\Files\Filesystem::signal_create_mount,
$hookName
);
$this->assertEquals(
$mountPoint,
$params[\OC\Files\Filesystem::signal_param_path]
);
$this->assertEquals(
$mountType,
$params[\OC\Files\Filesystem::signal_param_mount_type]
);
$this->assertEquals(
$applicable,
$params[\OC\Files\Filesystem::signal_param_users]
);
Test_Mount_Config_Hook_Test::clear();
// edit
$mountConfig['host'] = 'anothersmbhost';
$this->assertTrue(
OC_Mount_Config::addMountPoint(
$mountPoint,
'\OC\Files\Storage\SMB',
$mountConfig,
$mountType,
$applicable,
$isPersonal
)
);
// hook must not be called on edit
list($hookName, $params) = Test_Mount_Config_Hook_Test::getLastCall();
$this->assertEquals(
null,
$hookName
);
Test_Mount_Config_Hook_Test::clear();
$this->assertTrue(
OC_Mount_Config::removeMountPoint(
$mountPoint,
$mountType,
$applicable,
$isPersonal
)
);
list($hookName, $params) = Test_Mount_Config_Hook_Test::getLastCall();
$this->assertEquals(
\OC\Files\Filesystem::signal_delete_mount,
$hookName
);
$this->assertEquals(
$mountPoint,
$params[\OC\Files\Filesystem::signal_param_path]
);
$this->assertEquals(
$mountType,
$params[\OC\Files\Filesystem::signal_param_mount_type]
);
$this->assertEquals(
$applicable,
$params[\OC\Files\Filesystem::signal_param_users]
);
}
/**
* Test password obfuscation
*/
@@ -0,0 +1,91 @@
<?php
/**
* Copyright (c) 2014 Vincent Petry <pvince81@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace Test\Files\Storage;
class OwnCloudFunctions extends \PHPUnit_Framework_TestCase {
function configUrlProvider() {
return array(
array(
array(
'host' => 'testhost',
'root' => 'testroot',
'secure' => false
),
'http://testhost/remote.php/webdav/testroot/',
),
array(
array(
'host' => 'testhost',
'root' => 'testroot',
'secure' => true
),
'https://testhost/remote.php/webdav/testroot/',
),
array(
array(
'host' => 'http://testhost',
'root' => 'testroot',
'secure' => false
),
'http://testhost/remote.php/webdav/testroot/',
),
array(
array(
'host' => 'https://testhost',
'root' => 'testroot',
'secure' => false
),
'https://testhost/remote.php/webdav/testroot/',
),
array(
array(
'host' => 'https://testhost/testroot',
'root' => '',
'secure' => false
),
'https://testhost/testroot/remote.php/webdav/',
),
array(
array(
'host' => 'https://testhost/testroot',
'root' => 'subdir',
'secure' => false
),
'https://testhost/testroot/remote.php/webdav/subdir/',
),
array(
array(
'host' => 'http://testhost/testroot',
'root' => 'subdir',
'secure' => true
),
'http://testhost/testroot/remote.php/webdav/subdir/',
),
array(
array(
'host' => 'http://testhost/testroot/',
'root' => '/subdir',
'secure' => false
),
'http://testhost/testroot/remote.php/webdav/subdir/',
),
);
}
/**
* @dataProvider configUrlProvider
*/
public function testConfig($config, $expectedUri) {
$config['user'] = 'someuser';
$config['password'] = 'somepassword';
$instance = new \OC\Files\Storage\OwnCloud($config);
$this->assertEquals($expectedUri, $instance->createBaseUri());
}
}
+26 -12
View File
@@ -24,25 +24,39 @@ $owner = $_POST['owner'];
$name = $_POST['name'];
$password = $_POST['password'];
// Check for invalid name
if(!\OCP\Util::isValidFileName($name)) {
\OCP\JSON::error(array('data' => array('message' => $l->t('The mountpoint name contains invalid characters.'))));
exit();
}
$user = \OC::$server->getUserSession()->getUser();
$uid = ($user) ? $user->getUID() : null;
$externalManager = new \OCA\Files_Sharing\External\Manager(
\OC::$server->getDatabaseConnection(),
\OC\Files\Filesystem::getMountManager(),
\OC\Files\Filesystem::getLoader(),
\OC::$server->getUserSession()
$uid
);
$name = OCP\Files::buildNotExistingFileName('/', $name);
$mount = $externalManager->addShare($remote, $token, $password, $name, $owner);
/**
* @var \OCA\Files_Sharing\External\Storage $storage
*/
$storage = $mount->getStorage();
$result = $storage->file_exists('');
if($result){
$storage->getScanner()->scanAll();
\OCP\JSON::success();
// check for ssl cert
if (substr($remote, 0, 5) === 'https' and !OC_Util::getUrlContent($remote)) {
\OCP\JSON::error(array('data' => array('message' => $l->t("Invalid or untrusted ssl certificate"))));
exit;
} else {
$externalManager->removeShare($mount->getMountPoint());
\OCP\JSON::error(array('data' => array('message' => $l->t("Couldn't add remote share"))));
$mount = $externalManager->addShare($remote, $token, $password, $name, $owner);
/**
* @var \OCA\Files_Sharing\External\Storage $storage
*/
$storage = $mount->getStorage();
$result = $storage->file_exists('');
if ($result) {
$storage->getScanner()->scanAll();
\OCP\JSON::success();
} else {
$externalManager->removeShare($mount->getMountPoint());
\OCP\JSON::error(array('data' => array('message' => $l->t("Couldn't add remote share"))));
}
}
+2 -1
View File
@@ -14,7 +14,8 @@ function testUrl($url) {
try {
$result = file_get_contents($url);
$data = json_decode($result);
return is_object($data) and !empty($data->version);
// public link mount is only supported in ownCloud 7+
return is_object($data) and !empty($data->version) and version_compare($data->version, '7.0.0', '>=');
} catch (Exception $e) {
return false;
}
+4
View File
@@ -4,6 +4,7 @@ $l = OC_L10N::get('files_sharing');
OC::$CLASSPATH['OC_Share_Backend_File'] = 'files_sharing/lib/share/file.php';
OC::$CLASSPATH['OC_Share_Backend_Folder'] = 'files_sharing/lib/share/folder.php';
OC::$CLASSPATH['OC\Files\Storage\Shared'] = 'files_sharing/lib/sharedstorage.php';
OC::$CLASSPATH['OC\Files\Cache\SharedScanner'] = 'files_sharing/lib/scanner.php';
OC::$CLASSPATH['OC\Files\Cache\Shared_Cache'] = 'files_sharing/lib/cache.php';
OC::$CLASSPATH['OC\Files\Cache\Shared_Permissions'] = 'files_sharing/lib/permissions.php';
OC::$CLASSPATH['OC\Files\Cache\Shared_Updater'] = 'files_sharing/lib/updater.php';
@@ -12,6 +13,9 @@ OC::$CLASSPATH['OCA\Files\Share\Api'] = 'files_sharing/lib/api.php';
OC::$CLASSPATH['OCA\Files\Share\Maintainer'] = 'files_sharing/lib/maintainer.php';
OC::$CLASSPATH['OCA\Files\Share\Proxy'] = 'files_sharing/lib/proxy.php';
// Exceptions
OC::$CLASSPATH['OCA\Files_Sharing\Exceptions\BrokenPath'] = 'files_sharing/lib/exceptions.php';
\OCP\App::registerAdmin('files_sharing', 'settings-admin');
\OCA\Files_Sharing\Helper::registerHooks();
+1 -1
View File
@@ -32,7 +32,7 @@
<field>
<name>password</name>
<type>text</type>
<notnull>true</notnull>
<notnull>false</notnull>
<length>64</length>
<comments>Optional password for the public share</comments>
</field>
+5 -1
View File
@@ -2,7 +2,11 @@
<info>
<id>files_sharing</id>
<name>Share Files</name>
<description>File sharing between users</description>
<description>
This application enables users to share files within ownCloud. If enabled, the admin can choose which groups can share files. The applicable users can then share files and folders with other users and groups within ownCloud. In addition, if the admin enables the share link feature, an external link can be used to share files with other users outside of ownCloud. Admins can also enforce passwords, expirations dates, and enable server to server sharing via share links, as well as sharing from mobile devices.
Turning the feature off removes shared files and folders on the server for all share recipients, and also on the sync clients and mobile apps. More information is available in the ownCloud Documentation.
</description>
<licence>AGPL</licence>
<author>Michael Gapczynski, Bjoern Schiessle</author>
<requiremin>4.93</requiremin>
+1 -1
View File
@@ -74,7 +74,7 @@
// hack the buttons
$dialog.find('.ui-icon').remove();
$buttons.eq(0).text(t('core', 'Cancel'));
$buttons.eq(1).text(t('core', 'Add remote share'));
$buttons.eq(1).text(t('files_sharing', 'Add remote share'));
};
})();
+21 -12
View File
@@ -56,6 +56,11 @@ OCA.Sharing.PublicApp = {
}
var mimetype = $('#mimetype').val();
var mimetypeIcon = $('#mimetypeIcon').val();
mimetypeIcon = mimetypeIcon.substring(0, mimetypeIcon.length - 3);
mimetypeIcon = mimetypeIcon + 'svg';
var previewSupported = $('#previewSupported').val();
if (typeof FileActions !== 'undefined') {
// Show file preview if previewer is available, images are already handled by the template
@@ -68,21 +73,25 @@ OCA.Sharing.PublicApp = {
}
}
// dynamically load image previews
if (mimetype.substr(0, mimetype.indexOf('/')) === 'image') {
var params = {
x: $(document).width() * window.devicePixelRatio,
y: $(document).height() * window.devicePixelRatio,
a: 'true',
file: encodeURIComponent(this.initialDir + $('#filename').val()),
t: $('#sharingToken').val(),
scalingup: 0
};
var params = {
x: $(document).width() * window.devicePixelRatio,
y: $(document).height() * window.devicePixelRatio,
a: 'true',
file: encodeURIComponent(this.initialDir + $('#filename').val()),
t: $('#sharingToken').val(),
scalingup: 0
};
var img = $('<img class="publicpreview">');
var img = $('<img class="publicpreview">');
if (previewSupported === 'true' || mimetype.substr(0, mimetype.indexOf('/')) === 'image' && mimetype !== 'image/svg+xml') {
img.attr('src', OC.filePath('files_sharing', 'ajax', 'publicpreview.php') + '?' + OC.buildQueryString(params));
img.appendTo('#imgframe');
} else if (mimetype.substr(0, mimetype.indexOf('/')) !== 'video') {
img.attr('src', OC.Util.replaceSVGIcon(mimetypeIcon));
img.attr('width', 128);
img.appendTo('#imgframe');
}
if (this.fileList) {
@@ -201,7 +210,7 @@ OCA.Sharing.PublicApp = {
// this check needs to happen on the server due to the Content Security Policy directive
$.get(OC.generateUrl('apps/files_sharing/testremote'), {remote: remote}).then(function (protocol) {
if (protocol !== 'http' && protocol !== 'https') {
OC.dialogs.alert(t('files_sharing', 'No ownCloud installation found at {remote}', {remote: remote}),
OC.dialogs.alert(t('files_sharing', 'No ownCloud installation (7 or higher) found at {remote}', {remote: remote}),
t('files_sharing', 'Invalid ownCloud url'));
} else {
OC.redirect(protocol + '://' + url);
+5 -1
View File
@@ -30,6 +30,10 @@ $TRANSLATIONS = array(
"Direct link" => "Enllaz direutu",
"Remote Shares" => "Comparticiones remotes",
"Allow other instances to mount public links shared from this server" => "Permitir a otres instancies montar enllaces compartíos públicos d'esti sirvidor",
"Allow users to mount public link shares" => "Permitir a los usuarios montar enllaces compartíos públicos"
"Allow users to mount public link shares" => "Permitir a los usuarios montar enllaces compartíos públicos",
"Remote share" => "Compartición remota",
"Remote share password" => "Contraseña de compartición remota",
"Do you want to add the remote share {name} from {owner}@{remote}?" => "Quies amestar compartición remota {name} de {owner}@{remote}?",
"Add remote share" => "Amestar compartición remota",
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
+7 -1
View File
@@ -4,6 +4,12 @@ $TRANSLATIONS = array(
"Shared by" => "Споделено от",
"Name" => "Име",
"Save" => "Запис",
"Download" => "Изтегляне"
"Download" => "Изтегляне",
"Remote share" => "Прикачена Папка",
"Remote share password" => "Парола за прикачена папка",
"Do you want to add the remote share {name} from {owner}@{remote}?" => "Желаеш ли да добавиш като прикачената папка {name} от {owner}@{remote}?",
"Couldn't add remote share" => "Неуспешно добавяне на отдалечена споделена директория.",
"Add remote share" => "Добави прикачена папка",
"Remote Shares" => "Прикачени Папки",
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
+4 -1
View File
@@ -3,6 +3,9 @@ $TRANSLATIONS = array(
"Password" => "কূটশব্দ",
"Name" => "রাম",
"Save" => "সংরক্ষণ",
"Download" => "ডাউনলোড"
"Download" => "ডাউনলোড",
"Remote share" => "দুরবর্তী ভাগাভাগি",
"Couldn't add remote share" => "দুরবর্তী ভাগাভাগি যোগ করা গেলনা",
"Remote Shares" => "দুরবর্তী ভাগাভাগি",
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
+5 -1
View File
@@ -31,6 +31,10 @@ $TRANSLATIONS = array(
"Direct link" => "Enllaç directe",
"Remote Shares" => "Compartició remota",
"Allow other instances to mount public links shared from this server" => "Permet que altres instàncies muntin enllaços públics compartits des d'aqeust servidor",
"Allow users to mount public link shares" => "Permet que usuaris muntin compartits amb enllaços públics"
"Allow users to mount public link shares" => "Permet que usuaris muntin compartits amb enllaços públics",
"Remote share" => "Compartició remota",
"Remote share password" => "Contrasenya de compartició remota",
"Do you want to add the remote share {name} from {owner}@{remote}?" => "Voleu afegir la compartició remota {nom} des de {owner}@{remote}?",
"Add remote share" => "Afegeix compartició remota",
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
+5 -1
View File
@@ -31,6 +31,10 @@ $TRANSLATIONS = array(
"Direct link" => "Přímý odkaz",
"Remote Shares" => "Vzdálená úložiště",
"Allow other instances to mount public links shared from this server" => "Povolit připojování veřejně sdílených odkazů z tohoto serveru",
"Allow users to mount public link shares" => "Povolit uživatelům připojovat veřejně sdílené odkazy"
"Allow users to mount public link shares" => "Povolit uživatelům připojovat veřejně sdílené odkazy",
"Remote share" => "Vzdálené úložiště",
"Remote share password" => "Heslo ke vzdálenému úložišti",
"Do you want to add the remote share {name} from {owner}@{remote}?" => "Chcete přidat vzdálené úložiště {name} uživatele {owner}@{remote}?",
"Add remote share" => "Přidat vzdálené úložiště",
);
$PLURAL_FORMS = "nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;";
+7 -1
View File
@@ -22,6 +22,12 @@ $TRANSLATIONS = array(
"Save" => "Gem",
"Download" => "Download",
"Download %s" => "Download %s",
"Direct link" => "Direkte link"
"Direct link" => "Direkte link",
"Remote share" => "Ekstern deling",
"Remote share password" => "Adgangskode for ekstern deling",
"Do you want to add the remote share {name} from {owner}@{remote}?" => "Vil du tilføje den eksterne deling {name} fra {owner}@{remote}?",
"Couldn't add remote share" => "Kunne ikke tliføje den delte ekstern ressource",
"Add remote share" => "Tilføj ekstern deling",
"Remote Shares" => "Eksterne delinger",
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
+5 -1
View File
@@ -31,6 +31,10 @@ $TRANSLATIONS = array(
"Direct link" => "Direkter Link",
"Remote Shares" => "Entfernte Freigaben",
"Allow other instances to mount public links shared from this server" => "Andere Instanzen zum Hinzufügen von öffentlichen Links, die über diesen Server Freigegeben werden, erlauben",
"Allow users to mount public link shares" => "Erlaube Nutzern das Hinzufügen von freigegebenen öffentlichen Links"
"Allow users to mount public link shares" => "Erlaube Nutzern das Hinzufügen von freigegebenen öffentlichen Links",
"Remote share" => "Entfernte Freigabe",
"Remote share password" => "Passwort für die entfernte Freigabe",
"Do you want to add the remote share {name} from {owner}@{remote}?" => "Möchtest Du die entfernte Freigabe {name} von {owner}@{remote} hinzufügen?",
"Add remote share" => "Entfernte Freigabe hinzufügen",
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
+5 -1
View File
@@ -31,6 +31,10 @@ $TRANSLATIONS = array(
"Direct link" => "Direkte Verlinkung",
"Remote Shares" => "Entfernte Freigaben",
"Allow other instances to mount public links shared from this server" => "Andere Instanzen zum Hinzufügen von öffentlichen Links, die über diesen Server Freigegeben werden, erlauben",
"Allow users to mount public link shares" => "Erlaube Nutzern das Hinzufügen von freigegebenen öffentlichen Links"
"Allow users to mount public link shares" => "Erlaube Nutzern das Hinzufügen von freigegebenen öffentlichen Links",
"Remote share" => "Entfernte Freigabe",
"Remote share password" => "Passwort für die entfernte Freigabe",
"Do you want to add the remote share {name} from {owner}@{remote}?" => "Möchten Sie die entfernte Freigabe {name} von {owner}@{remote} hinzufügen?",
"Add remote share" => "Entfernte Freigabe hinzufügen",
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
+5 -1
View File
@@ -31,6 +31,10 @@ $TRANSLATIONS = array(
"Direct link" => "Άμεσος σύνδεσμος",
"Remote Shares" => "Απομακρυσμένοι Κοινόχρηστοι Φάκελοι",
"Allow other instances to mount public links shared from this server" => "Να επιτρέπεται σε άλλες εγκαταστάσεις να επιθέτουν δημόσιους συνδέσμους που έχουν διαμοιραστεί από αυτόν το διακομιστή",
"Allow users to mount public link shares" => "Να επιτρέπεται στους χρήστες να επιθέτουν κοινόχρηστους φακέλους με δημόσιους συνδέσμους"
"Allow users to mount public link shares" => "Να επιτρέπεται στους χρήστες να επιθέτουν κοινόχρηστους φακέλους με δημόσιους συνδέσμους",
"Remote share" => "Απομακρυσμένος κοινόχρηστος φάκελος",
"Remote share password" => "Κωδικός πρόσβασης απομακρυσμένου κοινόχρηστου φακέλου",
"Do you want to add the remote share {name} from {owner}@{remote}?" => "Θέλετε να προσθέσουμε τον απομακρυσμένο κοινόχρηστο φάκελο {name} από {owner}@{remote}?",
"Add remote share" => "Προσθήκη απομακρυσμένου κοινόχρηστου φακέλου",
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
+5 -1
View File
@@ -31,6 +31,10 @@ $TRANSLATIONS = array(
"Direct link" => "Direct link",
"Remote Shares" => "Remote Shares",
"Allow other instances to mount public links shared from this server" => "Allow other instances to mount public links shared from this server",
"Allow users to mount public link shares" => "Allow users to mount public link shares"
"Allow users to mount public link shares" => "Allow users to mount public link shares",
"Remote share" => "Remote share",
"Remote share password" => "Remote share password",
"Do you want to add the remote share {name} from {owner}@{remote}?" => "Do you want to add the remote share {name} from {owner}@{remote}?",
"Add remote share" => "Add remote share",
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
+5 -1
View File
@@ -31,6 +31,10 @@ $TRANSLATIONS = array(
"Direct link" => "Enlace directo",
"Remote Shares" => "Almacenamiento compartido remoto",
"Allow other instances to mount public links shared from this server" => "Permitir a otros montar enlaces publicos compartidos de este servidor",
"Allow users to mount public link shares" => "Permitir a los usuarios montar enlaces publicos compartidos"
"Allow users to mount public link shares" => "Permitir a los usuarios montar enlaces publicos compartidos",
"Remote share" => "Recurso compartido remoto",
"Remote share password" => "Contraseña del compartido remoto",
"Do you want to add the remote share {name} from {owner}@{remote}?" => "¿Desea añadir el recurso compartido remoto {name} de {owner}@{remote}?",
"Add remote share" => "Añadir recurso compartido remoto",
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
+5 -1
View File
@@ -30,6 +30,10 @@ $TRANSLATIONS = array(
"Direct link" => "Otsene link",
"Remote Shares" => "Eemalolevad jagamised",
"Allow other instances to mount public links shared from this server" => "Luba teistel instantsidel ühendada sellest serverist jagatud avalikke linke",
"Allow users to mount public link shares" => "Luba kasutajatel ühendada jagatud avalikke linke"
"Allow users to mount public link shares" => "Luba kasutajatel ühendada jagatud avalikke linke",
"Remote share" => "Kaugjagamine",
"Remote share password" => "Kaugjagamise parool",
"Do you want to add the remote share {name} from {owner}@{remote}?" => "Soovid lisata kaugjagamise {name} asukohast {owner}@{remote}?",
"Add remote share" => "Lisa kaugjagamine",
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
+5 -1
View File
@@ -31,6 +31,10 @@ $TRANSLATIONS = array(
"Direct link" => "Lotura zuzena",
"Remote Shares" => "Hurruneko Elkarbanaketak",
"Allow other instances to mount public links shared from this server" => "Baimendu beste instantziak zerbitzari honetatik elkarbanatutako lotura publikoak kargatzen",
"Allow users to mount public link shares" => "Baimendu erabiltzaileak lotura publiko bidezko elkarbanaketak kargatzen"
"Allow users to mount public link shares" => "Baimendu erabiltzaileak lotura publiko bidezko elkarbanaketak kargatzen",
"Remote share" => "Urrutiko parte hartzea",
"Remote share password" => "Urrutiko parte hartzeen pasahitza",
"Do you want to add the remote share {name} from {owner}@{remote}?" => "Nahi duzu gehitzea {name} urrutiko partekatzea honengandik {owner}@{remote}?",
"Add remote share" => "Gehitu urrutiko parte hartzea",
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
+7 -1
View File
@@ -15,6 +15,12 @@ $TRANSLATIONS = array(
"Save" => "ذخیره",
"Download" => "دانلود",
"Download %s" => "دانلود %s",
"Direct link" => "پیوند مستقیم"
"Direct link" => "پیوند مستقیم",
"Remote share" => "اشتراک از راه دور",
"Remote share password" => "رمز عبور اشتراک از راه دور",
"Do you want to add the remote share {name} from {owner}@{remote}?" => "آیا مایل به افزودن اشتراک از راه دور {name} از {owner}@{remote} هستید.",
"Couldn't add remote share" => "امکان افزودن اشتراک گذاری از راه دور وجود ندارد",
"Add remote share" => "افزودن اشتراک از راه دور",
"Remote Shares" => "اشتراک های از راه دور",
);
$PLURAL_FORMS = "nplurals=1; plural=0;";
+5 -1
View File
@@ -31,6 +31,10 @@ $TRANSLATIONS = array(
"Direct link" => "Suora linkki",
"Remote Shares" => "Etäjaot",
"Allow other instances to mount public links shared from this server" => "Salli muiden instanssien liittää tältä palvelimelta jaettuja julkisia linkkejä",
"Allow users to mount public link shares" => "Salli käyttäjien liittää julkisia linkkijakoja"
"Allow users to mount public link shares" => "Salli käyttäjien liittää julkisia linkkijakoja",
"Remote share" => "Etäjako",
"Remote share password" => "Etäjaon salasana",
"Do you want to add the remote share {name} from {owner}@{remote}?" => "Haluatko lisätä etäjaon {name} kohteesta {owner}@{remote}?",
"Add remote share" => "Lisää etäjako",
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
+11 -7
View File
@@ -2,12 +2,12 @@
$TRANSLATIONS = array(
"Server to server sharing is not enabled on this server" => "Le partage de serveur à serveur n'est pas activé sur ce serveur",
"Couldn't add remote share" => "Impossible d'ajouter un partage distant",
"Shared with you" => "Partagé avec vous",
"Shared with others" => "Partagé avec d'autres",
"Shared by link" => "Partagé par lien",
"No files have been shared with you yet." => "Aucun fichier n'est partagé avec vous pour l'instant",
"You haven't shared any files yet." => "Vous ne partagez pas de fichier pour l'instant",
"You haven't shared any files by link yet." => "Vous ne partagez aucun de fichier par lien pour l'instant.",
"Shared with you" => "Partagés avec vous",
"Shared with others" => "Partagés avec d'autres",
"Shared by link" => "Partagés par lien",
"No files have been shared with you yet." => "Aucun fichier n'est partagé avec vous pour l'instant.",
"You haven't shared any files yet." => "Vous ne partagez pas de fichier pour l'instant.",
"You haven't shared any files by link yet." => "Vous ne partagez pas de fichier par lien pour l'instant.",
"Add {name} from {owner}@{remote}" => "Ajouter {name} de {owner}@{remote}",
"Add Share" => "Ajouter un partage",
"Password" => "Mot de passe",
@@ -31,6 +31,10 @@ $TRANSLATIONS = array(
"Direct link" => "Lien direct",
"Remote Shares" => "Partages Distants",
"Allow other instances to mount public links shared from this server" => "Autorise d'autres instances à monter des liens publiques partagés depuis ce serveur",
"Allow users to mount public link shares" => "Autorise les utilisateurs à monter des liens de partages publiques"
"Allow users to mount public link shares" => "Autorise les utilisateurs à monter des liens de partages publiques",
"Remote share" => "Partage distant",
"Remote share password" => "Mot de passe du partage distant",
"Do you want to add the remote share {name} from {owner}@{remote}?" => "Voulez-vous ajouter le partage distant {name} de {owner}@{remote} ?",
"Add remote share" => "Ajouter un partage distant",
);
$PLURAL_FORMS = "nplurals=2; plural=(n > 1);";
+5 -1
View File
@@ -31,6 +31,10 @@ $TRANSLATIONS = array(
"Direct link" => "Ligazón directa",
"Remote Shares" => "Comparticións remotas",
"Allow other instances to mount public links shared from this server" => "Permitir que outras instancias monten ligazóns públicas compartidas desde este servidor",
"Allow users to mount public link shares" => "Permitirlle aos usuarios montar ligazóns públicas compartidas"
"Allow users to mount public link shares" => "Permitirlle aos usuarios montar ligazóns públicas compartidas",
"Remote share" => "Compartición remota",
"Remote share password" => "Contrasinal da compartición remota",
"Do you want to add the remote share {name} from {owner}@{remote}?" => "Quere engadir a compartición remota {name} desde {owner}@{remote}?",
"Add remote share" => "Engadir unha compartición remota",
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
+7 -1
View File
@@ -3,6 +3,12 @@ $TRANSLATIONS = array(
"Password" => "Lozinka",
"Name" => "Ime",
"Save" => "Snimi",
"Download" => "Preuzimanje"
"Download" => "Preuzimanje",
"Remote share" => "Udaljeni zajednički resurs (za raspodjelu)",
"Remote share password" => "Lozinka za udaljeni zajednički resurs",
"Do you want to add the remote share {name} from {owner}@{remote}?" => "Želite li dodati udaljeni zajednički resurs {name} od {owner}@{remote}?",
"Couldn't add remote share" => "Udaljeni zajednički resurs nije moguće dodati",
"Add remote share" => "Dodajte udaljeni zajednički resurs",
"Remote Shares" => "Udaljeni zajednički resursi (za raspodjelu)",
);
$PLURAL_FORMS = "nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;";

Some files were not shown because too many files have changed in this diff Show More