Compare commits

...

842 Commits

Author SHA1 Message Date
C Montero-Luque
f48fe48f19 Version 6.0.9 beta 2015-06-23 11:59:06 -04:00
Thomas Müller
8f8470cf10 Merge pull request #17023 from owncloud/stable6-verify-path
[stable6] Verify if path exists
2015-06-19 15:47:00 +02:00
Lukas Reschke
0a35d65b5d Verify if path exists
We need to check if the path exists and throw an error instead of handling this situation ungraciously.
2015-06-18 17:28:55 +02:00
Morris Jobke
24b21d2ed1 Merge pull request #16990 from owncloud/stable6-fix-verify-if-path-exists
[stable6] Verify if path exists
2015-06-17 16:58:40 +02:00
Lukas Reschke
a9838b37f1 Throw nicer error message instead 500 2015-06-17 15:42:00 +02:00
Lukas Reschke
7ee4acdf57 Verify if path exists
We need to verify if the specified path exists to gracefully prevent errors.
2015-06-17 15:09:24 +02:00
Thomas Müller
42cc039098 Merge pull request #16865 from owncloud/backport-concatenation-6
[stable6] Don't use command concatenation
2015-06-11 09:43:02 +02:00
Lukas Reschke
b49deb6d79 Don't use command concatenation
Possibly fixes https://github.com/owncloud/core/issues/16853
2015-06-10 15:20:18 +02:00
Morris Jobke
049d499aec Merge pull request #16683 from owncloud/stable6-check-array
Check if array
2015-06-10 07:37:06 +02:00
Frank Karlitschek
b1755bb7b0 6.0.8 2015-06-03 20:41:47 -04:00
Lukas Reschke
ba788a3539 Check if array
The great library that we use apparently uses mixed types for everything because 🙈

Fixes https://github.com/owncloud/core/issues/16679
2015-06-02 12:40:16 +02:00
Frank Karlitschek
42293195bc 6.0.8RC2 2015-06-01 18:54:04 -04:00
Thomas Müller
18b4d54f8a Merge pull request #16674 from owncloud/update-phpunit
Upgrade to use latest phpunit - fixes #16669
2015-06-01 22:12:09 +02:00
Thomas Müller
1b0756e49a Upgrade to use latest phpunit - fixes #16669 2015-06-01 21:11:01 +02:00
Lukas Reschke
84fcf80664 Disallow semicolons in passed commands 2015-06-01 17:07:08 +02:00
Lukas Reschke
5154cc3e2c Ensure that passed argument is always a string
Some code paths called the `normalizePath` functionality with types other than a string which resulted in unexpected behaviour.

Thus the function is now manually casting the type to a string and I corrected the usage in list.php as well.
2015-06-01 17:07:03 +02:00
Lukas Reschke
bf0f1a5092 Revert custom patch that can cause problems 2015-06-01 17:06:58 +02:00
Frank Karlitschek
0899f66232 6.0.8 RC1 2015-05-29 13:59:54 -04:00
Lukas Reschke
231bc00a50 Merge pull request #14499 from owncloud/kill-substr-mssql-stable6
[stable6] Remove hacky Substring support for MSSQL
2015-03-26 23:00:30 +01:00
Morris Jobke
f22e5da347 Merge pull request #14729 from owncloud/stable6-versioning_fix_path
[stable6] make sure that the versions array contains the correct path
2015-03-24 22:37:10 +01:00
Bjoern Schiessle
a917b78c3c make sure that the versions array contains the correct path 2015-03-06 13:48:38 +01:00
Lukas Reschke
68000eb1cf 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:10:44 +01:00
Frank Karlitschek
87345f80ea 6.0.7 2015-02-16 04:57:16 +01:00
Thomas Müller
b864fb4cc8 Merge pull request #14150 from owncloud/no-whitespace-from-themes-stable6
catch any whitespaces which might get written to the output buffer while...
2015-02-19 10:20:10 +01:00
Morris Jobke
24911a36f7 Merge pull request #14255 from owncloud/console-execution-time-stable6
[backport-14243-stable6] console commands shall not be limited with respect to execution time
2015-02-16 21:16:31 +01:00
Thomas Müller
9f01059ed9 console commands shall not be limited with respect to execution time 2015-02-16 16:27:21 +01:00
Thomas Müller
e9e1b0638c catch any whitespaces which might get written to the output buffer while loading a theme 2015-02-12 12:09:18 +01:00
Lukas Reschke
267341fbeb Normalize before processing 2015-02-06 15:53:13 +01:00
Frank Karlitschek
0bccd06bc8 6.0.7 RC1 2015-02-06 02:48:07 +01:00
Morris Jobke
cbb58b0d2f Merge pull request #12736 from owncloud/temp-handling-stable6
[stable6] Cleanup handling of temporary files
2015-01-09 00:38:40 +01:00
Morris Jobke
df5b5e4cf8 Merge pull request #13177 from owncloud/stable6-extstorage-fixsharedmountpointrootleadingslash
[stable6] Fix source path when share is a mount point
2015-01-09 00:00:23 +01:00
Robin Appelman
3adb47094e Use the TempManager to handle temporary files 2015-01-08 16:22:44 +01:00
Robin Appelman
299ff5a3b1 Add \OC\TempManager to handle creating and cleaning temporary files 2015-01-08 16:22:44 +01:00
Vincent Petry
aca2807da6 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.
2015-01-08 11:40:47 +01:00
Byron Marohn
441cdccc3e 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 18:04:58 +01:00
Victor Dubiniuk
c59b22ab55 Skip headers that can not be split 2014-12-10 08:22:29 +01:00
Frank Karlitschek
60e955bde4 6.0.6 2014-11-07 20:27:15 +01:00
Craig Morrissey
3cb244dd23 logging changes 2014-11-07 12:47:06 -05:00
Björn Schießle
78edcd9696 Merge pull request #11706 from owncloud/fix_trash_stable6
[oc6] make sure that trash bin is initialized correctly
2014-10-23 16:34:00 +02:00
Bjoern Schiessle
9320225daa make sure that trash bin is initialized for both the current user and the file owner 2014-10-22 15:14:30 +02:00
Bjoern Schiessle
9ea90ac82f no error if we try to delete a file which no longer exists 2014-10-21 16:55:17 +02:00
Arthur Schiwon
e46f87fdac 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

Conflicts:
	apps/user_ldap/group_ldap.php
	apps/user_ldap/lib/access.php
	apps/user_ldap/tests/group_ldap.php
2014-10-20 12:51:38 +02:00
blizzz
6fc04c2f91 Merge pull request #11217 from owncloud/backport-9225-stable6
Backport of #9225 to stable6
2014-10-20 11:42:51 +02:00
Lukas Reschke
55573645c6 Merge pull request #11371 from owncloud/backport-11368
Load public preview via JS
2014-10-20 09:13:26 +02:00
Frank Karlitschek
de8c624a15 Merge pull request #10576 from owncloud/ajaxify_user_list_for_files_external_stable6
Ajaxify user list for files external stable6
2014-10-18 18:28:28 +02:00
Lukas Reschke
65b439da8c Merge pull request #11560 from owncloud/stable6-encsharekeymatchingdirectbackport
[stable6] backport share key pattern matching fix
2014-10-17 11:36:03 +02:00
Arthur Schiwon
4e6a4e53cf Merge branch 'voxsim-backport-9225-stable6' into backport-9225-stable6 2014-10-16 16:38:26 +02:00
Lukas Reschke
870dc981aa Merge pull request #11248 from owncloud/11032-backport-stable6
Do only follow HTTP and HTTPS redirects
2014-10-16 13:54:21 +02:00
Lukas Reschke
979d2823b5 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.
2014-10-16 12:25:58 +02:00
Vincent Petry
d63bba391d Disabled assert known to fail
stable6 has a bug where the share keys are not properly deleted when
deleting a shared file as non-owner.

To make sure the more important fix from the backport of
1e631754d7 can be applied, the
corresponding assert introduced by the backport is disabled.
2014-10-16 10:29:24 +02:00
Frank Karlitschek
784931f835 6.0.6 RC1 2014-10-16 08:24:28 +02:00
Vincent Petry
962b410fcc Remove FileInfo instance check
FileInfo class doesn't exist in stable6
2014-10-15 17:26:13 +02:00
Vincent Petry
9878f00118 Removed broken/unneeded fixFileSize
fixFileSize is not needed as the target file will already have the
correct unencrypted size after renaming
2014-10-15 12:34:33 +02:00
Vincent Petry
828a939f96 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

Conflicts:
	apps/files_encryption/lib/keymanager.php
	apps/files_encryption/tests/hooks.php
	apps/files_encryption/tests/keymanager.php
	apps/files_encryption/tests/trashbin.php
2014-10-15 12:34:32 +02:00
Vincent Petry
9327abd2e4 Merge pull request #11561 from owncloud/stable6-enc-webdavcopywithencryptionfix
[stable6] add support for webdav copy to the encryption and versions app
2014-10-15 12:30:37 +02:00
Bjoern Schiessle
07377be378 make sure that we always find all versions 2014-10-14 11:36:39 +02:00
Bjoern Schiessle
fd55d73ac5 add unit test for rename and copy operation
Conflicts:
	apps/files_versions/appinfo/app.php
	apps/files_versions/tests/versions.php
2014-10-14 11:11:37 +02:00
Bjoern Schiessle
1aedc60aa2 make the versions and encryption app aware of the copy operation
Conflicts:
	apps/files_encryption/hooks/hooks.php
	apps/files_versions/appinfo/app.php
2014-10-14 11:10:00 +02:00
Jörn Friedrich Dreyer
2107915073 fix flickering users 2014-10-13 17:49:40 +02:00
Arthur Schiwon
abc2aad2a1 no need to load display names 2014-10-13 17:18:35 +02:00
Jörn Friedrich Dreyer
cb74d8ac0e fix deletion of shares 2014-10-13 17:18:35 +02:00
Jörn Friedrich Dreyer
5af5bd5498 replace chosen with select2 to provide ajaxified user and group selection for files_external, fixes #7499 2014-10-13 17:18:35 +02:00
Jörn Friedrich Dreyer
564d28b57c add select2 to app specific thirdparty 2014-10-13 17:18:35 +02:00
Lukas Reschke
af97529339 force loading of encryption app 2014-10-13 11:55:05 +02:00
Vincent Petry
3844585f91 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:55:32 +02:00
Robin Appelman
dfa57cdc01 Show a proper error message when trying to scan the filesystem for a non existing user
Backport of e8280c80da from master
2014-10-10 13:00:39 +02:00
Robin Appelman
c526ebb832 Don't keep the full info of all children in memory
Backport of f88021dbbc from master
2014-10-10 13:00:14 +02:00
Arthur Schiwon
94d5f9e6e2 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

Conflicts:
	apps/user_ldap/lib/access.php
	apps/user_ldap/lib/ildapwrapper.php
2014-10-09 14:46:20 +02:00
Lukas Reschke
65c655afad Merge pull request #8307 from owncloud/case_insensitive_search_oracle_stable6
on oracle use regex_like to make filename search case insensitive
2014-10-03 15:19:59 +02:00
Lukas Reschke
befbf1c150 Load public preview via JS
Backport of https://github.com/owncloud/core/pull/11368 to stable6 - since stable6 has no detection for SVG support this will just use the PNG icon instead of SVG ones.

I believe this is a better solution than backporting the whole SVG support stuff and potentially breaking a lot.
2014-10-01 13:49:59 +02:00
Lukas Reschke
d9ceeed60d Merge pull request #11153 from owncloud/parallel-upload-stable6
close the session for all DAV calls right after authentication - no need...
2014-10-01 10:42:20 +02:00
Jörn Friedrich Dreyer
5e0ea9f3b5 fix case insensitive search on oracle and postgresql
on oracle use regex_like
on postgres use ILIKE
add unit test to check case insensitivity
2014-09-29 14:31:40 +02:00
Lukas Reschke
b358547699 Clarify possible preview providers for type Office
a

Conflicts:
	lib/private/preview.php
2014-09-25 09:59:08 +02:00
Simon Vocella
e9cc95a403 Fix in stable6 after backport of #9225 2014-09-24 22:56:23 +02:00
Arthur Schiwon
a84250c6d1 ask implementsAction instead of checking method_exists for easier testing 2014-09-24 22:36:45 +02:00
Joas Schilling
79e6b60199 Fix getting group '0' from database backend
Fix #9972
2014-09-24 22:23:25 +02:00
Arthur Schiwon
01ce97f85f add optional countUsersInGroup method to group backends
Conflicts:
	lib/private/group/backend.php
	lib/private/group/database.php
	lib/private/group/dummy.php
2014-09-24 22:23:13 +02:00
Robin Appelman
03694be08a remove unneeded ; in comment 2014-09-24 22:08:01 +02:00
Robin Appelman
5525294f9b user Group->users as assosiative array 2014-09-24 22:07:56 +02:00
Robin Appelman
e9cf3b4e8b cache the result from inGroup 2014-09-24 22:07:47 +02:00
Robin Appelman
82c375cda5 Fix test cases for group manager 2014-09-24 09:39:39 +02:00
Robin Appelman
ed6588ff21 remove duplicate call to groupExists 2014-09-24 09:22:43 +02:00
Morris Jobke
34a803d83e Merge pull request #11246 from owncloud/backport-11211-stable6
Add a configuration switch for enabled preview mimetypes
2014-09-23 23:54:08 +02:00
Lukas Reschke
716613fda4 Merge branch 'stable6' into backport-11211-stable6
Conflicts:
	config/config.sample.php
2014-09-23 14:49:53 +02:00
Vincent Petry
3ec5cbb347 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-23 13:35:45 +02:00
Victor Dubiniuk
f2629142b0 Use non-empty defaults 2014-09-23 12:53:54 +02:00
Lukas Reschke
b2798afef5 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 12:05:34 +02:00
Bjoern Schiessle
5de19f38c4 first check if a private key exists, if not it is always a recovery szenario 2014-09-23 10:56:01 +02:00
Lukas Reschke
77a4b1609b Add a configuration switch for enabled preview mimetypes
Backport of https://github.com/owncloud/core/pull/11211 to stable6
2014-09-23 10:53:34 +02:00
Vincent Petry
e001dfb3be 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:09:25 +02:00
Lukas Reschke
e123b6db68 Merge pull request #11207 from owncloud/enc_create_backup_on_recovery_oc6
create backup from all keys before recovery (oc6 backport)
2014-09-22 15:11:16 +02:00
voxsim
45489ecce4 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;

Conflicts:
	tests/lib/group/manager.php
2014-09-22 12:26:47 +02:00
Bjoern Schiessle
7539309742 create backup from all keys before recovery 2014-09-22 09:53:40 +02:00
Thomas Müller
7217fb873c use session_write_close() because the Session class has no close() yet in this version 2014-09-18 13:21:08 +02:00
Thomas Müller
b963723c21 close the session for all DAV calls right after authentication - no need to write to the session afterwards 2014-09-18 11:58:38 +02:00
Lukas Reschke
7a2dbc25cb Revert "Reword the description"
This reverts commit 16c5925155.
2014-09-16 16:03:30 +02:00
Lukas Reschke
16c5925155 Reword the description
The old one was just horrible wrong.
Conflicts:
	config/config.sample.php
2014-09-16 16:02:48 +02:00
Thomas Müller
5ecbd9ddd6 Merge pull request #11025 from owncloud/nojavascript
introduce no-javascript message, manual backport of #6202 and #10944
2014-09-12 11:30:33 +02:00
Jan-Christoph Borchardt
c3002b3053 introduce no-javascript message, manual backport of #6202 and #10944, fix #10841 2014-09-11 16:11:44 +02:00
tomneedham
e962c190c7 Add displayname for admins 2014-09-11 08:51:31 +01:00
Vincent Petry
725360fa14 Merge pull request #10250 from owncloud/block-folder-upload-stable6
Prevent folder upload causing unexpected behavior
2014-09-03 17:15:59 +02:00
Thomas Müller
69f198d6fb Merge pull request #10645 from owncloud/backport_7728
Backport 7728
2014-09-03 12:46:12 +02:00
Thomas Müller
7507995485 Merge pull request #10774 from owncloud/backport-getUserFolder
Add optional user ID parameter for getUseFolder
2014-09-03 11:06:02 +02:00
Morris Jobke
4a4f52e7a4 Add optional user ID parameter for getUseFolder
Conflicts:
	lib/private/server.php
2014-08-31 13:42:41 +02:00
Arthur Schiwon
8d786ec456 retrieve local users, groups and group members in a sorted way 2014-08-31 11:59:57 +02:00
Thomas Müller
9c4fe0bc3a Merge pull request #10694 from owncloud/allow_empty_hostname_and_dots_in_service_name_for_oracle_autosetup
allow empty hostname and dots in service name for oracle autosetup
2014-08-29 17:07:21 +02:00
Jörn Friedrich Dreyer
25524e03c4 allow empty hostname and dots in service name for oracle autosetup 2014-08-28 15:54:28 +02:00
blizzz
da1d4bf4fd Merge pull request #10631 from owncloud/fixWizardTest_stable6
fix wizard test, adjust to changed parameters of the tested method, intr...
2014-08-28 11:33:42 +02:00
Lukas Reschke
1d5a664dc0 Escape error messages 2014-08-28 09:37:38 +02:00
Jörn Friedrich Dreyer
4a3e6dd528 Merge pull request #10660 from owncloud/use_notification_to_show_error_on_new_via_web_stable6
use notification to show error on new via web
2014-08-27 11:46:08 +02:00
Jörn Friedrich Dreyer
c2e7c19c49 use notification to shw error on new via web 2014-08-27 10:44:10 +02:00
Thomas Müller
f3d335b7c1 unit tests for specific image type output added 2014-08-26 19:39:46 +02:00
Georg Ehrke
6da05d0ca4 excerpt code changes from 79ba930ef9 2014-08-26 19:39:30 +02:00
Georg Ehrke
c82f158c16 OC_Image::_output() - throw exception instead of falling back to png 2014-08-26 19:36:54 +02:00
Georg Ehrke
f2b072bceb remove image/pjpeg from OC_Image::_output 2014-08-26 19:36:40 +02:00
Georg Ehrke
ee8ded88b3 don't change mimetype of whole image object 2014-08-26 19:36:28 +02:00
Georg Ehrke
3c65a503b2 always output a png 2014-08-26 19:36:18 +02:00
Georg Ehrke
8f45e8107a make it possible to influence output type of \OC_Image
Conflicts:
	lib/private/image.php
2014-08-26 19:35:53 +02:00
Frank Karlitschek
30098c34ad 6.0.5 2014-08-26 12:04:32 +02:00
Arthur Schiwon
e895f06165 fix wizard test, adjust to changed parameters of the tested method, introduced by 9caa354cfc 2014-08-26 10:50:00 +02:00
Jörn Friedrich Dreyer
96430a99f9 Merge pull request #10448 from owncloud/check_quota_on_new_via_web_stable6
check quota when trying to download a file via new -> web
2014-08-25 15:17:37 +02:00
Frank Karlitschek
eb276df08c 6.0.5 RC1 2014-08-21 05:37:53 +02:00
Lukas Reschke
d9ecfa3bd4 Also encode > and ' 2014-08-20 19:20:12 +02:00
Jörn Friedrich Dreyer
a5aa04ce19 properly encode groups as json, not ',' separated 2014-08-19 11:29:09 +02:00
Bjoern Schiessle
1e692e56e1 set incognitoMode to true, getUser should always return false during public upload 2014-08-19 10:16:07 +02:00
Lukas Reschke
663daf4bc7 Merge pull request #10146 from owncloud/fix-8578-stable6
Update 3rdparty to replace fpassthru() in Sabre.
2014-08-17 19:11:10 +02:00
Jörn Friedrich Dreyer
8f0d89a986 check quota when trying to download a file via new -> web 2014-08-15 16:47:50 +02:00
Clark Tomlinson
6d6dfe2329 Merge pull request #10440 from owncloud/enforce-debug
Remove ability to trigger DEBUG mode via cookie
2014-08-15 09:18:33 -04:00
Lukas Reschke
b067848509 Merge pull request #10034 from owncloud/remove-es_MX-from-stable6
Remove es mx from stable6
2014-08-15 14:07:52 +02:00
Bjoern Schiessle
ca33b2af72 we need the recipient as a additional parameter to know for which share the notification was send 2014-08-14 17:51:16 +02:00
Vincent Petry
f82aed0075 Fix Upload button does not disappear
Tipsy tooltip must be hidden when the upload starts. Otherwise it covers
the progress bar and stays in DOM.

Backport of fa28c089fa and
90839b784f from master
2014-08-14 13:57:39 +02:00
Volkan Gezer
5e85790f5e Minor changes in config.sample
* appcodechecker accepts boolean.
* using different ports in trusted domains

Partially fixes #330
2014-08-13 22:57:06 +02:00
Bjoern Schiessle
ffe3bd1429 fix broken variable name, recoveryPasswordSupported is now recoveryEnabledForUser 2014-08-12 19:28:05 +02:00
Bjoern Schiessle
851d478691 add unit tests 2014-08-12 18:10:49 +02:00
Bjoern Schiessle
74a994c561 fix detection of system wide mount points 2014-08-12 17:59:21 +02:00
Lukas Reschke
534336162e Merge pull request #10344 from owncloud/backport-10096-stable6
in case $_POST['itemSourceName'] does not exist we simply default it to...
2014-08-11 21:31:53 +02:00
Thomas Müller
274de5af86 in case $_POST['itemSourceName'] does not exist we simply default it to null 2014-08-11 17:56:36 +02:00
Jean-Louis Dupond
2a34f530b2 backport of #9848
Fix memberOf detection. Fixes: #9835

Conflicts:
	apps/user_ldap/lib/wizard.php

Fix remarks in #9848

Conflicts:
	apps/user_ldap/lib/wizard.php

Fix initializing in #9848

do not change var names here
2014-08-11 17:29:48 +02:00
Frank Karlitschek
d046527409 Merge pull request #10315 from owncloud/clarify-encryption-descripti
clearify the use-case of this app
2014-08-10 17:11:31 -04:00
Lukas Reschke
e7f9c21fb3 clearify the use-case of this app
Backport of https://github.com/owncloud/core/commit/8a24e1eb9624 to stable7
2014-08-09 22:59:42 +02:00
Jörn Friedrich Dreyer
e1a77bdcc9 Merge pull request #9675 from owncloud/stable6-9647
[stable6] Add unit test for multi-user configuration loading
2014-08-09 02:41:33 +02:00
Robin McCorkell
6b38c1de68 Add unit test for multi-user configuration loading 2014-08-08 15:52:22 +02:00
Robin Appelman
be07def0af Prevent folder upload causing unexpected behavior 2014-08-07 15:43:38 +02:00
Andreas Fischer
66cccd4e4e Update 3rdparty to replace fpassthru() in Sabre. 2014-08-04 15:15:55 +02:00
Georg Ehrke
2c192a1b76 don't preload videos on public sharing, fixes #10042 2014-07-30 21:12:02 +02:00
Morris Jobke
ca29c8bab1 Fix template rendering for 'blank' templates 2014-07-30 10:34:13 +02:00
Thomas Müller
f00563c652 remove l10n folder - sync script and transifex config are no longer required on a stable branch 2014-07-29 22:51:15 +02:00
Thomas Müller
3368af82aa remove language es_MX 2014-07-29 22:48:21 +02:00
Vincent Petry
a66b2f56b9 Merge pull request #9575 from owncloud/fix-7038
Hack to avoid Agent DN + Password being overwritten by some ugly browser...
2014-07-22 18:25:45 +02:00
Thomas Müller
8d5081f58f Merge pull request #9776 from owncloud/backport-9738-stable6
Backport 9738 stable6
2014-07-22 16:42:31 +02:00
Lukas Reschke
f99f48e26a Remove uneeded strip_tags
This `strip_tags` seems to be completely unneeded and will cause problems with passwords containing stripped characters. (e.g. `<` or `>`)

Needs https://github.com/owncloud/core/pull/9735 to be merged first.
2014-07-22 15:43:52 +02:00
Andreas Fischer
6fb60e9d4a Extract Auth Header logic into new function handleAuthHeaders().
Conflicts:
	lib/base.php
2014-07-22 15:43:47 +02:00
Andreas Fischer
e8be18a8d8 Deduplicate user/password extraction from alternative HTTP headers. 2014-07-22 15:40:50 +02:00
Vincent Petry
3a27cc5221 Merge pull request #9109 from owncloud/stable6-extstorage-multiplemountpointconfig
[6.0.5] Fix merging of external storage configurations
2014-07-22 15:28:00 +02:00
Vincent Petry
a47aad8628 Merge pull request #9717 from owncloud/backport_9668
[encryption] update keys recursively if a folder was moved (oc6 backport)
2014-07-18 15:03:17 +02:00
Andreas Fischer
3e2e766f64 login() must be called after getServerPublicHostKey(). 2014-07-18 13:32:46 +02:00
Bjoern Schiessle
51185c1b53 make sure that we don't connect hooks multiple times 2014-07-18 12:12:32 +02:00
Bjoern Schiessle
6ef2acb82b check that the file proxies are enabled after each test 2014-07-18 10:57:16 +02:00
Bjoern Schiessle
304cf0b90c update keys recursively if a folder was moved 2014-07-18 10:57:16 +02:00
Arthur Schiwon
add4ce4319 Hack to avoid Agent DN + Password being overwritten by some ugly browsers with stored site credentials 2014-07-16 19:26:24 +02:00
Vincent Petry
68fa6e6620 Merge pull request #9511 from owncloud/stable6-download-button-public-folder
[stable6] Bring back the download button public folder
2014-07-15 17:36:45 +02:00
Vincent Petry
e4b4c6ce6f Merge pull request #9635 from owncloud/stable6-files_external_fix_readData
[stable6 backport] Permit personal mount points to be used for sharing
2014-07-15 17:11:49 +02:00
Robin McCorkell
82be3674c9 Permit personal mount points to be used for sharing
An issue existed where `readData` used `OCP\User::getUser()` to get the user
for personal mount points, which worked in all situations apart from when a
personal mount point was used for sharing, so the return from `getUser()` is
not the user that owns the share. As such, any personal mount points would not
work correctly when shared.

`readData` and `writeData` have been changed from using a `$isPersonal`
boolean to using a `$user` string|null. `$isPersonal = false` can now be
written as `$user = NULL` (or left out in the case of `readData`), and
`$isPersonal = true` can be written as `$user = OCP\User::getUser()`.

Backport of abfd7ec from master
2014-07-15 13:33:23 +02:00
Vincent Petry
c3c87b012a Merge pull request #9618 from owncloud/fix_8345
throw exception if file is to large for trash bin
2014-07-15 12:15:25 +02:00
Thomas Müller
2aabe31cb5 append file extension to the temporary file which contains the downloaded archive - in case of zip files fileinfo doesn't seem to return anything reliable 2014-07-14 20:12:40 +02:00
Bjoern Schiessle
afa8006d7c throw exception if file is to large for trash bin 2014-07-14 17:29:19 +02:00
blizzz
c83c1749ce Merge pull request #9581 from owncloud/backport-9500
Backport of #9500 to stable6
2014-07-11 13:30:22 +02:00
Arthur Schiwon
0477d56f5b do not write to appconfig or preference tables if the value is unchanged 2014-07-11 00:13:52 +02:00
Arthur Schiwon
b77298b76d don't trigger update from checkPassword, it is already called by userExists, this is enough. 2014-07-10 23:48:38 +02:00
Vincent Petry
d5d55412e1 Merge pull request #9523 from owncloud/stable6-fix-9302-master
[stable6] Upload abortion is now detected within the  OC_Connector_Sabre_File::put...
2014-07-09 17:58:54 +02:00
Thomas Müller
a8ec0a7ccc Upload abortion is now detected within the OC_Connector_Sabre_File::put()
OC_Connector_Sabre_AbortedUploadDetectionPlugin is pointless

Adding unit test testUploadAbort()

Backport of ea269f0 from master
2014-07-08 17:28:16 +02:00
Christopher T. Johnson
3c3ebd5cf9 Fix Signiture Does Not Match when mounting Amazon S3 external storage
For some reason the aws-sdk-php package does not caclulate the
signiture correctly when accessing an object in a bucket with a name of
'.'.

When we are at the top of a S3 bucket there is a need(?) to have a directory
name.  Per standard Unix the name picked was '.' (dot or period).  This
choice exercises the aws-sdk bug.

This fix is to add a field to the method to store the name to use instead of
'.' which at this point is hard coded to '<root>'.  We also add a private
function 'cleanKey()' which will test for the '.' name and replace it with
the variable.  Finally all calls to manipulate objects where the path is
not obviously not '.' are processed through cleanKey().

An example where we don't process through clean key would be
	'Key' => $path.'/',

Use correct relationship operator

Per feed back use === instead of ==

use '/' instead of '<root>'
2014-07-08 14:37:55 +02:00
Thomas Müller
fca5af206f disable download button if zip download is disabled
Backport of 6e75b37
2014-07-08 10:44:35 +02:00
Jan-Christoph Borchardt
bfe76fa9e2 fix position and look of public download button
Backport of 899c7c0 from master
2014-07-08 10:40:50 +02:00
Jan-Christoph Borchardt
d9e9191248 remove unneeded header-right details styles
Backport a280a69
2014-07-08 10:39:41 +02:00
Thomas Müller
bbc997aa5e remove file name from upper right button
Backport of 003049e from master
2014-07-08 10:26:10 +02:00
Thomas Müller
114ce30153 reintroduce download button on public shares
Backport of df32254 from master
2014-07-08 10:24:14 +02:00
Arthur Schiwon
3bec0dc4f1 Backport of #9156 2014-07-04 15:17:20 +02:00
Björn Schießle
b87591a537 Merge pull request #9250 from owncloud/enc_check_if_file_exists_oc6
[encryption] check if file exists (OC6)
2014-07-01 11:15:21 +02:00
Bjoern Schiessle
46ade71b5a improved error message 2014-06-30 16:32:20 +02:00
Bjoern Schiessle
22cef86b91 unit tests 2014-06-27 23:13:28 +02:00
Bjoern Schiessle
cf46391f7c check if file exists before deleting keys, and add debug output for every
delete operation
2014-06-27 23:13:28 +02:00
Vincent Petry
ff8cd422b5 Merge pull request #9251 from owncloud/enc_always_find_mount_point
[encryption] make sure that we always detect the system wide mount point
2014-06-27 16:49:01 +02:00
Bjoern Schiessle
e8167999dc normalize path before comparison to make sure that we always find the mount point 2014-06-27 12:20:29 +02:00
Björn Schießle
e14e4f1dc4 Merge pull request #9173 from owncloud/enc_always_use_oc_filesview_oc6
[encryption] always use oc filesview, backport for OC6
2014-06-26 15:11:55 +02:00
Morris Jobke
28eabc15bf Merge pull request #9219 from owncloud/stable6-trashwarning
[stable6] Fix trashbin warnings in logs
2014-06-26 13:40:33 +02:00
Vincent Petry
a609d5e031 Do not retrieve storage stats for trash bin 2014-06-26 10:56:18 +02:00
Vincent Petry
da7641c232 Remove etag warning in trashbin
When previews are available, the etag attribute is used for the icon.
But when none is set, a warning is shown.

This fix uses the timestamp as a dummy etag.
2014-06-26 10:50:59 +02:00
Morris Jobke
2e264b3a02 Merge pull request #9197 from owncloud/fix_dir_seperator_oc6
always use '/' as dir seperator
2014-06-25 11:03:29 +02:00
Bjoern Schiessle
9a44862979 always use '/' as dir seperator 2014-06-24 18:45:22 +02:00
Frank Karlitschek
e4fb6d536b 6.0.4 2014-06-24 09:44:53 -04:00
Bjoern Schiessle
46cc6f5747 always use a \OC\Files\View 2014-06-23 22:06:50 +02:00
Bjoern Schiessle
b66d3632ea always use oc filesystem for rename operation 2014-06-23 17:44:05 +02:00
Frank Karlitschek
feca3d0ea9 Merge pull request #9075 from owncloud/autosetup-trusteddomains
trusted domains shall not be ignored on autosetup
2014-06-20 16:56:37 -04:00
Arthur Schiwon
6eb39f2194 Backport subset of #4179, re-established Oracle compatibility for LDAP 2014-06-20 20:47:51 +02:00
Vincent Petry
26ded10052 Fix merging of external storage configurations
Merging of configurations is whenever the same config is available for
multiple users/groups, in which case the config is considered as a
single one by the UI, and shows multiple users/groups selected.

Fixed merging logic to make sure that class, mount point and options are
the same before merging them.

Fixed merging to work correctly when the same mount point path is used
for separate users and configs. These are now correctly shows in the UI
as separate entries.

Backport of e002b72 from master
2014-06-19 18:26:12 +02:00
Arthur Schiwon
267c0ff567 trusted domains shall not be ignored on autosetup 2014-06-17 23:15:32 +02:00
blizzz
4b843dfcd1 Merge pull request #9002 from owncloud/ldap_wizard_pagedsearch
LDAP Wizard: get correct total no of users, groups and complete list of groups on big setups
2014-06-17 10:04:57 +02:00
Frank Karlitschek
508d84dcd8 6.0.4 beta 1 2014-06-17 08:48:46 +02:00
Arthur Schiwon
58d04d1772 remove unused vars; increase scrutinizer happiness 2014-06-16 17:52:12 +02:00
Arthur Schiwon
9caa354cfc simplify two methods a bit, because they are not used for group search anymore 2014-06-16 17:52:12 +02:00
Arthur Schiwon
0ba9a6b73d make all this work in an early configuration state in the wizard by marking the config active and ignoring the validation state. 2014-06-16 17:51:31 +02:00
Arthur Schiwon
c491fa272e Wizard: get really all groups from LDAP by power of Paged Search 2014-06-16 17:51:31 +02:00
Arthur Schiwon
e23e459c41 fix PHPdoc 2014-06-16 17:51:31 +02:00
Arthur Schiwon
78feb6514b consolidate requirement check 2014-06-16 17:51:31 +02:00
Arthur Schiwon
1c634ab772 LDAP Wizard: count users and groups with the power of paged search 2014-06-16 17:51:31 +02:00
Arthur Schiwon
53e036e5c0 add method to count groups on LDAP 2014-06-16 17:51:31 +02:00
Arthur Schiwon
f56a9c08f8 fix PHPdoc 2014-06-16 17:51:31 +02:00
blizzz
659a3d4a37 Merge pull request #8623 from owncloud/fix-8457
LDAP: fix possible infinite loop, that causes hanging wizard, fixes #8457
2014-06-16 17:42:46 +02:00
Lukas Reschke
3d26896431 Merge pull request #9033 from owncloud/validate-dire
Add deprecation notice to load* functions
2014-06-16 16:20:21 +02:00
Vincent Petry
f6c970e214 Merge pull request #9008 from owncloud/repair-parent-stable6
Repair broken parent link in the scanner - stable6
2014-06-16 15:00:22 +02:00
Robin Appelman
84222e30a7 Fix unit test 2014-06-16 13:37:08 +02:00
Lukas Reschke
81fc7cfb21 Add deprecation notice to load* functions
This functions are deprecated and/or removed since ownCloud 7. Additionally a issubdirectory check has been added here to prevent developers to use this function in a potentially insecure way.

Please review @karlitschek and others. Backport to stable5 and master requested.
2014-06-14 11:05:12 +02:00
Morris Jobke
04817fb0f3 Merge pull request #9015 from owncloud/stable6-downloadwithdisabledzip
[stable6] Fix public download link when zip download is disabled
2014-06-13 13:09:41 +02:00
Vincent Petry
bca536eb3d Merge pull request #8988 from owncloud/stable6_fix_encryption
Stable6 fix encryption
2014-06-13 10:31:18 +02:00
Morris Jobke
64534546be Merge pull request #9016 from owncloud/stable6-maxheartbeatinterval
[stable6] Added max heartbeat interval to prevent integer overflow
2014-06-13 00:19:36 +02:00
Vincent Petry
00ec5fc193 Added max heartbeat interval to prevent integer overflow
When using big session timeout values, the interval value might overflow
and cause the setInterval() call to ping the server in a loop without
any delay.

This fix adds a maximum ping interval of 24 hours.
2014-06-12 18:27:21 +02:00
Vincent Petry
8ef1542ad0 Fix public download link when zip download is disabled
When zip download is disabled, the public download action defined in
public.js is overridden by the one in fileactions.js because of the JS
loading order.

This quick fix prevents the override to happen when a download action is
already defined.

There are additional changes that were required to make the download
action icon work when registered from the public page.
2014-06-12 17:29:55 +02:00
Robin Appelman
eeca726d28 remove unused argument 2014-06-12 15:07:05 +02:00
Robin Appelman
e793a87954 add some comments 2014-06-12 15:06:01 +02:00
Robin Appelman
6e0a218d11 Repair broken parent link in the scanner 2014-06-12 15:05:45 +02:00
Jörn Friedrich Dreyer
b2fae8a8b7 Fix copy conflict dialog translation
backport of fileexist template translations
with minor fixes
2014-06-11 20:25:10 +02:00
Bjoern Schiessle
193d237b56 fix rename of encryption keys 2014-06-11 18:38:20 +02:00
Vincent Petry
4bc091965f Merge pull request #8970 from owncloud/cache-change-propagator-stable6
Cache change propagator stable6
2014-06-10 17:17:35 +02:00
Robin Appelman
3ea94a7930 Fix unit tests 2014-06-10 16:32:46 +02:00
Robin Appelman
129bfad204 Fix size calculation during recursive scan 2014-06-10 16:24:08 +02:00
Robin Appelman
4d7e1c568c Fix unit tests 2014-06-10 16:24:00 +02:00
Robin Appelman
f36e354a42 Fix recursive scanning 2014-06-10 16:20:59 +02:00
Robin Appelman
81f6e78c0c propagate changes in the scanner 2014-06-10 16:20:51 +02:00
Robin Appelman
a543f46699 Split of cache writes in the scanner to their own methods 2014-06-10 16:20:48 +02:00
Robin Appelman
2895261102 Add a change propagator class to handle propagating etag and mtime changes 2014-06-10 16:16:46 +02:00
Thomas Müller
2911906586 Merge pull request #8885 from owncloud/flock-stable6
[stable6][WIP] Move Flock basics into stable6
2014-06-06 17:58:08 +02:00
Thomas Müller
909913d581 fix failing unit test 2014-06-06 15:48:02 +02:00
Jan-Christoph Borchardt
edced60ed4 keep long file names in one line to not overflow download button on mobile 2014-06-06 15:35:12 +02:00
Jan-Christoph Borchardt
45d165405f add max-width to directLink input to prevent overflow 2014-06-06 15:34:36 +02:00
Robin Appelman
e98627d6ab Dont backport unit tests for code that isn't backported 2014-06-05 16:48:04 +02:00
Thomas Müller
a4c422a6da added missing LockNotAcquiredException 2014-06-05 16:48:03 +02:00
ringmaster
6ec29711fc Continued flock work.
add actual locking and log changes necessary for debugging.

Simpler log unique id.

Respect locked files, surface correct exception.

Conflicts:
	lib/private/connector/sabre/file.php

Remove unused methods.

Conflicts:
	lib/private/files/storage/local.php

Fix typo

Fix typo

Removed unused vars/declarations, update PHPDoc.

Don't error out on console.

Move Lock to private namespace, add interface. Update PHPDoc.

Restore the reference to this used exception class.

make sure to close the stream at the end of each test

Normalize lock exception messages.

don't ask for fileInfo if we already have one

Conflicts:
	apps/files_encryption/lib/proxy.php

name the storage wrapper to make sure that we don't apply the wrapper multiple times

Conflicts:
	lib/private/util.php

fix unit test after adding the additional parameter to addStorageWrapper()

only lock if unlink is called for a file

Can't use assertInstanceOf on wrapped storage; use assertTrue(instanceOfStorage() instead.

Conflicts:
	tests/lib/files/filesystem.php

Use ->instanceOfStorage() not instanceof for Storage instances.

Conflicts:
	lib/private/helper.php

get the storage from the view

Conflicts:
	apps/files_encryption/tests/webdav.php

workaround to get the unit test going

Conflicts:
	apps/files_encryption/hooks/hooks.php

Added isLocal() method to storage, used for xsendfile

Added isLocal() method to Storage to find out whether the storage is
local or not.
This method is used for the x-sendfile logic to find out whether to add
the headers.

Conflicts:
	lib/private/files.php

Add ->instanceOfStorage to handle instanceof for storage wrappers

Conflicts:
	lib/private/files/storage/common.php
	lib/private/files/storage/wrapper/wrapper.php
	lib/public/files/storage.php

Use instanceOfStorage instead of instanceof

Conflicts:
	lib/private/files.php

Fix storage wrapper being called with null

Pass any methods custom to specific storage implementations to the wrapped storage

remove duplicate declaration of isLocal()

remove file locking - code will continue to live in it's own app
2014-06-05 16:47:37 +02:00
Vincent Petry
49f2955119 Merge pull request #8870 from owncloud/storage-instanceof-stable6
Add storage->instanceOfStorage() - stable6
2014-06-05 11:16:08 +02:00
Robin Appelman
b62ba9808a Pass any methods custom to specific storage implementations to the wrapped storage 2014-06-04 14:30:40 +02:00
Robin Appelman
f814b9a23c Fix storage wrapper being called with null 2014-06-04 14:30:17 +02:00
Robin Appelman
b3c8b574df Use instanceOfStorage instead of instanceof 2014-06-04 14:29:55 +02:00
Robin Appelman
79b953a920 Add ->instanceOfStorage to handle instanceof for storage wrappers 2014-06-04 14:17:52 +02:00
Thomas Müller
d3445d9668 Merge pull request #8847 from owncloud/stable6_backport_8557
Stable6 backport of #8557
2014-06-04 10:26:59 +02:00
Thomas Müller
e5dcec75ba Merge pull request #8850 from owncloud/stable6_backport_8607
[backport] [stable6] Skip filescan but execute hooks
2014-06-04 09:34:39 +02:00
ringmaster
a908e281e7 [backport] [stable6] Skip filescan but execute hooks
Backport of #8607
2014-06-03 10:52:12 -04:00
ringmaster
2910486979 Allow apps to create custom session handlers. 2014-06-03 10:20:42 -04:00
blizzz
58b6b89ec4 Merge pull request #8579 from owncloud/ldap_nail_filter_on_upgrade
LDAP: fix filter can be reset and broken after upgrade from OC 5
2014-06-02 12:02:15 +02:00
Frank Karlitschek
8758b66fc4 Merge pull request #8672 from owncloud/stable6-obfuscatepasswords
[backport] [stable6] Added password obfuscation for external storage config
2014-06-02 11:56:36 +02:00
Thomas Müller
8429dde4d9 Merge pull request #8692 from owncloud/fix_unit_tests_oc6
fix failing unit tests on OC6
2014-05-28 17:44:40 +02:00
Arthur Schiwon
37ef48d9f4 simpler and better readable assignment 2014-05-28 17:24:04 +02:00
Thomas Müller
776d656ea9 Merge pull request #8683 from owncloud/log-upload-error-stable6
Log upload error stable6
2014-05-28 13:07:18 +02:00
Thomas Müller
d17335d7a8 fix expectation - same as in master 2014-05-27 23:44:09 +02:00
Jan-Christoph Borchardt
84b239f123 reduce multiselect max-width from 400 to 200px to not take too much space 2014-05-27 14:32:23 +02:00
Bjoern Schiessle
ab3b713c23 don't expect depreciated OC_FilesystemView 2014-05-23 15:13:59 +02:00
Thomas Müller
1eedab7f6e php upload errors are written to log 2014-05-23 11:45:35 +02:00
Vincent Petry
9a5da34721 Added password obfuscation for external storage config
Added obfuscation for all "password" options from external storages.
Added more ext storage unit tests config.
Added unit tests for reading/writing the configuration.
Added IV for ext storage password encryption
Moved the mounting code for external storage from
OC\Filesystem::initMountPoint to files_external using the post_initMountPoints hook
Fixed ext storage unit test for groups

Squashed backport of 2c561c9c50 from
master.
2014-05-22 12:29:15 +02:00
Bjoern Schiessle
6f29e1c67b only start migration if the encryption was initialized; allow to overwrite keys if no files exists 2014-05-21 17:36:39 +02:00
Arthur Schiwon
516f75fc6b add unit test to make sure the infinite loop never comes back 2014-05-16 18:03:40 +02:00
Arthur Schiwon
9f405339d6 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 2014-05-16 18:03:15 +02:00
tomneedham
419e0354d5 Only accept success as 100 like the OCS spec does 2014-05-14 19:24:08 +00:00
Arthur Schiwon
313324a7b4 bump version and don't overwrite values on next update if not necessary 2014-05-14 13:27:23 +02:00
Arthur Schiwon
c18f2943d5 get the correct version number for compare -.- 2014-05-14 12:01:41 +02:00
Vincent Petry
0c355cb1fb Fixed getAbsolutePath case when path is "0"
Make sure to correctly check for string emptiness when the passed path
is "0".

Backport of bab8c1f from master
2014-05-13 21:17:33 +02:00
Arthur Schiwon
68434510bd LDAP: set filter mode to raw, so filters will not be changed and broken after upgrade from oc5, when visiting the LDAP settings and opening filter tabs 2014-05-13 17:47:00 +02:00
Lukas Reschke
1e6b4576c2 Harden issubdirectory()
realpath() may return false in case the directory does not exist since we can not be sure how different PHP versions may behave here we do an additional check whether realpath returned false
2014-05-12 09:10:35 +02:00
Vincent Petry
8c1eff8f52 Merge pull request #8521 from owncloud/stable6-shareextstoragemountpointfix
[stable6] Fix sharing of ext storage mount points
2014-05-09 16:57:53 +02:00
Vincent Petry
37e29169e0 Fix getPathById for Oracle
Added extra code to handle the case of Oracle which saves empty strings
as null values.

Backport of 05dc694 from master
2014-05-09 14:37:26 +02:00
Vincent Petry
b91e3be5de Added unit test for sharing ext storage mount points
Backport of f73a168 from master
2014-05-09 14:37:16 +02:00
Vincent Petry
113cd404c0 Fix sharing of ext storage mount points
When sharing an ext storage mount point, it will now use the name of the
mount point instead of an empty string for the target path.

Backport of 28f0e63 from master
2014-05-09 14:37:07 +02:00
Robin Appelman
d2dbab21fb Fix getPath for storage roots 2014-05-07 21:51:10 +02:00
Vincent Petry
a152f3a50f Added PostgreSQL version warning + log on upgrade
Backport of 3cd09f2, a25b86a, 6bfeb34 from master
2014-05-07 12:15:55 +02:00
Morris Jobke
c341a971f8 fix getUserFolder() of server container 2014-05-05 23:09:06 +02:00
Georg Ehrke
1d2dc9b685 fix issue with spamming logging files when loading cached thumbnail
Conflicts:
	lib/private/preview.php
2014-05-05 16:04:05 +02:00
Bjoern Schiessle
4e1d57e815 always encrypt files to owner 2014-05-05 12:05:36 +02:00
Fabian Henze
76cdd85cd9 Add unit tests for OC_Helper::phpFileSize function 2014-05-03 13:04:10 +02:00
Fabian Henze
6f8a24c2cd Fix setting the max-upload-size for really large values.
php can only parse filesize units up to gigabytes, not terabytes or petabytes.
2014-05-03 13:03:59 +02:00
Frank Karlitschek
835025e569 6.0.3 2014-04-29 02:38:18 +02:00
Lukas Reschke
821ad6ad41 Merge pull request #8389 from owncloud/reset-3rdparty-stable6
Update 3rdparty
2014-04-28 22:25:43 +02:00
Thomas Müller
3fe45b1d4c Update 3rdparty 2014-04-28 20:38:48 +02:00
Thomas Müller
86757cdb45 Merge pull request #8384 from owncloud/kill_office_fallback_stable6
backport b68098ebba to stable6
2014-04-28 20:29:06 +02:00
Volkan Gezer
65ea07fc54 Update outdated comment 2014-04-28 20:24:17 +02:00
Georg Ehrke
a3d93f0ba1 backport b68098ebba to stable6 2014-04-28 15:42:48 +02:00
Lukas Reschke
283a8b9624 Clarify the trusted_domain error page
Backport of https://github.com/owncloud/core/pull/8372
2014-04-27 18:34:35 +02:00
Lukas Reschke
dacacacc4f Revert "Clarify the trusted_domain error page"
This reverts commit 4f9a5c9d3c.
2014-04-27 18:33:50 +02:00
Lukas Reschke
4f9a5c9d3c Clarify the trusted_domain error page
Conflicts:
	lib/base.php
2014-04-27 18:32:28 +02:00
Lukas Reschke
e5def25f40 Add another example to the trusted_domains config
Users often ask in IRC or the forum how to add another domain.
Hopefully they will be able to find it out on their own if we have an example with two domains.
2014-04-26 23:13:48 +02:00
Morris Jobke
2c92ef9e64 Merge pull request #8365 from owncloud/stable6-external-storage-css-fix
fix layout of external storage config table
2014-04-26 10:34:36 +02:00
Morris Jobke
16ae62f246 fix layout of external storage config table
Conflicts:
	apps/files_external/css/settings.css
2014-04-26 00:45:45 +02:00
Frank Karlitschek
53df9c93c4 6.0.3 RC1 2014-04-23 16:49:44 +02:00
blizzz
14c95086a9 Merge pull request #7745 from owncloud/fix_6946_stable6
Group Database backend must not gather user details itself but ask user backends, fixes #6946 in stable6
2014-04-23 16:30:26 +02:00
Lukas Reschke
4696b06060 Merge pull request #8261 from owncloud/stable6-backport-8182
Backport of #8182
2014-04-23 14:37:07 +02:00
Arthur Schiwon
0a9487ec80 fix after rebase 2014-04-23 13:55:21 +02:00
Arthur Schiwon
fcffccf018 keep the constant to not provoke PHP warnings 2014-04-23 13:35:01 +02:00
Arthur Schiwon
72b90816fa trim must not be used in empty in PHP < 5.5 2014-04-23 13:35:00 +02:00
Arthur Schiwon
6aeb5996b6 test for group manager's displayNamesInGroup 2014-04-23 13:35:00 +02:00
Arthur Schiwon
af45da94b3 adjust user manager tests 2014-04-23 13:35:00 +02:00
Arthur Schiwon
f93ab1105f implement getDisplayNames in group manager 2014-04-23 13:35:00 +02:00
Arthur Schiwon
637aa56197 remove now unnecessary test 2014-04-23 13:34:56 +02:00
Arthur Schiwon
649233e54c clean up group backends 2014-04-23 13:34:56 +02:00
Arthur Schiwon
8d00f1ca1f LDAP: getDisplayNamesInGroup is not an option for group backends anymore 2014-04-23 13:34:56 +02:00
Arthur Schiwon
60edf98c15 remove OC_GROUP_BACKEND_GET_DISPLAYNAME option for group backends 2014-04-23 13:34:56 +02:00
Thomas Müller
1041617a4e Merge pull request #8260 from owncloud/stable6-backport-8183-and-co
Backport of #8183 and #8197
2014-04-23 12:04:09 +02:00
ben-denham
a314508543 Backport of #8164
Added improved version of patch by @blizzz in https://github.com/owncloud/core/issues/6651#issuecomment-32261257 to stop filter settings from being reset under a race condition.

Moved LdapFilter into a separate js file in user_ldap.

Changed conditions in user_ldap's ldapFilter.js to use ===, fixed indentation.

fix comparison in determineMode, fixes problems with restoring the filter mode (assisted or manually) on page refresh

Give hint when composing filter failed

fixing some JSHint warnings
2014-04-23 11:21:28 +02:00
Thomas Müller
74241140d2 Update 3rdparty submodule 2014-04-22 23:59:03 +02:00
Lukas Reschke
d3a15b6b07 Check whether the user has permissions to add personal storage backends
Quick’n dirty back port of #8182 - master has a better fix but that
should be good enough…

missing return - OCP\JSON::success does not terminate the PHP process - which is good ;-)

Use error instead of success

Revert "Use error instead of success"

This reverts commit e2d5535a5aa436c3896e46f0b9e8ff1bd5640d4d.

Use error instead of success
2014-04-22 23:20:32 +02:00
blizzz
1403a85950 Merge pull request #8232 from owncloud/fix_8135
LDAP: optimize retrieval of displaynames, fixes #8135
2014-04-22 18:35:47 +02:00
Bernhard Posselt
130f2419f5 Merge pull request #8265 from owncloud/appframework-fix-backports
Appframework fix backports
2014-04-18 22:29:57 +02:00
Bernhard Posselt
a53ec9ebeb merge middleware string registration 2014-04-18 16:17:58 +02:00
Bernhard Posselt
33bdab1618 use references for middleware to fix problems on 5.3 2014-04-18 16:14:46 +02:00
Bernhard Posselt
3405342ab6 merge dicontainer 2014-04-18 16:14:44 +02:00
Bernhard Posselt
980b11f096 default to GET request when no method is set to fix unittests, also set parsed json parameters on the post attribute 2014-04-18 16:13:10 +02:00
Bernhard Posselt
22485fe743 Correctly process request parameters other than GET or POST, dont use globals in the class but inject it 2014-04-18 16:13:01 +02:00
Lukas Reschke
a7bc716b95 Merge pull request #8259 from owncloud/backport-7682-6
Backport #7682
2014-04-18 11:36:59 +02:00
Lukas Reschke
9b36224bd4 Backport of #8197 to stable6
This extends mimetypes.list.php to be a white-list of known secure mime
types as well as offering secure alternatives for know potentially
malicious mime types.
I kept this in the OC_Helper and OC\Files\Type\Detection classes as
each backend has its own way of detecting mime types.

This supersedes #8184 as discussed in owncloud/security-tracker#56
2014-04-18 11:19:47 +02:00
Lukas Reschke
9f1788f202 Backport of #8183 to stable6
Some headers were currently only added to the templates but not to
other components (e.g. SabreDAV / JSON / etc...)
The migration to base.php ensures that the headers are served to all
requests passing base.php
2014-04-18 11:13:47 +02:00
Lukas Reschke
a30040411c Backport of #7682 to stable6 2014-04-18 10:36:04 +02:00
Lukas Reschke
c4d4065dc2 Use JS as content-type due to mimesniffing 2014-04-17 17:15:35 +02:00
Robin Appelman
d4be12ab21 Verify that a file exists before we share it 2014-04-17 12:32:52 +02:00
Arthur Schiwon
02de48e1ba add additional comments, PHPdoc and check whether it's really applicable 2014-04-16 17:16:51 +02:00
Arthur Schiwon
97d6db966c LDAP: cache display names immediately on retrieval, saves tens of unecessary queries to LDAP server in the share dialog for example 2014-04-16 12:56:08 +02:00
Arthur Schiwon
cf2fc58c65 Backport of PR #7815, correct LDAP user count on setup with many users
(occ user:report)

LDAP: make sure cache key for paged result cookie matches when limit or offset is null or 0

LDAP: fix user report i.e. count for LDAP servers with really many users

initialize variable

var count is assigned in the inner loop so it must be checked inside there to be properly used as part of the exit condition of the outer loop

Put inner loop into own method, let's see whether it makes scrutinizer happier
2014-04-16 11:15:16 +02:00
Arthur Schiwon
e1b1ce684d adjust tests accordingly 2014-04-15 19:16:02 +02:00
Arthur Schiwon
793f20d728 Remove limit and offset manipulation when getting users or groups, because it does not work when more than one user or group backend. Fixing it would be too costly performancewise, so we switch back to the model used in OC 5: limit and offset are effective per backend, and not a general constraint 2014-04-15 19:15:55 +02:00
blizzz
15ebb4b8ad Merge pull request #8166 from owncloud/ldap_update_email
Also check for email address on userExists (next to Avatar and Quota)
2014-04-14 10:23:57 +02:00
Arthur Schiwon
80a294b334 LDAP: fetch email from LDAP on userExists check as well (along to Quota and Avatar) 2014-04-11 18:33:58 +02:00
Thomas Müller
6636c14c2a Merge pull request #8150 from owncloud/backport-8138-stable6
To isolate the variable scope used inside the $file it is required in i...
2014-04-11 12:30:18 +02:00
Bernhard Posselt
bf898f90bc Merge pull request #8151 from owncloud/backport-8137-stable6
add requirements to routing
2014-04-10 21:34:57 +02:00
Bernhard Posselt
de7a3861f3 Merge pull request #8119 from Raydiation/stable6
Remove dependency on container, removing service locator antipattern
2014-04-10 19:41:10 +02:00
Vincent Petry
d4951c68f3 Fixed Sabre Node implementation to correctly return timestamps as int
Negative timestamps were returned as string and were confusing other

Sabre API like Sabre_DAV_Property_GetLastModified.

This fix makes sure the timestamp is returned as int when defined.

Backport of 4f11786 from master
2014-04-10 17:46:36 +02:00
Vincent Petry
85e90c33fc Merge pull request #8148 from owncloud/backport-6676-stable6
Disabled internet checking as mentioned when in proxy mode
2014-04-10 17:28:00 +02:00
Bernhard Posselt
22632a227c Update controller.php
Backwards compability fix for faster merge ;)
2014-04-10 16:43:57 +02:00
Bernhard Posselt
fc8004d335 add requirements to routing
Conflicts:
	tests/lib/appframework/routing/RoutingTest.php
2014-04-10 16:25:44 +02:00
Thomas Müller
2149670328 fix code formatting 2014-04-10 16:20:42 +02:00
Thomas Müller
2741eb1fe3 To isolate the variable scope used inside the $file it is required in it's own method - refs #8138 2014-04-10 16:15:04 +02:00
Joan
b09614b61b Disabled internet checking as mentioned when in proxy mode 2014-04-10 15:48:04 +02:00
Morris Jobke
2257ae987f Merge pull request #8123 from owncloud/fix_filename_closing_tag
fix double closing </a> for filenames
2014-04-09 13:41:08 +02:00
Arthur Schiwon
88949d7f94 Backport of PR #7837 to stable6
LDAP Wizard: when determining objectclasses, we realy do not need to look at every entry. Fixes #7530

Conflicts:
	apps/user_ldap/lib/wizard.php

Fix wildcard handling and check even less DNs per filter, enough will be looked at anyway

Use the LDAP wrapper for checking resources, needs for proper testing

fix potential infinite loop when the DN of the first entry was already read.

add tests for cumulativeSearchOnAttribute

make tests work on systems without php5_ldap

define var

add comment to clearify when a skip in the foreach happens
2014-04-09 12:45:36 +02:00
Jörn Friedrich Dreyer
e34d00a958 fix double closing </a> for filenames 2014-04-09 11:23:57 +02:00
Bernhard Posselt
6b15731bfe Remove dependency on container, removing service locator antipattern 2014-04-08 22:48:57 +02:00
Vincent Petry
be30728bc2 Fixed chunking and insufficient storage check
- fixed free space detection based on the already uploaded chunks
- now deleting chunks as soon as it is read out before writing it into
  the part file, which reduces the space needed when assembling part
files

Backport of 4033eba from master
2014-04-07 09:48:07 +02:00
Vincent Petry
d34e1b524a Do not expire chunks while checking for their existence
The expiration should be done by the gc() function on login, not while
isComplete() is calling hasKey() for every chunk.

Backport of ab56f69416 from master
2014-04-04 17:17:53 +02:00
blizzz
3debb33346 Merge pull request #8038 from owncloud/fix_8028
Meanwhile, the quota value is stored human-readable in the DB
2014-04-04 16:34:48 +02:00
Robin Appelman
79635ccb41 Add bindParam to statement wrapper 2014-04-04 15:12:51 +02:00
Robin Appelman
d8097b48ea fix unit tests 2014-04-04 13:07:14 +02:00
Thomas Müller
1116455b3f Merge pull request #8037 from owncloud/fix-7216
authentication apps need to be loaded in any case - fixes #7216
2014-04-03 23:05:41 +02:00
Arthur Schiwon
09802ac217 Meanwhile, the quota value is stored human-readable in the DB 2014-04-03 20:51:05 +02:00
Thomas Müller
984586c20a authentication apps need to be loaded in any case - fixes #7216 2014-04-03 20:47:38 +02:00
Robin Appelman
a591160c32 use a non-recursive chmod on the datadir 2014-04-03 13:42:35 +02:00
Robin Appelman
6dd3215eae Improve phpdoc 2014-04-03 13:27:09 +02:00
Robin Appelman
e96c365054 Implement getPath for shared files 2014-04-03 13:27:01 +02:00
Robin Appelman
2150cac956 Give storages the option to implement the getById behaviour for View->getPath 2014-04-03 13:26:54 +02:00
blizzz
096b4d8b1b Merge pull request #7931 from owncloud/fix_7785_stable6
LDAP: Read email and quota when mapping user, fixes #7785
2014-04-02 19:24:22 +02:00
Volkan Gezer
47e3e73c8f Fix admin-dir_permissions redirection when cannot write warning
is shown.
2014-04-02 14:51:06 +02:00
Arthur Schiwon
519ab3a9c8 more precise php doc 2014-04-02 11:01:29 +02:00
Arthur Schiwon
5df99d3e61 add PHP docs 2014-04-01 21:57:01 +02:00
Jan-Christoph Borchardt
bd5eec7bb7 general styles for the content area 2014-04-01 18:55:37 +02:00
Rodrigo Hjort
2086e80e4d Correction: failure on sharing when user ID was prefixed by zero
Backport of 51b727c from master
2014-04-01 18:42:10 +02:00
Vincent Petry
f84168253b Merge pull request #7976 from owncloud/fix-7973-stable6-2
remove pl_PL - fixes #7973
2014-04-01 18:41:33 +02:00
Thomas Müller
a390bd2e73 Revert "remove Sabre_DAV_Browser_Plugin"
This reverts commit e4104e63d9.
2014-04-01 13:42:58 +02:00
Thomas Müller
456f02b476 remove pl_PL - fixes #7973 2014-03-31 18:10:12 +02:00
Bjoern Schiessle
027de54558 don't write file if opening a stream to encrypt the data fails 2014-03-28 15:00:27 +01:00
Arthur Schiwon
7dd34b1212 LDAP: Read email and quota when mapping user, fixes #7785 2014-03-28 12:18:24 +01:00
Jörn Friedrich Dreyer
24274acd6a don't block php session while download is in progress 2014-03-28 11:41:58 +01:00
Morris Jobke
5099caa55a Merge pull request #7901 from owncloud/fixed_position_ocdialogdim
prevent dimmed ocdialog div from scrolling
2014-03-28 02:43:08 +01:00
Vincent Petry
17e5c03a02 Fix swift touch operation
The touch() operation now uses "UpdateMetadata()" instead of "Update()"
which doesn't clear the object's contents.

This fixes syncing, as the sync client needs to use touch to update the
object's mtime.

Backport of 2a08e35 from master
2014-03-27 18:39:57 +01:00
Vincent Petry
a31b37e733 Fixed mtime reading from OpenStack API
The API seems to return floating point values, which prevents
the hasUpdated() check to work and causes the scanner to rescan
everything every time.

Backport of fa00a18 from master
2014-03-27 17:59:39 +01:00
Jörn Friedrich Dreyer
35e4784202 prevent dimmed ocdialog div from scrolling 2014-03-26 17:48:33 +01:00
Thomas Tanghus
f464620a65 Fix 'Undefined variable: message' in OCP\Util::logException 2014-03-25 18:07:07 +01:00
Arthur Schiwon
2d639b83ab add test for cloning and keeping configuration seperate 2014-03-21 18:03:05 +01:00
Arthur Schiwon
406747ab30 Use array_key_exists instead of isset, because the latter returns false if the assigned value is null 2014-03-21 18:02:59 +01:00
Arthur Schiwon
b41c1d7655 On clone create a new instance of the Configuration
To avide effects on the original instance of Connection when the clone
is modified, for instance on authentication checks.
2014-03-21 18:02:53 +01:00
Vincent Petry
b10b8a470b Fixed warning when browsing Shared folder
The virtual "Shared" folder doesn't have an unencrypted_size field.
This fix adds a check to prevent warnings in the log.

Backport of 022d76c from master
2014-03-21 17:56:56 +01:00
Thomas Müller
23ffdcc314 Merge pull request #7840 from owncloud/fix/7839
fixing wrong html close tags
2014-03-21 12:54:55 +01:00
Vincent Petry
ffdbdf7496 Merge pull request #7834 from owncloud/stable6-quota-usequotaevenwhenfreespaceunknown
[stable6] [backport] Still return quota value when free space is unknown
2014-03-21 12:29:19 +01:00
Thomas Müller
df636371a7 fixing wrong html close tags 2014-03-21 12:15:02 +01:00
Robin McCorkell
ceff4dae61 Fix duplicate ipauniqueid 2014-03-21 11:30:00 +01:00
Robin McCorkell
540d4af8a7 Add FreeIPA UUID compatibility, fixes #7796
Ability to use ipauniqueid for the UUID of a user
2014-03-21 11:29:50 +01:00
Vincent Petry
bb995c53c5 Still return quota value when free space is unknown
Fixed the quota storage wrapper to correctly return the quota value
when the free space is not known (which usually happens when the
disk_free_space function is disabled)

Backport of 66bc0f0 from master
2014-03-21 10:25:43 +01:00
Vincent Petry
eacb4b3f3e Return unencrypted_size of folder when queried
This fixes the "used space" to be based on the unencrypted size, not
encrypted size, to be consistent with how quota/space is handled when
encryption is enabled
2014-03-21 10:23:56 +01:00
Vincent Petry
a70b99ff62 Propagate unencrypted_size up to the file cache root 2014-03-21 10:23:48 +01:00
Vincent Petry
2c2fd5f3a0 Merge pull request #7819 from owncloud/stable6-datafolderexistence
[stable6] [backport] Added .ocdata file to check for data folder validity
2014-03-20 15:28:33 +01:00
Vincent Petry
288c40e2a6 Increase version to trigger upgrade related to .ocdata 2014-03-20 11:51:54 +01:00
Vincent Petry
d85d3a4493 Return 503 when a config/data dir error exists
Backport of b619ff6 from master
2014-03-20 11:51:14 +01:00
Vincent Petry
a1c0c5e1a2 Added .ocdata file to check for data folder validity
In environments where the data folder is mount from another partition,
it is important to check that the data folder we see is actually the
real one. If the mount failed for some reasons, this fix will make
ownCloud temporarily unavailable instead of causing unpredictable
behavior.

Backport of 3c46dcd from master
2014-03-20 11:50:53 +01:00
Robin McCorkell
6ccc8173d3 Fix smb4php to work with home shares
Stat'ing a share with url_stat now checks if the user can run 'ls' in that share rather than checking if the share is listed by the server. This means that OwnCloud can now mount user home shares, which are never listed by the server.
2014-03-18 21:37:14 +01:00
Vincent Petry
2cb342c3b8 Display admin option for public upload with encryption enabled
Now that public upload works with encryption, the admin option to toggle
it must be made visible.

Backport of b75ca9f from master
2014-03-18 13:15:50 +01:00
Vincent Petry
58db31e61e Added warning for trusted_domains after CLI upgrade
If trusted_domains is not set after a CLI upgrade, show a warning in the
output.

Backport of 1a11682 from master
2014-03-17 14:27:19 +01:00
Bjoern Schiessle
30cca2524f finally fix the paths for the OCS Share API 2014-03-13 20:28:08 +01:00
Vincent Petry
53ad7ebfea Merge pull request #7690 from owncloud/backport-7683-stable6
Backport 7683 stable6
2014-03-13 11:41:46 +01:00
Thomas Müller
bff2c20fce Merge pull request #7701 from owncloud/backport-7681-stable6
remove Sabre_DAV_Browser_Plugin
2014-03-13 09:42:28 +01:00
Thomas Müller
e4104e63d9 remove Sabre_DAV_Browser_Plugin 2014-03-12 23:56:28 +01:00
Vincent Petry
bc5145e267 Merge pull request #7698 from owncloud/backport_7631
only enable drag&drop upload if public upload is allowed
2014-03-12 23:51:45 +01:00
Vincent Petry
544495563f Merge pull request #7280 from owncloud/tune_legacy_cache_webdav_properties_prefixing_stable6
Concatenate string in SQL instead of PHP, use doctrine to construct concat expression
2014-03-12 18:55:11 +01:00
Bjoern Schiessle
112a277998 only enable drag&drop upload if public upload is allowed, backport of #7631 2014-03-12 17:50:26 +01:00
Thomas Müller
46657ad8a6 fixing method names 2014-03-12 15:40:54 +01:00
Thomas Müller
14b9eba428 set content-type on ocs exceptions 2014-03-12 15:40:54 +01:00
Frank Karlitschek
6a31fecca3 increase version number 2014-03-11 19:11:07 +01:00
Bjoern Schiessle
3ccbc25dba add 'received_from' info to the share, so that every share can have a different value 2014-03-11 17:16:04 +01:00
Bjoern Schiessle
c3c255b0ca fix path creation for re-shares, issue #7662 2014-03-11 17:15:56 +01:00
Thomas Müller
2e42b0555a Merge pull request #7672 from owncloud/backport-7659-stable6-2
Backport 7659 stable6 2
2014-03-11 16:26:28 +01:00
Thomas Müller
c1c6ce22e8 remove magic handling of recipient lists by exploding the string - this functionality is nowhere used this way and nowhere documented - and broken because only $toaddress will be exploded not $toname 2014-03-11 14:41:36 +01:00
Thomas Müller
a3bc3bbf2d backport #7659 2014-03-11 14:40:51 +01:00
Victor Dubiniuk
37e19534f1 Reset time of last update feed polling 2014-03-11 15:36:08 +03:00
Morris Jobke
d290f44fc7 Merge pull request #7608 from owncloud/stable6-publicpagedownloadall
[stable6] Fixed "select all" + download on public page
2014-03-11 10:29:08 +01:00
Vincent Petry
4966d632ae Disable XML entities when parsing XML 2014-03-10 20:41:40 +01:00
Thomas Müller
a5871c1811 Merge pull request #7653 from owncloud/backport-7646-stable6
we need the file_source to delete a share successfully
2014-03-10 17:55:27 +01:00
Bjoern Schiessle
0f40acb9a8 we need the file_source to delete a share successfully 2014-03-10 16:44:58 +01:00
Thomas Müller
cf2af3ce4d Merge pull request #7633 from owncloud/fix-7582-stable6
Fix 7582 stable6
2014-03-10 15:10:07 +01:00
Thomas Müller
d54f314c93 fixing ident 2014-03-07 20:05:11 +01:00
Thomas Müller
ff078db8cb we first shall check if the current session is valid - otherwise the session-id will be regenerated on login via basic auth 2014-03-07 20:03:51 +01:00
Björn Schießle
acc35849af Merge pull request #7586 from owncloud/dont_create_shared_folder_stable6
[oc6] don't allow to create a file or folder named 'Shared' in the root folder
2014-03-07 10:31:08 +01:00
Frank Karlitschek
c9c91c7e15 Merge pull request #7609 from owncloud/fix-updater-6
Use $installedVersion instead of $currentVersion
2014-03-06 23:19:11 +01:00
Lukas Reschke
ce5f8d72a4 Use $installedVersion instead of $currentVersion
Additionally use 6.00.4 as the internal version has been changed
2014-03-06 22:43:08 +01:00
Vincent Petry
b4c10eea60 Fixed "select all" + download on public page
When a user has lots of files, selecting all and downloading would send
the whole list of files to the server.

This fix makes it use the simpler default download URL in such cases
(the one that was used by the "Download" button that is now removed on
the public page)
2014-03-06 20:32:27 +01:00
Vincent Petry
c358373dfa Merge pull request #7578 from owncloud/introduce-generateUrl-stable6
adding new javascript function OC.generateUrl(url, params)
2014-03-06 17:26:17 +01:00
Frank Karlitschek
95ddadd146 increase the version number 2014-03-06 16:52:44 +01:00
Morris Jobke
91392c5a87 add dprecated warning for OC.Router 2014-03-06 15:17:55 +01:00
Jan-Christoph Borchardt
26b70bce28 fix noise not repeating 2014-03-06 14:55:04 +01:00
Bjoern Schiessle
7f81b14eff don't allow to create a file or folder named 'Shared' in the root folder, also exclude all combinations of lower and upper case letters 2014-03-06 12:09:32 +01:00
Thomas Müller
87d385303f adding new javascript function OC.generateUrl(url, params) 2014-03-06 00:28:11 +01:00
Lukas Reschke
eaf96335ad Merge pull request #7565 from owncloud/stable6-trusteddomainerrorpage
[stable6] Show warning page when accessing server from an untrusted domain
2014-03-05 21:04:11 +01:00
Vincent Petry
d7163c9b5a Fixed X-Forwarded-Host parsing 2014-03-05 20:06:05 +01:00
Vincent Petry
98ff74a70e Added unit tests for serverHost and other related functions 2014-03-05 20:06:04 +01:00
Vincent Petry
f1b948d4dc Added localhost as trusted domain 2014-03-05 18:59:34 +01:00
Vincent Petry
9b6b02af6d Show warning page when accessing server from an untrusted domain
Added early check for the requested domain host and show a warning
page if the domain is not trusted.
2014-03-05 18:59:34 +01:00
Jan-Christoph Borchardt
6b45835ecf add hover/focus states for star icons to hint at action 2014-03-05 15:29:52 +01:00
Bjoern Schiessle
c02c815603 don't create files folder, let ownCloud core handle it 2014-03-05 14:32:25 +01:00
Vincent Petry
5bf9aab464 Fixed configkey casing for PostgreSQL
Backport of fd5dec0 from master
2014-03-04 17:59:48 +01:00
Vincent Petry
722b81627c Merge pull request #7464 from owncloud/enc_fseek_fallback_stable6
Enc fseek fallback stable6
2014-03-04 12:53:08 +01:00
Vincent Petry
7e2659f017 Fix mail template to use p() for colors
Now using p() instead of print_unescaped() for colors.

Backport of 25251d4 from master
2014-03-03 17:43:52 +01:00
Frank Karlitschek
52b3187962 Merge pull request #7510 from owncloud/stable6-theme-mailtemplate
[stable6] Enable theming of the mail template header
2014-03-03 17:21:53 +01:00
Jan-Christoph Borchardt
b3c5aaa1ca make mail notification header color themable 2014-03-03 16:50:05 +01:00
Jan-Christoph Borchardt
ea62d23cb3 compress mail notification logo 2014-03-03 16:50:01 +01:00
Jan-Christoph Borchardt
289f64b191 mail template: remove off-white background color to better blend into mail client 2014-03-03 16:49:54 +01:00
Jan-Christoph Borchardt
5878d27068 remove border from log in input fields, simpler and works better with themes 2014-03-03 16:19:49 +01:00
Frank Karlitschek
071e371803 increasing the internal verison one more 2014-03-03 14:59:34 +01:00
Björn Schießle
ccf2bf74ea Merge pull request #7501 from owncloud/stable6-libxmlfixsubmoduleupdate
Updated submodule for libxml entity fixes
2014-03-03 13:04:05 +01:00
Vincent Petry
9e439305fd Updated submodule for libxml entity fixes 2014-03-03 12:58:18 +01:00
Björn Schießle
dadd67e7bd Merge pull request #7498 from owncloud/stable6-dbschemaxmlentityfix
Allow XML entity loader for MDB2 schema loader
2014-03-03 12:55:38 +01:00
Vincent Petry
762b0d9510 Allow XML entity loader for MDB2 schema loader 2014-03-03 12:15:51 +01:00
Frank Karlitschek
dc0a7428bd 6.0.2 2014-02-28 22:59:59 +01:00
Thomas Müller
7534fae9bc Merge pull request #7462 from owncloud/ldap_proxy_access
Ldap proxy access
2014-02-28 21:51:37 +01:00
Jan-Christoph Borchardt
68a9ceacbb Merge pull request #7472 from owncloud/stable6-icons.css-updates
stable6 icons.css backports
2014-02-28 15:24:56 +01:00
Jan-Christoph Borchardt
8a3a5a2ff1 icons: automatically show delete hover instead of using explicit class 2014-02-28 11:37:00 +01:00
jbtbnl
8995c81103 Remove necessity of icon class
Only the icon specific class is needed
2014-02-28 11:36:51 +01:00
jbtbnl
095f9114dd Add white color variant of checkmark icon 2014-02-28 11:36:39 +01:00
Arthur Schiwon
470a0ad611 remove remaining testing artefact 2014-02-28 10:58:51 +01:00
Bjoern Schiessle
9661001af1 remember original fopen access type in pre-proxy because sometimes they change
during the fopen call, e.g. 'r' becomes 'r+' if we open an URL
2014-02-28 10:38:58 +01:00
Vincent Petry
17f869b2fb Merge pull request #7459 from owncloud/deletestorage-legacy
Also delete legacy storages when deleting a user
2014-02-28 10:30:52 +01:00
Vincent Petry
162ba722f6 Merge pull request #7468 from owncloud/stable6-enc-fixfieldnametypo
[stable6] Fixed wrong field name
2014-02-27 23:52:20 +01:00
Vincent Petry
4756d18a14 Fixed wrong field name
This re-fixes an issue where the unencrypted size isn't updated
correctly when saving a text file in the UI multiple times.

Fixes #7467
2014-02-27 19:50:16 +01:00
Bjoern Schiessle
9cff832282 add test for the stream wrapper to read encrypted files from the system folder /tmp 2014-02-27 18:02:13 +01:00
Bjoern Schiessle
7ced22ccc6 test for isEncryptedPath() 2014-02-27 18:02:05 +01:00
Bjoern Schiessle
6455722f29 extend the encryption stream wrapper to handle local files and add a fall back for file size calculation if the storage doesn't support fseek 2014-02-27 18:01:58 +01:00
Bjoern Schiessle
8b3d99308c implement ftell stream wrapper and fix return value from fseek stream wrapper 2014-02-27 18:01:51 +01:00
Bjoern Schiessle
f87319f834 fall back to getLocalFile if storage doesn't support fseek 2014-02-27 18:01:45 +01:00
Arthur Schiwon
4605c2cc2d intendetion. where did the whitespaces come from? 2014-02-27 16:20:53 +01:00
Arthur Schiwon
49e567a5cc LDAP: let proxy for multiple server access methods from Access 2014-02-27 16:18:03 +01:00
Robin Appelman
7580518bd8 Also delete legacy storages when deleting a user 2014-02-27 14:52:36 +01:00
Jörn Friedrich Dreyer
d93b5af265 Merge pull request #7430 from owncloud/stable6-quote-oldcolumname
[stable6] Also quote old column name during DB migration
2014-02-27 13:12:32 +01:00
Bjoern Schiessle
9a0c78b831 close encryption session after decryption was finished 2014-02-27 11:48:29 +01:00
Jan-Christoph Borchardt
61a37331ce disable autocomplete for shared link password input, fix #7419 2014-02-26 22:21:36 +01:00
Thomas Müller
d265d290c3 Merge pull request #7426 from owncloud/stable6-fixmailnotificationtranslation
[stable6] Backported incorrect translation texts for German
2014-02-26 22:18:42 +01:00
Thomas Müller
aff7594ef3 let's name the column 'select' because this is a keyword on all platforms 2014-02-26 22:14:44 +01:00
Thomas Müller
5e586995a8 adding test for migrations on columns using keywords 2014-02-26 22:14:44 +01:00
Vincent Petry
1d0e45e179 Also quote old column name during DB migration
This fixes alter table commands that didn't quote the old column name
2014-02-26 16:30:38 +01:00
Vincent Petry
cab94eb719 Fix German message for "Enter new" 2014-02-26 15:50:02 +01:00
Vincent Petry
c1cc4df26e Fixed German shared notification message 2014-02-26 15:49:44 +01:00
Bjoern Schiessle
b4f154f9b4 fix path in sharing results if it is a file in the Shared folder 2014-02-26 15:22:20 +01:00
Bjoern Schiessle
ac3f1d6f61 only add "received_from" if a share was found 2014-02-26 14:49:41 +01:00
Morris Jobke
d27f2929d2 Merge pull request #7402 from owncloud/stable6-ie9-navigation
Stable6 IE9 navigation bar width
2014-02-26 13:49:03 +01:00
Vincent Petry
6aee04bba4 Merge pull request #7397 from owncloud/stable6-scrollperformance
Users list scrolling performance / improvements
2014-02-26 13:19:27 +01:00
Thomas Müller
a88b253c78 introduce new theme function to allow full creation of documentation links: buildDocLinkToKey() 2014-02-26 12:52:49 +01:00
Jan-Christoph Borchardt
751c1b0418 manual backport of IE9 navigation bar pull request #6808, fix #7321 2014-02-26 09:19:02 +01:00
Vincent Petry
a0feffb2a7 Added loading spinner to users list on scroll 2014-02-25 19:37:33 +01:00
Vincent Petry
34d17e6168 Improve users list scrolling performance
- fixed JS error when avatar mode is disabled
- added spinner at the bottom of the table
- scroll detection now happens earlier
- single/multiselect init is deferred so that the new rows are first appended
  into the list (more responsive) and initialized afterwards
- disabled users sorting after add (assuming they are always sorted on
  the server side)
2014-02-25 19:37:23 +01:00
Owen Winkler
c30377392b Merge pull request #7394 from owncloud/backport-7344
Allow apps to add/modify config js output via hook.
2014-02-25 10:37:33 -05:00
ringmaster
0d2482a1a9 Allow apps to add/modify config js output via hook. 2014-02-25 09:16:38 -05:00
Vincent Petry
149814d95b Replace deleteAll call with unlink call
The method deleteAll() doesn't officially exist on the Storage class as
it's not defined on the interface, which means it fails on the Quota
storage wrapper and might fail on some external storage classes.
Also, this here is the only use case for that one method.
2014-02-25 15:01:38 +01:00
Frank Karlitschek
16e24dc4c5 Merge branch 'stable6' of https://github.com/owncloud/core into stable6 2014-02-25 13:56:30 +01:00
Frank Karlitschek
dc11b87a1d 6.0.2 RC1 2014-02-25 13:56:06 +01:00
Bjoern Schiessle
c8d34eaf9c add test case if a file gets moved out from the shared folder 2014-02-25 12:42:34 +01:00
Bjoern Schiessle
9183ade655 don't overwrite keys if rename was done by a stream copy 2014-02-25 12:36:06 +01:00
Vincent Petry
678afc4906 Merge pull request #7386 from owncloud/stable6-fixhostnamewithport
Fix case where port is missing
2014-02-25 12:32:41 +01:00
Vincent Petry
6d3b5b24fd Fix case where port is missing 2014-02-25 11:22:53 +01:00
icewind1991
4286eeb531 Merge pull request #7369 from owncloud/stable6-smbmissingfiles
[stable6] Fixed missing files on SMB storage
2014-02-24 13:57:57 +01:00
Vincent Petry
0187537a2e Fixed missing files on SMB storage
Files with attribute "N" weren't parsed out of the file list returned by
smbclient. It seems that these files appear when created on a Linux SMB
mount directly and that have no executable bit.
2014-02-24 09:22:02 +01:00
Vincent Petry
928947f1c3 Added extra checks for ext storage class 2014-02-22 08:13:11 +01:00
Lukas Reschke
fb1ebf13c6 Adjust version for stable6 2014-02-22 08:09:49 +01:00
Lukas Reschke
ed7e9be7cd Add overwritehost config on setup and upgrade 2014-02-22 07:59:39 +01:00
Bjoern Schiessle
e903c8b57b fix test so that it doesn't depend on the array order 2014-02-21 15:53:11 +01:00
Bjoern Schiessle
210832ddf1 fix usersPath and add unit tests 2014-02-21 15:53:03 +01:00
Vincent Petry
96ebefc597 Updated submodule
Includes XML fixes
2014-02-21 15:49:08 +01:00
Bjoern Schiessle
5348e2eb54 fix sharing unit tests 2014-02-21 14:44:09 +01:00
Bjoern Schiessle
f6e6f465f2 add unit test for \OC\URLGenerator::getAbsoluteURL to verify #6935 2014-02-21 13:49:11 +01:00
Thomas Müller
ce87f933a4 Merge pull request #7349 from owncloud/backport-7347
Backport of #7347 to stable6
2014-02-21 11:21:06 +01:00
Arthur Schiwon
a04af7854d LDAP: fix and extend tests 2014-02-21 10:15:09 +01:00
Arthur Schiwon
75c7fd2886 LDAP: improve compilation of filters 2014-02-21 10:15:00 +01:00
Lukas Reschke
92b4d52079 Fix "headers are already sent" introduced with #6519
Backport of #7347
2014-02-21 10:05:05 +01:00
Thomas Tanghus
91b4045791 Test if $url is already prefixed by '/' 2014-02-20 18:19:05 +01:00
Thomas Tanghus
0f87a0248f Add missing slash in URLGenerator::getAbsoluteURL(). Refs. #6840 2014-02-20 18:18:54 +01:00
Arthur Schiwon
3c9421381b LDAP: prevent other configuration from being deleted when deleting the first one which has an empty prefix for historical reasons 2014-02-20 16:25:50 +01:00
nhirokinet
2d946d2766 Update user.php to fix duplicate session-duplicate 2014-02-20 14:31:28 +01:00
NARUKAWA Hiroki
a422f19fac Security Update: session fixation
Previous version is vulnerable to session fixation attack in some situations, guessing non-apache-module-php5 environment. Regeneration of session id should be done here.
2014-02-20 14:31:23 +01:00
Lukas Reschke
ebb1a70abc Check whether the app is set 2014-02-20 11:26:55 +01:00
Lukas Reschke
b9d013e3ce Check whether the Key is set 2014-02-20 11:26:47 +01:00
Lukas Reschke
b044ec0420 An admin should not be able to add remote and public services on its own. This should only be possible programmatically.
This change is due the fact that an admin may not be expected to execute arbitrary code in every environment.
2014-02-20 11:26:41 +01:00
Jörn Friedrich Dreyer
3520529430 Concatenate string in SQL instead of PHP, use doctrine to construct concat expression 2014-02-19 12:06:04 +01:00
Joas Schilling
864f0342af Make google drive client secret and dropbox api secret a password field
Fix issue #5794

Backport of 828985d
2014-02-18 18:33:13 +01:00
Joas Schilling
5a2e99c975 External FTP Storage should request hostname instead of URL
Fix issue #6277

Backport of 658af62
2014-02-18 18:15:19 +01:00
Lukas Reschke
d07f459409 Use the proper content-type
We should use the proper content-type `application/xml` instead of the default `text/html` here.

Backport requested.
2014-02-18 11:45:05 +01:00
Vincent Petry
3d5d6b5ad1 Now using PHP session lifetime as default value for the JS config
This will fix the heartbeat when the session_lifetime config parameter
hasn't been set explicitly.

Backport of f9763e1fc5
2014-02-18 10:53:35 +01:00
Vincent Petry
80dcec773a Merge pull request #7225 from owncloud/enc_improved_error_handling_oc6
[encryption] improved error handling (OC6)
2014-02-17 11:26:21 +01:00
Bjoern Schiessle
43738dacfb don't block login forever if we are stuck in the middle of the initial encryption 2014-02-17 10:24:04 +01:00
Bjoern Schiessle
78b10de7d6 catch errors during decryption
Conflicts:
	apps/files_encryption/tests/util.php
2014-02-17 10:23:48 +01:00
Bjoern Schiessle
37db8a13d4 catch errors during initial encryption 2014-02-17 10:21:16 +01:00
Joas Schilling
eb8b2210cd Send correct path on file upload when using public app
Fix issue #7152
2014-02-14 12:27:34 +01:00
Robin Appelman
118033cac6 Also clean up the filecache table when deleting a storage entry 2014-02-12 14:03:30 +01:00
Robin Appelman
b0ba69ff31 Also remove the user's home storage from the storage table when deleting a user 2014-02-12 14:03:30 +01:00
Thomas Müller
c1241b1691 Load authentication apps to get users from all backends - fixes #7019 2014-02-11 18:42:09 +01:00
Vincent Petry
ad813da7b1 Merge pull request #7157 from owncloud/stable6-xsendfilequotacheck
Fix xsendfile local storage detection with quota
2014-02-11 17:03:55 +01:00
Vincent Petry
b4f04c18db Fix xsendfile local storage detection with quota 2014-02-11 15:04:17 +01:00
blizzz
23985428ea Merge pull request #6778 from owncloud/fix_6430
on filtering the share box users and groups whose name begins with the s...
2014-02-11 10:38:04 +01:00
Bjoern Schiessle
018fed6014 getData() always needs to return an array 2014-02-10 15:16:58 +01:00
Arthur Schiwon
3be50224ff intendation 2014-02-10 14:53:59 +01:00
Arthur Schiwon
0213928735 fix DI 2014-02-10 14:53:59 +01:00
Arthur Schiwon
1cf599d494 Inject logger 2014-02-10 14:53:59 +01:00
Arthur Schiwon
8a4dbdedcf wrong tld 2014-02-10 14:53:59 +01:00
Arthur Schiwon
35b316f93f test for share dialoge sorter 2014-02-10 14:53:59 +01:00
Arthur Schiwon
7e451a24bc sort following entries in alphabetical order 2014-02-10 14:53:59 +01:00
Arthur Schiwon
f8620704d4 move sorter into a class 2014-02-10 14:53:58 +01:00
Arthur Schiwon
c6687e159b respect coding guidelines 2014-02-10 14:53:58 +01:00
Arthur Schiwon
8227bc41cd on filtering the share box users and groups whose name begins with the search term shall appear on top, fixes #6430 2014-02-10 14:53:58 +01:00
Bjoern Schiessle
6f5caaa87a refuse login as long as the initial encryption is running 2014-02-10 14:51:34 +01:00
blizzz
e5dac9fa24 Merge pull request #7124 from owncloud/fix_6541
LDAP: also try MS AD's thumbnailPhoto when looking for an avatar image
2014-02-10 14:44:43 +01:00
Joas Schilling
48bb8aeb01 Only add files to file list when uploading to current directory
Fix Issue #6683
2014-02-10 12:41:45 +01:00
blizzz
fd32501fe0 Merge pull request #7081 from owncloud/fix_6670
LDAP: Wizard cannot determine Base DN in some cases, fixes #6670
2014-02-10 11:27:31 +01:00
Arthur Schiwon
0a475bdab3 LDAP: improve debug message 2014-02-10 10:19:37 +01:00
Arthur Schiwon
3d6ab2b53b LDAP: also try MS AD's thumbnailPhoto when looking for an avatar image 2014-02-10 10:19:37 +01:00
Björn Schießle
5e315495c2 Merge pull request #7130 from owncloud/enc_fix_unit_tests
name users after test
2014-02-07 17:56:21 +01:00
Thomas Müller
b353637e45 Merge pull request #7129 from owncloud/ldap_info_doc
LDAP: add documentation info in info.xml
2014-02-07 17:13:45 +01:00
Thomas Müller
fb6290c87a Merge pull request #7083 from owncloud/backport_6777_stable6
Backport 6777 stable6
2014-02-07 17:08:25 +01:00
Bjoern Schiessle
76cb5a50c0 name users after test 2014-02-07 17:01:02 +01:00
Arthur Schiwon
5c40ef090a LDAP: add documentation info in info.xml 2014-02-07 15:55:35 +01:00
Bjoern Schiessle
9c9b161f51 replace 'size' with 'unencrypted_size' if encryption is enabled 2014-02-07 15:26:21 +01:00
Bjoern Schiessle
9b257ad862 change order of issubdirectory() calls to avoid error messages for non-apps 2014-02-07 14:48:01 +01:00
Thomas Müller
5edc4c95bc Merge branch 'stable6' into backport_6777_stable6
Conflicts:
	apps/files_sharing/css/public.css
	apps/files_sharing/templates/public.php
2014-02-07 14:21:10 +01:00
Vincent Petry
f9bd4c5d24 Fixed searchByMime in shared cache
- searchByMime now correctly returns files recursively search through
  all the dirs
- added unit test for searchByMime

Backport of fa5ddc3 to stable6
2014-02-06 16:23:15 +01:00
Thomas Müller
88a5f7d994 remove css files from rewrite rule - there is no need to rewrite css any more 2014-02-06 15:13:23 +01:00
Jan-Christoph Borchardt
04b4c7c042 remove %webroot from files_sharing app 2014-02-06 14:28:26 +01:00
Jan-Christoph Borchardt
87d06bae85 remove %webroot% from files app 2014-02-06 14:28:17 +01:00
Jan-Christoph Borchardt
c096c6edc3 add icons.css file, first step to get rid of %webroot% 2014-02-06 14:28:08 +01:00
Bjoern Schiessle
713c5c4275 use appstoreenabled config switch 2014-02-05 16:52:18 +01:00
Jan-Christoph Borchardt
e48c7675b9 do not show 'Add app' and 'More apps' for themed ownCloud 2014-02-05 16:52:15 +01:00
Bjoern Schiessle
f824986742 add function to extract filename from sharekey name + tests 2014-02-05 14:32:32 +01:00
Bjoern Schiessle
5e788ae1fa added tests for the delete hooks if the trash bin is disabled 2014-02-05 14:32:13 +01:00
Bjoern Schiessle
78b390da31 don't expect OC_FilesystemView, this is depreciated 2014-02-05 14:31:47 +01:00
Bjoern Schiessle
b3257a315d better error detection and don't use glob() 2014-02-05 14:31:34 +01:00
Bjoern Schiessle
fc1763dc6b move unlink proxy to a hook which handles pre and post conditions 2014-02-05 14:31:13 +01:00
Vincent Petry
7b948b0580 Added session_keepalive setting
When session_keepalive is true (default) the heartbeat will be send as
often as the half of the session timeout value.

Backport of 912da8d to stable6
2014-02-05 13:46:49 +01:00
Jörn Friedrich Dreyer
379ddd88d6 make header scroll up for single shares, more view of content on small screens 2014-02-05 11:39:02 +01:00
Jörn Friedrich Dreyer
23c015ba52 adding class to header div: share-folder or share-file 2014-02-05 11:38:21 +01:00
Jörn Friedrich Dreyer
0f97d9555c adjust file type icon placement for when no preview can be generated 2014-02-05 11:37:23 +01:00
Jörn Friedrich Dreyer
0992a77cfb permanently show download action on mobile, only icon 2014-02-05 11:33:43 +01:00
Jörn Friedrich Dreyer
4b1f93b61c fix horizontal scrollbar appearing when footer is too long, footer wraps now 2014-02-05 11:30:54 +01:00
Jörn Friedrich Dreyer
916122b166 fix multiselect bar being too short on big displays 2014-02-05 11:29:39 +01:00
Jörn Friedrich Dreyer
a3b351738a Instead of 'No preview available for ...' we simple display the mime-type icon 2014-02-05 11:27:46 +01:00
Jörn Friedrich Dreyer
37f8607a88 remove background and width from multiselect bar, fix Download button not showing on mobile 2014-02-05 11:24:34 +01:00
Jörn Friedrich Dreyer
a4895e4df1 focus link text only on click in the input field - closes #6817 2014-02-05 11:17:04 +01:00
Jörn Friedrich Dreyer
a9a92892be remove unused variable 2014-02-05 11:15:04 +01:00
Jörn Friedrich Dreyer
d8770d1284 fix input element closing tag 2014-02-05 11:13:31 +01:00
Jörn Friedrich Dreyer
e3d8758a32 make sure there's enough room for the file actions 2014-02-05 11:12:01 +01:00
Jörn Friedrich Dreyer
5a5496f4e7 restrict zooming on mobile devices for the publicly accessible, optimized pages 2014-02-05 11:10:30 +01:00
Jörn Friedrich Dreyer
b33cfce2fa add icons for file list and picture view toggles 2014-02-05 11:08:34 +01:00
Jörn Friedrich Dreyer
025ab0dabb on mobile, show single shared image at full width without margin 2014-02-05 11:06:42 +01:00
Jörn Friedrich Dreyer
63b078b550 fix public share download button width 2014-02-05 11:02:21 +01:00
Jörn Friedrich Dreyer
fa1288c6b3 tweak color and position of username in public share 2014-02-05 10:59:52 +01:00
Jörn Friedrich Dreyer
9f9466d001 improvements to public files mobile view 2014-02-05 10:57:26 +01:00
Jörn Friedrich Dreyer
249df3864b remove min-width rule to fix mobile views 2014-02-05 10:53:54 +01:00
Jörn Friedrich Dreyer
615f0c4a1c first mobile style rules, hide extra columns in files view and scroll header 2014-02-05 10:52:25 +01:00
Jörn Friedrich Dreyer
a096f19bb2 add download button on single file share page 2014-02-05 10:49:57 +01:00
Arthur Schiwon
a967acee4c Rephrase and clarify log message 2014-02-05 10:33:44 +01:00
Arthur Schiwon
2801edc451 Wizard: enable base DN for editing, if not base DN could have been detected. Also part of fix for #6670 2014-02-05 10:30:56 +01:00
Arthur Schiwon
acebc3f41e Wizard: disable LDAP referrals, fixes #6670 2014-02-05 10:29:09 +01:00
Vincent Petry
9404389d83 Allow getting info or renaming part files through WebDAV
When mounting an ownCloud (backend OC) inside another ownCloud (frontend
OC), the frontend OC will use WebDAV to upload file, which will create
part files. These part files need to be accessible for the frontend OC
to rename them to the actual file name.

This fix leaves the file cache untouched but gives direct access to part
file info when requested.

This means that part file can be accessed only when their path and name
are known. These won't appear in file listtings.

Fixes #6068
2014-02-05 10:11:28 +01:00
Arthur Schiwon
60b75b25f8 throw an info message, when base dn test failed 2014-02-04 19:37:40 +01:00
Arthur Schiwon
608fe55889 LDAP: extend LDAP wrapper search method for sizelimit, improves performance in wizard 2014-02-04 17:56:53 +01:00
Jörn Friedrich Dreyer
37d2c0a4be remove unused js code and css rules 2014-02-04 16:32:39 +01:00
Jörn Friedrich Dreyer
3ccbc984f4 no new menu on public upload 2014-02-04 16:29:59 +01:00
Jörn Friedrich Dreyer
8bd3ce2fe2 fixing preview generation 2014-02-04 16:28:51 +01:00
Jörn Friedrich Dreyer
ebcbf85396 reuse file upload as used within files app - remove public upload button 2014-02-04 16:25:23 +01:00
Bjoern Schiessle
44a6d2a98c add test for password remove method 2014-02-04 14:42:41 +01:00
Bjoern Schiessle
8ee368ddad remove needless element tag 2014-02-03 17:03:30 +01:00
Bjoern Schiessle
34069e00c4 also load error handler if debugging is enabled 2014-02-03 17:00:30 +01:00
Bjoern Schiessle
88542819f0 remove passwords in URLs from all log messages 2014-02-03 17:00:17 +01:00
Vincent Petry
8a66c30895 Fixed image preview in trashbin subdirs 2014-01-31 16:35:23 +01:00
Bjoern Schiessle
e6579a3c0a public upload is also possible with encryption enabled, since OC6 2014-01-29 11:51:50 +01:00
Bjoern Schiessle
9016093b4c use more accurate error codes 2014-01-28 16:46:58 +01:00
Vincent Petry
301e4988a1 Added exception logger plugin for sabre connector
Whenever an exception occurs in the sabre connector code or code called
by it, it will be logged.

This plugin approach is needed because Sabre already catches exceptions
to return them to the client in the XML response, so they don't appear
logged in the web server log.

This will make it much easier to debug syncing issues.

Backport of 11ef12a to stable6
2014-01-28 14:19:13 +01:00
Otto Sabart
e6391d84a1 Add check for apc.enabled option
Sometimes it's not possible to disable APC entirely and some of
apc_functions are disabled. Only thing which is possible is
to disable apc.enable option.
2014-01-27 23:33:39 +03:00
Bjoern Schiessle
4c305ef459 disable button and input field during decryption 2014-01-27 14:23:56 +01:00
Bjoern Schiessle
72e308788f remove the form, it isn't needed here 2014-01-27 14:23:43 +01:00
Bjoern Schiessle
f1dc6e1441 use localised date in notification mails 2014-01-27 14:18:10 +01:00
Bjoern Schiessle
33801c311e only update file cache with the unenecrypted size when the file was written 2014-01-27 10:39:11 +01:00
Jan-Christoph Borchardt
0cd68cfedc prevent autofill for password change settings, prevent leak of existing password, fix #6552 2014-01-26 20:04:24 +01:00
Bjoern Schiessle
e00f483238 add expire date to link share if possible 2014-01-24 16:57:18 +01:00
Bjoern Schiessle
5cc8df3723 increase size of mimetype column 2014-01-24 16:09:22 +01:00
Bjoern Schiessle
08bf128255 added website field 2014-01-24 13:58:51 +01:00
Bjoern Schiessle
3979508dae distinguish app links from doc links 2014-01-24 13:58:43 +01:00
Bjoern Schiessle
a5a2fe9180 show link to app documentation 2014-01-24 13:58:29 +01:00
Bjoern Schiessle
29d63893ff add link to documentation 2014-01-24 13:58:18 +01:00
Vincent Petry
39354eaaf1 Fixed sharing results to include the correct permissions
Passing $includeCollections would return more than one entry which gives
mixed up file permissions.

Added a method getFile() that doesn't set $includeCollections to make
sure we only get one result which is the file itself.

Fixes #6265
2014-01-23 15:31:14 +01:00
Bjoern Schiessle
2e8418b362 fix infinite loop if folder and subfolder has the same name 2014-01-23 13:36:33 +01:00
Bjoern Schiessle
1a93891222 add path relative to the files folder of the currently logged in user to the output of getFolderContent() 2014-01-23 13:36:22 +01:00
Vincent Petry
099ccfa254 Fixed isPreviewAvailable warnings in log
isPreviewAvailable wasn't always set as the files formatting code is
slightly different than the one from the files app.

Fixes #6423

Backport of f4c198b to stable6
2014-01-23 12:32:10 +01:00
Björn Schießle
d41b2c5401 Merge pull request #6891 from owncloud/version_fix_array_order_stable6
Version fix array order stable6
2014-01-22 03:21:50 -08:00
Myles McNamara
5f7bc2cf4d change publicUploadButtonMock to public_upload
Changed jQuery selector for public preview to public_upload to correctly show preview
2014-01-22 11:36:47 +01:00
Myles McNamara
6d330e8a3f change em to px 2014-01-22 11:36:42 +01:00
Myles McNamara
72b680ca2d modify js to move upload wrapper, modify css to match core values 2014-01-22 11:36:38 +01:00
Myles McNamara
5e1c3732e5 remove extra upload controls 2014-01-22 11:36:29 +01:00
Myles McNamara
7251c65996 fix upload button layout 2014-01-22 11:36:24 +01:00
Bjoern Schiessle
fea0ba84c5 fix size calculation 2014-01-22 11:28:09 +01:00
Bjoern Schiessle
cdfc6ff5d5 fix array ordering issue 2014-01-22 11:25:19 +01:00
Björn Schießle
50721da77b Merge pull request #6874 from owncloud/versioning_expire_fixes_stable6
selective backport of the bug fixes from pr #6863
2014-01-22 02:21:55 -08:00
Frank Karlitschek
14cbec6d6b 6.0.1 2014-01-22 09:28:41 +01:00
Thomas Müller
ea334cfa18 fixing comment + adding unit test for checkPasswordProtectedShare 2014-01-21 20:52:16 +01:00
Thomas Müller
c10af30381 in case no share is found for the given token we can return right away 2014-01-21 20:52:16 +01:00
Thomas Müller
4351609df9 adding password protection check to getShareByToken() 2014-01-21 20:52:16 +01:00
Thomas Müller
c430fe6612 Merge pull request #6869 from owncloud/fix-setupfs-only-for-existing-users-stable6
Fix setupfs only for existing users stable6
2014-01-21 10:18:29 -08:00
Tigran Mkrtchyan
3501007074 webdav: return SPACE_UNKNOWN if server do not support quota
Backport of a78dc11732 to stable6
2014-01-21 18:15:14 +01:00
Bjoern Schiessle
603828366f selective backport of the bug fixes from pr #6863 2014-01-21 17:49:56 +01:00
Vincent Petry
e46df97c3a Replaced time() with uniqid() to make sure the file name is unique
The cache isn't cleared properly because unlink() doesn't remove the
cache entry which caused side-effects when reusing the same file name
(which randomly happens when time() returns the same value)

This fix first makes sure the unit tests don't fail any more.
The unlink() case with the cache will be investigated separately.

Backport of f09c19c to stable6
2014-01-21 17:47:46 +01:00
Björn Schießle
180bb9fa9f Merge pull request #6867 from owncloud/protect-versions-preview-stable6
don't use the user id within the versions preview call as it could be us...
2014-01-21 07:46:37 -08:00
Thomas Müller
81f1c04b85 Merge pull request #6456 from owncloud/fix_home_storage_quota_stable6
Fix home storage quota stable6
2014-01-21 07:42:35 -08:00
Thomas Müller
b722ce6cc3 OC_Util::setupFS($user) will create a data dir for the given string - no matter if the user really exists - OCP\JSON::checkUserExists($owner); introduces a ready to use check which will bail out with an JSON error
Conflicts:
	lib/public/json.php
2014-01-21 16:39:31 +01:00
Jörn Friedrich Dreyer
65fa896bc2 add getOwner impementation to Home Storage 2014-01-21 15:18:46 +01:00
Thomas Müller
464b31157e don't use the user id within the versions preview call as it could be used to access previews of another user 2014-01-21 15:18:36 +01:00
Thomas Müller
a9f7764879 Merge pull request #6865 from owncloud/fix_user_ldap_sql_on_oracle_stable6
user workarount to compare CLOB column with CHAR value
2014-01-21 06:15:02 -08:00
Jörn Friedrich Dreyer
047ae7fb23 user workarount to compare CLOB column with CHAR value 2014-01-21 14:03:51 +01:00
Thomas Müller
98db90ba70 Merge pull request #6862 from owncloud/neutral_download_zip_default_name_stable6
use 'download.zip' as default name for zip downloads instead of 'owncloud.zip'
2014-01-21 04:20:02 -08:00
Jörn Friedrich Dreyer
0b11762b1c use 'download.zip' as default name for zip downloads instead of 'owncloud.zip' 2014-01-21 12:43:43 +01:00
Vincent Petry
127ab3cb47 When reading the size of "files" mountpoints need to be excluded
The versions and trashbin app are now passing "includeMountPoints=false"
to "getFileInfo()" to make sure that the calculated total size doesn't
include mount points like Shared or external storage.

This is because the default call (legacy) used to return the size of
mount points as well.

Fixes #6731

Backport of ca57a84 to stable6
2014-01-20 18:29:27 +01:00
Vincent Petry
09cc0c5cc9 Fixed quota wrapper to not wrap failed fopen streams
When calling fopen() on some storage types, these return false instead
of throwing an exception.

This fix makes sure that in case the stream wasn't opened (for example
when a file doesn't exist any more) the stream isn't wrapped.

Also added 'rb' as another case that doesn't need to be wrapped.

Fixes #6832
2014-01-20 14:32:57 +01:00
rnveach
c4c5e34110 added trigger to redo selection text on a directory change 2014-01-20 13:03:40 +01:00
rnveach
89d60a2680 fixed selector string and removed all checkbox if it was selected 2014-01-20 13:03:34 +01:00
Thomas Müller
369ec65d12 Merge pull request #6828 from owncloud/dont_add_queuedtasks_during_upgrade
add needUpgrade() check to addQueuedTask()
2014-01-18 03:46:31 -08:00
Jörn Friedrich Dreyer
40c2f47cd9 add needUpgrade() check to addQueuedTask() 2014-01-17 19:50:37 +01:00
Vincent Petry
bc22799160 Fix array access syntax for older PHP
There was a syntax error when running tests in PHP 5.3.10.
2014-01-17 14:39:49 +01:00
Bjoern Schiessle
4c1510b729 updated description of the files encryption app 2014-01-17 12:56:58 +01:00
Vincent Petry
d44b98d3dd Fix to not destroy draggable when no draggable was set
When a dir has no delete permission, the draggable isn't initialized on
files. This fix makes sure we don't try to destroy a draggable when it
wasn't inited in the first place.

Fixes #6254

Backport of 8135828 to stable6
2014-01-16 17:50:07 +01:00
Frank Karlitschek
a4e842f19a 6.0.1 RC1 2014-01-16 17:09:54 +01:00
Volkan Gezer
aec0f06501 Fix untranslated text when deleting user
This should fix issue #6728
2014-01-16 12:23:34 +01:00
ben-denham
f9e4d0a5e2 updated the unit test for OCP\Share::unshareAll() to verify that shares by all users are removed for an item. 2014-01-16 12:14:53 +01:00
ben-denham
3093c63024 Unshare all will now delete all shares for the item, instead of only for a single owner. 2014-01-16 12:14:37 +01:00
Thomas Müller
b0edbd8ebd Merge pull request #6783 from owncloud/backport-6530-stable6
Backport 6530 stable6
2014-01-15 11:01:47 -08:00
Vincent Petry
5dd20db05f Fixed Dropbox/Google storage async save call
When clicking "Grant access", the settings for Dropbox/Google were saved
through a call that gets cancelled when redirecting to the grant page
(for example in Firefox)

This fix makes sure the "save settings" call finished before redirecting
to the grant page.

Fixes #6176

Backport of e13be94 to stable6
2014-01-15 16:41:54 +01:00
Thomas Müller
0c140d5f6e in order to work properly with encryption ocTransferId is added to the file path - questionable usage of magic string 2014-01-15 16:37:23 +01:00
Thomas Müller
49969825ad Adding a random postfix to the part file. 2014-01-15 16:37:23 +01:00
Bjoern Schiessle
3b21499b34 extended test to also check the status messages 2014-01-15 16:10:31 +01:00
Bjoern Schiessle
3fde29ead4 keep response message 2014-01-15 16:10:22 +01:00
Bjoern Schiessle
afe35ca12d call getFileInfo to enforce a file cache entry for the new version, fix #6286 2014-01-15 16:01:48 +01:00
Bjoern Schiessle
a83e37c799 remove old code 2014-01-15 15:59:04 +01:00
Bjoern Schiessle
3c7541e97c don't try to encrypt/decrypt cache chunks or files in the trash bin 2014-01-15 15:58:56 +01:00
Bjoern Schiessle
3ec3ebb3db copy files to owner trash recursively 2014-01-15 15:58:48 +01:00
Morris Jobke
3e71827bea Merge pull request #6293 from owncloud/stable6-legacy-settings-popup
Stable6 legacy settings popup
2014-01-15 02:12:27 -08:00
Robin Appelman
6adac6a673 Use storage_mtime when determining if we can reuse cached data while scanning
Backport to stable6 of the following commits, in order:
- 203d5d0
- 4113042
- 7e4c80f
- 16b898d
2014-01-15 10:36:32 +01:00
Vincent Petry
88dc71381f Fix calculated folder size to use unencrypted size
The encrypted size was used when calculating folder sizes.
This fix now also sums up the unencrypted size and shows that one when
available.

Backport of 4faba49 to stable6
2014-01-14 16:37:48 +01:00
icewind1991
c6ca9be406 Merge pull request #6612 from owncloud/user-no-change-displayname-stable
Backport: Re-add the config options to remove the ability for users to change their displayname
2014-01-14 07:13:21 -08:00
Bjoern Schiessle
7dddf59942 it is not an urgent error... a DEBUG message is enough at this point 2014-01-14 15:09:26 +01:00
Vincent Petry
8ef32821be Fixed timezone issue with SMB storage
Now forcing smbclient to also run on UTC

Backport of 1eb5ebd to stable6
2014-01-14 15:04:41 +01:00
Thomas Müller
1e9f0409c3 Merge pull request #6408 from owncloud/ldap_fix_tls_detection
LDAP fix TLS detection
2014-01-14 05:01:08 -08:00
Andreas Fischer
bcec9cea78 Merge pull request #6756 from owncloud/remove-ru_RU-stable6
remove ru_RU - it's almost untranslated

* owncloud/remove-ru_RU-stable6:
  remove ru_RU - it's almost untranslated
2014-01-14 00:45:55 +01:00
Björn Schießle
87cfbb3a2b Merge pull request #6753 from owncloud/no_unshare_on_delete
don't unshare on delete
2014-01-13 07:48:22 -08:00
Thomas Müller
3b1396b538 remove ru_RU - it's almost untranslated 2014-01-13 16:44:03 +01:00
Carlos Cerrillo
ce1a1996f7 Fixing Issue #6301 on master branch
Added private var $certPath to store the user root cert

Move logic to determine the $certPath path to the constructor and modify to get the path from OC_User::getHome()

Add curl options to use the certificate to avoid certificate errors with self-signed certicates in the downdload/upload method so we don't get blank files

Only set SSL things when ```$this->secure``` is ```true```

Fix ```createCertificateBundle``` and  ```getCertificates``` methods
from ```OC_Mount_config``` to use ```OC_User::getHome``` to get the
path

Backport of 7c264c88fe,
b245e2e3d8 and
c06844c374 to stable6 (squashed)
2014-01-13 16:38:30 +01:00
st3so
5f2e8f7723 fixing typo in redirection query string
Backport of a2cae551f3 to stable6
2014-01-13 15:58:29 +01:00
Bjoern Schiessle
54cd174f61 don't unshare on delete 2014-01-13 15:25:59 +01:00
Vincent Petry
28be8496a9 Fixed various file name escaping issues in core apps
- Refactored file tr lookup into FileList.findFileEl that uses
  filterAttr to avoid escaping issues in jQuery selectors
- Fixed versions and sharing app to properly escape file names in
  attributes

Backport to stable6 of 1042733
2014-01-12 13:29:54 +01:00
Georg Ehrke
3ae7bfc298 fix preview for reshared file 2014-01-11 11:31:43 +01:00
Vincent Petry
1cbe1896e7 Prevent deleting storage root
Storage mount points are not deletable, so make sure that the unlink
operation and its hooks aren't run in such cases.

Note that some storages might recursively delete their contents when
calling unlink on their root. This fix prevents that as well.

Backport of f642ad3 to stable6
2014-01-10 16:50:26 +01:00
Arthur Schiwon
ebe3872c64 Infowarning about 32bit 2014-01-09 17:00:35 +01:00
Arthur Schiwon
f1ea0bcafc add tests for user counting 2014-01-09 17:00:28 +01:00
Arthur Schiwon
cf8fc2294e if backends have the same class name, sum their users up instead of overwriting 2014-01-09 17:00:21 +01:00
Arthur Schiwon
1636c6dbd8 LDAP: add tests for countUsers 2014-01-09 17:00:14 +01:00
Arthur Schiwon
59ff8388ea remove unnecessary line 2014-01-09 17:00:06 +01:00
Arthur Schiwon
1c58d8b226 LDAP: implement userCount action. This required to (finally) clean up and refactor the search method, which will have a positive performance impact on paged search. 2014-01-09 16:59:58 +01:00
Arthur Schiwon
0f58bd02c1 Add command line tool to show numbers of users and user directories 2014-01-09 16:59:47 +01:00
Arthur Schiwon
4b4901519d Introduce user count action to user management 2014-01-09 16:59:39 +01:00
Vincent Petry
a711d4e39a Removed special handling of part files in shared storage rename
This fixes the issue introduced by the transfer id which itself wasn't
taken into account by the shortcut code for part file in the shared
storage class.

Backport of 8eaa39f to stable6
2014-01-09 15:23:55 +01:00
Thomas Müller
52dc90d5fd Merge pull request #6696 from owncloud/backport-6693-stable6
Backport 6693 stable6
2014-01-09 04:56:26 -08:00
Thomas Müller
9a1cbabdd6 rename user-id to loginname to stay consistent 2014-01-09 12:34:19 +01:00
Thomas Müller
596ab7552e set login name within apache auth backend 2014-01-09 12:34:19 +01:00
Thomas Müller
ea23a09c05 fixing PHPDoc and use cameCase names 2014-01-09 12:34:19 +01:00
Arthur Schiwon
394bd17251 typo, grammar 2014-01-08 19:55:28 +01:00
Thomas Müller
627612c9e0 Merge pull request #6679 from owncloud/backport-6675-stable6
Backport 6675 stable6
2014-01-08 04:33:40 -08:00
Thomas Müller
c6fa2dd8e2 turn off mod_pagespeed 2014-01-08 12:19:30 +01:00
Thomas Müller
8d38228c98 Merge pull request #6678 from owncloud/backport-6660-stable6
Backport 6660 stable6
2014-01-08 02:50:15 -08:00
Thomas Müller
bbba8fd09d trimming all array elements 2014-01-08 10:45:37 +01:00
Thomas Müller
5e928fc988 we shall explode on ',' only 2014-01-08 10:45:37 +01:00
Thomas Müller
7e36763631 reuse existing helper function OC_Helper::is_function_enabled 2014-01-08 10:45:37 +01:00
Vincent Petry
542cf79595 Now also preventing to override "files" dir size with -1
Fixes #6526

Backport of 5be4af9 to stable6
2014-01-08 09:56:00 +01:00
Vincent Petry
2ea3765359 Added isUserAgent() method to request
- added isUserAgent() method to OC_Request which makes it possible to
  test it
- OC_Response::setContentDisposition now uses OC_Request::isUserAgent()
2014-01-07 22:11:39 +01:00
Vincent Petry
b7aaebf94f Added workaround for Android content disposition
Fixes #5807
2014-01-07 22:11:30 +01:00
Vincent Petry
c9cb258616 Moved content disposition code+workarounds to OCP\Response
Added new OC\Response API called setContentDispositionHeader() that
contains the needed workarounds for UTF8 and IE.

Refactored download code to use the new API.

Removed unused trashbin download file.
2014-01-07 22:11:22 +01:00
Thomas Müller
697ad1ca9e Merge pull request #6666 from ogasser/decimal_precision_scale_stable6_bp
DB: Support DECIMAL(precision,scale) syntax in XML
2014-01-07 11:11:32 -08:00
Thomas Müller
6a838718df Merge pull request #6664 from owncloud/fix_empty_mimetypes_stable6
remove duplicate exe mimetype, add correct msi mimetype
2014-01-07 07:31:29 -08:00
Oliver Gasser
6a21922854 DB: Support DECIMAL(precision,scale) syntax in XML
Add support for specifying the precision and scale of a decimal data
type to the XML description language. Added new unit tests and adapted
existing ones.

See owncloud/core#6475

Backported from owncloud/core#6476
2014-01-07 16:07:54 +01:00
Jörn Friedrich Dreyer
c81a05cbb1 remove duplicate exe mimetype, add correct msi mimetype 2014-01-07 15:54:33 +01:00
Robin Appelman
956a4419d8 Fix APCIterator syntax in \OC\Memcache\APCU::clear
see http://www.php.net/manual/en/apciterator.construct.php
2014-01-03 14:31:19 +01:00
Robin Appelman
f356ef90d7 Return SPACE_UNKNOWN if disk_free_space is disabled when getting the free space on a local storage 2014-01-02 17:30:39 +01:00
Robin Appelman
a8fd55d90d Pass config object in testGetHomeNotSupported 2014-01-02 16:58:30 +01:00
Robin Appelman
208037b56a Replace static usage of OC_Config and OC_Preferences with the injected \OC\ConfigAll 2014-01-02 16:58:12 +01:00
Robin Appelman
62887c67ab fix the config option to remove the ability for users to set their displayname 2014-01-02 16:58:05 +01:00
Robin Appelman
9960596f4e fix fallback overwriting result of getHome 2014-01-02 16:57:52 +01:00
Robin Appelman
b5ef21b22d cache the home folder of a User 2014-01-02 16:57:45 +01:00
Robin Appelman
44fb817a4e Also add default to the \OCP\IConfig interface 2014-01-02 16:54:44 +01:00
Robin Appelman
2c54dcda89 add default parameter for AllConfig->get*Value() 2014-01-02 16:54:39 +01:00
Frank Karlitschek
0bb7202ff7 Merge pull request #6562 from syncloud/stable6
Made admin password field required on client side
2013-12-25 03:36:00 -08:00
Vladimir Sapronov
75eaea1dff Made password field required on client side
Fix for case described in https://github.com/syncloud/owncloud-setup/issues/19
2013-12-23 21:39:14 -05:00
Andreas Fischer
93b6c83814 Backport of PR #4378: Don't use xcache in case admin auth is enabled. 2013-12-20 17:15:48 +01:00
Andreas Fischer
d9df271113 Do not use xcache variable cache if cache size is 0.
This is possible because it is possible to only use xcache as an opcode cache
but not a variable cache.
2013-12-20 16:50:18 +01:00
Bjoern Schiessle
13461698e4 tests added 2013-12-19 20:10:42 +01:00
Bjoern Schiessle
eaa5dd0282 we can also have a path user/cache/... 2013-12-19 20:10:29 +01:00
Bjoern Schiessle
672cbc5378 check if the old owner and the old path is available 2013-12-19 19:20:29 +01:00
Bjoern Schiessle
2f568c9766 fix rename of shared files 2013-12-19 19:20:17 +01:00
Vincent Petry
c4c972fd2f Merge pull request #6498 from owncloud/stable6-oracleencryptiontestfix
[stable6] Trying to fix failing encryption tests on Oracle
2013-12-19 06:45:37 -08:00
Thomas Müller
6de259e0ac Merge pull request #6291 from owncloud/ldap_doc_link
LDAP: Adjust help link to documentation
2013-12-19 02:56:34 -08:00
Vincent Petry
1f93b4e842 Removed numRows usage from encryption app
numRows on Oracle always seem to return 0.

This fix removes numRows usage from the encryption and sharing app.

This fixes unit tests and potentially the encryption app itself
(migration status) when running on Oracle
2013-12-18 21:14:26 +01:00
Robin Appelman
4c2d2f4dc9 check if a $_SESSION entry exists before we try to remove it 2013-12-18 14:26:27 +01:00
Robin Appelman
148c16bf70 preserve 3rd party values in in the Session destructor 2013-12-18 14:26:21 +01:00
Vincent Petry
77af1a7127 Fixed JS plural function to be per app
Some apps might not define the same "nplural" value.
To avoid conflicts, the plural function is now generated per app.

Fixes #6427
2013-12-18 12:13:22 +01:00
Bjoern Schiessle
2f0ec8256f reliable detect encrypted files 2013-12-17 18:14:36 +01:00
Frank Karlitschek
913df0c5ed clarifying license 2013-12-17 17:30:57 +01:00
Bjoern Schiessle
c88109a496 always show home breadcrumb in files view 2013-12-17 11:02:02 +01:00
Bjoern Schiessle
8f5dfd0920 always show 'Deleted Files' breadcrumb 2013-12-17 11:01:43 +01:00
Vincent Petry
ae58a385b7 Do not use L10n when logging exceptions
In some specific situations, the L10N bundle isn't loadable yet (for
example when there is an issue with the app_config table). In such case,
we still want to be able to log the real exception.

This fixes errors that say "OC_L10N_String::__toString must not throw
exceptions"
2013-12-17 10:56:02 +01:00
Bjoern Schiessle
3160b23291 update file cache for target file 2013-12-16 17:49:14 +01:00
Bjoern Schiessle
73a0b690e9 only remove encryption keys if a real file gets deleted, skip this method if a file outside of /data/user/files was deleted 2013-12-16 17:49:05 +01:00
Bjoern Schiessle
bdb4890d04 call set password hook because it doesn't get triggered during test execution and fix paths 2013-12-16 17:48:52 +01:00
Bjoern Schiessle
9091dd7833 enable more tests 2013-12-16 17:48:44 +01:00
Thomas Tanghus
a8a35f4d07 Use DEBUG instead of ERROR when favourites not found. Fix #6419 2013-12-16 17:31:03 +01:00
Frank Karlitschek
0d24b22485 6.0.0a 2013-12-14 20:40:17 +01:00
Frank Karlitschek
e8a696cff9 Merge pull request #6389 from owncloud/ignore_comments_on_columns
ignore comments on schema as a quickfix for oc6
2013-12-14 11:31:20 -08:00
Vincent Petry
811ef19ada Removed comments in database schema of encryption app 2013-12-14 11:18:48 +01:00
Jörn Friedrich Dreyer
db696a2dda ignore comments on schema as a quickfix for oc6 2013-12-13 19:21:14 +01:00
Arthur Schiwon
3d81009347 LDAP: only read config from database, if configID is given. Not what we want to do when on-the-fly-testing settings from the admin page 2013-12-13 18:01:42 +01:00
Vincent Petry
0b665700b5 Merge pull request #6406 from owncloud/stable6-no-backgroundjobs-during-upgrade
dont try to register background jobs if we haven't upgraded yet
2013-12-13 08:58:50 -08:00
Arthur Schiwon
1e407482be remove unused variables 2013-12-13 17:52:43 +01:00
Arthur Schiwon
d343c66f85 LDAP: fix TLS detection 2013-12-13 17:52:19 +01:00
Robin Appelman
0a0d89296b dont try to register background jobs if we haven't upgraded yet 2013-12-13 17:13:18 +01:00
blizzz
fede36d515 Merge pull request #6308 from owncloud/fix_webdav_session_login_user_comparison
Fix webdav session login user comparison
2013-12-13 07:56:28 -08:00
Vincent Petry
527a16852e Merge pull request #6367 from owncloud/fix_expiration_date_conversion
rely only on php DateTime to parse the db datetime string
2013-12-13 07:36:30 -08:00
blizzz
aab7c187f2 Merge pull request #6372 from owncloud/ldap_fix_setConfig
LDAP: fix method behind save button on advancend and expert tabs, fixes ...
2013-12-13 07:28:44 -08:00
Vincent Petry
dd7b074dfa Fix webroot for update page
On the update page, config.js was missing which caused oc_webroot to not
be available. That would trigger the faulty oc_webroot fallback that
didn't take URLs like "/owncloud/index.php/files/apps" into account.

This fix adds config.js in the update page and also a fix for the
oc_webroot fallback, in case it is used elsewhere.

Backport of df1a404
2013-12-13 14:36:35 +01:00
Robin Appelman
71e93c2b79 remove unneeded ; in comment 2013-12-13 13:52:39 +01:00
Robin Appelman
ca161e2a96 Add test for having utf8 filenames in the cache 2013-12-13 13:52:32 +01:00
Arthur Schiwon
ab8691d84b adjust test 2013-12-13 12:56:06 +01:00
Thomas Müller
a48cf28e17 Merge pull request #6364 from owncloud/backport-6302-stable6
Send "SET NAMES utf8" to MySQL for PHP below 5.3.6
2013-12-13 00:56:28 -08:00
Thomas Müller
cd7c974fb6 Updated 3rdparty ref 2013-12-13 00:03:20 +01:00
Arthur Schiwon
3b5d032dd5 LDAP: fix method behind save button on advancend and expert tabs, fixes at least Home Folder setinng 2013-12-12 23:09:31 +01:00
Jörn Friedrich Dreyer
f8088ecd29 rely only on php DateTime to parse the db datetime string 2013-12-12 19:09:21 +01:00
Bjoern Schiessle
e83ff69465 toggle select all checkbox 2013-12-12 18:47:31 +01:00
Andreas Fischer
66af605697 Send "SET NAMES utf8" to MySQL for PHP below 5.3.6 2013-12-12 12:26:17 -05:00
Jörn Friedrich Dreyer
71dc81d420 update 3rdparty 2013-12-12 17:59:46 +01:00
blizzz
02c9bb76ff Merge pull request #6350 from owncloud/ldap_dont_autofill
LDAP: the browser shall not autofill userdn and password, usually login ...
2013-12-12 05:14:44 -08:00
Arthur Schiwon
7b388eb4a8 LDAP: the browser shall not autofill userdn and password, usually login credentials are inserted. fixes #6283 2013-12-12 14:04:10 +01:00
Arthur Schiwon
c770089b50 coding style 2013-12-11 14:01:48 +01:00
Arthur Schiwon
afaac05f61 coding style 2013-12-11 13:57:02 +01:00
Arthur Schiwon
aba8199a82 On webdav sesssions, loginname was compared to username which does not need to match necessarily 2013-12-11 13:56:45 +01:00
Arthur Schiwon
0134b1ebfa LDAP: adjust documentation URL for OC 6 2013-12-10 17:45:03 +01:00
Jan-Christoph Borchardt
339e073399 fix shadow size and arrow position 2013-12-10 14:39:23 +01:00
Jan-Christoph Borchardt
4feafda822 fix the legacy popup to make calendar settings look nicer 2013-12-10 14:39:15 +01:00
Andreas Fischer
5ac339b866 Document memcached settings in config.sample.php 2013-12-09 14:35:20 +01:00
Morris Jobke
95c90ddbc4 fix wrong test data in l10n 2013-12-09 10:41:57 +01:00
Morris Jobke
2417c8a49e fix plural translation - fixes #6226 2013-12-09 10:41:51 +01:00
Frank Karlitschek
26d0adf2fe 6.0.0 2013-12-06 21:20:22 +01:00
Frank Karlitschek
734fdbddea RC4 2013-12-06 21:06:42 +01:00
Robin Appelman
33144941a9 add test case for removing background jobs that are throwing exceptions 2013-12-06 20:58:12 +01:00
Robin Appelman
f309920bef Dont use exceptions for the backgroundjob test cases 2013-12-06 20:58:06 +01:00
Robin Appelman
e78a309111 remove background jobs if they are failing 2013-12-06 20:57:58 +01:00
Robin Appelman
46a4ad4f3c Catch exceptions from background jobs and log them 2013-12-06 20:57:52 +01:00
Frank Karlitschek
3842c0d766 Merge pull request #6225 from owncloud/stable6-backgroundscan-reuse-etag
Stable6 backgroundscan reuse etag
2013-12-06 11:55:23 -08:00
Robin Appelman
8369c1f05b get rid of failing test that don't cause additional downloads 2013-12-06 19:19:10 +01:00
Robin Appelman
cadf1c232e extend test case for etag preservation 2013-12-06 19:19:10 +01:00
Robin Appelman
713651738c reuse etags when doing a background scan 2013-12-06 19:19:10 +01:00
Bart Visscher
1475245465 XSendfile and encryption don't work together
The file on disk is encrypted, and not readable on client systems
2013-12-06 19:07:22 +01:00
Bart Visscher
281bbf4bd4 Don't try to encrypt a file when the temp file isn't created 2013-12-06 19:07:11 +01:00
Bart Visscher
a2bbbb1448 Users of getFolderContent are mostly interested in the unecrypted file size 2013-12-06 19:06:42 +01:00
root
87a28957aa correctly propagate the return value of ldap_set_option
otherwise LDAP_OPT_REFERRALS won't be set to 0 and in turn
active directory paging will stop working
(Operations error on ldap_control_paged_result_response)
2013-12-06 18:01:42 +01:00
Bjoern Schiessle
01de6c565a set unencrypted_size to 0 after decryption... so that the unencrypted_size gets re-calculated if encryption was enabled again 2013-12-06 17:08:17 +01:00
Bjoern Schiessle
f3e341edac add a optional parameter to skip check for expired files, this is necessary to find out to whom a file was shared after it was expired. 2013-12-06 14:42:09 +01:00
Bjoern Schiessle
c5d6af3c5a get owner from share item, if we expire a share while the user updates his /Shared folder than the owner is different from the currently logged in user 2013-12-06 14:41:59 +01:00
Bjoern Schiessle
cc1577054d it is not possible to unshare files 2013-12-06 12:36:31 +01:00
Björn Schießle
3e6b18b2d0 Merge pull request #6208 from owncloud/enc_only_create_new_key_if_no_other_key_exists
[Encryption] Only create new key if no other key exists
2013-12-06 03:07:52 -08:00
Nico Kaiser
7eb505e6dd Fix user's displayName being overwritten by (old) cookie 2013-12-05 20:56:41 +01:00
Bjoern Schiessle
91ca1cf985 fix typo 2013-12-05 20:02:41 +01:00
Bjoern Schiessle
f8a4bcdd50 only create new key on password change if a recovery key exists or if the user don't have any private/public keys 2013-12-05 19:41:01 +01:00
Bjoern Schiessle
418d401bf9 show change password form if key couldn't be decrypted 2013-12-05 18:50:52 +01:00
Bjoern Schiessle
d0afd774b7 add method to check if users private/public key exists 2013-12-05 18:49:55 +01:00
Morris Jobke
0af65cae37 fix appearance of error message - .errors is outdated 2013-12-05 16:11:52 +01:00
Frank Karlitschek
4d50fe5f12 ownCloud 6 RC3 2013-12-05 12:02:53 +01:00
Vincent Petry
f24aca61a9 Merge pull request #6180 from owncloud/fix_6143
fixes checkboxes in Advanced Tab don't save unchecked state anymore, #6143
2013-12-04 08:33:12 -08:00
Bjoern Schiessle
d3e2226b38 config switch to disable auto expire for the trash bin 2013-12-04 16:55:07 +01:00
Arthur Schiwon
73fa6259be LDAP Wizard: avoid a manually deactivated LDAP configuration is enabled by just opening the admin page 2013-12-04 14:01:31 +01:00
Morris Jobke
dffc2a8b1c Revert "Adjust files_encryption requirements to the new core requirement (PHP 5.3.8)."
This reverts commit efbf18652c.
2013-12-04 13:26:59 +01:00
Vincent Petry
fd634fdec8 Added unit test for the test() method
This is to make sure that method isn't broken
2013-12-04 13:22:25 +01:00
Arthur Schiwon
328ebaefde LDAP: make unsetting checkboxes from Advanced tab work again, fixes #6143 2013-12-04 13:15:17 +01:00
Thomas Müller
4de8c4e5db Merge pull request #6175 from owncloud/fix_6142
LDAP Wizard: make sure auto-detected suggestions are really applied initially, fixes #6142
2013-12-04 02:54:07 -08:00
Frank Karlitschek
8dc3cb2ffb lower required php version to 5.3.3 2013-12-04 10:51:12 +01:00
Arthur Schiwon
c67ece0f6b LDAP Wizard: don't generate filter when not allowed 2013-12-03 20:50:46 +01:00
Arthur Schiwon
6640e120b7 some equals are more equal than other equals 2013-12-03 20:45:05 +01:00
Thomas Mueller
6f7b394d99 fixing PHPDoc and spelling 2013-12-03 17:49:37 +01:00
Andreas Fischer
91f47645b0 Use getLastError() everywhere. 2013-12-03 17:49:37 +01:00
Andreas Fischer
18903cc8f7 Add getLastError() 2013-12-03 17:49:37 +01:00
Andreas Fischer
7e467484a8 No function as oci_last_error. It's oci_error. 2013-12-03 17:49:37 +01:00
Andreas Fischer
21bf6abd41 There is no property such as dbusername. It's 'dbuser'. 2013-12-03 17:49:37 +01:00
Andreas Fischer
401728b2a2 Correct property name. It's 'dbpassword', with the 'db' prefix. 2013-12-03 17:49:37 +01:00
Andreas Fischer
bfd0dc3314 Correct property name. It's just 'tableprefix', without the 'db' prefix. 2013-12-03 17:49:37 +01:00
Jan-Christoph Borchardt
ad92b12559 fix time input field properly, details 2013-12-03 17:42:03 +01:00
Morris Jobke
4391992b8c fix public page - gallery view issues 2013-12-03 17:20:29 +01:00
Morris Jobke
728e6d735a fix trashbin and pbulic page controls 2013-12-03 17:20:23 +01:00
Morris Jobke
66df8c3bb3 fix and cleanup CSS for public page 2013-12-03 17:20:17 +01:00
Jan-Christoph Borchardt
ca08d21da0 change different shades of grey for public share page to white 2013-12-03 17:20:08 +01:00
Jan-Christoph Borchardt
7d0f458f11 remove app specific code 2013-12-03 17:20:00 +01:00
Jan-Christoph Borchardt
f15aeb3bbc fix details for buttons in header and controls bar 2013-12-03 17:19:53 +01:00
Jan-Christoph Borchardt
9333244925 account for shift of controls bar due to app navigation, do not shift on public page 2013-12-03 17:19:38 +01:00
Vincent Petry
50f5ab8515 Merge pull request #6173 from owncloud/stable6-extstorage-s3fixes
Backport of S3 ext storage fixes to stable6
2013-12-03 08:16:10 -08:00
Arthur Schiwon
4df0d2e7e8 LDAP Wizard: return correct var 2013-12-03 16:37:11 +01:00
Vincent Petry
f2e17a0b68 Fixed placeholder after page reload
The placeholder somehow had too many characters stripping from it...
2013-12-03 15:55:24 +01:00
Vincent Petry
e372971f2b Fixed test function for S3
Fixes #5752
2013-12-03 15:55:15 +01:00
Vincent Petry
3bf30377b8 Fixed Amazon S3 ext storage config UI
Optional parameters are now really optional

Fixes #5861
2013-12-03 15:55:08 +01:00
Arthur Schiwon
67b67b6d66 LDAP Wizard: make sure auto-detected suggestions are really applied initially. Also make initial filter compilation and user counting robust against race conditions. 2013-12-03 13:27:45 +01:00
Arthur Schiwon
b8390f15d4 LDAP: on testing configuration, set active property to true, otherwise inactive connections cannot be tested properly 2013-12-03 13:21:55 +01:00
Robin Appelman
5ac3f9bfa5 check if a directory exists before we try to remove it 2013-12-03 12:45:41 +01:00
Arthur Schiwon
02fe013d2f LDAP: set default value for login filter to empty, otherwise the wizard signals completed configuration too early when it might be not correct, i.e. login won't work 2013-12-03 12:11:43 +01:00
Bjoern Schiessle
5e5e4fe3a4 make it possible to select folders 2013-12-02 22:23:51 +01:00
Arthur Schiwon
d49e4e53fd LDAP Wizard: don't send ldap_tls change back to the interface as the element was removed, for it is detected fully automatically. Resolves an JS error and thus an ever-spinning spinner 2013-12-02 21:11:20 +01:00
Bjoern Schiessle
2d11290121 check explicitely all possible dir values 2013-12-02 16:06:51 +01:00
Bjoern Schiessle
1a197292da set delete all to true if a complete folder was deleted 2013-12-02 16:06:36 +01:00
Bjoern Schiessle
3b59979746 fix delete files from trash bin 2013-12-02 16:06:24 +01:00
Bjoern Schiessle
259d619af3 fix restore from files in sub-folders 2013-12-02 16:06:14 +01:00
1524 changed files with 18622 additions and 314202 deletions

View File

@@ -26,7 +26,7 @@ RewriteRule ^.well-known/carddav /remote.php/carddav/ [R]
RewriteRule ^.well-known/caldav /remote.php/caldav/ [R]
RewriteRule ^apps/calendar/caldav.php remote.php/caldav/ [QSA,L]
RewriteRule ^apps/contacts/carddav.php remote.php/carddav/ [QSA,L]
RewriteRule ^apps/([^/]*)/(.*\.(css|php))$ index.php?app=$1&getfile=$2 [QSA,L]
RewriteRule ^apps/([^/]*)/(.*\.(php))$ index.php?app=$1&getfile=$2 [QSA,L]
RewriteRule ^remote/(.*) remote.php [QSA,L]
</IfModule>
<IfModule mod_mime.c>
@@ -38,3 +38,6 @@ DirectoryIndex index.php index.html
</IfModule>
AddDefaultCharset utf-8
Options -Indexes
<IfModule pagespeed_module>
ModPagespeed Off
</IfModule>

View File

@@ -17,7 +17,9 @@ $success = true;
//Now delete
foreach ($files as $file) {
if (($dir === '' && $file === 'Shared') || !\OC\Files\Filesystem::unlink($dir . '/' . $file)) {
if (($dir === '' && $file === 'Shared') ||
(\OC\Files\Filesystem::file_exists($dir . '/' . $file) &&
!\OC\Files\Filesystem::unlink($dir . '/' . $file))) {
$filesWithError .= $file . "\n";
$success = false;
}

View File

@@ -9,7 +9,7 @@ $RUNTIME_APPTYPES=array('filesystem');
OCP\JSON::checkLoggedIn();
// Load the files
$dir = isset( $_GET['dir'] ) ? $_GET['dir'] : '';
$dir = isset($_GET['dir']) ? (string)$_GET['dir'] : '';
$dir = \OC\Files\Filesystem::normalizePath($dir);
if (!\OC\Files\Filesystem::is_dir($dir . '/')) {
header("HTTP/1.0 404 Not Found");

View File

@@ -18,7 +18,7 @@ if(\OC\Files\Filesystem::file_exists($target . '/' . $file)) {
exit;
}
if ($dir != '' || $file != 'Shared') {
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)) {

View File

@@ -77,14 +77,53 @@ if (\OC\Files\Filesystem::file_exists($target)) {
}
if($source) {
if(substr($source, 0, 8)!='https://' and substr($source, 0, 7)!='http://') {
OCP\JSON::error(array('data' => array( 'message' => $l10n->t('Not a valid source') )));
$httpHelper = \OC::$server->getHTTPHelper();
if(!$httpHelper->isHTTPURL($source)) {
OCP\JSON::error(array('data' => array('message' => $l10n->t('Not a valid source'))));
exit();
}
$ctx = stream_context_create(null, array('notification' =>'progress'));
$sourceStream=fopen($source, 'rb', false, $ctx);
$result=\OC\Files\Filesystem::file_put_contents($target, $sourceStream);
if (!ini_get('allow_url_fopen')) {
$eventSource->send('error', $l10n->t('Server is not allowed to open URLs, please check the server configuration'));
$eventSource->close();
exit();
}
$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)) {
$meta = stream_get_meta_data($sourceStream);
if (isset($meta['wrapper_data']) && is_array($meta['wrapper_data'])) {
//check stream size
$storageStats = \OCA\Files\Helper::buildFileStorageStatistics($dir);
$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);
if ($length > $freeSpace) {
$delta = $length - $freeSpace;
$humanDelta = OCP\Util::humanFileSize($delta);
$eventSource->send('error', (string)$l10n->t('The file exceeds your quota by %s', array($humanDelta)));
$eventSource->close();
fclose($sourceStream);
exit();
}
}
}
}
$result=\OC\Files\Filesystem::file_put_contents($target, $sourceStream);
}
if($result) {
$meta = \OC\Files\Filesystem::getFileInfo($target);
$mime=$meta['mimetype'];
@@ -93,6 +132,9 @@ if($source) {
} else {
$eventSource->send('error', $l10n->t('Error while downloading %s to %s', array($source, $target)));
}
if (is_resource($sourceStream)) {
fclose($sourceStream);
}
$eventSource->close();
exit();
} else {

View File

@@ -19,8 +19,12 @@ if (empty($_POST['dirToken'])) {
die();
}
} else {
\OC_User::setIncognitoMode(true);
// return only read permissions for public upload
$allowedPermissions = OCP\PERMISSION_READ;
$public_directory = !empty($_POST['subdir']) ? $_POST['subdir'] : '/';
$linkItem = OCP\Share::getShareByToken($_POST['dirToken']);
if ($linkItem === false) {
@@ -34,16 +38,21 @@ if (empty($_POST['dirToken'])) {
// resolve reshares
$rootLinkItem = OCP\Share::resolveReShare($linkItem);
OCP\JSON::checkUserExists($rootLinkItem['uid_owner']);
// Setup FS with owner
OC_Util::tearDownFS();
OC_Util::setupFS($rootLinkItem['uid_owner']);
// The token defines the target directory (security reasons)
$path = \OC\Files\Filesystem::getPath($linkItem['file_source']);
if($path === null) {
OCP\JSON::error(array('data' => array_merge(array('message' => $l->t('Unable to set upload directory.')))));
die();
}
$dir = sprintf(
"/%s/%s",
$path,
isset($_POST['subdir']) ? $_POST['subdir'] : ''
$public_directory
);
if (!$dir || empty($dir) || $dir === false) {
@@ -77,7 +86,9 @@ foreach ($_FILES['files']['error'] as $error) {
UPLOAD_ERR_NO_TMP_DIR => $l->t('Missing a temporary folder'),
UPLOAD_ERR_CANT_WRITE => $l->t('Failed to write to disk'),
);
OCP\JSON::error(array('data' => array_merge(array('message' => $errors[$error]), $storageStats)));
$errorMessage = $errors[$error];
\OCP\Util::writeLog('files', "Upload error: $error - $errorMessage", \OCP\Util::ERROR);
OCP\JSON::error(array('data' => array_merge(array('message' => $errorMessage), $storageStats)));
exit();
}
}
@@ -110,7 +121,14 @@ if (strpos($dir, '..') === false) {
} else {
$target = \OC\Files\Filesystem::normalizePath(stripslashes($dir).'/'.$files['name'][$i]);
}
$directory = \OC\Files\Filesystem::normalizePath(stripslashes($dir));
if (isset($public_directory)) {
// If we are uploading from the public app,
// we want to send the relative path in the ajax request.
$directory = $public_directory;
}
if ( ! \OC\Files\Filesystem::file_exists($target)
|| (isset($_POST['resolution']) && $_POST['resolution']==='replace')
) {
@@ -136,7 +154,8 @@ if (strpos($dir, '..') === false) {
'originalname' => $files['tmp_name'][$i],
'uploadMaxFilesize' => $maxUploadFileSize,
'maxHumanFilesize' => $maxHumanFileSize,
'permissions' => $meta['permissions'] & $allowedPermissions
'permissions' => $meta['permissions'] & $allowedPermissions,
'directory' => $directory,
);
}
@@ -146,7 +165,7 @@ if (strpos($dir, '..') === false) {
} catch(Exception $ex) {
$error = $ex->getMessage();
}
} else {
// file already exists
$meta = \OC\Files\Filesystem::getFileInfo($target);
@@ -163,7 +182,8 @@ if (strpos($dir, '..') === false) {
'originalname' => $files['tmp_name'][$i],
'uploadMaxFilesize' => $maxUploadFileSize,
'maxHumanFilesize' => $maxHumanFileSize,
'permissions' => $meta['permissions'] & $allowedPermissions
'permissions' => $meta['permissions'] & $allowedPermissions,
'directory' => $directory,
);
}
}

View File

@@ -49,9 +49,9 @@ $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 OC_Connector_Sabre_FilesPlugin());
$server->addPlugin(new OC_Connector_Sabre_AbortedUploadDetectionPlugin());
$server->addPlugin(new OC_Connector_Sabre_QuotaPlugin());
$server->addPlugin(new OC_Connector_Sabre_MaintenancePlugin());
$server->addPlugin(new OC_Connector_Sabre_ExceptionLoggerPlugin('webdav'));
// And off we go!
$server->exec();

View File

@@ -3,17 +3,14 @@
// fix webdav properties,add namespace in front of the property, update for OC4.5
$installedVersion=OCP\Config::getAppValue('files', 'installed_version');
if (version_compare($installedVersion, '1.1.6', '<')) {
$query = OC_DB::prepare( 'SELECT `propertyname`, `propertypath`, `userid` FROM `*PREFIX*properties`' );
$result = $query->execute();
$updateQuery = OC_DB::prepare('UPDATE `*PREFIX*properties`'
.' SET `propertyname` = ?'
.' WHERE `userid` = ?'
.' AND `propertypath` = ?');
while( $row = $result->fetchRow()) {
if ( $row['propertyname'][0] != '{' ) {
$updateQuery->execute(array('{DAV:}' + $row['propertyname'], $row['userid'], $row['propertypath']));
}
}
$concat = OC_DB::getConnection()->getDatabasePlatform()->
getConcatExpression( '\'{DAV:}\'', '`propertyname`' );
$query = OC_DB::prepare('
UPDATE `*PREFIX*properties`
SET `propertyname` = ' . $concat . '
WHERE `propertyname` NOT LIKE \'{%\'
');
$query->execute();
}
//update from OC 3

View File

@@ -57,6 +57,7 @@ class Scan extends Command {
}
protected function execute(InputInterface $input, OutputInterface $output) {
\OC_App::loadApps('authentication');
if ($input->getOption('all')) {
$users = $this->userManager->search('');
} else {
@@ -67,7 +68,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>");
}
}
}
}

View File

@@ -65,9 +65,14 @@
top: 44px;
width: 100%;
}
#filestable, #controls {
min-width: 680px;
/* make sure there's enough room for the file actions */
#body-user #filestable {
min-width: 750px;
}
#body-user #controls {
min-width: 600px;
}
#filestable tbody tr { background-color:#fff; height:2.5em; }
#filestable tbody tr:hover, tbody tr:active {
background-color: rgb(240,240,240);
@@ -98,7 +103,7 @@ table td {
}
table th#headerName {
position: relative;
width: 100em; /* not really sure why this works better than 100% … table styling */
width: 9999px; /* not really sure why this works better than 100% … table styling */
padding: 0;
}
#headerName-container {
@@ -140,7 +145,7 @@ table.multiselect thead th {
}
table.multiselect #headerName {
position: relative;
width: 100%;
width: 9999px; /* when we use 100%, the styling breaks on mobile … table styling */
}
table td.selection, table th.selection, table td.fileaction { width:2em; text-align:center; }
table td.filename a.name {
@@ -237,7 +242,7 @@ table td.filename form { font-size:.85em; margin-left:3em; margin-right:3em; }
#fileList tr td.filename a.name label {
position: absolute;
width: 100%;
width: 80%;
height: 50px;
}

View File

@@ -18,9 +18,6 @@
margin: -5px -3px;
cursor: pointer;
z-index: 10;
background-image: url('%webroot%/core/img/actions/upload.svg');
background-repeat: no-repeat;
background-position: center;
opacity: .65;
}
.file_upload_target { display:none; }
@@ -119,11 +116,6 @@
.oc-dialog .fileexists .conflict input[type='checkbox'] {
float: left;
}
.oc-dialog .fileexists .toggle {
background-image: url('%webroot%/core/img/actions/triangle-e.png');
width: 16px;
height: 16px;
}
.oc-dialog .fileexists #allfileslabel {
float:right;
}

View File

@@ -24,6 +24,9 @@
// Check if we are a user
OCP\User::checkLoggedIn();
// don't block php session during download
session_write_close();
$filename = $_GET["file"];
if(!\OC\Files\Filesystem::file_exists($filename)) {
@@ -37,12 +40,7 @@ if(!\OC\Files\Filesystem::file_exists($filename)) {
$ftype=\OC\Files\Filesystem::getMimeType( $filename );
header('Content-Type:'.$ftype);
if ( preg_match( "/MSIE/", $_SERVER["HTTP_USER_AGENT"] ) ) {
header( 'Content-Disposition: attachment; filename="' . rawurlencode( basename($filename) ) . '"' );
} else {
header( 'Content-Disposition: attachment; filename*=UTF-8\'\'' . rawurlencode( basename($filename) )
. '; filename="' . rawurlencode( basename($filename) ) . '"' );
}
OCP\Response::setContentDispositionHeader(basename($filename), 'attachment');
OCP\Response::disableCaching();
header('Content-Length: '.\OC\Files\Filesystem::filesize($filename));

View File

@@ -70,7 +70,7 @@ OC.Upload = {
*/
isProcessing:function() {
var count = 0;
jQuery.each(this._uploads,function(i, data) {
if (data.state() === 'pending') {
count++;
@@ -170,7 +170,7 @@ OC.Upload = {
$(document).ready(function() {
if ( $('#file_upload_start').exists() ) {
if ( $('#file_upload_start').exists()&& $('#file_upload_start').is(':visible') ) {
var file_upload_param = {
dropZone: $('#content'), // restrict dropZone to content div
@@ -196,13 +196,13 @@ $(document).ready(function() {
add: function(e, data) {
OC.Upload.log('add', e, data);
var that = $(this);
// we need to collect all data upload objects before starting the upload so we can check their existence
// and set individual conflict actions. unfortunately there is only one variable that we can use to identify
// the selection a data upload is part of, so we have to collect them in data.originalFiles
// turning singleFileUploads off is not an option because we want to gracefully handle server errors like
// already exists
// create a container where we can store the data objects
if ( ! data.originalFiles.selection ) {
// initialize selection and remember number of files to upload
@@ -213,32 +213,40 @@ $(document).ready(function() {
};
}
var selection = data.originalFiles.selection;
// add uploads
if ( selection.uploads.length < selection.filesToUpload ) {
// remember upload
selection.uploads.push(data);
}
//examine file
var file = data.files[0];
if (file.type === '' && file.size === 4096) {
try {
// FIXME: not so elegant... need to refactor that method to return a value
Files.isFileNameValid(file.name, FileList.getCurrentDirectory());
}
catch (errorMessage) {
data.textStatus = 'invalidcharacters';
data.errorThrown = errorMessage;
}
if ((file.type === '' && file.size === 4096) || file.relativePath) {
data.textStatus = 'dirorzero';
data.errorThrown = t('files', 'Unable to upload {filename} as it is a directory or has 0 bytes',
{filename: file.name}
);
}
// add size
selection.totalBytes += file.size;
//check max upload size
if (selection.totalBytes > $('#max_upload').val()) {
data.textStatus = 'notenoughspace';
data.errorThrown = t('files', 'Not enough space available');
}
// end upload for whole selection on error
if (data.errorThrown) {
// trigger fileupload fail
@@ -249,12 +257,12 @@ $(document).ready(function() {
// check existing files when all is collected
if ( selection.uploads.length >= selection.filesToUpload ) {
//remove our selection hack:
delete data.originalFiles.selection;
var callbacks = {
onNoConflicts: function (selection) {
$.each(selection.uploads, function(i, upload) {
upload.submit();
@@ -277,7 +285,7 @@ $(document).ready(function() {
};
OC.Upload.checkExistingFiles(selection, callbacks);
}
return true; // continue adding files
@@ -288,6 +296,8 @@ $(document).ready(function() {
*/
start: function(e) {
OC.Upload.log('start', e, null);
//hide the tooltip otherwise it covers the progress bar
$('#upload').tipsy('hide');
},
submit: function(e, data) {
OC.Upload.rememberUpload(data);
@@ -400,7 +410,7 @@ $(document).ready(function() {
});
fileupload.on('fileuploadstop', function(e, data) {
OC.Upload.log('progress handle fileuploadstop', e, data);
$('#uploadprogresswrapper input.stop').fadeOut();
$('#uploadprogressbar').fadeOut();
Files.updateStorageStatistics();
@@ -492,7 +502,7 @@ $(document).ready(function() {
if ($(this).children('p').length === 0) {
return;
}
$('#new .error').tipsy('hide');
$('#new li').each(function(i,element) {
@@ -506,7 +516,7 @@ $(document).ready(function() {
var text=$(this).children('p').text();
$(this).data('text',text);
$(this).children('p').remove();
// add input field
var form = $('<form></form>');
var input = $('<input type="text">');
@@ -523,7 +533,7 @@ $(document).ready(function() {
throw t('files', 'URL cannot be empty');
} else if (type !== 'web' && !Files.isFileNameValid(filename)) {
// Files.isFileNameValid(filename) throws an exception itself
} else if ($('#dir').val() === '/' && filename === 'Shared') {
} else if (FileList.getCurrentDirectory() === '/' && filename.toLowerCase() === 'shared') {
throw t('files', 'In the home folder \'Shared\' is a reserved filename');
} else if (FileList.inList(filename)) {
throw t('files', '{new_name} already exists', {new_name: filename});
@@ -605,7 +615,7 @@ $(document).ready(function() {
if (result.status === 'success') {
var date=new Date();
FileList.addDir(name, 0, date, hidden);
var tr=$('tr[data-file="'+name+'"]');
var tr = FileList.findFileEl(name);
tr.attr('data-id', result.data.id);
} else {
OC.dialogs.alert(result.data.message, t('core', 'Could not create folder'));
@@ -647,7 +657,7 @@ $(document).ready(function() {
$('#uploadprogressbar').fadeOut();
var date = new Date();
FileList.addFile(localName, size, date, false, hidden);
var tr = $('tr[data-file="'+localName+'"]');
var tr = FileList.findFileEl(localName);
tr.data('mime', mime).data('id', id);
tr.attr('data-id', id);
var path = $('#dir').val()+'/'+localName;
@@ -658,7 +668,11 @@ $(document).ready(function() {
});
eventSource.listen('error',function(error) {
$('#uploadprogressbar').fadeOut();
alert(error);
OC.Notification.show(error);
// hide notification after 10 sec
setTimeout(function() {
OC.Notification.hide();
}, 10000);
});
break;
}

View File

@@ -71,7 +71,7 @@ var FileActions = {
FileActions.currentFile = parent;
var actions = FileActions.get(FileActions.getCurrentMimeType(), FileActions.getCurrentType(), FileActions.getCurrentPermissions());
var file = FileActions.getCurrentFile();
if ($('tr[data-file="'+file+'"]').data('renaming')) {
if (FileList.findFileEl(file).data('renaming')) {
return;
}
@@ -103,9 +103,9 @@ var FileActions = {
}
var html = '<a href="#" class="action" data-action="' + name + '">';
if (img) {
html += '<img class ="svg" src="' + img + '" /> ';
html += '<img class ="svg" src="' + img + '" />';
}
html += t('files', name) + '</a>';
html += '<span> ' + t('files', name) + '</span></a>';
var element = $(html);
element.data('action', name);
@@ -163,13 +163,18 @@ var FileActions = {
};
$(document).ready(function () {
var hasDownloadAction = false;
var downloadScope;
if ($('#allowZipDownload').val() == 1) {
var downloadScope = 'all';
downloadScope = 'all';
} else {
var downloadScope = 'file';
downloadScope = 'file';
}
if (typeof disableDownloadActions == 'undefined' || !disableDownloadActions) {
hasDownloadAction = FileActions.actions[downloadScope] && FileActions.actions[downloadScope].Download;
// do not override download action if it exists (might have been registered by an app already)
if ((typeof disableDownloadActions == 'undefined' || !disableDownloadActions) && !hasDownloadAction) {
FileActions.register(downloadScope, 'Download', OC.PERMISSION_READ, function () {
return OC.imagePath('core', 'actions/download');
}, function (filename) {

View File

@@ -6,6 +6,13 @@ var FileList={
$(this).attr('data-file',decodeURIComponent($(this).attr('data-file')));
});
},
/**
* Returns the tr element for a given file name
*/
findFileEl: function(fileName){
// use filterAttr to avoid escaping issues
return $('#fileList tr').filterAttr('data-file', fileName);
},
update:function(fileListHtml) {
var $fileList = $('#fileList');
$fileList.empty().html(fileListHtml);
@@ -20,6 +27,8 @@ var FileList={
Files.setupDragAndDrop();
}
FileList.updateFileSummary();
procesSelection();
$fileList.trigger(jQuery.Event("updated"));
},
createRow:function(type, name, iconurl, linktarget, size, lastModified, permissions) {
@@ -292,8 +301,12 @@ var FileList={
$('#filestable').toggleClass('hidden', show);
},
remove:function(name){
$('tr').filterAttr('data-file',name).find('td.filename').draggable('destroy');
$('tr').filterAttr('data-file',name).remove();
var fileEl = FileList.findFileEl(name);
if (fileEl.data('permissions') & OC.PERMISSION_DELETE) {
// file is only draggable when delete permissions are set
fileEl.find('td.filename').draggable('destroy');
}
fileEl.remove();
FileList.updateFileSummary();
if ( ! $('tr[data-file]').exists() ) {
$('#emptycontent').removeClass('hidden');
@@ -334,7 +347,7 @@ var FileList={
FileList.updateFileSummary();
},
loadingDone:function(name, id) {
var mime, tr = $('tr[data-file="'+name+'"]');
var mime, tr = FileList.findFileEl(name);
tr.data('loading', false);
mime = tr.data('mime');
tr.attr('data-mime', mime);
@@ -347,12 +360,12 @@ var FileList={
}, null, null, tr.attr('data-etag'));
tr.find('td.filename').draggable(dragOptions);
},
isLoading:function(name) {
return $('tr[data-file="'+name+'"]').data('loading');
isLoading:function(file) {
return FileList.findFileEl(file).data('loading');
},
rename:function(oldname) {
var tr, td, input, form;
tr = $('tr[data-file="'+oldname+'"]');
tr = FileList.findFileEl(oldname);
tr.data('renaming',true);
td = tr.children('td.filename');
input = $('<input type="text" class="filename"/>').val(oldname);
@@ -367,15 +380,12 @@ var FileList={
len = input.val().length;
}
input.selectRange(0, len);
var checkInput = function () {
var filename = input.val();
if (filename !== oldname) {
if (!Files.isFileNameValid(filename)) {
// Files.isFileNameValid(filename) throws an exception itself
} else if($('#dir').val() === '/' && filename === 'Shared') {
throw t('files','In the home folder \'Shared\' is a reserved filename');
} else if (FileList.inList(filename)) {
// Files.isFileNameValid(filename) throws an exception itself
Files.isFileNameValid(filename, FileList.getCurrentDirectory());
if (FileList.inList(filename)) {
throw t('files', '{new_name} already exists', {new_name: filename});
}
}
@@ -500,14 +510,16 @@ var FileList={
form.trigger('submit');
});
},
inList:function(filename) {
return $('#fileList tr[data-file="'+filename+'"]').length;
inList:function(file) {
return FileList.findFileEl(file).length;
},
replace:function(oldName, newName, isNewFile) {
// Finish any existing actions
$('tr[data-file="'+oldName+'"]').hide();
$('tr[data-file="'+newName+'"]').hide();
var tr = $('tr[data-file="'+oldName+'"]').clone();
var oldFileEl = FileList.findFileEl(oldName);
var newFileEl = FileList.findFileEl(newName);
oldFileEl.hide();
newFileEl.hide();
var tr = oldFileEl.clone();
tr.attr('data-replace', 'true');
tr.attr('data-file', newName);
var td = tr.children('td.filename');
@@ -559,7 +571,7 @@ var FileList={
files=[files];
}
for (var i=0; i<files.length; i++) {
var deleteAction = $('tr[data-file="'+files[i]+'"]').children("td.date").children(".action.delete");
var deleteAction = FileList.findFileEl(files[i]).children("td.date").children(".action.delete");
deleteAction.removeClass('delete-icon').addClass('progress-icon');
}
// Finish any existing actions
@@ -573,7 +585,7 @@ var FileList={
function(result) {
if (result.status === 'success') {
$.each(files,function(index,file) {
var files = $('tr[data-file="'+file+'"]');
var files = FileList.findFileEl(file);
files.remove();
files.find('input[type="checkbox"]').removeAttr('checked');
files.removeClass('selected');
@@ -595,7 +607,7 @@ var FileList={
OC.Notification.hide();
}, 10000);
$.each(files,function(index,file) {
var deleteAction = $('tr[data-file="' + file + '"] .action.delete');
var deleteAction = FileList.findFileEl(file).find('.action.delete');
deleteAction.removeClass('progress-icon').addClass('delete-icon');
});
}
@@ -737,7 +749,7 @@ var FileList={
},
scrollTo:function(file) {
//scroll to and highlight preselected file
var $scrolltorow = $('tr[data-file="'+file+'"]');
var $scrolltorow = FileList.findFileEl(file);
if ($scrolltorow.exists()) {
$scrolltorow.addClass('searchresult');
$(window).scrollTop($scrolltorow.position().top);
@@ -880,8 +892,8 @@ $(document).ready(function() {
data.context.find('td.filesize').text(humanFileSize(size));
} else {
// only append new file if dragged onto current dir's crumb (last)
if (data.context && data.context.hasClass('crumb') && !data.context.hasClass('last')) {
// only append new file if uploaded into the current folder
if (file.directory !== FileList.getCurrentDirectory()) {
return;
}
@@ -949,7 +961,7 @@ $(document).ready(function() {
$('#notification').on('click', '.undo', function() {
if (FileList.deleteFiles) {
$.each(FileList.deleteFiles,function(index,file) {
$('tr[data-file="'+file+'"]').show();
FileList.findFileEl(file).show();
});
FileList.deleteCanceled=true;
FileList.deleteFiles=null;
@@ -959,10 +971,10 @@ $(document).ready(function() {
FileList.deleteCanceled = false;
FileList.deleteFiles = [FileList.replaceOldName];
} else {
$('tr[data-file="'+FileList.replaceOldName+'"]').show();
FileList.findFileEl(FileList.replaceOldName).show();
}
$('tr[data-replace="true"').remove();
$('tr[data-file="'+FileList.replaceNewName+'"]').show();
FileList.findFileEl(FileList.replaceNewName).show();
FileList.replaceCanceled = true;
FileList.replaceOldName = null;
FileList.replaceNewName = null;
@@ -977,7 +989,8 @@ $(document).ready(function() {
});
});
$('#notification:first-child').on('click', '.suggest', function() {
$('tr[data-file="'+$('#notification > span').attr('data-oldName')+'"]').show();
var file = $('#notification > span').attr('data-oldName');
FileList.findFileEl(file).show();
OC.Notification.hide();
});
$('#notification:first-child').on('click', '.cancel', function() {

View File

@@ -67,10 +67,21 @@ Files={
return fileName;
},
isFileNameValid:function (name) {
if (name === '.') {
throw t('files', '\'.\' is an invalid file name.');
} else if (name.length === 0) {
/**
* Checks whether the given file name is valid.
* @param name file name to check
* @return true if the file name is valid.
* Throws a string exception with an error message if
* the file name is not valid
*/
isFileNameValid: function (name, root) {
var trimmedName = name.trim();
if (trimmedName === '.'
|| trimmedName === '..'
|| (root === '/' && trimmedName.toLowerCase() === 'shared'))
{
throw t('files', '"{name}" is an invalid file name.', {name: name});
} else if (trimmedName.length === 0) {
throw t('files', 'File name cannot be empty.');
}
@@ -282,7 +293,7 @@ $(document).ready(function() {
procesSelection();
} else {
var filename=$(this).parent().parent().attr('data-file');
var tr=$('tr[data-file="'+filename+'"]');
var tr = FileList.findFileEl(filename);
var renaming=tr.data('renaming');
if (!renaming && !FileList.isLoading(filename)) {
FileActions.currentFile = $(this).parent();
@@ -350,7 +361,12 @@ $(document).ready(function() {
// use special download URL if provided, e.g. for public shared files
var downloadURL = document.getElementById("downloadURL");
if ( downloadURL ) {
window.location = downloadURL.value+"&download&files=" + encodeURIComponent(fileslist);
// downloading all in root of public share ? (replacement for old "Download" button)
if ($('#isPublic').val() && dir === '/' && $('#select_all').is(':checked')) {
window.location = downloadURL.value;
} else {
window.location = downloadURL.value+"&download&files=" + encodeURIComponent(fileslist);
}
} else {
window.location = OC.filePath('files', 'ajax', 'download.php') + '?'+ $.param({ dir: dir, files: fileslist });
}
@@ -541,10 +557,12 @@ var folderDropOptions={
if (result) {
if (result.status === 'success') {
//recalculate folder size
var oldSize = $('#fileList tr[data-file="'+target+'"]').data('size');
var newSize = oldSize + $('#fileList tr[data-file="'+file+'"]').data('size');
$('#fileList tr[data-file="'+target+'"]').data('size', newSize);
$('#fileList tr[data-file="'+target+'"]').find('td.filesize').text(humanFileSize(newSize));
var oldFile = FileList.findFileEl(target);
var newFile = FileList.findFileEl(file);
var oldSize = oldFile.data('size');
var newSize = oldSize + newFile.data('size');
oldFile.data('size', newSize);
oldFile.find('td.filesize').text(humanFileSize(newSize));
FileList.remove(file);
procesSelection();
@@ -610,11 +628,12 @@ function procesSelection() {
return el.type==='dir';
});
if (selectedFiles.length === 0 && selectedFolders.length === 0) {
$('#headerName>span.name').text(t('files','Name'));
$('#headerName span.name').text(t('files','Name'));
$('#headerSize').text(t('files','Size'));
$('#modified').text(t('files','Modified'));
$('table').removeClass('multiselect');
$('.selectedActions').hide();
$('#select_all').removeAttr('checked');
}
else {
$('.selectedActions').show();
@@ -717,7 +736,7 @@ Files.lazyLoadPreview = function(path, mime, ready, width, height, etag) {
console.warn('Files.lazyLoadPreview(): missing etag argument');
}
if ( $('#publicUploadButtonMock').length ) {
if ( $('#isPublic').length ) {
urlSpec.t = $('#dirToken').val();
previewURL = OC.Router.generate('core_ajax_public_preview', urlSpec);
} else {
@@ -738,7 +757,7 @@ Files.lazyLoadPreview = function(path, mime, ready, width, height, etag) {
}
function getUniqueName(name) {
if ($('tr[data-file="'+name+'"]').exists()) {
if (FileList.findFileEl(name).exists()) {
var parts=name.split('.');
var extension = "";
if (parts.length > 1) {

View File

@@ -1,7 +0,0 @@
<?php
$TRANSLATIONS = array(
"_%n folder_::_%n folders_" => array("",""),
"_%n file_::_%n files_" => array("",""),
"_Uploading %n file_::_Uploading %n files_" => array("","")
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";

View File

@@ -1,5 +0,0 @@
<?php
$TRANSLATIONS = array(
"Save" => "Zapisz"
);
$PLURAL_FORMS = "nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);";

View File

@@ -1,17 +0,0 @@
<?php
$TRANSLATIONS = array(
"Files" => "Файлы",
"Share" => "Сделать общим",
"Rename" => "Переименовать",
"_%n folder_::_%n folders_" => array("","",""),
"_%n file_::_%n files_" => array("","",""),
"_Uploading %n file_::_Uploading %n files_" => array("","",""),
"Error" => "Ошибка",
"Size" => "Размер",
"Upload" => "Загрузка",
"Save" => "Сохранить",
"Cancel upload" => "Отмена загрузки",
"Download" => "Загрузка",
"Delete" => "Удалить"
);
$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);";

View File

@@ -15,7 +15,8 @@ class Helper
return array('uploadMaxFilesize' => $maxUploadFilesize,
'maxHumanFilesize' => $maxHumanFilesize,
'usedSpacePercent' => (int)$storageInfo['relative']);
'usedSpacePercent' => (int)$storageInfo['relative'],
'freeSpace' => (int)$storageInfo['free']);
}
public static function determineIcon($file) {

View File

@@ -3,8 +3,8 @@
<span class="what">{what}<!-- If you select both versions, the copied file will have a number added to its name. --></span><br/>
<br/>
<table>
<th><label><input class="allnewfiles" type="checkbox" />New Files<span class="count"></span></label></th>
<th><label><input class="allexistingfiles" type="checkbox" />Already existing files<span class="count"></span></label></th>
<th><label><input class="allnewfiles" type="checkbox" />{allnewfiles}<span class="count"></span></label></th>
<th><label><input class="allexistingfiles" type="checkbox" />{allexistingfiles}<span class="count"></span></label></th>
</table>
<div class="conflicts">
<div class="template">

View File

@@ -1,6 +1,7 @@
<div id="controls">
<?php print_unescaped($_['breadcrumb']); ?>
<div class="actions creatable <?php if (!$_['isCreatable']):?>hidden<?php endif; ?>">
<?php if(!isset($_['dirToken'])):?>
<div id="new" class="button">
<a><?php p($l->t('New'));?></a>
<ul>
@@ -12,21 +13,26 @@
data-type='web'><p><?php p($l->t('From link'));?></p></li>
</ul>
</div>
<?php endif;?>
<div id="upload" class="button"
title="<?php p($l->t('Upload') . ' max. '.$_['uploadMaxHumanFilesize']) ?>">
<?php if($_['uploadMaxFilesize'] >= 0):?>
<input type="hidden" name="MAX_FILE_SIZE" id="max_upload"
value="<?php p($_['uploadMaxFilesize']) ?>">
<?php endif;?>
<?php if(isset($_['dirToken'])):?>
<input type="hidden" id="publicUploadRequestToken" name="requesttoken" value="<?php p($_['requesttoken']) ?>" />
<input type="hidden" id="dirToken" name="dirToken" value="<?php p($_['dirToken']) ?>" />
<?php endif;?>
<input type="hidden" class="max_human_file_size"
value="(max <?php p($_['uploadMaxHumanFilesize']); ?>)">
<input type="hidden" name="dir" value="<?php p($_['dir']) ?>" id="dir">
<input type="file" id="file_upload_start" name='files[]'
data-url="<?php print_unescaped(OCP\Util::linkTo('files', 'ajax/upload.php')); ?>" />
<a href="#" class="svg"></a>
<a href="#" class="svg icon icon-upload"></a>
</div>
<?php if ($_['trash']): ?>
<input id="trash" type="button" value="<?php p($l->t('Deleted files'));?>" class="button" <?php $_['trashEmpty'] ? p('disabled') : '' ?>></input>
<input id="trash" type="button" value="<?php p($l->t('Deleted files'));?>" class="button" <?php $_['trashEmpty'] ? p('disabled') : '' ?> />
<?php endif; ?>
<div id="uploadprogresswrapper">
<div id="uploadprogressbar"></div>
@@ -44,7 +50,7 @@
<div id="emptycontent" <?php if (!$_['emptyContent']):?>class="hidden"<?php endif; ?>><?php p($l->t('Nothing in here. Upload something!'))?></div>
<input type="hidden" id="disableSharing" data-status="<?php p($_['disableSharing']); ?>"></input>
<input type="hidden" id="disableSharing" data-status="<?php p($_['disableSharing']); ?>" />
<table id="filestable" data-allow-public-upload="<?php p($_['publicUploadEnabled'])?>" data-preview-x="36" data-preview-y="36">
<thead>
@@ -69,20 +75,11 @@
<th <?php if (!$_['fileHeader']):?>class="hidden"<?php endif; ?> id="headerDate">
<span id="modified"><?php p($l->t( 'Modified' )); ?></span>
<?php if ($_['permissions'] & OCP\PERMISSION_DELETE): ?>
<!-- NOTE: Temporary fix to allow unsharing of files in root of Shared folder -->
<?php if ($_['dir'] == '/Shared'): ?>
<span class="selectedActions"><a href="" class="delete-selected">
<?php p($l->t('Unshare'))?>
<img class="svg" alt="<?php p($l->t('Unshare'))?>"
src="<?php print_unescaped(OCP\image_path("core", "actions/delete.svg")); ?>" />
</a></span>
<?php else: ?>
<span class="selectedActions"><a href="" class="delete-selected">
<?php p($l->t('Delete'))?>
<img class="svg" alt="<?php p($l->t('Delete'))?>"
src="<?php print_unescaped(OCP\image_path("core", "actions/delete.svg")); ?>" />
</a></span>
<?php endif; ?>
<span class="selectedActions"><a href="" class="delete-selected">
<?php p($l->t('Delete'))?>
<img class="svg" alt="<?php p($l->t('Delete'))?>"
src="<?php print_unescaped(OCP\image_path("core", "actions/delete.svg")); ?>" />
</a></span>
<?php endif; ?>
</th>
</tr>

View File

@@ -1,10 +1,8 @@
<?php if(count($_["breadcrumb"])):?>
<div class="crumb" data-dir=''>
<a href="<?php print_unescaped($_['baseURL']); ?>">
<img src="<?php print_unescaped(OCP\image_path('core', 'places/home.svg'));?>" class="svg" />
</a>
</div>
<?php endif;?>
<div class="crumb <?php if(!count($_["breadcrumb"])) p('last');?>" data-dir=''>
<a href="<?php print_unescaped($_['baseURL']); ?>">
<img src="<?php print_unescaped(OCP\image_path('core', 'places/home.svg'));?>" class="svg" />
</a>
</div>
<?php for($i=0; $i<count($_["breadcrumb"]); $i++):
$crumb = $_["breadcrumb"][$i];
$dir = \OCP\Util::encodePath($crumb["dir"]); ?>

View File

@@ -18,7 +18,7 @@ $totalsize = 0; ?>
data-size="<?php p($file['size']);?>"
data-etag="<?php p($file['etag']);?>"
data-permissions="<?php p($file['permissions']); ?>">
<?php if($file['isPreviewAvailable']): ?>
<?php if(isset($file['isPreviewAvailable']) and $file['isPreviewAvailable']): ?>
<td class="filename svg preview-icon"
<?php else: ?>
<td class="filename svg"
@@ -34,17 +34,15 @@ $totalsize = 0; ?>
<span class="nametext">
<?php print_unescaped(htmlspecialchars($file['name']));?>
</span>
<span class="uploadtext" currentUploads="0">
</span>
</a>
<?php else: ?>
<a class="name" href="<?php p(rtrim($_['downloadURL'],'/').'/'.trim($directory,'/').'/'.$name); ?>">
<label class="filetext" title="" for="select-<?php p($file['fileid']); ?>"></label>
<span class="nametext"><?php print_unescaped(htmlspecialchars($file['basename']));?><span class='extension'><?php p($file['extension']);?></span></span>
</a>
<?php endif; ?>
<?php if($file['type'] == 'dir'):?>
<span class="uploadtext" currentUploads="0">
</span>
<?php endif;?>
</a>
</td>
<td class="filesize"
style="color:rgb(<?php p($simple_size_color.','.$simple_size_color.','.$simple_size_color) ?>)">

View File

@@ -6,6 +6,7 @@ if (OC::$CLI) {
if (count($argv) === 2) {
$file = $argv[1];
list(, $user) = explode('/', $file);
OCP\JSON::checkUserExists($owner);
OC_Util::setupFS($user);
$view = new \OC\Files\View('');
/**

View File

@@ -13,16 +13,14 @@ use OCA\Encryption\Util;
$loginname = isset($_POST['user']) ? $_POST['user'] : '';
$password = isset($_POST['password']) ? $_POST['password'] : '';
$migrationCompleted = true;
$migrationStatus = Util::MIGRATION_COMPLETED;
if ($loginname !== '' && $password !== '') {
$username = \OCP\User::checkPassword($loginname, $password);
if ($username) {
$util = new Util(new \OC_FilesystemView('/'), $username);
if ($util->getMigrationStatus() !== Util::MIGRATION_COMPLETED) {
$migrationCompleted = false;
}
$migrationStatus = $util->getMigrationStatus();
}
}
\OCP\JSON::success(array('data' => array('migrationCompleted' => $migrationCompleted)));
\OCP\JSON::success(array('data' => array('migrationStatus' => $migrationStatus)));

View File

@@ -10,6 +10,7 @@ OC::$CLASSPATH['OCA\Encryption\Session'] = 'files_encryption/lib/session.php';
OC::$CLASSPATH['OCA\Encryption\Capabilities'] = 'files_encryption/lib/capabilities.php';
OC::$CLASSPATH['OCA\Encryption\Helper'] = 'files_encryption/lib/helper.php';
\OCP\Util::addscript('files_encryption', 'encryption');
\OCP\Util::addscript('files_encryption', 'detect-migration');
if (!OC_Config::getValue('maintenance', false)) {

View File

@@ -18,22 +18,19 @@
<type>text</type>
<notnull>true</notnull>
<length>64</length>
<comments>What client-side / server-side configuration is used</comments>
</field>
<field>
<name>recovery_enabled</name>
<type>integer</type>
<notnull>true</notnull>
<default>0</default>
<comments>Whether encryption key recovery is enabled</comments>
</field>
<field>
<name>migration_status</name>
<type>integer</type>
<notnull>true</notnull>
<default>0</default>
<comments>Whether encryption migration has been performed</comments>
</field>
</declaration>
</table>
</database>
</database>

View File

@@ -2,11 +2,15 @@
<info>
<id>files_encryption</id>
<name>Encryption</name>
<description>The new ownCloud 5 files encryption system. After the app was enabled you need to re-login to initialize your encryption keys.</description>
<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>
<licence>AGPL</licence>
<author>Sam Tuke, Bjoern Schiessle, Florin Peter</author>
<require>4</require>
<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>
</documentation>
<rememberlogin>false</rememberlogin>
<types>
<filesystem/>

View File

@@ -5,6 +5,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) {

View File

@@ -30,6 +30,11 @@ use OC\Files\Filesystem;
*/
class Hooks {
// file for which we want to rename the keys after the rename operation was successful
private static $renamedFiles = array();
// file for which we want to delete the keys after the delete operation was successful
private static $deleteFiles = array();
/**
* @brief Startup encryption backend upon user login
* @note This method should never be called for users using client side encryption
@@ -75,8 +80,14 @@ class Hooks {
// Check if first-run file migration has already been performed
$ready = false;
if ($util->getMigrationStatus() === Util::MIGRATION_OPEN) {
$migrationStatus = $util->getMigrationStatus();
if ($migrationStatus === Util::MIGRATION_OPEN && $session !== false) {
$ready = $util->beginMigration();
} elseif ($migrationStatus === Util::MIGRATION_IN_PROGRESS) {
// refuse login as long as the initial encryption is running
sleep(5);
\OCP\User::logout();
return false;
}
// If migration not yet done
@@ -90,28 +101,32 @@ class Hooks {
$userView->file_exists('encryption.key')
&& $encLegacyKey = $userView->file_get_contents('encryption.key')
) {
$plainLegacyKey = Crypt::legacyDecrypt($encLegacyKey, $params['password']);
$plainLegacyKey = Crypt::legacyDecrypt($encLegacyKey, $params['password']);
$session->setLegacyKey($plainLegacyKey);
$session->setLegacyKey($plainLegacyKey);
}
// Encrypt existing user files:
if (
$util->encryptAll('/' . $params['uid'] . '/' . 'files', $session->getLegacyKey(), $params['password'])
) {
// Encrypt existing user files
try {
$result = $util->encryptAll('/' . $params['uid'] . '/' . 'files', $session->getLegacyKey(), $params['password']);
} catch (\Exception $ex) {
\OCP\Util::writeLog('Encryption library', 'Initial encryption failed! Error: ' . $ex->getMessage(), \OCP\Util::FATAL);
$util->resetMigrationStatus();
\OCP\User::logout();
$result = false;
}
if ($result) {
\OC_Log::write(
'Encryption library', 'Encryption of existing files belonging to "' . $params['uid'] . '" completed'
, \OC_Log::INFO
);
// Register successful migration in DB
$util->finishMigration();
}
// Register successful migration in DB
$util->finishMigration();
}
return true;
@@ -179,20 +194,23 @@ class Hooks {
// the necessary keys)
if (Crypt::mode() === 'server') {
if ($params['uid'] === \OCP\User::getUser()) {
$view = new \OC_FilesystemView('/');
$session = new \OCA\Encryption\Session($view);
$view = new \OC_FilesystemView('/');
// 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']);
// Save private key
Keymanager::setPrivateKey($encryptedPrivateKey);
if ($encryptedPrivateKey) {
Keymanager::setPrivateKey($encryptedPrivateKey);
} else {
\OCP\Util::writeLog('files_encryption', 'Could not update users encryption password', \OCP\Util::ERROR);
}
// NOTE: Session does not need to be updated as the
// private key has not changed, only the passphrase
@@ -202,36 +220,48 @@ class Hooks {
} else { // admin changed the password for a different user, create new keys and reencrypt file keys
$user = $params['uid'];
$recoveryPassword = $params['recoveryPassword'];
$newUserPassword = $params['password'];
$util = new Util($view, $user);
$recoveryPassword = isset($params['recoveryPassword']) ? $params['recoveryPassword'] : null;
$view = new \OC_FilesystemView('/');
// we generate new keys if...
// ...we have a recovery password and the user enabled the recovery key
// ...encryption was activated for the first time (no keys exists)
// ...the user doesn't have any files
if (($util->recoveryEnabledForUser() && $recoveryPassword)
|| !$util->userKeysExists()
|| !$view->file_exists($user . '/files')) {
// make sure that the users home is mounted
\OC\Files\Filesystem::initMountPoints($user);
// backup old keys
$util->backupAllKeys('recovery');
$keypair = Crypt::createKeypair();
$newUserPassword = $params['password'];
// Disable encryption proxy to prevent recursive calls
$proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false;
// make sure that the users home is mounted
\OC\Files\Filesystem::initMountPoints($user);
// Save public key
$view->file_put_contents('/public-keys/' . $user . '.public.key', $keypair['publicKey']);
$keypair = Crypt::createKeypair();
// Encrypt private key empty passphrase
$encryptedPrivateKey = Crypt::symmetricEncryptFileContent($keypair['privateKey'], $newUserPassword);
// Disable encryption proxy to prevent recursive calls
$proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false;
// Save private key
$view->file_put_contents(
'/' . $user . '/files_encryption/' . $user . '.private.key', $encryptedPrivateKey);
// Save public key
$view->file_put_contents('/public-keys/' . $user . '.public.key', $keypair['publicKey']);
if ($recoveryPassword) { // if recovery key is set we can re-encrypt the key files
$util = new Util($view, $user);
$util->recoverUsersFiles($recoveryPassword);
// Encrypt private key empty passphrase
$encryptedPrivateKey = Crypt::symmetricEncryptFileContent($keypair['privateKey'], $newUserPassword);
// Save private key
$view->file_put_contents(
'/' . $user . '/files_encryption/' . $user . '.private.key', $encryptedPrivateKey);
if ($recoveryPassword) { // if recovery key is set we can re-encrypt the key files
$util = new Util($view, $user);
$util->recoverUsersFiles($recoveryPassword);
}
\OC_FileProxy::$enabled = $proxyStatus;
}
\OC_FileProxy::$enabled = $proxyStatus;
}
}
}
@@ -306,7 +336,6 @@ class Hooks {
if ($params['itemType'] === 'file' || $params['itemType'] === 'folder') {
$view = new \OC_FilesystemView('/');
$session = new \OCA\Encryption\Session($view);
$userId = \OCP\User::getUser();
$util = new Util($view, $userId);
$path = $util->fileIdToPath($params['itemSource']);
@@ -363,25 +392,41 @@ class Hooks {
}
}
$sharingEnabled = \OCP\Share::isEnabled();
// get the path including mount point only if not a shared folder
if (strncmp($path, '/Shared', strlen('/Shared') !== 0)) {
// get path including the the storage mount point
$path = $util->getPathWithMountPoint($params['itemSource']);
}
// if a folder was shared, get a list of all (sub-)folders
if ($params['itemType'] === 'folder') {
$allFiles = $util->getAllFiles($path);
} else {
$allFiles = array($path);
}
self::updateKeyfiles($path, $params['itemType']);
}
}
foreach ($allFiles as $path) {
$usersSharing = $util->getSharingUsersArray($sharingEnabled, $path);
$util->setSharedFileKeyfiles($session, $usersSharing, $path);
}
/**
* update keyfiles and share keys recursively
*
* @param string $path to the file/folder
* @param string $type 'file' or 'folder'
*/
private static function updateKeyfiles($path, $type) {
$view = new \OC_FilesystemView('/');
$session = new \OCA\Encryption\Session($view);
$userId = \OCP\User::getUser();
$util = new Util($view, $userId);
$sharingEnabled = \OCP\Share::isEnabled();
// if a folder was shared, get a list of all (sub-)folders
if ($type === 'folder') {
$allFiles = $util->getAllFiles($path);
} else {
$allFiles = array($path);
}
foreach ($allFiles as $path) {
$usersSharing = $util->getSharingUsersArray($sharingEnabled, $path);
$util->setSharedFileKeyfiles($session, $usersSharing, $path);
}
}
@@ -475,13 +520,63 @@ class Hooks {
}
/**
* @brief after a file is renamed, rename its keyfile and share-keys also fix the file size and fix also the sharing
* @param array with oldpath and newpath
*
* This function is connected to the rename signal of OC_Filesystem and adjust the name and location
* of the stored versions along the actual file
* @brief mark file as renamed so that we know the original source after the file was renamed
* @param array $params with the old path and the new path
*/
public static function postRename($params) {
public static function preRename($params) {
$user = \OCP\User::getUser();
$view = new \OC_FilesystemView('/');
$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',
);
}
}
/**
* mark file as renamed so that we know the original source after the file was renamed
* @param array $params with the old path and the new path
*/
public static function preCopy($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' => 'copy');
}
}
/**
* after a file is renamed/copied, rename/copy its keyfile and share-keys also fix the file size and fix also the sharing
*
* @param array $params array with oldpath and newpath
*/
public static function postRenameOrCopy($params) {
if (\OCP\App::isEnabled('files_encryption') === false) {
return true;
@@ -492,56 +587,75 @@ class Hooks {
\OC_FileProxy::$enabled = false;
$view = new \OC_FilesystemView('/');
$session = new \OCA\Encryption\Session($view);
$userId = \OCP\User::getUser();
$util = new Util($view, $userId);
// Format paths to be relative to user files dir
if ($util->isSystemWideMountPoint($params['oldpath'])) {
$baseDir = 'files_encryption/';
$oldKeyfilePath = $baseDir . 'keyfiles/' . $params['oldpath'];
if (isset(self::$renamedFiles[$params['oldpath']]['uid']) &&
isset(self::$renamedFiles[$params['oldpath']]['path'])) {
$ownerOld = self::$renamedFiles[$params['oldpath']]['uid'];
$pathOld = self::$renamedFiles[$params['oldpath']]['path'];
$type = self::$renamedFiles[$params['oldpath']]['type'];
$operation = self::$renamedFiles[$params['oldpath']]['operation'];
unset(self::$renamedFiles[$params['oldpath']]);
} else {
$baseDir = $userId . '/' . 'files_encryption/';
$oldKeyfilePath = $baseDir . 'keyfiles/' . $params['oldpath'];
\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;
}
if ($util->isSystemWideMountPoint($params['newpath'])) {
$newKeyfilePath = $baseDir . 'keyfiles/' . $params['newpath'];
list($ownerNew, $pathNew) = $util->getUidAndFilename($params['newpath']);
// Format paths to be relative to user files dir
if ($util->isSystemWideMountPoint($pathOld)) {
$oldKeyfilePath = 'files_encryption/keyfiles/' . $pathOld;
$oldShareKeyPath = 'files_encryption/share-keys/' . $pathOld;
} else {
$newKeyfilePath = $baseDir . 'keyfiles/' . $params['newpath'];
$oldKeyfilePath = $ownerOld . '/' . 'files_encryption/keyfiles/' . $pathOld;
$oldShareKeyPath = $ownerOld . '/' . 'files_encryption/share-keys/' . $pathOld;
}
if ($util->isSystemWideMountPoint($pathNew)) {
$newKeyfilePath = 'files_encryption/keyfiles/' . $pathNew;
$newShareKeyPath = 'files_encryption/share-keys/' . $pathNew;
} else {
$newKeyfilePath = $ownerNew . '/files_encryption/keyfiles/' . $pathNew;
$newShareKeyPath = $ownerNew . '/files_encryption/share-keys/' . $pathNew;
}
// add key ext if this is not an folder
if (!$view->is_dir($oldKeyfilePath)) {
if ($type === 'file') {
$oldKeyfilePath .= '.key';
$newKeyfilePath .= '.key';
// create destination folder if not exists
$localKeyPath = $view->getLocalFile($oldShareKeyPath);
$newLocalKeyPath = \OC\Files\Filesystem::normalizePath(str_replace($pathOld, $pathNew, $localKeyPath));
if (!file_exists(dirname($newLocalKeyPath))) {
mkdir(dirname($newLocalKeyPath), 0750, true);
}
// handle share-keys
$localKeyPath = $view->getLocalFile($baseDir . 'share-keys/' . $params['oldpath']);
$escapedPath = Helper::escapeGlobPattern($localKeyPath);
$matches = glob($escapedPath . '*.shareKey');
$matches = Helper::findShareKeys($pathOld, $oldShareKeyPath, $view);
if (count($matches) === 0) {
\OC_Log::write(
'Encryption library', 'No share keys found for "' . $pathOld . '"',
\OC_Log::WARN
);
}
foreach ($matches as $src) {
$dst = \OC\Files\Filesystem::normalizePath(str_replace($params['oldpath'], $params['newpath'], $src));
// create destination folder if not exists
if (!file_exists(dirname($dst))) {
mkdir(dirname($dst), 0750, true);
}
rename($src, $dst);
$dst = \OC\Files\Filesystem::normalizePath(str_replace($pathOld, $pathNew, $src));
$view->$operation($src, $dst);
}
} else {
// handle share-keys folders
$oldShareKeyfilePath = $baseDir . 'share-keys/' . $params['oldpath'];
$newShareKeyfilePath = $baseDir . 'share-keys/' . $params['newpath'];
// create destination folder if not exists
if (!$view->file_exists(dirname($newShareKeyfilePath))) {
$view->mkdir(dirname($newShareKeyfilePath), 0750, true);
if (!$view->file_exists(dirname($newShareKeyPath))) {
mkdir($view->getLocalFile($newShareKeyPath), 0750, true);
}
$view->rename($oldShareKeyfilePath, $newShareKeyfilePath);
$view->$operation($oldShareKeyPath, $newShareKeyPath);
}
// Rename keyfile so it isn't orphaned
@@ -549,26 +663,17 @@ class Hooks {
// create destination folder if not exists
if (!$view->file_exists(dirname($newKeyfilePath))) {
$view->mkdir(dirname($newKeyfilePath), 0750, true);
mkdir(dirname($view->getLocalFile($newKeyfilePath)), 0750, true);
}
$view->rename($oldKeyfilePath, $newKeyfilePath);
$view->$operation($oldKeyfilePath, $newKeyfilePath);
}
// build the path to the file
$newPath = '/' . $userId . '/files' . $params['newpath'];
$newPathRelative = $params['newpath'];
$newPath = '/' . $ownerNew . '/files' . $pathNew;
if ($util->fixFileSize($newPath)) {
// get sharing app state
$sharingEnabled = \OCP\Share::isEnabled();
// get users
$usersSharing = $util->getSharingUsersArray($sharingEnabled, $newPathRelative);
// update sharing-keys
$util->setSharedFileKeyfiles($session, $usersSharing, $newPathRelative);
}
// update sharing-keys
self::updateKeyfiles($params['newpath'], $type);
\OC_FileProxy::$enabled = $proxyStatus;
}
@@ -600,4 +705,66 @@ class Hooks {
}
}
/**
* @brief if the file was really deleted we remove the encryption keys
* @param array $params
* @return boolean
*/
public static function postDelete($params) {
if (!isset(self::$deleteFiles[$params[\OC\Files\Filesystem::signal_param_path]])) {
return true;
}
$deletedFile = self::$deleteFiles[$params[\OC\Files\Filesystem::signal_param_path]];
$path = $deletedFile['path'];
$user = $deletedFile['uid'];
// we don't need to remember the file any longer
unset(self::$deleteFiles[$params[\OC\Files\Filesystem::signal_param_path]]);
$view = new \OC\Files\View('/');
// return if the file still exists and wasn't deleted correctly
if ($view->file_exists('/' . $user . '/files/' . $path)) {
return true;
}
// Disable encryption proxy to prevent recursive calls
$proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false;
// Delete keyfile & shareKey so it isn't orphaned
if (!Keymanager::deleteFileKey($view, $path, $user)) {
\OCP\Util::writeLog('Encryption library',
'Keyfile or shareKey could not be deleted for file "' . $user.'/files/'.$path . '"', \OCP\Util::ERROR);
}
Keymanager::delAllShareKeys($view, $user, $path);
\OC_FileProxy::$enabled = $proxyStatus;
}
/**
* @brief remember the file which should be deleted and it's owner
* @param array $params
* @return boolean
*/
public static function preDelete($params) {
$path = $params[\OC\Files\Filesystem::signal_param_path];
// skip this method if the trash bin is enabled or if we delete a file
// outside of /data/user/files
if (\OCP\App::isEnabled('files_trashbin')) {
return true;
}
$util = new Util(new \OC_FilesystemView('/'), \OCP\USER::getUser());
list($owner, $ownerPath) = $util->getUidAndFilename($path);
self::$deleteFiles[$params[\OC\Files\Filesystem::signal_param_path]] = array(
'uid' => $owner,
'path' => $ownerPath);
}
}

View File

@@ -17,10 +17,14 @@ $(document).ready(function(){
data: {user: user, password: password},
async: false,
success: function(response) {
if (response.data.migrationCompleted === false) {
if (response.data.migrationStatus === OC.Encryption.MIGRATION_OPEN) {
var message = t('files_encryption', 'Initial encryption started... This can take some time. Please wait.');
$('#messageText').text(message);
$('#message').removeClass('hidden').addClass('update');
} else if (response.data.migrationStatus === OC.Encryption.MIGRATION_IN_PROGRESS) {
var message = t('files_encryption', 'Initial encryption running... Please try again later.');
$('#messageText').text(message);
$('#message').removeClass('hidden').addClass('update');
}
}
});

View File

@@ -0,0 +1,12 @@
/**
* Copyright (c) 2014
* Bjoern Schiessle <schiessle@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or later.
* See the COPYING-README file.
*/
OC.Encryption={
MIGRATION_OPEN:0,
MIGRATION_COMPLETED:1,
MIGRATION_IN_PROGRESS:-1,
};

View File

@@ -29,6 +29,8 @@ namespace OCA\Encryption;
*/
class Helper {
private static $tmpFileMapping; // Map tmp files to files in data/user/files
/**
* @brief register share related hooks
*
@@ -59,7 +61,12 @@ class Helper {
*/
public static function registerFilesystemHooks() {
\OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OCA\Encryption\Hooks', 'postRename');
\OCP\Util::connectHook('OC_Filesystem', 'rename', 'OCA\Encryption\Hooks', 'preRename');
\OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OCA\Encryption\Hooks', 'postRenameOrCopy');
\OCP\Util::connectHook('OC_Filesystem', 'copy', 'OCA\Encryption\Hooks', 'preCopy');
\OCP\Util::connectHook('OC_Filesystem', 'post_copy', 'OCA\Encryption\Hooks', 'postRenameOrCopy');
\OCP\Util::connectHook('OC_Filesystem', 'post_delete', 'OCA\Encryption\Hooks', 'postDelete');
\OCP\Util::connectHook('OC_Filesystem', 'delete', 'OCA\Encryption\Hooks', 'preDelete');
}
/**
@@ -274,7 +281,7 @@ class Helper {
$split = explode('/', $trimmed);
// it is not a file relative to data/user/files
if (count($split) < 2 || $split[1] !== 'files') {
if (count($split) < 2 || ($split[1] !== 'files' && $split[1] !== 'cache')) {
return false;
}
@@ -360,9 +367,14 @@ class Helper {
$post = 0;
if(count($_POST) > 0) {
$post = 1;
}
header('Location: ' . $location . '?p=' . $post . '&errorCode=' . $errorCode);
exit();
}
if(defined('PHPUNIT_RUN') and PHPUNIT_RUN) {
throw new \Exception("Encryption error: $errorCode");
}
header('Location: ' . $location . '?p=' . $post . '&errorCode=' . $errorCode);
exit();
}
/**
@@ -370,7 +382,14 @@ class Helper {
* @return bool true if requirements are met
*/
public static function checkRequirements() {
return extension_loaded('openssl');
$result = true;
//openssl extension needs to be loaded
$result &= extension_loaded("openssl");
// we need php >= 5.3.3
$result &= version_compare(phpversion(), '5.3.3', '>=');
return (bool) $result;
}
/**
@@ -409,12 +428,66 @@ class Helper {
}
/**
* @brief glob uses different pattern than regular expressions, escape glob pattern only
* @param unescaped path
* @return escaped path
* find all share keys for a given file
*
* @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 escapeGlobPattern($path) {
return preg_replace('/(\*|\?|\[)/', '[$1]', $path);
public static function findShareKeys($filePath, $shareKeyPath, $rootView) {
$result = array();
$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 "' . $pathOld . '"',
\OC_Log::WARN
);
}
}
return $result;
}
/**
* @brief remember from which file the tmp file (getLocalFile() call) was created
* @param string $tmpFile path of tmp file
* @param string $originalFile path of the original file relative to data/
*/
public static function addTmpFileToMapper($tmpFile, $originalFile) {
self::$tmpFileMapping[$tmpFile] = $originalFile;
}
/**
* @brief get the path of the original file
* @param string $tmpFile path of the tmp file
* @return mixed path of the original file or false
*/
public static function getPathFromTmpFile($tmpFile) {
if (isset(self::$tmpFileMapping[$tmpFile])) {
return self::$tmpFileMapping[$tmpFile];
}
return false;
}
}

View File

@@ -32,12 +32,12 @@ class Keymanager {
/**
* @brief retrieve the ENCRYPTED private key from a user
*
* @param \OC_FilesystemView $view
* @param \OC\Files\View $view
* @param string $user
* @return string private key or false (hopefully)
* @note the key returned by this method must be decrypted before use
*/
public static function getPrivateKey(\OC_FilesystemView $view, $user) {
public static function getPrivateKey($view, $user) {
$path = '/' . $user . '/' . 'files_encryption' . '/' . $user . '.private.key';
$key = false;
@@ -133,7 +133,7 @@ class Keymanager {
$basePath = '/' . $owner . '/files_encryption/keyfiles';
}
$targetPath = self::keySetPreparation($view, $filename, $basePath, $owner);
$targetPath = self::keySetPreparation($view, $filename, $basePath);
if (!$view->is_dir($basePath . '/' . $targetPath)) {
@@ -214,15 +214,24 @@ class Keymanager {
*
* @param \OC_FilesystemView $view
* @param string $path path of the file the key belongs to
* @param string $userId the user to whom the file belongs
* @return bool Outcome of unlink operation
* @note $path must be relative to data/user/files. e.g. mydoc.txt NOT
* /data/admin/files/mydoc.txt
*/
public static function deleteFileKey(\OC_FilesystemView $view, $path) {
public static function deleteFileKey($view, $path, $userId=null) {
$trimmed = ltrim($path, '/');
$userId = Helper::getUser($path);
if ($trimmed === '') {
\OCP\Util::writeLog('Encryption library',
'Can\'t delete file-key empty path given!', \OCP\Util::ERROR);
return false;
}
if ($userId === null) {
$userId = Helper::getUser($path);
}
$util = new Util($view, $userId);
if($util->isSystemWideMountPoint($path)) {
@@ -232,24 +241,23 @@ class Keymanager {
}
$result = false;
$fileExists = $view->file_exists('/' . $userId . '/files/' . $trimmed);
if ($view->is_dir($keyPath)) {
if ($view->is_dir($keyPath) && !$fileExists) {
\OCP\Util::writeLog('files_encryption', 'deleteFileKey: delete file key: ' . $keyPath, \OCP\Util::DEBUG);
$result = $view->unlink($keyPath);
} elseif ($view->file_exists($keyPath . '.key') && !$fileExists) {
\OCP\Util::writeLog('files_encryption', 'deleteFileKey: delete file key: ' . $keyPath, \OCP\Util::DEBUG);
$result = $view->unlink($keyPath . '.key');
} else {
if ($view->file_exists($keyPath . '.key')) {
$result = $view->unlink($keyPath . '.key');
}
}
if (!$result) {
if ($fileExists) {
\OCP\Util::writeLog('Encryption library',
'Could not delete keyfile; does not exist: "' . $keyPath, \OCP\Util::ERROR);
'Did not delete the file key, file still exists: ' . '/' . $userId . '/files/' . $trimmed, \OCP\Util::ERROR);
} elseif (!$result) {
\OCP\Util::writeLog('Encryption library',
'Could not delete keyfile; does not exist: "' . $keyPath, \OCP\Util::ERROR);
}
return $result;
@@ -272,8 +280,9 @@ class Keymanager {
$proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false;
if (!$view->file_exists(''))
if (!$view->file_exists('')) {
$view->mkdir('');
}
$result = $view->file_put_contents($user . '.private.key', $key);
@@ -331,7 +340,7 @@ class Keymanager {
$basePath = '/' . $owner . '/files_encryption/share-keys';
}
$shareKeyPath = self::keySetPreparation($view, $filename, $basePath, $owner);
$shareKeyPath = self::keySetPreparation($view, $filename, $basePath);
$result = true;
@@ -402,7 +411,21 @@ class Keymanager {
* @param string $userId owner of the file
* @param string $filePath path to the file, relative to the owners file dir
*/
public static function delAllShareKeys(\OC_FilesystemView $view, $userId, $filePath) {
public static function delAllShareKeys($view, $userId, $filePath) {
$filePath = ltrim($filePath, '/');
if ($view->file_exists('/' . $userId . '/files/' . $filePath)) {
\OCP\Util::writeLog('Encryption library',
'File still exists, stop deleting share keys!', \OCP\Util::ERROR);
return false;
}
if ($filePath === '') {
\OCP\Util::writeLog('Encryption library',
'Can\'t delete share-keys empty path given!', \OCP\Util::ERROR);
return false;
}
$util = new util($view, $userId);
@@ -412,21 +435,28 @@ class Keymanager {
$baseDir = $userId . '/files_encryption/share-keys/';
}
$result = true;
if ($view->is_dir($userId . '/files/' . $filePath)) {
$view->unlink($baseDir . $filePath);
if ($view->is_dir($baseDir . $filePath)) {
\OCP\Util::writeLog('files_encryption', 'delAllShareKeys: delete share keys: ' . $baseDir . $filePath, \OCP\Util::DEBUG);
$result = $view->unlink($baseDir . $filePath);
} else {
$localKeyPath = $view->getLocalFile($baseDir . $filePath);
$escapedPath = Helper::escapeGlobPattern($localKeyPath);
$matches = glob($escapedPath . '*.shareKey');
foreach ($matches as $ma) {
$result = unlink($ma);
if (!$result) {
\OCP\Util::writeLog('Encryption library',
'Keyfile or shareKey could not be deleted for file "' . $filePath . '"', \OCP\Util::ERROR);
$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);
}
}
}
return (bool)$result;
}
/**
@@ -451,19 +481,23 @@ class Keymanager {
if ($view->is_dir($shareKeyPath)) {
$localPath = \OC\Files\Filesystem::normalizePath($view->getLocalFolder($shareKeyPath));
self::recursiveDelShareKeys($localPath, $userIds);
self::recursiveDelShareKeys($shareKeyPath, $userIds, $owner, $view);
} else {
foreach ($userIds as $userId) {
if (!$view->unlink($shareKeyPath . '.' . $userId . '.shareKey')) {
if ($userId === $owner && $view->file_exists('/' . $owner . '/files/' . $filename)) {
\OCP\Util::writeLog('files_encryption', 'Tried to delete owner key, but the file still exists!', \OCP\Util::FATAL);
continue;
}
$result = $view->unlink($shareKeyPath . '.' . $userId . '.shareKey');
\OCP\Util::writeLog('files_encryption', 'delShareKey: delete share key: ' . $shareKeyPath . '.' . $userId . '.shareKey' , \OCP\Util::DEBUG);
if (!$result) {
\OCP\Util::writeLog('Encryption library',
'Could not delete shareKey; does not exist: "' . $shareKeyPath . '.' . $userId
. '.shareKey"', \OCP\Util::ERROR);
}
}
}
@@ -475,31 +509,47 @@ class Keymanager {
*
* @param string $dir directory
* @param array $userIds user ids for which the share keys should be deleted
* @param string $owner owner of the file
* @param \OC\Files\View $view view relative to data/
*/
private static function recursiveDelShareKeys($dir, $userIds) {
foreach ($userIds as $userId) {
$extension = '.' . $userId . '.shareKey';
$escapedDir = Helper::escapeGlobPattern($dir);
$escapedExtension = Helper::escapeGlobPattern($extension);
$matches = glob($escapedDir . '/*' . $escapedExtension);
}
/** @var $matches array */
foreach ($matches as $ma) {
if (!unlink($ma)) {
\OCP\Util::writeLog('Encryption library',
'Could not delete shareKey; does not exist: "' . $ma . '"', \OCP\Util::ERROR);
private static function recursiveDelShareKeys($dir, $userIds, $owner, $view) {
$dirContent = $view->opendir($dir);
$dirSlices = explode('/', ltrim($dir, '/'));
$realFileDir = '/' . $owner . '/files/' . implode('/', array_slice($dirSlices, 3)) . '/';
if (is_resource($dirContent)) {
while (($file = readdir($dirContent)) !== false) {
if (!\OC\Files\Filesystem::isIgnoredDir($file)) {
if ($view->is_dir($dir . '/' . $file)) {
self::recursiveDelShareKeys($dir . '/' . $file, $userIds, $owner, $view);
} else {
foreach ($userIds as $userId) {
$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);
}
}
}
}
}
$subdirs = $directories = glob($escapedDir . '/*', GLOB_ONLYDIR);
foreach ($subdirs as $subdir) {
self::recursiveDelShareKeys($subdir, $userIds);
closedir($dirContent);
}
}
/**
* @brief Make preparations to vars and filesystem for saving a keyfile
*/
public static function keySetPreparation(\OC_FilesystemView $view, $path, $basePath, $userId) {
public static function keySetPreparation(\OC_FilesystemView $view, $path, $basePath) {
$targetPath = ltrim($path, '/');
@@ -510,7 +560,7 @@ class Keymanager {
isset($path_parts['dirname'])
&& !$view->file_exists($basePath . '/' . $path_parts['dirname'])
) {
$sub_dirs = explode(DIRECTORY_SEPARATOR, $basePath . '/' . $path_parts['dirname']);
$sub_dirs = explode('/', $basePath . '/' . $path_parts['dirname']);
$dir = '';
foreach ($sub_dirs as $sub_dir) {
$dir .= '/' . $sub_dir;
@@ -523,4 +573,22 @@ class Keymanager {
return $targetPath;
}
/**
* @brief extract filename from share key name
* @param string $shareKey (filename.userid.sharekey)
* @return string|false filename or false
*/
protected static function getFilenameFromShareKey($shareKey, $userId) {
$expectedSuffix = '.' . $userId . '.' . 'shareKey';
$suffixLen = strlen($expectedSuffix);
$suffix = substr($shareKey, -$suffixLen);
if ($suffix !== $expectedSuffix) {
return false;
}
return substr($shareKey, 0, -$suffixLen);
}
}

View File

@@ -37,6 +37,8 @@ namespace OCA\Encryption;
class Proxy extends \OC_FileProxy {
private static $blackList = null; //mimetypes blacklisted from encryption
private static $unencryptedSizes = array(); // remember unencrypted size
private static $fopenMode = array(); // remember the fopen mode
/**
* Check if a file requires encryption
@@ -114,11 +116,20 @@ class Proxy extends \OC_FileProxy {
// get encrypted content
$data = $view->file_get_contents($tmpPath);
// 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_Filesystem::normalizePath($path)] = $tmpFileInfo['size'];
}
// remove our temp file
$view->deleteAll('/' . \OCP\User::getUser() . '/cache/' . $cacheFolder);
// re-enable proxy - our work is done
\OC_FileProxy::$enabled = $proxyStatus;
} else {
return false;
}
}
}
@@ -127,6 +138,24 @@ class Proxy extends \OC_FileProxy {
}
/**
* @brief update file cache with the new unencrypted size after file was written
* @param string $path
* @param mixed $result
* @return mixed
*/
public function postFile_put_contents($path, $result) {
$normalizedPath = \OC_Filesystem::normalizePath($path);
if ( isset(self::$unencryptedSizes[$normalizedPath]) ) {
$view = new \OC_FilesystemView('/');
$view->putFileInfo($normalizedPath,
array('encrypted' => true, 'unencrypted_size' => self::$unencryptedSizes[$normalizedPath]));
unset(self::$unencryptedSizes[$normalizedPath]);
}
return $result;
}
/**
* @param string $path Path of file from which has been read
* @param string $data Data that has been read from file
@@ -177,47 +206,6 @@ class Proxy extends \OC_FileProxy {
}
/**
* @brief When a file is deleted, remove its keyfile also
*/
public function preUnlink($path) {
// let the trashbin handle this
if (\OCP\App::isEnabled('files_trashbin')) {
return true;
}
// Disable encryption proxy to prevent recursive calls
$proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false;
$view = new \OC_FilesystemView('/');
$userId = \OCP\USER::getUser();
$util = new Util($view, $userId);
// get relative path
$relativePath = \OCA\Encryption\Helper::stripUserFilesPath($path);
list($owner, $ownerPath) = $util->getUidAndFilename($relativePath);
// Delete keyfile & shareKey so it isn't orphaned
if (!Keymanager::deleteFileKey($view, $ownerPath)) {
\OCP\Util::writeLog('Encryption library',
'Keyfile or shareKey could not be deleted for file "' . $ownerPath . '"', \OCP\Util::ERROR);
}
Keymanager::delAllShareKeys($view, $owner, $ownerPath);
\OC_FileProxy::$enabled = $proxyStatus;
// If we don't return true then file delete will fail; better
// to leave orphaned keyfiles than to disallow file deletion
return true;
}
/**
* @param $path
* @return bool
@@ -228,6 +216,16 @@ class Proxy extends \OC_FileProxy {
return true;
}
/**
* @brief remember initial fopen mode because sometimes it gets changed during the request
* @param string $path path
* @param string $mode type of access
*/
public function preFopen($path, $mode) {
self::$fopenMode[$path] = $mode;
}
/**
* @param $path
* @param $result
@@ -246,8 +244,8 @@ class Proxy extends \OC_FileProxy {
// split the path parts
$pathParts = explode('/', $path);
// FIXME: handling for /userId/cache used by webdav for chunking. The cache chunks are NOT encrypted
if (isset($pathParts[2]) && $pathParts[2] === 'cache') {
// don't try to encrypt/decrypt cache chunks or files in the trash bin
if (isset($pathParts[2]) && ($pathParts[2] === 'cache' || $pathParts[2] === 'files_trashbin')) {
return $result;
}
@@ -255,7 +253,15 @@ class Proxy extends \OC_FileProxy {
$proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false;
$meta = stream_get_meta_data($result);
// if we remember the mode from the pre proxy we re-use it
// oterwise we fall back to stream_get_meta_data()
if (isset(self::$fopenMode[$path])) {
$mode = self::$fopenMode[$path];
unset(self::$fopenMode[$path]);
} else {
$meta = stream_get_meta_data($result);
$mode = $meta['mode'];
}
$view = new \OC_FilesystemView('');
@@ -273,14 +279,14 @@ class Proxy extends \OC_FileProxy {
// Open the file using the crypto stream wrapper
// protocol and let it do the decryption work instead
$result = fopen('crypt://' . $path, $meta['mode']);
$result = fopen('crypt://' . $path, $mode);
} elseif (
self::shouldEncrypt($path)
and $meta ['mode'] !== 'r'
and $meta['mode'] !== 'rb'
self::shouldEncrypt($path)
and $mode !== 'r'
and $mode !== 'rb'
) {
$result = fopen('crypt://' . $path, $meta['mode']);
$result = fopen('crypt://' . $path, $mode);
}
// Re-enable the proxy
@@ -305,7 +311,7 @@ class Proxy extends \OC_FileProxy {
\OC_FileProxy::$enabled = false;
// get file size
$data['size'] = self::postFileSize($path, $data['size']);
$data['size'] = self::postFileSize($path, $data['size'], $data);
// Re-enable the proxy
\OC_FileProxy::$enabled = $proxyStatus;
@@ -319,7 +325,7 @@ class Proxy extends \OC_FileProxy {
* @param $size
* @return bool
*/
public function postFileSize($path, $size) {
public function postFileSize($path, $size, $fileInfo = null) {
$view = new \OC_FilesystemView('/');
@@ -335,6 +341,13 @@ class Proxy extends \OC_FileProxy {
// if path is a folder do nothing
if ($view->is_dir($path)) {
$proxyState = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false;
$fileInfo = $view->getFileInfo($path);
\OC_FileProxy::$enabled = $proxyState;
if (isset($fileInfo['unencrypted_size']) && $fileInfo['unencrypted_size'] > 0) {
return $fileInfo['unencrypted_size'];
}
return $size;
}
@@ -346,9 +359,8 @@ class Proxy extends \OC_FileProxy {
return $size;
}
$fileInfo = false;
// get file info from database/cache if not .part file
if (!Helper::isPartialFilePath($path)) {
if (empty($fileInfo) && !Helper::isPartialFilePath($path)) {
$proxyState = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false;
$fileInfo = $view->getFileInfo($path);
@@ -356,7 +368,7 @@ class Proxy extends \OC_FileProxy {
}
// if file is encrypted return real file size
if (is_array($fileInfo) && $fileInfo['encrypted'] === true) {
if (isset($fileInfo['encrypted']) && $fileInfo['encrypted'] === true) {
// try to fix unencrypted file size if it doesn't look plausible
if ((int)$fileInfo['size'] > 0 && (int)$fileInfo['unencrypted_size'] === 0 ) {
$fixSize = $util->getFileSize($path);

View File

@@ -132,6 +132,14 @@ class Session {
}
/**
* @brief remove encryption keys and init status from session
*/
public function closeSession() {
\OC::$session->remove('encryptionInitialized');
\OC::$session->remove('privateKey');
}
/**
* @brief Gets status if we already tried to initialize the encryption app

View File

@@ -64,6 +64,9 @@ class Stream {
private $publicKey;
private $encKeyfile;
private $newFile; // helper var, we only need to write the keyfile for new files
private $isLocalTmpFile = false; // do we operate on a local tmp file
private $localTmpFile; // path of local tmp file
/**
* @var \OC\Files\View
*/
@@ -91,13 +94,18 @@ class Stream {
$this->rootView = new \OC_FilesystemView('/');
}
$this->session = new \OCA\Encryption\Session($this->rootView);
$this->privateKey = $this->session->getPrivateKey();
// rawPath is relative to the data directory
$this->rawPath = \OC\Files\Filesystem::normalizePath(str_replace('crypt://', '', $path));
$normalizedPath = \OC\Files\Filesystem::normalizePath(str_replace('crypt://', '', $path));
if ($originalFile = Helper::getPathFromTmpFile($normalizedPath)) {
$this->rawPath = $originalFile;
$this->isLocalTmpFile = true;
$this->localTmpFile = $normalizedPath;
} else {
$this->rawPath = $normalizedPath;
}
$this->userId = Helper::getUser($this->rawPath);
@@ -141,10 +149,14 @@ class Stream {
\OCA\Encryption\Helper::redirectToErrorPage($this->session);
}
$this->size = $this->rootView->filesize($this->rawPath, $mode);
$this->size = $this->rootView->filesize($this->rawPath);
}
$this->handle = $this->rootView->fopen($this->rawPath, $mode);
if ($this->isLocalTmpFile) {
$this->handle = fopen($this->localTmpFile, $mode);
} else {
$this->handle = $this->rootView->fopen($this->rawPath, $mode);
}
\OC_FileProxy::$enabled = $proxyStatus;
@@ -155,6 +167,9 @@ class Stream {
} else {
$this->meta = stream_get_meta_data($this->handle);
// sometimes fopen changes the mode, e.g. for a url "r" convert to "r+"
// but we need to remember the original access type
$this->meta['mode'] = $mode;
}
@@ -163,15 +178,26 @@ class Stream {
}
/**
* @brief Returns the current position of the file pointer
* @return int position of the file pointer
*/
public function stream_tell() {
return ftell($this->handle);
}
/**
* @param $offset
* @param int $whence
* @return bool true if fseek was successful, otherwise false
*/
public function stream_seek($offset, $whence = SEEK_SET) {
$this->flush();
fseek($this->handle, $offset, $whence);
// this wrapper needs to return "true" for success.
// the fseek call itself returns 0 on succeess
return !fseek($this->handle, $offset, $whence);
}
@@ -477,7 +503,7 @@ class Stream {
if ($this->privateKey === false) {
// cleanup
if ($this->meta['mode'] !== 'r' && $this->meta['mode'] !== 'rb') {
if ($this->meta['mode'] !== 'r' && $this->meta['mode'] !== 'rb' && !$this->isLocalTmpFile) {
// Disable encryption proxy to prevent recursive calls
$proxyStatus = \OC_FileProxy::$enabled;
@@ -498,6 +524,7 @@ class Stream {
if (
$this->meta['mode'] !== 'r' &&
$this->meta['mode'] !== 'rb' &&
$this->isLocalTmpFile === false &&
$this->size > 0 &&
$this->unencryptedSize > 0
) {
@@ -518,7 +545,7 @@ class Stream {
$util = new Util($this->rootView, $this->userId);
// Get all users sharing the file includes current user
$uniqueUserIds = $util->getSharingUsersArray($sharingEnabled, $this->relPath, $this->userId);
$uniqueUserIds = $util->getSharingUsersArray($sharingEnabled, $this->relPath);
$checkedUserIds = $util->filterShareReadyUsers($uniqueUserIds);
// Fetch public keys for all sharing users

View File

@@ -2,9 +2,10 @@
/**
* ownCloud
*
* @author Sam Tuke, Frank Karlitschek
* @author Sam Tuke, Frank Karlitschek, Bjoern Schiessle
* @copyright 2012 Sam Tuke <samtuke@owncloud.com>,
* Frank Karlitschek <frank@owncloud.org>
* Frank Karlitschek <frank@owncloud.org>,
* Bjoern Schiessle <schiessle@owncloud.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
@@ -56,7 +57,7 @@ class Util {
* @param $userId
* @param bool $client
*/
public function __construct(\OC_FilesystemView $view, $userId, $client = false) {
public function __construct($view, $userId, $client = false) {
$this->view = $view;
$this->client = $client;
@@ -101,15 +102,24 @@ class Util {
or !$this->view->file_exists($this->publicKeyPath)
or !$this->view->file_exists($this->privateKeyPath)
) {
return false;
} else {
return true;
}
}
/**
* @brief check if the users private & public key exists
* @return boolean
*/
public function userKeysExists() {
if (
$this->view->file_exists($this->privateKeyPath) &&
$this->view->file_exists($this->publicKeyPath)) {
return true;
} else {
return false;
}
}
/**
@@ -123,7 +133,6 @@ class Util {
// Set directories to check / create
$setUpDirs = array(
$this->userDir,
$this->userFilesDir,
$this->publicKeyDir,
$this->encryptionDir,
$this->keyfilesPath,
@@ -232,11 +241,9 @@ class Util {
if (\OCP\DB::isError($result)) {
\OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
} else {
if ($result->numRows() > 0) {
$row = $result->fetchRow();
if (isset($row['recovery_enabled'])) {
$recoveryEnabled[] = $row['recovery_enabled'];
}
$row = $result->fetchRow();
if ($row && isset($row['recovery_enabled'])) {
$recoveryEnabled[] = $row['recovery_enabled'];
}
}
@@ -280,7 +287,7 @@ class Util {
$sql = 'UPDATE `*PREFIX*encryption` SET `recovery_enabled` = ? WHERE `uid` = ?';
$args = array(
$enabled,
$enabled ? '1' : '0',
$this->userId
);
@@ -308,7 +315,8 @@ class Util {
$found = array(
'plain' => array(),
'encrypted' => array(),
'legacy' => array()
'legacy' => array(),
'broken' => array(),
);
}
@@ -319,10 +327,7 @@ class Util {
if(is_resource($handle)) {
while (false !== ($file = readdir($handle))) {
if (
$file !== "."
&& $file !== ".."
) {
if ($file !== "." && $file !== "..") {
$filePath = $directory . '/' . $this->view->getRelativePath('/' . $file);
$relPath = \OCA\Encryption\Helper::stripUserFilesPath($filePath);
@@ -349,15 +354,23 @@ class Util {
// NOTE: This is inefficient;
// scanning every file like this
// will eat server resources :(
if (
Keymanager::getFileKey($this->view, $this, $relPath)
&& $isEncryptedPath
) {
if ($isEncryptedPath) {
$found['encrypted'][] = array(
'name' => $file,
'path' => $filePath
);
$fileKey = Keymanager::getFileKey($this->view, $this, $relPath);
$shareKey = Keymanager::getShareKey($this->view, $this->userId, $this, $relPath);
// if file is encrypted but now file key is available, throw exception
if ($fileKey === false || $shareKey === false) {
\OCP\Util::writeLog('encryption library', 'No keys available to decrypt the file: ' . $filePath, \OCP\Util::ERROR);
$found['broken'][] = array(
'name' => $file,
'path' => $filePath,
);
} else {
$found['encrypted'][] = array(
'name' => $file,
'path' => $filePath,
);
}
// If the file uses old
// encryption system
@@ -455,20 +468,36 @@ class Util {
*/
public function isEncryptedPath($path) {
$relPath = Helper::getPathToRealFile($path);
// Disable encryption proxy so data retrieved is in its
// original form
$proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false;
if ($relPath === false) {
$relPath = Helper::stripUserFilesPath($path);
// we only need 24 byte from the last chunk
$data = '';
$handle = $this->view->fopen($path, 'r');
if (is_resource($handle)) {
// suppress fseek warining, we handle the case that fseek doesn't
// work in the else branch
if (@fseek($handle, -24, SEEK_END) === 0) {
$data = fgets($handle);
} else {
// if fseek failed on the storage we create a local copy from the file
// and read this one
fclose($handle);
$localFile = $this->view->getLocalFile($path);
$handle = fopen($localFile, 'r');
if (is_resource($handle) && fseek($handle, -24, SEEK_END) === 0) {
$data = fgets($handle);
}
}
fclose($handle);
}
$fileKey = Keymanager::getFileKey($this->view, $this, $relPath);
if ($fileKey === false) {
return false;
}
return true;
// re-enable proxy
\OC_FileProxy::$enabled = $proxyStatus;
return Crypt::isCatfileContent($data);
}
/**
@@ -514,7 +543,20 @@ class Util {
$lastChunckPos = ($lastChunkNr * 8192);
// seek to end
fseek($stream, $lastChunckPos);
if (@fseek($stream, $lastChunckPos) === -1) {
// storage doesn't support fseek, we need a local copy
fclose($stream);
$localFile = $this->view->getLocalFile($path);
Helper::addTmpFileToMapper($localFile, $path);
$stream = fopen('crypt://' . $localFile, "r");
if (fseek($stream, $lastChunckPos) === -1) {
// if fseek also fails on the local storage, than
// there is nothing we can do
fclose($stream);
\OCP\Util::writeLog('Encryption library', 'couldn\'t determine size of "' . $path, \OCP\Util::ERROR);
return $result;
}
}
// get the content of the last chunk
$lastChunkContent = fread($stream, $lastChunkSize);
@@ -761,7 +803,7 @@ class Util {
\OC\Files\Filesystem::putFileInfo($relPath, array(
'encrypted' => false,
'size' => $size,
'unencrypted_size' => $size,
'unencrypted_size' => 0,
'etag' => $fileInfo['etag']
));
@@ -777,6 +819,12 @@ class Util {
$successful = false;
}
// if there are broken encrypted files than the complete decryption
// was not successful
if (!empty($found['broken'])) {
$successful = false;
}
if ($successful) {
$this->view->deleteAll($this->keyfilesPath);
$this->view->deleteAll($this->shareKeysPath);
@@ -831,32 +879,35 @@ class Util {
// Open enc file handle for binary writing, with same filename as original plain file
$encHandle = fopen('crypt://' . $rawPath . '.part', 'wb');
// Move plain file to a temporary location
$size = stream_copy_to_stream($plainHandle, $encHandle);
if (is_resource($encHandle)) {
// Move plain file to a temporary location
$size = stream_copy_to_stream($plainHandle, $encHandle);
fclose($encHandle);
fclose($plainHandle);
fclose($encHandle);
fclose($plainHandle);
$fakeRoot = $this->view->getRoot();
$this->view->chroot('/' . $this->userId . '/files');
$fakeRoot = $this->view->getRoot();
$this->view->chroot('/' . $this->userId . '/files');
$this->view->rename($relPath . '.part', $relPath);
$this->view->rename($relPath . '.part', $relPath);
// set timestamp
$this->view->touch($relPath, $timestamp);
// set timestamp
$this->view->touch($relPath, $timestamp);
$this->view->chroot($fakeRoot);
$encSize = $this->view->filesize($relPath);
// Add the file to the cache
\OC\Files\Filesystem::putFileInfo($relPath, array(
'encrypted' => true,
'size' => $size,
'unencrypted_size' => $size,
'etag' => $fileInfo['etag']
));
$this->view->chroot($fakeRoot);
$encryptedFiles[] = $relPath;
// Add the file to the cache
\OC\Files\Filesystem::putFileInfo($relPath, array(
'encrypted' => true,
'size' => $encSize,
'unencrypted_size' => $size,
'etag' => $fileInfo['etag']
));
$encryptedFiles[] = $relPath;
}
}
// Encrypt legacy encrypted files
@@ -973,8 +1024,8 @@ class Util {
if (\OCP\DB::isError($result)) {
\OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
} else {
if ($result->numRows() > 0) {
$row = $result->fetchRow();
$row = $result->fetchRow();
if ($row) {
$path = substr($row['path'], strlen('files'));
}
}
@@ -1090,6 +1141,10 @@ class Util {
// Re-enc keyfile to (additional) sharekeys
$multiEncKey = Crypt::multiKeyEncrypt($plainKeyfile, $userPubKeys);
if ($multiEncKey === false) {
return false;
}
// Save the recrypted key to it's owner's keyfiles directory
// Save new sharekeys to all necessary user directory
if (
@@ -1113,8 +1168,10 @@ class Util {
/**
* @brief Find, sanitise and format users sharing a file
* @note This wraps other methods into a portable bundle
* @param boolean $sharingEnabled
* @param string $filePath path relativ to current users files folder
*/
public function getSharingUsersArray($sharingEnabled, $filePath, $currentUserId = false) {
public function getSharingUsersArray($sharingEnabled, $filePath) {
// Check if key recovery is enabled
if (
@@ -1131,12 +1188,14 @@ class Util {
$ownerPath = \OCA\Encryption\Helper::stripPartialFileExtension($ownerPath);
$userIds = array();
// always add owner to the list of users with access to the file
$userIds = array($owner);
if ($sharingEnabled) {
// Find out who, if anyone, is sharing the file
$result = \OCP\Share::getUsersSharingFile($ownerPath, $owner, true);
$userIds = $result['users'];
$result = \OCP\Share::getUsersSharingFile($ownerPath, $owner);
$userIds = \array_merge($userIds, $result['users']);
if ($result['public']) {
$userIds[] = $this->publicShareKeyId;
}
@@ -1152,17 +1211,12 @@ class Util {
$userIds[] = $recoveryKeyId;
}
// add current user if given
if ($currentUserId !== false) {
$userIds[] = $currentUserId;
}
// check if it is a group mount
if (\OCP\App::isEnabled("files_external")) {
$mount = \OC_Mount_Config::getSystemMountPoints();
foreach ($mount as $mountPoint => $data) {
if ($mountPoint == substr($ownerPath, 1, strlen($mountPoint))) {
$userIds = array_merge($userIds, $this->getUserWithAccessToMountPoint($data['applicable']['users'], $data['applicable']['groups']));
$mounts = \OC_Mount_Config::getSystemMountPoints();
foreach ($mounts as $mount) {
if ($mount['mountpoint'] == substr($ownerPath, 1, strlen($mount['mountpoint']))) {
$userIds = array_merge($userIds, $this->getUserWithAccessToMountPoint($mount['applicable']['users'], $mount['applicable']['groups']));
}
}
}
@@ -1188,27 +1242,49 @@ class Util {
return $result;
}
/**
* @brief set migration status
* @param int $status
* @return boolean
*/
private function setMigrationStatus($status) {
$sql = 'UPDATE `*PREFIX*encryption` SET `migration_status` = ? WHERE `uid` = ?';
$args = array($status, $this->userId);
$query = \OCP\DB::prepare($sql);
$manipulatedRows = $query->execute($args);
if ($manipulatedRows === 1) {
$result = true;
\OCP\Util::writeLog('Encryption library', "Migration status set to " . self::MIGRATION_OPEN, \OCP\Util::INFO);
} else {
$result = false;
\OCP\Util::writeLog('Encryption library', "Could not set migration status to " . self::MIGRATION_OPEN, \OCP\Util::WARN);
}
return $result;
}
/**
* @brief start migration mode to initially encrypt users data
* @return boolean
*/
public function beginMigration() {
$return = false;
$result = $this->setMigrationStatus(self::MIGRATION_IN_PROGRESS);
$sql = 'UPDATE `*PREFIX*encryption` SET `migration_status` = ? WHERE `uid` = ? and `migration_status` = ?';
$args = array(self::MIGRATION_IN_PROGRESS, $this->userId, self::MIGRATION_OPEN);
$query = \OCP\DB::prepare($sql);
$manipulatedRows = $query->execute($args);
if ($manipulatedRows === 1) {
$return = true;
if ($result) {
\OCP\Util::writeLog('Encryption library', "Start migration to encryption mode for " . $this->userId, \OCP\Util::INFO);
} else {
\OCP\Util::writeLog('Encryption library', "Could not activate migration mode for " . $this->userId . ". Probably another process already started the initial encryption", \OCP\Util::WARN);
}
return $return;
return $result;
}
public function resetMigrationStatus() {
return $this->setMigrationStatus(self::MIGRATION_OPEN);
}
/**
@@ -1216,22 +1292,15 @@ class Util {
* @return boolean
*/
public function finishMigration() {
$result = $this->setMigrationStatus(self::MIGRATION_COMPLETED);
$return = false;
$sql = 'UPDATE `*PREFIX*encryption` SET `migration_status` = ? WHERE `uid` = ? and `migration_status` = ?';
$args = array(self::MIGRATION_COMPLETED, $this->userId, self::MIGRATION_IN_PROGRESS);
$query = \OCP\DB::prepare($sql);
$manipulatedRows = $query->execute($args);
if ($manipulatedRows === 1) {
$return = true;
if ($result) {
\OCP\Util::writeLog('Encryption library', "Finish migration successfully for " . $this->userId, \OCP\Util::INFO);
} else {
\OCP\Util::writeLog('Encryption library', "Could not deactivate migration mode for " . $this->userId, \OCP\Util::WARN);
}
return $return;
return $result;
}
/**
@@ -1254,11 +1323,9 @@ class Util {
if (\OCP\DB::isError($result)) {
\OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
} else {
if ($result->numRows() > 0) {
$row = $result->fetchRow();
if (isset($row['migration_status'])) {
$migrationStatus[] = $row['migration_status'];
}
$row = $result->fetchRow();
if ($row && isset($row['migration_status'])) {
$migrationStatus[] = $row['migration_status'];
}
}
@@ -1366,59 +1433,32 @@ class Util {
}
}
/**
* @brief go recursively through a dir and collect all files and sub files.
* @param string $dir relative to the users files folder
* @return array with list of files relative to the users files folder
*/
public function getAllFiles($dir) {
$result = array();
$dirList = array($dir);
$content = $this->view->getDirectoryContent(\OC\Files\Filesystem::normalizePath(
$this->userFilesDir . '/' . $dir));
// handling for re shared folders
$pathSplit = explode('/', $dir);
foreach ($content as $c) {
$sharedPart = $pathSplit[sizeof($pathSplit) - 1];
$targetPathSplit = array_reverse(explode('/', $c['path']));
$path = '';
// rebuild path
foreach ($targetPathSplit as $pathPart) {
if ($pathPart !== $sharedPart) {
$path = '/' . $pathPart . $path;
while ($dirList) {
$dir = array_pop($dirList);
$content = $this->view->getDirectoryContent(\OC\Files\Filesystem::normalizePath(
$this->userFilesDir . '/' . $dir));
foreach ($content as $c) {
$usersPath = isset($c['usersPath']) ? $c['usersPath'] : $c['path'];
if ($c['type'] === 'dir') {
$dirList[] = substr($usersPath, strlen("files"));
} else {
break;
$result[] = substr($usersPath, strlen("files"));
}
}
$path = $dir . $path;
if ($c['type'] === 'dir') {
$result = array_merge($result, $this->getAllFiles($path));
} else {
$result[] = $path;
}
}
return $result;
}
/**
@@ -1438,9 +1478,7 @@ class Util {
if (\OCP\DB::isError($result)) {
\OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
} else {
if ($result->numRows() > 0) {
$row = $result->fetchRow();
}
$row = $result->fetchRow();
}
return $row;
@@ -1464,9 +1502,7 @@ class Util {
if (\OCP\DB::isError($result)) {
\OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
} else {
if ($result->numRows() > 0) {
$row = $result->fetchRow();
}
$row = $result->fetchRow();
}
return $row;
@@ -1485,18 +1521,16 @@ class Util {
$result = $query->execute(array($id));
$source = array();
$source = null;
if (\OCP\DB::isError($result)) {
\OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
} else {
if ($result->numRows() > 0) {
$source = $result->fetchRow();
}
$source = $result->fetchRow();
}
$fileOwner = false;
if (isset($source['parent'])) {
if ($source && isset($source['parent'])) {
$parent = $source['parent'];
@@ -1506,16 +1540,14 @@ class Util {
$result = $query->execute(array($parent));
$item = array();
$item = null;
if (\OCP\DB::isError($result)) {
\OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
} else {
if ($result->numRows() > 0) {
$item = $result->fetchRow();
}
$item = $result->fetchRow();
}
if (isset($item['parent'])) {
if ($item && isset($item['parent'])) {
$parent = $item['parent'];
@@ -1738,14 +1770,61 @@ class Util {
/**
* @brief check if the file is stored on a system wide mount point
* @param $path relative to /data/user with leading '/'
* 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 = '') {
\OC_FileProxy::$enabled = false;
$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->copyRecursive($this->shareKeysPath, $backupDir . 'share-keys/');
$this->copyRecursive($this->keyfilesPath, $backupDir . 'keyfiles/');
$this->view->copy($this->privateKeyPath, $backupDir . $this->userId . '.private.key');
$this->view->copy($this->publicKeyPath, $backupDir . $this->userId . '.public.key');
\OC_FileProxy::$enabled = true;
}
/**
* helper method to copy a folder recursively, only needed in OC6.
* OC7 filesystem and newer can copy folder structures
*
* @param string $source
* @param string $target
*/
private function copyRecursive($source, $target) {
if ($this->view->is_dir($source)) {
$this->view->mkdir($target);
$dir = $this->view->opendir($source);
while ($file = readdir($dir)) {
if(!\OC\Files\Filesystem::isIgnoredDir($file)) {
$this->copyRecursive($source . '/' . $file, $target . '/' . $file);
}
}
closedir($dir);
} else {
$this->view->copy($source, $target);
}
}
/**
* check if the file is stored on a system wide mount point
* @param string $path relative to /data/user with leading '/'
* @return boolean
*/
public function isSystemWideMountPoint($path) {
$normalizedPath = ltrim($path, '/');
if (\OCP\App::isEnabled("files_external")) {
$mount = \OC_Mount_Config::getSystemMountPoints();
foreach ($mount as $mountPoint => $data) {
if ($mountPoint == substr($path, 1, strlen($mountPoint))) {
return true;
$mounts = \OC_Mount_Config::getSystemMountPoints();
foreach ($mounts as $mount) {
if ($mount['mountpoint'] == substr($normalizedPath, 0, strlen($mount['mountpoint']))) {
if ($this->isMountPointApplicableToUser($mount)) {
return true;
}
}
}
}
@@ -1753,7 +1832,30 @@ class Util {
}
/**
* @brief decrypt private key and add it to the current session
* check if mount point is applicable to user
*
* @param array $mount contains $mount['applicable']['users'], $mount['applicable']['groups']
* @return boolean
*/
protected function isMountPointApplicableToUser($mount) {
$uid = \OCP\User::getUser();
$acceptedUids = array('all', $uid);
// check if mount point is applicable for the user
$intersection = array_intersect($acceptedUids, $mount['applicable']['users']);
if (!empty($intersection)) {
return true;
}
// check if mount point is applicable for group where the user is a member
foreach ($mount['applicable']['groups'] as $gid) {
if (\OC_Group::inGroup($uid, $gid)) {
return true;
}
}
return false;
}
/**
* decrypt private key and add it to the current session
* @param array $params with 'uid' and 'password'
* @return mixed session or false
*/
@@ -1780,4 +1882,12 @@ class Util {
return $session;
}
/*
* @brief remove encryption related keys from the session
*/
public function closeEncryptionSession() {
$session = new \OCA\Encryption\Session($this->view);
$session->closeSession();
}
}

View File

@@ -2,7 +2,7 @@
<fieldset class="personalblock">
<h2><?php p( $l->t( 'Encryption' ) ); ?></h2>
<?php if ( ! $_["privateKeySet"] && $_["initialized"] ): ?>
<?php if ( $_["initialized"] === '1' ): ?>
<p>
<a name="changePKPasswd" />
<label for="changePrivateKeyPasswd">

View File

@@ -46,13 +46,12 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
\OC_User::clearBackends();
\OC_User::useBackend('database');
// Filesystem related hooks
// clear hooks and register encryption hooks
\OC_Hook::clear();
\OCA\Encryption\Helper::registerFilesystemHooks();
// Filesystem related hooks
\OCA\Encryption\Helper::registerUserHooks();
// clear and register hooks
// clear and register proxies
\OC_FileProxy::clearProxies();
\OC_FileProxy::register(new OCA\Encryption\Proxy());
@@ -95,6 +94,8 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
} else {
OC_App::disable('files_trashbin');
}
$this->assertTrue(\OC_FileProxy::$enabled);
}
public static function tearDownAfterClass() {
@@ -155,7 +156,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
*/
function testSymmetricStreamEncryptShortFileContent() {
$filename = 'tmp-' . time() . '.test';
$filename = 'tmp-' . uniqid() . '.test';
$util = new Encryption\Util(new \OC_FilesystemView(), $this->userId);
@@ -214,7 +215,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
function testSymmetricStreamEncryptLongFileContent() {
// Generate a a random filename
$filename = 'tmp-' . time() . '.test';
$filename = 'tmp-' . uniqid() . '.test';
$util = new Encryption\Util(new \OC_FilesystemView(), $this->userId);
@@ -297,7 +298,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
*/
function testSymmetricStreamDecryptShortFileContent() {
$filename = 'tmp-' . time();
$filename = 'tmp-' . uniqid();
// Save long data as encrypted file using stream wrapper
$cryptedFile = file_put_contents('crypt:///'. $this->userId . '/files/' . $filename, $this->dataShort);
@@ -327,7 +328,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
*/
function testSymmetricStreamDecryptLongFileContent() {
$filename = 'tmp-' . time();
$filename = 'tmp-' . uniqid();
// Save long data as encrypted file using stream wrapper
$cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/' . $filename, $this->dataLong);
@@ -418,7 +419,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
*/
function testRenameFile() {
$filename = 'tmp-' . time();
$filename = 'tmp-' . uniqid();
// Save long data as encrypted file using stream wrapper
$cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/' . $filename, $this->dataLong);
@@ -431,7 +432,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
$this->assertEquals($this->dataLong, $decrypt);
$newFilename = 'tmp-new-' . time();
$newFilename = 'tmp-new-' . uniqid();
$view = new \OC\Files\View('/' . $this->userId . '/files');
$view->rename($filename, $newFilename);
@@ -449,7 +450,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
*/
function testMoveFileIntoFolder() {
$filename = 'tmp-' . time();
$filename = 'tmp-' . uniqid();
// Save long data as encrypted file using stream wrapper
$cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/' . $filename, $this->dataLong);
@@ -462,8 +463,8 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
$this->assertEquals($this->dataLong, $decrypt);
$newFolder = '/newfolder' . time();
$newFilename = 'tmp-new-' . time();
$newFolder = '/newfolder' . uniqid();
$newFilename = 'tmp-new-' . uniqid();
$view = new \OC\Files\View('/' . $this->userId . '/files');
$view->mkdir($newFolder);
$view->rename($filename, $newFolder . '/' . $newFilename);
@@ -484,8 +485,8 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
$view = new \OC\Files\View('/' . $this->userId . '/files');
$filename = '/tmp-' . time();
$folder = '/folder' . time();
$filename = '/tmp-' . uniqid();
$folder = '/folder' . uniqid();
$view->mkdir($folder);
@@ -500,7 +501,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
$this->assertEquals($this->dataLong, $decrypt);
$newFolder = '/newfolder/subfolder' . time();
$newFolder = '/newfolder/subfolder' . uniqid();
$view->mkdir('/newfolder');
$view->rename($folder, $newFolder);
@@ -519,7 +520,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
* @medium
*/
function testChangePassphrase() {
$filename = 'tmp-' . time();
$filename = 'tmp-' . uniqid();
// Save long data as encrypted file using stream wrapper
$cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/' . $filename, $this->dataLong);
@@ -557,7 +558,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
*/
function testViewFilePutAndGetContents() {
$filename = '/tmp-' . time();
$filename = '/tmp-' . uniqid();
$view = new \OC\Files\View('/' . $this->userId . '/files');
// Save short data as encrypted file using stream wrapper
@@ -590,7 +591,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
* @large
*/
function testTouchExistingFile() {
$filename = '/tmp-' . time();
$filename = '/tmp-' . uniqid();
$view = new \OC\Files\View('/' . $this->userId . '/files');
// Save short data as encrypted file using stream wrapper
@@ -614,7 +615,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
* @medium
*/
function testTouchFile() {
$filename = '/tmp-' . time();
$filename = '/tmp-' . uniqid();
$view = new \OC\Files\View('/' . $this->userId . '/files');
$view->touch($filename);
@@ -638,7 +639,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
* @medium
*/
function testFopenFile() {
$filename = '/tmp-' . time();
$filename = '/tmp-' . uniqid();
$view = new \OC\Files\View('/' . $this->userId . '/files');
// Save short data as encrypted file using stream wrapper

View File

@@ -8,6 +8,7 @@
require_once __DIR__ . '/../lib/helper.php';
require_once __DIR__ . '/util.php';
use OCA\Encryption;
@@ -16,6 +17,18 @@ use OCA\Encryption;
*/
class Test_Encryption_Helper extends \PHPUnit_Framework_TestCase {
const TEST_ENCRYPTION_HELPER_USER1 = "test-helper-user1";
public static function setUpBeforeClass() {
// create test user
\Test_Encryption_Util::loginHelper(\Test_Encryption_Helper::TEST_ENCRYPTION_HELPER_USER1, true);
}
public static function tearDownAfterClass() {
// cleanup test user
\OC_User::deleteUser(\Test_Encryption_Helper::TEST_ENCRYPTION_HELPER_USER1);
}
/**
* @medium
*/
@@ -64,4 +77,84 @@ class Test_Encryption_Helper extends \PHPUnit_Framework_TestCase {
$this->assertEquals($relativePath, Encryption\Helper::getPathToRealFile($cachePath));
}
function testGetUser() {
$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_USER1 . "/thumbnails/foo";
$path4 ="/" . "/" . 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();
// 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));
$this->assertEquals(self::TEST_ENCRYPTION_HELPER_USER1, Encryption\Helper::getUser($path2));
$this->assertFalse(Encryption\Helper::getUser($path3));
$this->assertFalse(Encryption\Helper::getUser($path4));
// Log-in again
\Test_Encryption_Util::loginHelper(\Test_Encryption_Helper::TEST_ENCRYPTION_HELPER_USER1);
}
function userNamesProvider() {
return array(
array('testuser' . uniqid()),
array('user.name.with.dots'),
);
}
/**
* Tests whether share keys can be found
*
* @dataProvider userNamesProvider
*/
function testFindShareKeys($userName) {
// 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
\Test_Encryption_Util::setupHooks();
\Test_Encryption_Util::loginHelper($userName, true);
$testDir = 'testFindShareKeys' . uniqid() . '/';
$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
);
}
// clean up
$rootView->unlink($baseDir);
\Test_Encryption_Util::logoutHelper();
\OC_User::deleteUser($userName);
}
}

View File

@@ -0,0 +1,462 @@
<?php
/**
* ownCloud
*
* @author Bjoern Schiessle
* @copyright 2014 Bjoern Schiessle <schiessle@owncloud.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
require_once __DIR__ . '/../../../lib/base.php';
require_once __DIR__ . '/../lib/crypt.php';
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;
/**
* Class Test_Encryption_Hooks
* @brief this class provide basic hook app tests
*/
class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase {
const TEST_ENCRYPTION_HOOKS_USER1 = "test-encryption-hooks-user1.dot";
const TEST_ENCRYPTION_HOOKS_USER2 = "test-encryption-hooks-user2.dot";
/**
* @var \OC_FilesystemView
*/
public $user1View; // view on /data/user1/files
public $user2View; // view on /data/user2/files
public $rootView; // view on /data/user
public $data;
public $filename;
public $folder;
private static $testFiles;
public static function 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');
\OC_Hook::clear('OC_Filesystem');
\OC_Hook::clear('OC_User');
// clear share hooks
\OC_Hook::clear('OCP\\Share');
\OC::registerShareHooks();
\OCP\Util::connectHook('OC_Filesystem', 'setup', '\OC\Files\Storage\Shared', 'setup');
// Filesystem related hooks
\OCA\Encryption\Helper::registerFilesystemHooks();
// Sharing related hooks
\OCA\Encryption\Helper::registerShareHooks();
// clear and register proxies
\OC_FileProxy::clearProxies();
\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);
}
function setUp() {
// set user id
\Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
\OC_User::setUserId(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
// init filesystem view
$this->user1View = new \OC_FilesystemView('/'. \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1 . '/files');
$this->user2View = new \OC_FilesystemView('/'. \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '/files');
$this->rootView = new \OC_FilesystemView('/');
// init short data
$this->data = 'hats';
$this->filename = 'enc_hooks_tests-' . uniqid() . '.txt';
$this->folder = 'enc_hooks_tests_folder-' . uniqid();
}
public static function tearDownAfterClass() {
// cleanup test user
\OC_User::deleteUser(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
\OC_User::deleteUser(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2);
}
function testDeleteHooks() {
// remember files_trashbin state
$stateFilesTrashbin = OC_App::isEnabled('files_trashbin');
// we want to tests with app files_trashbin disabled
\OC_App::disable('files_trashbin');
// make sure that the trash bin is disabled
$this->assertFalse(\OC_APP::isEnabled('files_trashbin'));
$this->user1View->file_put_contents($this->filename, $this->data);
// check if all keys are generated
$this->assertTrue($this->rootView->file_exists(
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
$this->assertTrue($this->rootView->file_exists(
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);
\OC_User::setUserId(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2);
$this->user2View->file_put_contents($this->filename, $this->data);
// check if all keys are generated
$this->assertTrue($this->rootView->file_exists(
self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/share-keys/'
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey'));
$this->assertTrue($this->rootView->file_exists(
self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
// create a dummy file that we can delete something outside of data/user/files
// in this case no share or file keys should be deleted
$this->rootView->file_put_contents(self::TEST_ENCRYPTION_HOOKS_USER2 . "/" . $this->filename, $this->data);
// delete dummy file outside of data/user/files
$this->rootView->unlink(self::TEST_ENCRYPTION_HOOKS_USER2 . "/" . $this->filename);
// all keys should still exist
$this->assertTrue($this->rootView->file_exists(
self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/share-keys/'
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey'));
$this->assertTrue($this->rootView->file_exists(
self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
// delete the file in data/user/files
// now the correspondig share and file keys from user2 should be deleted
$this->user2View->unlink($this->filename);
// check if keys from user2 are really deleted
$this->assertFalse($this->rootView->file_exists(
self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/share-keys/'
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey'));
$this->assertFalse($this->rootView->file_exists(
self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
// but user1 keys should still exist
$this->assertTrue($this->rootView->file_exists(
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
$this->assertTrue($this->rootView->file_exists(
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
if ($stateFilesTrashbin) {
OC_App::enable('files_trashbin');
}
else {
OC_App::disable('files_trashbin');
}
}
function testDeleteHooksForSharedFiles() {
\Test_Encryption_Util::logoutHelper();
\Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
\OC_User::setUserId(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
// remember files_trashbin state
$stateFilesTrashbin = OC_App::isEnabled('files_trashbin');
// we want to tests with app files_trashbin disabled
\OC_App::disable('files_trashbin');
// make sure that the trash bin is disabled
$this->assertFalse(\OC_APP::isEnabled('files_trashbin'));
$this->user1View->file_put_contents($this->filename, $this->data);
// check if all keys are generated
$this->assertTrue($this->rootView->file_exists(
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
$this->assertTrue($this->rootView->file_exists(
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
// get the file info from previous created file
$fileInfo = $this->user1View->getFileInfo($this->filename);
// check if we have a valid file info
$this->assertTrue(is_array($fileInfo));
// share the file with user2
\OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, self::TEST_ENCRYPTION_HOOKS_USER2, OCP\PERMISSION_ALL);
// check if new share key exists
$this->assertTrue($this->rootView->file_exists(
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);
\OC_User::setUserId(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2);
// user2 has a local file with the same name
$this->user2View->file_put_contents($this->filename, $this->data);
// check if all keys are generated
$this->assertTrue($this->rootView->file_exists(
self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/share-keys/'
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey'));
$this->assertTrue($this->rootView->file_exists(
self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
// delete the Shared file from user1 in data/user2/files/Shared
$this->user2View->unlink('/Shared/' . $this->filename);
// now keys from user1s home should be gone
$this->assertFalse($this->rootView->file_exists(
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
// FIXME: key is not properly removed
/*
$this->assertFalse($this->rootView->file_exists(
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey'));
*/
$this->assertFalse($this->rootView->file_exists(
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
// but user2 keys should still exist
$this->assertTrue($this->rootView->file_exists(
self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/share-keys/'
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey'));
$this->assertTrue($this->rootView->file_exists(
self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
// cleanup
$this->user2View->unlink($this->filename);
\Test_Encryption_Util::logoutHelper();
\Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
\OC_User::setUserId(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
// unshare the file
\OCP\Share::unshare('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, self::TEST_ENCRYPTION_HOOKS_USER2);
$this->user1View->unlink($this->filename);
if ($stateFilesTrashbin) {
OC_App::enable('files_trashbin');
}
else {
OC_App::disable('files_trashbin');
}
}
/**
* @brief test rename operation
*/
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 doTestRenameHook($filename) {
// check if keys exists
$this->assertTrue($this->rootView->file_exists(
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
. $filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
$this->assertTrue($this->rootView->file_exists(
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/'
. $filename . '.key'));
// make subfolder and sub-subfolder
$this->rootView->mkdir('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder);
$this->rootView->mkdir('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder . '/' . $this->folder);
$this->assertTrue($this->rootView->is_dir('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder . '/' . $this->folder));
// move the file to the sub-subfolder
$root = $this->rootView->getRoot();
$this->rootView->chroot('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/');
$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/' . $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/'
. $filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
$this->assertFalse($this->rootView->file_exists(
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/'
. $filename . '.key'));
$this->assertTrue($this->rootView->file_exists(
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/' . $this->folder . '/' . $this->folder . '/'
. $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 . '/'
. $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 doTestCopyHook($filename) {
// check if keys exists
$this->assertTrue($this->rootView->file_exists(
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
. $filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
$this->assertTrue($this->rootView->file_exists(
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/'
. $filename . '.key'));
// make subfolder and sub-subfolder
$this->rootView->mkdir('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder);
$this->rootView->mkdir('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder . '/' . $this->folder);
$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($filename, '/' . $this->folder . '/' . $this->folder . '/' . $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/'
. $filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
$this->assertTrue($this->rootView->file_exists(
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/'
. $filename . '.key'));
$this->assertTrue($this->rootView->file_exists(
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/' . $this->folder . '/' . $this->folder . '/'
. $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 . '/'
. $filename . '.key'));
// cleanup
$this->rootView->unlink('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder);
$this->rootView->unlink('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $filename);
}
/**
* @brief replacing encryption keys during password change should be allowed
* until the user logged in for the first time
*/
public function testSetPassphrase() {
$view = new \OC\Files\View();
// set user password for the first time
\OCA\Encryption\Hooks::postCreateUser(array('uid' => 'newUser', 'password' => 'newUserPassword'));
$this->assertTrue($view->file_exists('public-keys/newUser.public.key'));
$this->assertTrue($view->file_exists('newUser/files_encryption/newUser.private.key'));
// check if we are able to decrypt the private key
$encryptedKey = \OCA\Encryption\Keymanager::getPrivateKey($view, 'newUser');
$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'));
$encryptedKey = \OCA\Encryption\Keymanager::getPrivateKey($view, 'newUser');
$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');
// change the password after the user logged in, now the password should not change
\OCA\Encryption\Hooks::setPassphrase(array('uid' => 'newUser', 'password' => 'passwordChanged2'));
$encryptedKey = \OCA\Encryption\Keymanager::getPrivateKey($view, 'newUser');
$privateKey = \OCA\Encryption\Crypt::decryptPrivateKey($encryptedKey, 'passwordChanged2');
$this->assertFalse($privateKey);
$privateKey = \OCA\Encryption\Crypt::decryptPrivateKey($encryptedKey, 'passwordChanged');
$this->assertTrue(is_string($privateKey));
}
}

View File

@@ -23,11 +23,11 @@ use OCA\Encryption;
*/
class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
const TEST_USER = "test-keymanager-user";
const TEST_USER = "test-keymanager-user.dot";
public $userId;
public $pass;
public $stateFilesTrashbin;
public static $stateFilesTrashbin;
/**
* @var OC_FilesystemView
*/
@@ -50,6 +50,12 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
// disable file proxy by default
\OC_FileProxy::$enabled = false;
// remember files_trashbin state
self::$stateFilesTrashbin = OC_App::isEnabled('files_trashbin');
// we don't want to tests with app files_trashbin enabled
\OC_App::disable('files_trashbin');
// create test user
\OC_User::deleteUser(\Test_Encryption_Keymanager::TEST_USER);
\Test_Encryption_Util::loginHelper(\Test_Encryption_Keymanager::TEST_USER, true);
@@ -70,28 +76,17 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
$this->view = new \OC_FilesystemView('/');
\OC_User::setUserId(\Test_Encryption_Keymanager::TEST_USER);
\Test_Encryption_Util::loginHelper(Test_Encryption_Keymanager::TEST_USER);
$this->userId = \Test_Encryption_Keymanager::TEST_USER;
$this->pass = \Test_Encryption_Keymanager::TEST_USER;
$userHome = \OC_User::getHome($this->userId);
$this->dataDir = str_replace('/' . $this->userId, '', $userHome);
// remember files_trashbin state
$this->stateFilesTrashbin = OC_App::isEnabled('files_trashbin');
// we don't want to tests with app files_trashbin enabled
\OC_App::disable('files_trashbin');
}
function tearDown() {
// reset app files_trashbin
if ($this->stateFilesTrashbin) {
OC_App::enable('files_trashbin');
}
else {
OC_App::disable('files_trashbin');
}
$this->view->deleteAll('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys');
$this->view->deleteAll('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/keyfiles');
}
public static function tearDownAfterClass() {
@@ -99,6 +94,10 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
// cleanup test user
\OC_User::deleteUser(\Test_Encryption_Keymanager::TEST_USER);
// reset app files_trashbin
if (self::$stateFilesTrashbin) {
OC_App::enable('files_trashbin');
}
}
/**
@@ -136,6 +135,27 @@ 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($fileName, $user, $expectedFileName) {
$this->assertEquals($expectedFileName,
\TestProtectedKeymanagerMethods::testGetFilenameFromShareKey($fileName, $user)
);
}
/**
* @medium
*/
@@ -143,7 +163,7 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
$key = $this->randomKey;
$file = 'unittest-' . time() . '.txt';
$file = 'unittest-' . uniqid() . '.txt';
$util = new Encryption\Util($this->view, $this->userId);
@@ -193,44 +213,256 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
/**
* @medium
*/
function testRecursiveDelShareKeys() {
function testRecursiveDelShareKeysFolder() {
// generate filename
$filename = '/tmp-' . time() . '.txt';
// create folder structure
$this->view->mkdir('/'.Test_Encryption_Keymanager::TEST_USER.'/files/folder1');
$this->view->mkdir('/'.Test_Encryption_Keymanager::TEST_USER.'/files/folder1/subfolder');
$this->view->mkdir('/'.Test_Encryption_Keymanager::TEST_USER.'/files/folder1/subfolder/subsubfolder');
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files/folder1/existingFile.txt', 'data');
// enable encryption proxy
$proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = true;
// create folder structure for some dummy share key files
$this->view->mkdir('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1');
$this->view->mkdir('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/subfolder');
$this->view->mkdir('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/subfolder/subsubfolder');
// save file with content
$cryptedFile = file_put_contents('crypt:///'.Test_Encryption_Keymanager::TEST_USER.'/files/folder1/subfolder/subsubfolder' . $filename, $this->dataShort);
// create some dummy share keys
$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');
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/subfolder/subsubfolder/file1.user1.shareKey', 'data');
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/subfolder/subsubfolder/file2.user2.shareKey', 'data');
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/subfolder/subsubfolder/file2.user3.shareKey', 'data');
// test that data was successfully written
$this->assertTrue(is_int($cryptedFile));
// recursive delete share keys from user1 and user2
Encryption\Keymanager::delShareKey($this->view, array('user1', 'user2', Test_Encryption_Keymanager::TEST_USER), '/folder1/');
// change encryption proxy to previous state
\OC_FileProxy::$enabled = $proxyStatus;
// recursive delete keys
Encryption\Keymanager::delShareKey($this->view, array('admin'), '/folder1/');
// check if share key not exists
// check if share keys from user1 and user2 are deleted
$this->assertFalse($this->view->file_exists(
'/admin/files_encryption/share-keys/folder1/subfolder/subsubfolder/' . $filename . '.admin.shareKey'));
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/existingFile.user1.shareKey'));
$this->assertFalse($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.user1.shareKey'));
$this->assertFalse($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file2.user2.shareKey'));
$this->assertFalse($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/subfolder/subsubfolder/file1.user1.shareKey'));
$this->assertFalse($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/subfolder/subsubfolder/file2.user2.shareKey'));
// enable encryption proxy
$proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = true;
// check if share keys from user3 still exists
$this->assertTrue($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file2.user3.shareKey'));
$this->assertTrue($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/subfolder/subsubfolder/file2.user3.shareKey'));
$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'));
// cleanup
$this->view->unlink('/admin/files/folder1');
$this->view->deleteAll('/'.Test_Encryption_Keymanager::TEST_USER.'/files/folder1');
}
/**
* @medium
*/
function testRecursiveDelShareKeysFile() {
$this->view->mkdir('/'.Test_Encryption_Keymanager::TEST_USER.'/files/folder1');
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files/folder1/existingFile.txt', 'data');
// create folder structure for some dummy share key files
$this->view->mkdir('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1');
// create some dummy share keys
$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.user2.shareKey', 'data');
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/existingFile.txt.user3.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');
// recursive delete share keys from user1 and user2
Encryption\Keymanager::delShareKey($this->view, array('user1', 'user2', Test_Encryption_Keymanager::TEST_USER), '/folder1/existingFile.txt');
// check if share keys from user1 and user2 are deleted
$this->assertFalse($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/existingFile.user1.shareKey'));
$this->assertFalse($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/existingFile.user2.shareKey'));
// check if share keys for user3 and owner
$this->assertTrue($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/existingFile.txt.' . Test_Encryption_Keymanager::TEST_USER . '.shareKey'));
$this->assertTrue($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/existingFile.txt.user3.shareKey'));
// cleanup
$this->view->deleteAll('/'.Test_Encryption_Keymanager::TEST_USER.'/files/folder1');
}
/**
* @medium
*/
function testDeleteFileKey() {
$this->view->mkdir('/'.Test_Encryption_Keymanager::TEST_USER.'/files/folder1');
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files/folder1/existingFile.txt', 'data');
// create folder structure for some dummy file key files
$this->view->mkdir('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/keyfiles/folder1');
// create dummy keyfile
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/keyfiles/folder1/dummyFile.txt.key', 'data');
// recursive delete share keys from user1 and user2
$result = Encryption\Keymanager::deleteFileKey($this->view, '/folder1/existingFile.txt');
$this->assertFalse($result);
$result2 = Encryption\Keymanager::deleteFileKey($this->view, '/folder1/dummyFile.txt');
$this->assertTrue($result2);
// check if file key from dummyFile was deleted
$this->assertFalse($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/keyfiles/folder1/dummyFile.txt.key'));
// check if file key from existing file still exists
$this->assertTrue($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/keyfiles/folder1/existingFile.txt.key'));
// cleanup
$this->view->deleteAll('/'.Test_Encryption_Keymanager::TEST_USER.'/files/folder1');
}
/**
* @medium
*/
function testDeleteFileKeyFolder() {
$this->view->mkdir('/'.Test_Encryption_Keymanager::TEST_USER.'/files/folder1');
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files/folder1/existingFile.txt', 'data');
// create folder structure for some dummy file key files
$this->view->mkdir('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/keyfiles/folder1');
// create dummy keyfile
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/keyfiles/folder1/dummyFile.txt.key', 'data');
// recursive delete share keys from user1 and user2
$result = Encryption\Keymanager::deleteFileKey($this->view, '/folder1');
$this->assertFalse($result);
// all file keys should still exists if we try to delete a folder with keys for which some files still exists
$this->assertTrue($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/keyfiles/folder1/dummyFile.txt.key'));
$this->assertTrue($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/keyfiles/folder1/existingFile.txt.key'));
// delete folder
$this->view->unlink('/'.Test_Encryption_Keymanager::TEST_USER.'/files/folder1');
// create dummy keyfile
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/keyfiles/folder1/dummyFile.txt.key', 'data');
// now file keys should be deleted since the folder no longer exists
$result = Encryption\Keymanager::deleteFileKey($this->view, '/folder1');
$this->assertTrue($result);
$this->assertFalse($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/keyfiles/folder1'));
// cleanup
$this->view->deleteAll('/'.Test_Encryption_Keymanager::TEST_USER.'/files/folder1');
}
function testDelAllShareKeysFile() {
$this->view->mkdir('/'.Test_Encryption_Keymanager::TEST_USER.'/files/folder1');
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files/folder1/existingFile.txt', 'data');
// create folder structure for some dummy share key files
$this->view->mkdir('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1');
// create some dummy share keys for the existing file
$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.user2.shareKey', 'data');
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/existingFile.txt.user3.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');
// create some dummy share keys for a non-existing file
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/nonexistingFile.txt.user1.shareKey', 'data');
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/nonexistingFile.txt.user2.shareKey', 'data');
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/nonexistingFile.txt.user3.shareKey', 'data');
$this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/nonexistingFile.txt.' . Test_Encryption_Keymanager::TEST_USER . '.shareKey', 'data');
// try to del all share keys from a existing file, should fail because the file still exists
$result = Encryption\Keymanager::delAllShareKeys($this->view, Test_Encryption_Keymanager::TEST_USER, 'folder1/existingFile.txt');
$this->assertFalse($result);
// check if share keys still exists
$this->assertTrue($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/existingFile.txt.' . Test_Encryption_Keymanager::TEST_USER . '.shareKey'));
$this->assertTrue($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/existingFile.txt.user1.shareKey'));
$this->assertTrue($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/existingFile.txt.user2.shareKey'));
$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 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'));
// 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->assertTrue($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/nonexistingFile.txt.user2.shareKey'));
$this->assertTrue($this->view->file_exists(
'/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/nonexistingFile.txt.user3.shareKey'));
// cleanup
$this->view->deleteAll('/'.Test_Encryption_Keymanager::TEST_USER.'/files/folder1');
// change encryption proxy to previous state
\OC_FileProxy::$enabled = $proxyStatus;
}
}
/**
* dummy class to access protected methods of \OCA\Encryption\Keymanager for testing
*/
class TestProtectedKeymanagerMethods extends \OCA\Encryption\Keymanager {
/**
* @param string $sharekey
*/
public static function testGetFilenameFromShareKey($sharekey, $user) {
return self::getFilenameFromShareKey($sharekey, $user);
}
}

View File

@@ -44,8 +44,10 @@ class Test_Encryption_Proxy extends \PHPUnit_Framework_TestCase {
/**
* @var \OC_FilesystemView
*/
public $view;
public $view; // view in /data/user/files
public $rootView; // view on /data/user
public $data;
public $filename;
public static function setUpBeforeClass() {
// reset backend
@@ -74,9 +76,12 @@ class Test_Encryption_Proxy extends \PHPUnit_Framework_TestCase {
// init filesystem view
$this->view = new \OC_FilesystemView('/'. \Test_Encryption_Proxy::TEST_ENCRYPTION_PROXY_USER1 . '/files');
$this->rootView = new \OC_FilesystemView('/'. \Test_Encryption_Proxy::TEST_ENCRYPTION_PROXY_USER1 );
// init short data
$this->data = 'hats';
$this->filename = 'enc_proxy_tests-' . uniqid() . '.txt';
}
public static function tearDownAfterClass() {
@@ -90,21 +95,41 @@ class Test_Encryption_Proxy extends \PHPUnit_Framework_TestCase {
*/
function testPostFileSize() {
// generate filename
$filename = 'tmp-' . time() . '.txt';
$this->view->file_put_contents($filename, $this->data);
$this->view->file_put_contents($this->filename, $this->data);
\OC_FileProxy::$enabled = false;
$unencryptedSize = $this->view->filesize($filename);
$unencryptedSize = $this->view->filesize($this->filename);
\OC_FileProxy::$enabled = true;
$encryptedSize = $this->view->filesize($filename);
$encryptedSize = $this->view->filesize($this->filename);
$this->assertTrue($encryptedSize !== $unencryptedSize);
// cleanup
$this->view->unlink($this->filename);
}
function testPostFileSizeWithDirectory() {
$this->view->file_put_contents($this->filename, $this->data);
\OC_FileProxy::$enabled = false;
// get root size, must match the file's unencrypted size
$unencryptedSize = $this->view->filesize('');
\OC_FileProxy::$enabled = true;
$encryptedSize = $this->view->filesize('');
$this->assertTrue($encryptedSize !== $unencryptedSize);
// cleanup
$this->view->unlink($this->filename);
}
}

View File

@@ -64,7 +64,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
\OC_Appconfig::setValue('core', 'shareapi_allow_resharing', 'yes');
// clear share hooks
\OC_Hook::clear('OCP\\Share');
\OC_Hook::clear();
\OC::registerShareHooks();
\OCP\Util::connectHook('OC_Filesystem', 'setup', '\OC\Files\Storage\Shared', 'setup');
@@ -127,6 +127,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
\OC_User::deleteUser(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4);
}
/**
* @medium
* @param bool $withTeardown
@@ -194,8 +195,9 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
// cleanup
$this->view->unlink(
'/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
$this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/');
$this->view->unlink($this->filename);
$this->view->chroot('/');
// check if share key not exists
$this->assertFalse($this->view->file_exists(
@@ -265,8 +267,9 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
// cleanup
$this->view->unlink(
'/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
$this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/');
$this->view->unlink($this->filename);
$this->view->chroot('/');
// check if share key not exists
$this->assertFalse($this->view->file_exists(
@@ -352,7 +355,9 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
// cleanup
$this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files' . $this->folder1);
$this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files');
$this->view->unlink($this->folder1);
$this->view->chroot('/');
// check if share key not exists
$this->assertFalse($this->view->file_exists(
@@ -482,9 +487,9 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
// cleanup
$this->view->unlink(
'/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files' . $this->folder1 . $this->subfolder
. $this->subsubfolder . '/' . $this->filename);
$this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files');
$this->view->unlink($this->folder1 . $this->subfolder . $this->subsubfolder . '/' . $this->filename);
$this->view->chroot('/');
// check if share key not exists
$this->assertFalse($this->view->file_exists(
@@ -494,6 +499,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);
@@ -559,7 +565,9 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->filename . '.' . $publicShareKeyId . '.shareKey'));
// cleanup
$this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
$this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/');
$this->view->unlink($this->filename);
$this->view->chroot('/');
// check if share key not exists
$this->assertFalse($this->view->file_exists(
@@ -636,7 +644,9 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4 . '.shareKey'));
// cleanup
$this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
$this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/');
$this->view->unlink($this->filename);
$this->view->chroot('/');
// check if share key not exists
$this->assertFalse($this->view->file_exists(
@@ -649,9 +659,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
* @large
*/
function testRecoveryFile() {
$this->markTestIncomplete(
'No idea what\'s wrong here, this works perfectly in real-world. removeRecoveryKeys(\'/\') L709 removes correctly the keys, but for some reasons afterwards also the top-level folder "share-keys" is gone...'
);
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
@@ -733,8 +741,10 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->filename . '.' . $recoveryKeyId . '.shareKey'));
// cleanup
$this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
$this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->folder1);
$this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/');
$this->view->unlink($this->filename);
$this->view->unlink($this->folder1);
$this->view->chroot('/');
// check if share key for recovery not exists
$this->assertFalse($this->view->file_exists(
@@ -754,13 +764,13 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
* @large
*/
function testRecoveryForUser() {
$this->markTestIncomplete(
'This test drives Jenkins crazy - "Cannot modify header information - headers already sent" - line 811'
);
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
\OCA\Encryption\Helper::adminEnableRecovery(null, 'test123');
$result = \OCA\Encryption\Helper::adminEnableRecovery(null, 'test123');
$this->assertTrue($result);
$recoveryKeyId = OC_Appconfig::getValue('files_encryption', 'recoveryKeyId');
// login as user2
@@ -771,6 +781,9 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
// enable recovery for admin
$this->assertTrue($util->setRecoveryForUser(1));
// add recovery keys for existing files (e.g. the auto-generated welcome.txt)
$util->addRecoveryKeys();
// create folder structure
$this->view->mkdir('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files' . $this->folder1);
$this->view->mkdir(
@@ -809,6 +822,10 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
// change password
\OC_User::setPassword(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, 'test', 'test123');
$params = array('uid' => \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2,
'password' => 'test',
'recoveryPassword' => 'test123');
\OCA\Encryption\Hooks::setPassphrase($params);
// login as user2
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, false, 'test');
@@ -823,8 +840,10 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
$this->assertEquals($this->dataShort, $retrievedCryptedFile2);
// cleanup
$this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files' . $this->folder1);
$this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files' . $this->filename);
$this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/');
$this->view->unlink($this->folder1);
$this->view->unlink($this->filename);
$this->view->chroot('/');
// check if share key for user and recovery exists
$this->assertFalse($this->view->file_exists(
@@ -842,11 +861,21 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->subfolder . $this->subsubfolder . '/'
. $this->filename . '.' . $recoveryKeyId . '.shareKey'));
// enable recovery for admin
// disable recovery for admin
$this->assertTrue($util->setRecoveryForUser(0));
\OCA\Encryption\Helper::adminDisableRecovery('test123');
$this->assertEquals(0, \OC_Appconfig::getValue('files_encryption', 'recoveryAdminEnabled'));
//clean up, reset passwords
\OC_User::setPassword(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, 'test123');
$params = array('uid' => \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2,
'password' => \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2,
'recoveryPassword' => 'test123');
\OCA\Encryption\Hooks::setPassphrase($params);
}
/**
@@ -889,8 +918,8 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
} catch (Exception $e) {
$this->assertEquals(0, strpos($e->getMessage(), "Following users are not set up for encryption"));
}
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
@@ -925,7 +954,177 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '.shareKey'));
// cleanup
$this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
$this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/');
$this->view->unlink($this->filename);
$this->view->chroot('/');
}
/**
* @brief test moving a shared file out of the Shared folder
*/
function testRename() {
// login as admin
\Test_Encryption_Util::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);
// test that data was successfully written
$this->assertTrue(is_int($cryptedFile));
// get the file info from previous created file
$fileInfo = $this->view->getFileInfo(
'/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
// check if we have a valid file info
$this->assertTrue(is_array($fileInfo));
// share the file
\OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, OCP\PERMISSION_ALL);
// check if share key for user2exists
$this->assertTrue($this->view->file_exists(
'/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
// login as user2
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
$this->assertTrue($this->view->file_exists('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/Shared/' . $this->filename));
// get file contents
$retrievedCryptedFile = $this->view->file_get_contents(
'/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/Shared/' . $this->filename);
// check if data is the same as we previously written
$this->assertEquals($this->dataShort, $retrievedCryptedFile);
// move the file out of the shared folder
$this->view->rename('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/Shared/' . $this->filename,
'/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->filename);
// check if we can read the moved file
$retrievedRenamedFile = $this->view->file_get_contents(
'/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->filename);
// check if data is the same as we previously written
$this->assertEquals($this->dataShort, $retrievedRenamedFile);
// the owners file should be deleted
$this->assertFalse($this->view->file_exists('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename));
// cleanup
$this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->filename);
}
/**
* test if additional share keys are added if we move a folder to a shared parent
* @medium
*/
function testMoveFolder() {
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
$view = new \OC\Files\View('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
$filename = '/tmp-' . uniqid();
$folder = '/folder' . uniqid();
\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);
$newFolder = '/newfolder/subfolder' . uniqid();
\OC\Files\Filesystem::mkdir('/newfolder');
// get the file info from previous created file
$fileInfo = \OC\Files\Filesystem::getFileInfo('/newfolder');
$this->assertTrue(is_array($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);
\OC\Files\Filesystem::rename($folder, $newFolder);
// Get file decrypted contents
$newDecrypt = \OC\Files\Filesystem::file_get_contents($newFolder . $filename);
$this->assertEquals($this->dataShort, $newDecrypt);
// 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 testMoveFileToFolder() {
$view = new \OC\Files\View('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
$filename = '/tmp-' . uniqid();
$folder = '/folder' . uniqid();
\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' . uniqid();
\OC\Files\Filesystem::mkdir($subFolder);
// get the file info from previous created file
$fileInfo = \OC\Files\Filesystem::getFileInfo($folder);
// 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
\OC\Files\Filesystem::rename($folder . $filename, $subFolder . $filename);
// 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);
}
}

View File

@@ -99,7 +99,7 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase {
}
function testStreamOptions() {
$filename = '/tmp-' . time();
$filename = '/tmp-' . uniqid();
$view = new \OC\Files\View('/' . $this->userId . '/files');
// Save short data as encrypted file using stream wrapper
@@ -122,7 +122,7 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase {
}
function testStreamSetBlocking() {
$filename = '/tmp-' . time();
$filename = '/tmp-' . uniqid();
$view = new \OC\Files\View('/' . $this->userId . '/files');
// Save short data as encrypted file using stream wrapper
@@ -136,6 +136,8 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase {
// set stream options
$this->assertTrue(stream_set_blocking($handle, 1));
fclose($handle);
// tear down
$view->unlink($filename);
}
@@ -144,7 +146,7 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase {
* @medium
*/
function testStreamSetTimeout() {
$filename = '/tmp-' . time();
$filename = '/tmp-' . uniqid();
$view = new \OC\Files\View('/' . $this->userId . '/files');
// Save short data as encrypted file using stream wrapper
@@ -158,12 +160,14 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase {
// set stream options
$this->assertFalse(stream_set_timeout($handle, 1));
fclose($handle);
// tear down
$view->unlink($filename);
}
function testStreamSetWriteBuffer() {
$filename = '/tmp-' . time();
$filename = '/tmp-' . uniqid();
$view = new \OC\Files\View('/' . $this->userId . '/files');
// Save short data as encrypted file using stream wrapper
@@ -177,7 +181,48 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase {
// set stream options
$this->assertEquals(0, stream_set_write_buffer($handle, 1024));
fclose($handle);
// tear down
$view->unlink($filename);
}
/**
* @medium
* @brief test if stream wrapper can read files outside from the data folder
*/
function testStreamFromLocalFile() {
$filename = '/' . $this->userId . '/files/' . 'tmp-' . time().'.txt';
$tmpFilename = "/tmp/" . time() . ".txt";
// write an encrypted file
$cryptedFile = $this->view->file_put_contents($filename, $this->dataShort);
// Test that data was successfully written
$this->assertTrue(is_int($cryptedFile));
// create a copy outside of the data folder in /tmp
$proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false;
$encryptedContent = $this->view->file_get_contents($filename);
\OC_FileProxy::$enabled = $proxyStatus;
file_put_contents($tmpFilename, $encryptedContent);
\OCA\Encryption\Helper::addTmpFileToMapper($tmpFilename, $filename);
// try to read the file from /tmp
$handle = fopen("crypt://".$tmpFilename, "r");
$contentFromTmpFile = stream_get_contents($handle);
// check if it was successful
$this->assertEquals($this->dataShort, $contentFromTmpFile);
// clean up
unlink($tmpFilename);
$this->view->unlink($filename);
}
}

View File

@@ -119,25 +119,34 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase {
function testDeleteFile() {
// generate filename
$filename = 'tmp-' . time() . '.txt';
$filename = 'tmp-' . uniqid() . '.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);
$cryptedFile2 = file_put_contents('crypt:///' .\Test_Encryption_Trashbin::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
. '.key'));
$this->assertTrue($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::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'));
$this->assertTrue($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/'
. $filename2 . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey'));
// delete file
// delete first file
\OC\FIles\Filesystem::unlink($filename);
// check if file not exists
@@ -154,6 +163,20 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase {
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/'
. $filename . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey'));
// check that second file still exists
$this->assertTrue($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files/' . $filename2));
// check that key for second file still exists
$this->assertTrue($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/keyfiles/' . $filename2
. '.key'));
// check that share key for second file still exists
$this->assertTrue($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/'
. $filename2 . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey'));
// get files
$trashFiles = $this->view->getDirectoryContent(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/files/');
@@ -179,41 +202,75 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase {
$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;
}
/**
* @medium
* @brief test restore file
*
* @depends testDeleteFile
* test restore file
*/
function testRestoreFile($filename) {
function testRestoreFile() {
// generate filename
$filename = 'tmp-' . uniqid() . '.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);
$cryptedFile2 = file_put_contents('crypt:///' .\Test_Encryption_Trashbin::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(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/files/');
$trashFileSuffix = null;
$trashFileSuffix2 = null;
// find created file with timestamp
foreach ($trashFiles as $file) {
if (strncmp($file['path'], $filename, strlen($filename))) {
$path_parts = pathinfo($file['name']);
$trashFileSuffix = $path_parts['extension'];
}
if (strncmp($file['path'], $filename2, strlen($filename2))) {
$path_parts = pathinfo($file['name']);
$trashFileSuffix2 = $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));
'/' . \Test_Encryption_Trashbin::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'));
. $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'));
. $filename . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey'));
// check that second file was NOT restored
$this->assertFalse($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files/' . $filename2));
// check if key for admin exists
$this->assertFalse($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/keyfiles/'
. $filename2 . '.key'));
// check if share key for admin exists
$this->assertFalse($this->view->file_exists(
'/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/'
. $filename2 . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey'));
}
/**
@@ -223,7 +280,7 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase {
function testPermanentDeleteFile() {
// generate filename
$filename = 'tmp-' . time() . '.txt';
$filename = 'tmp-' . uniqid() . '.txt';
// save file with content
$cryptedFile = file_put_contents('crypt:///' .$this->userId. '/files/' . $filename, $this->dataShort);
@@ -242,7 +299,7 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase {
. $filename . '.' . \Test_Encryption_Trashbin::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(

View File

@@ -22,6 +22,9 @@ use OCA\Encryption;
class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
const TEST_ENCRYPTION_UTIL_USER1 = "test-util-user1";
const TEST_ENCRYPTION_UTIL_USER2 = "test-util-user2";
const TEST_ENCRYPTION_UTIL_GROUP1 = "test-util-group1";
const TEST_ENCRYPTION_UTIL_GROUP2 = "test-util-group2";
const TEST_ENCRYPTION_UTIL_LEGACY_USER = "test-legacy-user";
public $userId;
@@ -50,20 +53,25 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
\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);
// create groups
\OC_Group::createGroup(self::TEST_ENCRYPTION_UTIL_GROUP1);
\OC_Group::createGroup(self::TEST_ENCRYPTION_UTIL_GROUP2);
// add user 1 to group1
\OC_Group::addToGroup(self::TEST_ENCRYPTION_UTIL_USER1, self::TEST_ENCRYPTION_UTIL_GROUP1);
}
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;
@@ -114,7 +122,20 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
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);
//cleanup groups
\OC_Group::deleteGroup(self::TEST_ENCRYPTION_UTIL_GROUP1);
\OC_Group::deleteGroup(self::TEST_ENCRYPTION_UTIL_GROUP2);
}
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());
}
/**
@@ -132,6 +153,41 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
}
/**
* @medium
* @brief test detection of encrypted files
*/
function testIsEncryptedPath() {
$util = new Encryption\Util($this->view, $this->userId);
self::loginHelper($this->userId);
$unencryptedFile = '/tmpUnencrypted-' . time() . '.txt';
$encryptedFile = '/tmpEncrypted-' . time() . '.txt';
// Disable encryption proxy to write a unencrypted file
$proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false;
$this->view->file_put_contents($this->userId . '/files/' . $unencryptedFile, $this->dataShort);
// Re-enable proxy - our work is done
\OC_FileProxy::$enabled = $proxyStatus;
// write a encrypted file
$this->view->file_put_contents($this->userId . '/files/' . $encryptedFile, $this->dataShort);
// test if both files are detected correctly
$this->assertFalse($util->isEncryptedPath($this->userId . '/files/' . $unencryptedFile));
$this->assertTrue($util->isEncryptedPath($this->userId . '/files/' . $encryptedFile));
// cleanup
$this->view->unlink($this->userId . '/files/' . $unencryptedFile, $this->dataShort);
$this->view->unlink($this->userId . '/files/' . $encryptedFile, $this->dataShort);
}
/**
* @medium
* @brief test setup of encryption directories
@@ -219,7 +275,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
\OC_User::setUserId(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1);
$filename = '/tmp-' . time() . '.test';
$filename = '/tmp-' . uniqid() . '.test';
// Disable encryption proxy to prevent recursive calls
$proxyStatus = \OC_FileProxy::$enabled;
@@ -247,7 +303,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
function testGetFileSize() {
\Test_Encryption_Util::loginHelper(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1);
$filename = 'tmp-' . time();
$filename = 'tmp-' . uniqid();
$externalFilename = '/' . $this->userId . '/files/' . $filename;
// Test for 0 byte files
@@ -283,7 +339,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
function testEncryptAll() {
$filename = "/encryptAll" . time() . ".txt";
$filename = "/encryptAll" . uniqid() . ".txt";
$util = new Encryption\Util($this->view, $this->userId);
// disable encryption to upload a unencrypted file
@@ -315,7 +371,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
function testDecryptAll() {
$filename = "/decryptAll" . time() . ".txt";
$filename = "/decryptAll" . uniqid() . ".txt";
$util = new Encryption\Util($this->view, $this->userId);
$this->view->file_put_contents($this->userId . '/files/' . $filename, $this->dataShort);
@@ -323,9 +379,12 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
$fileInfoEncrypted = $this->view->getFileInfo($this->userId . '/files/' . $filename);
$this->assertTrue(is_array($fileInfoEncrypted));
$this->assertEquals($fileInfoEncrypted['encrypted'], 1);
// encrypt all unencrypted files
$util->decryptAll('/' . $this->userId . '/' . 'files');
// decrypt all encrypted files
$result = $util->decryptAll('/' . $this->userId . '/' . 'files');
$this->assertTrue($result);
$fileInfoUnencrypted = $this->view->getFileInfo($this->userId . '/files/' . $filename);
@@ -334,11 +393,133 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
// check if mtime and etags unchanged
$this->assertEquals($fileInfoEncrypted['mtime'], $fileInfoUnencrypted['mtime']);
$this->assertEquals($fileInfoEncrypted['etag'], $fileInfoUnencrypted['etag']);
// file should no longer be encrypted
$this->assertEquals(0, $fileInfoUnencrypted['encrypted']);
$this->view->unlink($this->userId . '/files/' . $filename);
}
/**
* 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');
$this->view->mkdir($encPath . '/keyfiles/subfolder/');
$this->view->mkdir($encPath . '/share-keys/subfolder/');
$this->view->file_put_contents($encPath . '/keyfiles/subfolder/foo.key', 'key');
$this->view->file_put_contents($encPath . '/share-keys/subfolder/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 . '/keyfiles/subfolder/foo.key'));
$this->assertTrue($this->view->file_exists($backupPath . '/share-keys/subfolder/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";
$util = new Encryption\Util($this->view, $this->userId);
$this->view->file_put_contents($this->userId . '/files/' . $file1, $this->dataShort);
$this->view->file_put_contents($this->userId . '/files/' . $file2, $this->dataShort);
$fileInfoEncrypted1 = $this->view->getFileInfo($this->userId . '/files/' . $file1);
$fileInfoEncrypted2 = $this->view->getFileInfo($this->userId . '/files/' . $file2);
$this->assertTrue(is_array($fileInfoEncrypted1));
$this->assertTrue(is_array($fileInfoEncrypted2));
$this->assertEquals($fileInfoEncrypted1['encrypted'], 1);
$this->assertEquals($fileInfoEncrypted2['encrypted'], 1);
// rename keyfile for file1 so that the decryption for file1 fails
// Expected behaviour: decryptAll() returns false, file2 gets decrypted anyway
$this->view->rename($this->userId . '/files_encryption/keyfiles/' . $file1 . '.key',
$this->userId . '/files_encryption/keyfiles/' . $file1 . '.key.moved');
// decrypt all encrypted files
$result = $util->decryptAll('/' . $this->userId . '/' . 'files');
$this->assertFalse($result);
$fileInfoUnencrypted1 = $this->view->getFileInfo($this->userId . '/files/' . $file1);
$fileInfoUnencrypted2 = $this->view->getFileInfo($this->userId . '/files/' . $file2);
$this->assertTrue(is_array($fileInfoUnencrypted1));
$this->assertTrue(is_array($fileInfoUnencrypted2));
// file1 should be still encrypted; file2 should be decrypted
$this->assertEquals(1, $fileInfoUnencrypted1['encrypted']);
$this->assertEquals(0, $fileInfoUnencrypted2['encrypted']);
// keyfiles and share keys should still exist
$this->assertTrue($this->view->is_dir($this->userId . '/files_encryption/keyfiles/'));
$this->assertTrue($this->view->is_dir($this->userId . '/files_encryption/share-keys/'));
// rename the keyfile for file1 back
$this->view->rename($this->userId . '/files_encryption/keyfiles/' . $file1 . '.key.moved',
$this->userId . '/files_encryption/keyfiles/' . $file1 . '.key');
// try again to decrypt all encrypted files
$result = $util->decryptAll('/' . $this->userId . '/' . 'files');
$this->assertTrue($result);
$fileInfoUnencrypted1 = $this->view->getFileInfo($this->userId . '/files/' . $file1);
$fileInfoUnencrypted2 = $this->view->getFileInfo($this->userId . '/files/' . $file2);
$this->assertTrue(is_array($fileInfoUnencrypted1));
$this->assertTrue(is_array($fileInfoUnencrypted2));
// now both files should be decrypted
$this->assertEquals(0, $fileInfoUnencrypted1['encrypted']);
$this->assertEquals(0, $fileInfoUnencrypted2['encrypted']);
// keyfiles and share keys should be deleted
$this->assertFalse($this->view->is_dir($this->userId . '/files_encryption/keyfiles/'));
$this->assertFalse($this->view->is_dir($this->userId . '/files_encryption/share-keys/'));
$this->view->unlink($this->userId . '/files/' . $file1);
$this->view->unlink($this->userId . '/files/' . $file2);
}
/**
* @large
*/
@@ -392,7 +573,30 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
}
/**
* @param $user
* @dataProvider dataProviderFortestIsMountPointApplicableToUser
*/
function testIsMountPointApplicableToUser($mount, $expectedResult) {
self::loginHelper(self::TEST_ENCRYPTION_UTIL_USER1);
$dummyClass = new DummyUtilClass($this->view, self::TEST_ENCRYPTION_UTIL_USER1);
$result = $dummyClass->testIsMountPointApplicableToUser($mount);
$this->assertSame($expectedResult, $result);
}
function dataProviderFortestIsMountPointApplicableToUser() {
return array(
array(array('applicable' => array('groups' => array(), 'users' => array(self::TEST_ENCRYPTION_UTIL_USER1))), true),
array(array('applicable' => array('groups' => array(), 'users' => array(self::TEST_ENCRYPTION_UTIL_USER2))), false),
array(array('applicable' => array('groups' => array(self::TEST_ENCRYPTION_UTIL_GROUP1), 'users' => array())), true),
array(array('applicable' => array('groups' => array(self::TEST_ENCRYPTION_UTIL_GROUP1), 'users' => array(self::TEST_ENCRYPTION_UTIL_USER2))), true),
array(array('applicable' => array('groups' => array(self::TEST_ENCRYPTION_UTIL_GROUP2), 'users' => array(self::TEST_ENCRYPTION_UTIL_USER2))), false),
array(array('applicable' => array('groups' => array(self::TEST_ENCRYPTION_UTIL_GROUP2), 'users' => array(self::TEST_ENCRYPTION_UTIL_USER2, 'all'))), true),
array(array('applicable' => array('groups' => array(self::TEST_ENCRYPTION_UTIL_GROUP2), 'users' => array('all'))), true),
);
}
/**
* @param string $user
* @param bool $create
* @param bool $password
*/
@@ -416,6 +620,12 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
OCA\Encryption\Hooks::login($params);
}
public static function logoutHelper() {
\OC_Util::tearDownFS();
\OC_User::setUserId('');
\OC\Files\Filesystem::tearDown();
}
/**
* helper function to set migration status to the right value
* to be able to test the migration path
@@ -440,3 +650,12 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
}
}
/**
* dummy class extends \OCA\Encryption\Util to access protected methods for testing
*/
class DummyUtilClass extends \OCA\Encryption\Util {
public function testIsMountPointApplicableToUser($mount) {
return $this->isMountPointApplicableToUser($mount);
}
}

View File

@@ -48,6 +48,8 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase {
public $dataShort;
public $stateFilesTrashbin;
private $storage;
public static function setUpBeforeClass() {
// reset backend
\OC_User::clearBackends();
@@ -77,8 +79,8 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase {
$this->pass = \Test_Encryption_Webdav::TEST_ENCRYPTION_WEBDAV_USER1;
// init filesystem view
$this->view = new \OC_FilesystemView('/');
$this->view = new \OC\Files\View('/');
list($this->storage, $intPath) = $this->view->resolvePath('/');
// init short data
$this->dataShort = 'hats';
@@ -113,7 +115,7 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase {
function testWebdavPUT() {
// generate filename
$filename = '/tmp-' . time() . '.txt';
$filename = '/tmp-' . uniqid() . '.txt';
// set server vars
$_SERVER['REQUEST_METHOD'] = 'OPTIONS';
@@ -196,6 +198,9 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase {
$_SERVER['HTTP_AUTHORIZATION'] = 'Basic dGVzdC13ZWJkYXYtdXNlcjE6dGVzdC13ZWJkYXYtdXNlcjE=';
$_SERVER['PATH_INFO'] = '/webdav' . $filename;
// at the beginning the file should exist
$this->assertTrue($this->view->file_exists('/' . $this->userId . '/files' . $filename));
// handle webdav request
$content = $this->handleWebdavRequest();

View File

@@ -72,8 +72,16 @@ class Dropbox_OAuth_Curl extends Dropbox_OAuth {
if (strtoupper($method) == 'POST') {
curl_setopt($ch, CURLOPT_URL, $uri);
curl_setopt($ch, CURLOPT_POST, true);
// if (is_array($arguments))
// $arguments=http_build_query($arguments);
//if (is_array($arguments))
// $arguments=http_build_query($arguments);
if(is_array($arguments)) {
foreach ($arguments as $key => $value) {
if ($value[0] === '@') {
exit();
}
}
}
curl_setopt($ch, CURLOPT_POSTFIELDS, $arguments);
// $httpHeaders['Content-Length']=strlen($arguments);
} else {

View File

@@ -0,0 +1,2 @@
.idea

View File

@@ -0,0 +1,18 @@
Copyright 2014 Igor Vaynberg
Version: @@ver@@ Timestamp: @@timestamp@@
This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU
General Public License version 2 (the "GPL License"). You may choose either license to govern your
use of this software only upon the condition that you accept all of the terms of either the Apache
License or the GPL License.
You may obtain a copy of the Apache License and the GPL License at:
http://www.apache.org/licenses/LICENSE-2.0
http://www.gnu.org/licenses/gpl-2.0.html
Unless required by applicable law or agreed to in writing, software distributed under the Apache License
or the GPL Licesnse is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
either express or implied. See the Apache License and the GPL License for the specific language governing
permissions and limitations under the Apache License and the GPL License.

View File

@@ -0,0 +1,90 @@
Select2
=======
Select2 is a jQuery-based replacement for select boxes. It supports searching, remote data sets, and infinite scrolling of results.
To get started, checkout examples and documentation at http://ivaynberg.github.com/select2
Use cases
---------
* Enhancing native selects with search.
* Enhancing native selects with a better multi-select interface.
* Loading data from JavaScript: easily load items via ajax and have them searchable.
* Nesting optgroups: native selects only support one level of nested. Select2 does not have this restriction.
* Tagging: ability to add new items on the fly.
* Working with large, remote datasets: ability to partially load a dataset based on the search term.
* Paging of large datasets: easy support for loading more pages when the results are scrolled to the end.
* Templating: support for custom rendering of results and selections.
Browser compatibility
---------------------
* IE 8+
* Chrome 8+
* Firefox 10+
* Safari 3+
* Opera 10.6+
Usage
-----
You can source Select2 directly from a [CDN like JSDliver](http://www.jsdelivr.com/#!select2), [download it from this GitHub repo](https://github.com/ivaynberg/select2/tags), or use one of the integrations below.
Integrations
------------
* [Wicket-Select2](https://github.com/ivaynberg/wicket-select2) (Java / [Apache Wicket](http://wicket.apache.org))
* [select2-rails](https://github.com/argerim/select2-rails) (Ruby on Rails)
* [AngularUI](http://angular-ui.github.com/#directives-select2) ([AngularJS](angularjs.org))
* [Django](https://github.com/applegrew/django-select2)
* [Symfony](https://github.com/19Gerhard85/sfSelect2WidgetsPlugin)
* [Symfony2](https://github.com/avocode/FormExtensions)
* [Bootstrap 2](https://github.com/t0m/select2-bootstrap-css) and [Bootstrap 3](https://github.com/t0m/select2-bootstrap-css/tree/bootstrap3) (CSS skins)
* [Meteor](https://github.com/nate-strauser/meteor-select2) (modern reactive JavaScript framework; + [Bootstrap 3 skin](https://github.com/esperadomedia/meteor-select2-bootstrap3-css/))
* [Yii 2.x](http://demos.krajee.com/widgets#select2)
* [Yii 1.x](https://github.com/tonybolzan/yii-select2)
Internationalization (i18n)
---------------------------
Select2 supports multiple languages by simply including the right
language JS file (`select2_locale_it.js`, `select2_locale_nl.js`, etc.).
Missing a language? Just copy `select2_locale_en.js.template`, translate
it, and make a pull request back to Select2 here on GitHub.
Bug tracker
-----------
Have a bug? Please create an issue here on GitHub!
https://github.com/ivaynberg/select2/issues
Mailing list
------------
Have a question? Ask on our mailing list!
select2@googlegroups.com
https://groups.google.com/d/forum/select2
Copyright and license
---------------------
Copyright 2012 Igor Vaynberg
This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU
General Public License version 2 (the "GPL License"). You may choose either license to govern your
use of this software only upon the condition that you accept all of the terms of either the Apache
License or the GPL License.
You may obtain a copy of the Apache License and the GPL License in the LICENSE file, or at:
http://www.apache.org/licenses/LICENSE-2.0
http://www.gnu.org/licenses/gpl-2.0.html
Unless required by applicable law or agreed to in writing, software distributed under the Apache License
or the GPL License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
either express or implied. See the Apache License and the GPL License for the specific language governing
permissions and limitations under the Apache License and the GPL License.

View File

@@ -0,0 +1,8 @@
{
"name": "select2",
"version": "3.4.8",
"main": ["select2.js", "select2.css", "select2.png", "select2x2.png", "select2-spinner.gif"],
"dependencies": {
"jquery": ">= 1.7.1"
}
}

View File

@@ -0,0 +1,66 @@
{
"name": "select2",
"repo": "ivaynberg/select2",
"description": "Select2 is a jQuery based replacement for select boxes. It supports searching, remote data sets, and infinite scrolling of results.",
"version": "3.4.8",
"demo": "http://ivaynberg.github.io/select2/",
"keywords": [
"jquery"
],
"main": "select2.js",
"styles": [
"select2.css",
"select2-bootstrap.css"
],
"scripts": [
"select2.js",
"select2_locale_ar.js",
"select2_locale_bg.js",
"select2_locale_ca.js",
"select2_locale_cs.js",
"select2_locale_da.js",
"select2_locale_de.js",
"select2_locale_el.js",
"select2_locale_es.js",
"select2_locale_et.js",
"select2_locale_eu.js",
"select2_locale_fa.js",
"select2_locale_fi.js",
"select2_locale_fr.js",
"select2_locale_gl.js",
"select2_locale_he.js",
"select2_locale_hr.js",
"select2_locale_hu.js",
"select2_locale_id.js",
"select2_locale_is.js",
"select2_locale_it.js",
"select2_locale_ja.js",
"select2_locale_ka.js",
"select2_locale_ko.js",
"select2_locale_lt.js",
"select2_locale_lv.js",
"select2_locale_mk.js",
"select2_locale_ms.js",
"select2_locale_nl.js",
"select2_locale_no.js",
"select2_locale_pl.js",
"select2_locale_pt-BR.js",
"select2_locale_pt-PT.js",
"select2_locale_ro.js",
"select2_locale_ru.js",
"select2_locale_sk.js",
"select2_locale_sv.js",
"select2_locale_th.js",
"select2_locale_tr.js",
"select2_locale_uk.js",
"select2_locale_vi.js",
"select2_locale_zh-CN.js",
"select2_locale_zh-TW.js"
],
"images": [
"select2-spinner.gif",
"select2.png",
"select2x2.png"
],
"license": "MIT"
}

View File

@@ -0,0 +1,29 @@
{
"name":
"ivaynberg/select2",
"description": "Select2 is a jQuery based replacement for select boxes.",
"version": "3.4.8",
"type": "component",
"homepage": "http://ivaynberg.github.io/select2/",
"license": "Apache-2.0",
"require": {
"robloach/component-installer": "*",
"components/jquery": ">=1.7.1"
},
"extra": {
"component": {
"scripts": [
"select2.js"
],
"files": [
"select2.js",
"select2_locale_*.js",
"select2.css",
"select2-bootstrap.css",
"select2-spinner.gif",
"select2.png",
"select2x2.png"
]
}
}
}

View File

@@ -0,0 +1,20 @@
{
"name" : "Select2",
"description": "Select2 is a jQuery based replacement for select boxes. It supports searching, remote data sets, and infinite scrolling of results.",
"homepage": "http://ivaynberg.github.io/select2",
"author": "Igor Vaynberg",
"repository": {"type": "git", "url": "git://github.com/ivaynberg/select2.git"},
"main": "select2.js",
"version": "3.4.8",
"jspm": {
"main": "select2",
"files": ["select2.js", "select2.png", "select2.css", "select2-spinner.gif"],
"shim": {
"select2": {
"imports": ["jquery", "./select2.css!"],
"exports": "$"
}
},
"buildConfig": { "uglify": true }
}
}

View File

@@ -0,0 +1,79 @@
#!/bin/bash
set -e
echo -n "Enter the version for this release: "
read ver
if [ ! $ver ]; then
echo "Invalid version."
exit
fi
name="select2"
js="$name.js"
mini="$name.min.js"
css="$name.css"
release="$name-$ver"
tag="$ver"
branch="build-$ver"
curbranch=`git branch | grep "*" | sed "s/* //"`
timestamp=$(date)
tokens="s/@@ver@@/$ver/g;s/\@@timestamp@@/$timestamp/g"
remote="github"
echo "Pulling from origin"
git pull
echo "Updating Version Identifiers"
sed -E -e "s/\"version\": \"([0-9\.]+)\",/\"version\": \"$ver\",/g" -i -- bower.json select2.jquery.json component.json composer.json package.json
git add bower.json
git add select2.jquery.json
git add component.json
git add composer.json
git add package.json
git commit -m "modified version identifiers in descriptors for release $ver"
git push
git branch "$branch"
git checkout "$branch"
echo "Tokenizing..."
find . -name "$js" | xargs -I{} sed -e "$tokens" -i -- {}
find . -name "$css" | xargs -I{} sed -e "$tokens" -i -- {}
sed -e "s/latest/$ver/g" -i -- bower.json
git add "$js"
git add "$css"
echo "Minifying..."
echo "/*" > "$mini"
cat LICENSE | sed "$tokens" >> "$mini"
echo "*/" >> "$mini"
curl -s \
--data-urlencode "js_code@$js" \
http://marijnhaverbeke.nl/uglifyjs \
>> "$mini"
git add "$mini"
git commit -m "release $ver"
echo "Tagging..."
git tag -a "$tag" -m "tagged version $ver"
git push "$remote" --tags
echo "Cleaning Up..."
git checkout "$curbranch"
git branch -D "$branch"
echo "Done"

View File

@@ -0,0 +1,87 @@
.form-control .select2-choice {
border: 0;
border-radius: 2px;
}
.form-control .select2-choice .select2-arrow {
border-radius: 0 2px 2px 0;
}
.form-control.select2-container {
height: auto !important;
padding: 0;
}
.form-control.select2-container.select2-dropdown-open {
border-color: #5897FB;
border-radius: 3px 3px 0 0;
}
.form-control .select2-container.select2-dropdown-open .select2-choices {
border-radius: 3px 3px 0 0;
}
.form-control.select2-container .select2-choices {
border: 0 !important;
border-radius: 3px;
}
.control-group.warning .select2-container .select2-choice,
.control-group.warning .select2-container .select2-choices,
.control-group.warning .select2-container-active .select2-choice,
.control-group.warning .select2-container-active .select2-choices,
.control-group.warning .select2-dropdown-open.select2-drop-above .select2-choice,
.control-group.warning .select2-dropdown-open.select2-drop-above .select2-choices,
.control-group.warning .select2-container-multi.select2-container-active .select2-choices {
border: 1px solid #C09853 !important;
}
.control-group.warning .select2-container .select2-choice div {
border-left: 1px solid #C09853 !important;
background: #FCF8E3 !important;
}
.control-group.error .select2-container .select2-choice,
.control-group.error .select2-container .select2-choices,
.control-group.error .select2-container-active .select2-choice,
.control-group.error .select2-container-active .select2-choices,
.control-group.error .select2-dropdown-open.select2-drop-above .select2-choice,
.control-group.error .select2-dropdown-open.select2-drop-above .select2-choices,
.control-group.error .select2-container-multi.select2-container-active .select2-choices {
border: 1px solid #B94A48 !important;
}
.control-group.error .select2-container .select2-choice div {
border-left: 1px solid #B94A48 !important;
background: #F2DEDE !important;
}
.control-group.info .select2-container .select2-choice,
.control-group.info .select2-container .select2-choices,
.control-group.info .select2-container-active .select2-choice,
.control-group.info .select2-container-active .select2-choices,
.control-group.info .select2-dropdown-open.select2-drop-above .select2-choice,
.control-group.info .select2-dropdown-open.select2-drop-above .select2-choices,
.control-group.info .select2-container-multi.select2-container-active .select2-choices {
border: 1px solid #3A87AD !important;
}
.control-group.info .select2-container .select2-choice div {
border-left: 1px solid #3A87AD !important;
background: #D9EDF7 !important;
}
.control-group.success .select2-container .select2-choice,
.control-group.success .select2-container .select2-choices,
.control-group.success .select2-container-active .select2-choice,
.control-group.success .select2-container-active .select2-choices,
.control-group.success .select2-dropdown-open.select2-drop-above .select2-choice,
.control-group.success .select2-dropdown-open.select2-drop-above .select2-choices,
.control-group.success .select2-container-multi.select2-container-active .select2-choices {
border: 1px solid #468847 !important;
}
.control-group.success .select2-container .select2-choice div {
border-left: 1px solid #468847 !important;
background: #DFF0D8 !important;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1,646 @@
/*
Version: 3.4.8 Timestamp: Thu May 1 09:50:32 EDT 2014
*/
.select2-container {
margin: 0;
position: relative;
display: inline-block;
/* inline-block for ie7 */
zoom: 1;
*display: inline;
vertical-align: middle;
}
.select2-container,
.select2-drop,
.select2-search,
.select2-search input {
/*
Force border-box so that % widths fit the parent
container without overlap because of margin/padding.
More Info : http://www.quirksmode.org/css/box.html
*/
-webkit-box-sizing: border-box; /* webkit */
-moz-box-sizing: border-box; /* firefox */
box-sizing: border-box; /* css3 */
}
.select2-container .select2-choice {
display: block;
height: 26px;
padding: 0 0 0 8px;
overflow: hidden;
position: relative;
border: 1px solid #aaa;
white-space: nowrap;
line-height: 26px;
color: #444;
text-decoration: none;
border-radius: 4px;
background-clip: padding-box;
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-color: #fff;
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(0.5, #fff));
background-image: -webkit-linear-gradient(center bottom, #eee 0%, #fff 50%);
background-image: -moz-linear-gradient(center bottom, #eee 0%, #fff 50%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#ffffff', endColorstr = '#eeeeee', GradientType = 0);
background-image: linear-gradient(to top, #eee 0%, #fff 50%);
}
.select2-container.select2-drop-above .select2-choice {
border-bottom-color: #aaa;
border-radius: 0 0 4px 4px;
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(0.9, #fff));
background-image: -webkit-linear-gradient(center bottom, #eee 0%, #fff 90%);
background-image: -moz-linear-gradient(center bottom, #eee 0%, #fff 90%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);
background-image: linear-gradient(to bottom, #eee 0%, #fff 90%);
}
.select2-container.select2-allowclear .select2-choice .select2-chosen {
margin-right: 42px;
}
.select2-container .select2-choice > .select2-chosen {
margin-right: 26px;
display: block;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
float: none;
width: auto;
}
.select2-container .select2-choice abbr {
display: none;
width: 12px;
height: 12px;
position: absolute;
right: 24px;
top: 8px;
font-size: 1px;
text-decoration: none;
border: 0;
background: url('select2.png') right top no-repeat;
cursor: pointer;
outline: 0;
}
.select2-container.select2-allowclear .select2-choice abbr {
display: inline-block;
}
.select2-container .select2-choice abbr:hover {
background-position: right -11px;
cursor: pointer;
}
.select2-drop-mask {
border: 0;
margin: 0;
padding: 0;
position: fixed;
left: 0;
top: 0;
min-height: 100%;
min-width: 100%;
height: auto;
width: auto;
opacity: 0;
z-index: 9998;
/* styles required for IE to work */
background-color: #fff;
filter: alpha(opacity=0);
}
.select2-drop {
width: 100%;
margin-top: -1px;
position: absolute;
z-index: 9999;
top: 100%;
background: #fff;
color: #000;
border: 1px solid #aaa;
border-top: 0;
border-radius: 0 0 4px 4px;
-webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
}
.select2-drop.select2-drop-above {
margin-top: 1px;
border-top: 1px solid #aaa;
border-bottom: 0;
border-radius: 4px 4px 0 0;
-webkit-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
}
.select2-drop-active {
border: 1px solid #5897fb;
border-top: none;
}
.select2-drop.select2-drop-above.select2-drop-active {
border-top: 1px solid #5897fb;
}
.select2-drop-auto-width {
border-top: 1px solid #aaa;
width: auto;
}
.select2-drop-auto-width .select2-search {
padding-top: 4px;
}
.select2-container .select2-choice .select2-arrow {
display: inline-block;
width: 18px;
height: 100%;
position: absolute;
right: 0;
top: 0;
border-left: 1px solid #aaa;
border-radius: 0 4px 4px 0;
background-clip: padding-box;
background: #ccc;
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #ccc), color-stop(0.6, #eee));
background-image: -webkit-linear-gradient(center bottom, #ccc 0%, #eee 60%);
background-image: -moz-linear-gradient(center bottom, #ccc 0%, #eee 60%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#eeeeee', endColorstr = '#cccccc', GradientType = 0);
background-image: linear-gradient(to top, #ccc 0%, #eee 60%);
}
.select2-container .select2-choice .select2-arrow b {
display: block;
width: 100%;
height: 100%;
background: url('select2.png') no-repeat 0 1px;
}
.select2-search {
display: inline-block;
width: 100%;
min-height: 26px;
margin: 0;
padding-left: 4px;
padding-right: 4px;
position: relative;
z-index: 10000;
white-space: nowrap;
}
.select2-search input {
width: 100%;
height: auto !important;
min-height: 26px;
padding: 4px 20px 4px 5px;
margin: 0;
outline: 0;
font-family: sans-serif;
font-size: 1em;
border: 1px solid #aaa;
border-radius: 0;
-webkit-box-shadow: none;
box-shadow: none;
background: #fff url('select2.png') no-repeat 100% -22px;
background: url('select2.png') no-repeat 100% -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee));
background: url('select2.png') no-repeat 100% -22px, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%);
background: url('select2.png') no-repeat 100% -22px, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%);
background: url('select2.png') no-repeat 100% -22px, linear-gradient(to bottom, #fff 85%, #eee 99%) 0 0;
}
.select2-drop.select2-drop-above .select2-search input {
margin-top: 4px;
}
.select2-search input.select2-active {
background: #fff url('select2-spinner.gif') no-repeat 100%;
background: url('select2-spinner.gif') no-repeat 100%, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee));
background: url('select2-spinner.gif') no-repeat 100%, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%);
background: url('select2-spinner.gif') no-repeat 100%, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%);
background: url('select2-spinner.gif') no-repeat 100%, linear-gradient(to bottom, #fff 85%, #eee 99%) 0 0;
}
.select2-container-active .select2-choice,
.select2-container-active .select2-choices {
border: 1px solid #5897fb;
outline: none;
-webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .3);
box-shadow: 0 0 5px rgba(0, 0, 0, .3);
}
.select2-dropdown-open .select2-choice {
border-bottom-color: transparent;
-webkit-box-shadow: 0 1px 0 #fff inset;
box-shadow: 0 1px 0 #fff inset;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
background-color: #eee;
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #fff), color-stop(0.5, #eee));
background-image: -webkit-linear-gradient(center bottom, #fff 0%, #eee 50%);
background-image: -moz-linear-gradient(center bottom, #fff 0%, #eee 50%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0);
background-image: linear-gradient(to top, #fff 0%, #eee 50%);
}
.select2-dropdown-open.select2-drop-above .select2-choice,
.select2-dropdown-open.select2-drop-above .select2-choices {
border: 1px solid #5897fb;
border-top-color: transparent;
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #fff), color-stop(0.5, #eee));
background-image: -webkit-linear-gradient(center top, #fff 0%, #eee 50%);
background-image: -moz-linear-gradient(center top, #fff 0%, #eee 50%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0);
background-image: linear-gradient(to bottom, #fff 0%, #eee 50%);
}
.select2-dropdown-open .select2-choice .select2-arrow {
background: transparent;
border-left: none;
filter: none;
}
.select2-dropdown-open .select2-choice .select2-arrow b {
background-position: -18px 1px;
}
.select2-hidden-accessible {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
/* results */
.select2-results {
max-height: 200px;
padding: 0 0 0 4px;
margin: 4px 4px 4px 0;
position: relative;
overflow-x: hidden;
overflow-y: auto;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
.select2-results ul.select2-result-sub {
margin: 0;
padding-left: 0;
}
.select2-results li {
list-style: none;
display: list-item;
background-image: none;
}
.select2-results li.select2-result-with-children > .select2-result-label {
font-weight: bold;
}
.select2-results .select2-result-label {
padding: 3px 7px 4px;
margin: 0;
cursor: pointer;
min-height: 1em;
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.select2-results-dept-1 .select2-result-label { padding-left: 20px }
.select2-results-dept-2 .select2-result-label { padding-left: 40px }
.select2-results-dept-3 .select2-result-label { padding-left: 60px }
.select2-results-dept-4 .select2-result-label { padding-left: 80px }
.select2-results-dept-5 .select2-result-label { padding-left: 100px }
.select2-results-dept-6 .select2-result-label { padding-left: 110px }
.select2-results-dept-7 .select2-result-label { padding-left: 120px }
.select2-results .select2-highlighted {
background: #3875d7;
color: #fff;
}
.select2-results li em {
background: #feffde;
font-style: normal;
}
.select2-results .select2-highlighted em {
background: transparent;
}
.select2-results .select2-highlighted ul {
background: #fff;
color: #000;
}
.select2-results .select2-no-results,
.select2-results .select2-searching,
.select2-results .select2-selection-limit {
background: #f4f4f4;
display: list-item;
padding-left: 5px;
}
/*
disabled look for disabled choices in the results dropdown
*/
.select2-results .select2-disabled.select2-highlighted {
color: #666;
background: #f4f4f4;
display: list-item;
cursor: default;
}
.select2-results .select2-disabled {
background: #f4f4f4;
display: list-item;
cursor: default;
}
.select2-results .select2-selected {
display: none;
}
.select2-more-results.select2-active {
background: #f4f4f4 url('select2-spinner.gif') no-repeat 100%;
}
.select2-more-results {
background: #f4f4f4;
display: list-item;
}
/* disabled styles */
.select2-container.select2-container-disabled .select2-choice {
background-color: #f4f4f4;
background-image: none;
border: 1px solid #ddd;
cursor: default;
}
.select2-container.select2-container-disabled .select2-choice .select2-arrow {
background-color: #f4f4f4;
background-image: none;
border-left: 0;
}
.select2-container.select2-container-disabled .select2-choice abbr {
display: none;
}
/* multiselect */
.select2-container-multi .select2-choices {
height: auto !important;
height: 1%;
margin: 0;
padding: 0;
position: relative;
border: 1px solid #aaa;
cursor: text;
overflow: hidden;
background-color: #fff;
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(1%, #eee), color-stop(15%, #fff));
background-image: -webkit-linear-gradient(top, #eee 1%, #fff 15%);
background-image: -moz-linear-gradient(top, #eee 1%, #fff 15%);
background-image: linear-gradient(to bottom, #eee 1%, #fff 15%);
}
.select2-locked {
padding: 3px 5px 3px 5px !important;
}
.select2-container-multi .select2-choices {
min-height: 26px;
}
.select2-container-multi.select2-container-active .select2-choices {
border: 1px solid #5897fb;
outline: none;
-webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .3);
box-shadow: 0 0 5px rgba(0, 0, 0, .3);
}
.select2-container-multi .select2-choices li {
float: left;
list-style: none;
}
html[dir="rtl"] .select2-container-multi .select2-choices li
{
float: right;
}
.select2-container-multi .select2-choices .select2-search-field {
margin: 0;
padding: 0;
white-space: nowrap;
}
.select2-container-multi .select2-choices .select2-search-field input {
padding: 5px;
margin: 1px 0;
font-family: sans-serif;
font-size: 100%;
color: #666;
outline: 0;
border: 0;
-webkit-box-shadow: none;
box-shadow: none;
background: transparent !important;
}
.select2-container-multi .select2-choices .select2-search-field input.select2-active {
background: #fff url('select2-spinner.gif') no-repeat 100% !important;
}
.select2-default {
color: #999 !important;
}
.select2-container-multi .select2-choices .select2-search-choice {
padding: 3px 5px 3px 18px;
margin: 3px 0 3px 5px;
position: relative;
line-height: 13px;
color: #333;
cursor: default;
border: 1px solid #aaaaaa;
border-radius: 3px;
-webkit-box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, 0.05);
box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, 0.05);
background-clip: padding-box;
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-color: #e4e4e4;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#f4f4f4', GradientType=0);
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eee));
background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
background-image: linear-gradient(to top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
}
html[dir="rtl"] .select2-container-multi .select2-choices .select2-search-choice
{
margin-left: 0;
margin-right: 5px;
}
.select2-container-multi .select2-choices .select2-search-choice .select2-chosen {
cursor: default;
}
.select2-container-multi .select2-choices .select2-search-choice-focus {
background: #d4d4d4;
}
.select2-search-choice-close {
display: block;
width: 12px;
height: 13px;
position: absolute;
right: 3px;
top: 4px;
font-size: 1px;
outline: none;
background: url('select2.png') right top no-repeat;
}
html[dir="rtl"] .select2-search-choice-close {
right: auto;
left: 3px;
}
.select2-container-multi .select2-search-choice-close {
left: 3px;
}
.select2-container-multi .select2-choices .select2-search-choice .select2-search-choice-close:hover {
background-position: right -11px;
}
.select2-container-multi .select2-choices .select2-search-choice-focus .select2-search-choice-close {
background-position: right -11px;
}
/* disabled styles */
.select2-container-multi.select2-container-disabled .select2-choices {
background-color: #f4f4f4;
background-image: none;
border: 1px solid #ddd;
cursor: default;
}
.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice {
padding: 3px 5px 3px 5px;
border: 1px solid #ddd;
background-image: none;
background-color: #f4f4f4;
}
.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice .select2-search-choice-close { display: none;
background: none;
}
/* end multiselect */
.select2-result-selectable .select2-match,
.select2-result-unselectable .select2-match {
text-decoration: underline;
}
.select2-offscreen, .select2-offscreen:focus {
clip: rect(0 0 0 0) !important;
width: 1px !important;
height: 1px !important;
border: 0 !important;
margin: 0 !important;
padding: 0 !important;
overflow: hidden !important;
position: absolute !important;
outline: 0 !important;
left: 0px !important;
top: 0px !important;
}
.select2-display-none {
display: none;
}
.select2-measure-scrollbar {
position: absolute;
top: -10000px;
left: -10000px;
width: 100px;
height: 100px;
overflow: scroll;
}
/* Retina-ize icons */
@media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 2dppx) {
.select2-search input,
.select2-search-choice-close,
.select2-container .select2-choice abbr,
.select2-container .select2-choice .select2-arrow b {
background-image: url('select2x2.png') !important;
background-repeat: no-repeat !important;
background-size: 60px 40px !important;
}
.select2-search input {
background-position: 100% -21px !important;
}
}

View File

@@ -0,0 +1,36 @@
{
"name": "select2",
"title": "Select2",
"description": "Select2 is a jQuery based replacement for select boxes. It supports searching, remote data sets, and infinite scrolling of results.",
"keywords": [
"select",
"autocomplete",
"typeahead",
"dropdown",
"multiselect",
"tag",
"tagging"
],
"version": "3.4.8",
"author": {
"name": "Igor Vaynberg",
"url": "https://github.com/ivaynberg"
},
"licenses": [
{
"type": "Apache",
"url": "http://www.apache.org/licenses/LICENSE-2.0"
},
{
"type": "GPL v2",
"url": "http://www.gnu.org/licenses/gpl-2.0.html"
}
],
"bugs": "https://github.com/ivaynberg/select2/issues",
"homepage": "http://ivaynberg.github.com/select2",
"docs": "http://ivaynberg.github.com/select2/",
"download": "https://github.com/ivaynberg/select2/tags",
"dependencies": {
"jquery": ">=1.7.1"
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 613 B

View File

@@ -0,0 +1,17 @@
/**
* Select2 Arabic translation.
*
* Author: Adel KEDJOUR <adel@kedjour.com>
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "لم يتم العثور على مطابقات"; },
formatInputTooShort: function (input, min) { var n = min - input.length; if (n == 1){ return "الرجاء إدخال حرف واحد على الأكثر"; } return n == 2 ? "الرجاء إدخال حرفين على الأكثر" : "الرجاء إدخال " + n + " على الأكثر"; },
formatInputTooLong: function (input, max) { var n = input.length - max; if (n == 1){ return "الرجاء إدخال حرف واحد على الأقل"; } return n == 2 ? "الرجاء إدخال حرفين على الأقل" : "الرجاء إدخال " + n + " على الأقل "; },
formatSelectionTooBig: function (limit) { if (n == 1){ return "يمكنك أن تختار إختيار واحد فقط"; } return n == 2 ? "يمكنك أن تختار إختيارين فقط" : "يمكنك أن تختار " + n + " إختيارات فقط"; },
formatLoadMore: function (pageNumber) { return "تحميل المزيد من النتائج…"; },
formatSearching: function () { return "البحث…"; }
});
})(jQuery);

View File

@@ -0,0 +1,18 @@
/**
* Select2 Bulgarian translation.
*
* @author Lubomir Vikev <lubomirvikev@gmail.com>
* @author Uriy Efremochkin <efremochkin@uriy.me>
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "Няма намерени съвпадения"; },
formatInputTooShort: function (input, min) { var n = min - input.length; return "Моля въведете още " + n + " символ" + (n > 1 ? "а" : ""); },
formatInputTooLong: function (input, max) { var n = input.length - max; return "Моля въведете с " + n + " по-малко символ" + (n > 1 ? "а" : ""); },
formatSelectionTooBig: function (limit) { return "Можете да направите до " + limit + (limit > 1 ? " избора" : " избор"); },
formatLoadMore: function (pageNumber) { return "Зареждат се още…"; },
formatSearching: function () { return "Търсене…"; }
});
})(jQuery);

View File

@@ -0,0 +1,17 @@
/**
* Select2 Catalan translation.
*
* Author: David Planella <david.planella@gmail.com>
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "No s'ha trobat cap coincidència"; },
formatInputTooShort: function (input, min) { var n = min - input.length; return "Introduïu " + n + " caràcter" + (n == 1 ? "" : "s") + " més"; },
formatInputTooLong: function (input, max) { var n = input.length - max; return "Introduïu " + n + " caràcter" + (n == 1? "" : "s") + "menys"; },
formatSelectionTooBig: function (limit) { return "Només podeu seleccionar " + limit + " element" + (limit == 1 ? "" : "s"); },
formatLoadMore: function (pageNumber) { return "S'estan carregant més resultats…"; },
formatSearching: function () { return "S'està cercant…"; }
});
})(jQuery);

View File

@@ -0,0 +1,49 @@
/**
* Select2 Czech translation.
*
* Author: Michal Marek <ahoj@michal-marek.cz>
* Author - sklonovani: David Vallner <david@vallner.net>
*/
(function ($) {
"use strict";
// use text for the numbers 2 through 4
var smallNumbers = {
2: function(masc) { return (masc ? "dva" : "dvě"); },
3: function() { return "tři"; },
4: function() { return "čtyři"; }
}
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "Nenalezeny žádné položky"; },
formatInputTooShort: function (input, min) {
var n = min - input.length;
if (n == 1) {
return "Prosím zadejte ještě jeden znak";
} else if (n <= 4) {
return "Prosím zadejte ještě další "+smallNumbers[n](true)+" znaky";
} else {
return "Prosím zadejte ještě dalších "+n+" znaků";
}
},
formatInputTooLong: function (input, max) {
var n = input.length - max;
if (n == 1) {
return "Prosím zadejte o jeden znak méně";
} else if (n <= 4) {
return "Prosím zadejte o "+smallNumbers[n](true)+" znaky méně";
} else {
return "Prosím zadejte o "+n+" znaků méně";
}
},
formatSelectionTooBig: function (limit) {
if (limit == 1) {
return "Můžete zvolit jen jednu položku";
} else if (limit <= 4) {
return "Můžete zvolit maximálně "+smallNumbers[limit](false)+" položky";
} else {
return "Můžete zvolit maximálně "+limit+" položek";
}
},
formatLoadMore: function (pageNumber) { return "Načítají se další výsledky…"; },
formatSearching: function () { return "Vyhledávání…"; }
});
})(jQuery);

View File

@@ -0,0 +1,17 @@
/**
* Select2 Danish translation.
*
* Author: Anders Jenbo <anders@jenbo.dk>
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "Ingen resultater fundet"; },
formatInputTooShort: function (input, min) { var n = min - input.length; return "Angiv venligst " + n + " tegn mere"; },
formatInputTooLong: function (input, max) { var n = input.length - max; return "Angiv venligst " + n + " tegn mindre"; },
formatSelectionTooBig: function (limit) { return "Du kan kun vælge " + limit + " emne" + (limit === 1 ? "" : "r"); },
formatLoadMore: function (pageNumber) { return "Indlæser flere resultater…"; },
formatSearching: function () { return "Søger…"; }
});
})(jQuery);

View File

@@ -0,0 +1,15 @@
/**
* Select2 German translation
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "Keine Übereinstimmungen gefunden"; },
formatInputTooShort: function (input, min) { var n = min - input.length; return "Bitte " + n + " Zeichen mehr eingeben"; },
formatInputTooLong: function (input, max) { var n = input.length - max; return "Bitte " + n + " Zeichen weniger eingeben"; },
formatSelectionTooBig: function (limit) { return "Sie können nur " + limit + " Eintr" + (limit === 1 ? "ag" : "äge") + " auswählen"; },
formatLoadMore: function (pageNumber) { return "Lade mehr Ergebnisse…"; },
formatSearching: function () { return "Suche…"; }
});
})(jQuery);

View File

@@ -0,0 +1,17 @@
/**
* Select2 Greek translation.
*
* @author Uriy Efremochkin <efremochkin@uriy.me>
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "Δεν βρέθηκαν αποτελέσματα"; },
formatInputTooShort: function (input, min) { var n = min - input.length; return "Παρακαλούμε εισάγετε " + n + " περισσότερο" + (n > 1 ? "υς" : "") + " χαρακτήρ" + (n > 1 ? "ες" : "α"); },
formatInputTooLong: function (input, max) { var n = input.length - max; return "Παρακαλούμε διαγράψτε " + n + " χαρακτήρ" + (n > 1 ? "ες" : "α"); },
formatSelectionTooBig: function (limit) { return "Μπορείτε να επιλέξετε μόνο " + limit + " αντικείμεν" + (limit > 1 ? "α" : "ο"); },
formatLoadMore: function (pageNumber) { return "Φόρτωση περισσότερων…"; },
formatSearching: function () { return "Αναζήτηση…"; }
});
})(jQuery);

View File

@@ -0,0 +1,18 @@
/**
* Select2 <Language> translation.
*
* Author: Your Name <your@email>
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatMatches: function (matches) { return matches + " results are available, use up and down arrow keys to navigate."; },
formatNoMatches: function () { return "No matches found"; },
formatInputTooShort: function (input, min) { var n = min - input.length; return "Please enter " + n + " more character" + (n == 1 ? "" : "s"); },
formatInputTooLong: function (input, max) { var n = input.length - max; return "Please delete " + n + " character" + (n == 1 ? "" : "s"); },
formatSelectionTooBig: function (limit) { return "You can only select " + limit + " item" + (limit == 1 ? "" : "s"); },
formatLoadMore: function (pageNumber) { return "Loading more results…"; },
formatSearching: function () { return "Searching…"; }
});
})(jQuery);

View File

@@ -0,0 +1,15 @@
/**
* Select2 Spanish translation
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "No se encontraron resultados"; },
formatInputTooShort: function (input, min) { var n = min - input.length; return "Por favor, introduzca " + n + " car" + (n == 1? "ácter" : "acteres"); },
formatInputTooLong: function (input, max) { var n = input.length - max; return "Por favor, elimine " + n + " car" + (n == 1? "ácter" : "acteres"); },
formatSelectionTooBig: function (limit) { return "Sólo puede seleccionar " + limit + " elemento" + (limit == 1 ? "" : "s"); },
formatLoadMore: function (pageNumber) { return "Cargando más resultados…"; },
formatSearching: function () { return "Buscando…"; }
});
})(jQuery);

View File

@@ -0,0 +1,17 @@
/**
* Select2 Estonian translation.
*
* Author: Kuldar Kalvik <kuldar@kalvik.ee>
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "Tulemused puuduvad"; },
formatInputTooShort: function (input, min) { var n = min - input.length; return "Sisesta " + n + " täht" + (n == 1 ? "" : "e") + " rohkem"; },
formatInputTooLong: function (input, max) { var n = input.length - max; return "Sisesta " + n + " täht" + (n == 1? "" : "e") + " vähem"; },
formatSelectionTooBig: function (limit) { return "Saad vaid " + limit + " tulemus" + (limit == 1 ? "e" : "t") + " valida"; },
formatLoadMore: function (pageNumber) { return "Laen tulemusi.."; },
formatSearching: function () { return "Otsin.."; }
});
})(jQuery);

View File

@@ -0,0 +1,43 @@
/**
* Select2 Basque translation.
*
* Author: Julen Ruiz Aizpuru <julenx at gmail dot com>
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () {
return "Ez da bat datorrenik aurkitu";
},
formatInputTooShort: function (input, min) {
var n = min - input.length;
if (n === 1) {
return "Idatzi karaktere bat gehiago";
} else {
return "Idatzi " + n + " karaktere gehiago";
}
},
formatInputTooLong: function (input, max) {
var n = input.length - max;
if (n === 1) {
return "Idatzi karaktere bat gutxiago";
} else {
return "Idatzi " + n + " karaktere gutxiago";
}
},
formatSelectionTooBig: function (limit) {
if (limit === 1 ) {
return "Elementu bakarra hauta dezakezu";
} else {
return limit + " elementu hauta ditzakezu soilik";
}
},
formatLoadMore: function (pageNumber) {
return "Emaitza gehiago kargatzen…";
},
formatSearching: function () {
return "Bilatzen…";
}
});
})(jQuery);

View File

@@ -0,0 +1,19 @@
/**
* Select2 Persian translation.
*
* Author: Ali Choopan <choopan@arsh.co>
* Author: Ebrahim Byagowi <ebrahim@gnu.org>
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatMatches: function (matches) { return matches + " نتیجه موجود است، کلیدهای جهت بالا و پایین را برای گشتن استفاده کنید."; },
formatNoMatches: function () { return "نتیجه‌ای یافت نشد."; },
formatInputTooShort: function (input, min) { var n = min - input.length; return "لطفاً " + n + " نویسه بیشتر وارد نمایید"; },
formatInputTooLong: function (input, max) { var n = input.length - max; return "لطفاً " + n + " نویسه را حذف کنید."; },
formatSelectionTooBig: function (limit) { return "شما فقط می‌توانید " + limit + " مورد را انتخاب کنید"; },
formatLoadMore: function (pageNumber) { return "در حال بارگیری موارد بیشتر…"; },
formatSearching: function () { return "در حال جستجو…"; }
});
})(jQuery);

View File

@@ -0,0 +1,28 @@
/**
* Select2 Finnish translation
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () {
return "Ei tuloksia";
},
formatInputTooShort: function (input, min) {
var n = min - input.length;
return "Ole hyvä ja anna " + n + " merkkiä lisää";
},
formatInputTooLong: function (input, max) {
var n = input.length - max;
return "Ole hyvä ja anna " + n + " merkkiä vähemmän";
},
formatSelectionTooBig: function (limit) {
return "Voit valita ainoastaan " + limit + " kpl";
},
formatLoadMore: function (pageNumber) {
return "Ladataan lisää tuloksia…";
},
formatSearching: function () {
return "Etsitään…";
}
});
})(jQuery);

View File

@@ -0,0 +1,16 @@
/**
* Select2 French translation
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatMatches: function (matches) { return matches + " résultats sont disponibles, utilisez les flèches haut et bas pour naviguer."; },
formatNoMatches: function () { return "Aucun résultat trouvé"; },
formatInputTooShort: function (input, min) { var n = min - input.length; return "Merci de saisir " + n + " caractère" + (n == 1 ? "" : "s") + " de plus"; },
formatInputTooLong: function (input, max) { var n = input.length - max; return "Merci de supprimer " + n + " caractère" + (n == 1 ? "" : "s"); },
formatSelectionTooBig: function (limit) { return "Vous pouvez seulement sélectionner " + limit + " élément" + (limit == 1 ? "" : "s"); },
formatLoadMore: function (pageNumber) { return "Chargement de résultats supplémentaires…"; },
formatSearching: function () { return "Recherche en cours…"; }
});
})(jQuery);

View File

@@ -0,0 +1,43 @@
/**
* Select2 Galician translation
*
* Author: Leandro Regueiro <leandro.regueiro@gmail.com>
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () {
return "Non se atoparon resultados";
},
formatInputTooShort: function (input, min) {
var n = min - input.length;
if (n === 1) {
return "Engada un carácter";
} else {
return "Engada " + n + " caracteres";
}
},
formatInputTooLong: function (input, max) {
var n = input.length - max;
if (n === 1) {
return "Elimine un carácter";
} else {
return "Elimine " + n + " caracteres";
}
},
formatSelectionTooBig: function (limit) {
if (limit === 1 ) {
return "Só pode seleccionar un elemento";
} else {
return "Só pode seleccionar " + limit + " elementos";
}
},
formatLoadMore: function (pageNumber) {
return "Cargando máis resultados…";
},
formatSearching: function () {
return "Buscando…";
}
});
})(jQuery);

View File

@@ -0,0 +1,17 @@
/**
* Select2 Hebrew translation.
*
* Author: Yakir Sitbon <http://www.yakirs.net/>
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "לא נמצאו התאמות"; },
formatInputTooShort: function (input, min) { var n = min - input.length; return "נא להזין עוד " + n + " תווים נוספים"; },
formatInputTooLong: function (input, max) { var n = input.length - max; return "נא להזין פחות " + n + " תווים"; },
formatSelectionTooBig: function (limit) { return "ניתן לבחור " + limit + " פריטים"; },
formatLoadMore: function (pageNumber) { return "טוען תוצאות נוספות…"; },
formatSearching: function () { return "מחפש…"; }
});
})(jQuery);

View File

@@ -0,0 +1,22 @@
/**
* Select2 Croatian translation.
*
* @author Edi Modrić <edi.modric@gmail.com>
* @author Uriy Efremochkin <efremochkin@uriy.me>
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "Nema rezultata"; },
formatInputTooShort: function (input, min) { return "Unesite još" + character(min - input.length); },
formatInputTooLong: function (input, max) { return "Unesite" + character(input.length - max) + " manje"; },
formatSelectionTooBig: function (limit) { return "Maksimalan broj odabranih stavki je " + limit; },
formatLoadMore: function (pageNumber) { return "Učitavanje rezultata…"; },
formatSearching: function () { return "Pretraga…"; }
});
function character (n) {
return " " + n + " znak" + (n%10 < 5 && n%10 > 0 && (n%100 < 5 || n%100 > 19) ? n%10 > 1 ? "a" : "" : "ova");
}
})(jQuery);

View File

@@ -0,0 +1,15 @@
/**
* Select2 Hungarian translation
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "Nincs találat."; },
formatInputTooShort: function (input, min) { var n = min - input.length; return "Túl rövid. Még " + n + " karakter hiányzik."; },
formatInputTooLong: function (input, max) { var n = input.length - max; return "Túl hosszú. " + n + " karakterrel több, mint kellene."; },
formatSelectionTooBig: function (limit) { return "Csak " + limit + " elemet lehet kiválasztani."; },
formatLoadMore: function (pageNumber) { return "Töltés…"; },
formatSearching: function () { return "Keresés…"; }
});
})(jQuery);

View File

@@ -0,0 +1,17 @@
/**
* Select2 Indonesian translation.
*
* Author: Ibrahim Yusuf <ibrahim7usuf@gmail.com>
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "Tidak ada data yang sesuai"; },
formatInputTooShort: function (input, min) { var n = min - input.length; return "Masukkan " + n + " huruf lagi" + (n == 1 ? "" : "s"); },
formatInputTooLong: function (input, max) { var n = input.length - max; return "Hapus " + n + " huruf" + (n == 1 ? "" : "s"); },
formatSelectionTooBig: function (limit) { return "Anda hanya dapat memilih " + limit + " pilihan" + (limit == 1 ? "" : "s"); },
formatLoadMore: function (pageNumber) { return "Mengambil data…"; },
formatSearching: function () { return "Mencari…"; }
});
})(jQuery);

View File

@@ -0,0 +1,15 @@
/**
* Select2 Icelandic translation.
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "Ekkert fannst"; },
formatInputTooShort: function (input, min) { var n = min - input.length; return "Vinsamlegast skrifið " + n + " staf" + (n > 1 ? "i" : "") + " í viðbót"; },
formatInputTooLong: function (input, max) { var n = input.length - max; return "Vinsamlegast styttið texta um " + n + " staf" + (n > 1 ? "i" : ""); },
formatSelectionTooBig: function (limit) { return "Þú getur aðeins valið " + limit + " atriði"; },
formatLoadMore: function (pageNumber) { return "Sæki fleiri niðurstöður…"; },
formatSearching: function () { return "Leita…"; }
});
})(jQuery);

View File

@@ -0,0 +1,15 @@
/**
* Select2 Italian translation
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "Nessuna corrispondenza trovata"; },
formatInputTooShort: function (input, min) { var n = min - input.length; return "Inserisci ancora " + n + " caratter" + (n == 1? "e" : "i"); },
formatInputTooLong: function (input, max) { var n = input.length - max; return "Inserisci " + n + " caratter" + (n == 1? "e" : "i") + " in meno"; },
formatSelectionTooBig: function (limit) { return "Puoi selezionare solo " + limit + " element" + (limit == 1 ? "o" : "i"); },
formatLoadMore: function (pageNumber) { return "Caricamento in corso…"; },
formatSearching: function () { return "Ricerca…"; }
});
})(jQuery);

View File

@@ -0,0 +1,15 @@
/**
* Select2 Japanese translation.
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "該当なし"; },
formatInputTooShort: function (input, min) { var n = min - input.length; return "後" + n + "文字入れてください"; },
formatInputTooLong: function (input, max) { var n = input.length - max; return "検索文字列が" + n + "文字長すぎます"; },
formatSelectionTooBig: function (limit) { return "最多で" + limit + "項目までしか選択できません"; },
formatLoadMore: function (pageNumber) { return "読込中・・・"; },
formatSearching: function () { return "検索中・・・"; }
});
})(jQuery);

View File

@@ -0,0 +1,17 @@
/**
* Select2 Georgian (Kartuli) translation.
*
* Author: Dimitri Kurashvili dimakura@gmail.com
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "ვერ მოიძებნა"; },
formatInputTooShort: function (input, min) { var n = min - input.length; return "გთხოვთ შეიყვანოთ კიდევ " + n + " სიმბოლო"; },
formatInputTooLong: function (input, max) { var n = input.length - max; return "გთხოვთ წაშალოთ " + n + " სიმბოლო"; },
formatSelectionTooBig: function (limit) { return "თქვენ შეგიძლიათ მხოლოდ " + limit + " ჩანაწერის მონიშვნა"; },
formatLoadMore: function (pageNumber) { return "შედეგის ჩატვირთვა…"; },
formatSearching: function () { return "ძებნა…"; }
});
})(jQuery);

View File

@@ -0,0 +1,17 @@
/**
* Select2 Korean translation.
*
* @author Swen Mun <longfinfunnel@gmail.com>
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "결과 없음"; },
formatInputTooShort: function (input, min) { var n = min - input.length; return "너무 짧습니다. "+n+"글자 더 입력해주세요."; },
formatInputTooLong: function (input, max) { var n = input.length - max; return "너무 깁니다. "+n+"글자 지워주세요."; },
formatSelectionTooBig: function (limit) { return "최대 "+limit+"개까지만 선택하실 수 있습니다."; },
formatLoadMore: function (pageNumber) { return "불러오는 중…"; },
formatSearching: function () { return "검색 중…"; }
});
})(jQuery);

View File

@@ -0,0 +1,24 @@
/**
* Select2 Lithuanian translation.
*
* @author CRONUS Karmalakas <cronus dot karmalakas at gmail dot com>
* @author Uriy Efremochkin <efremochkin@uriy.me>
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "Atitikmenų nerasta"; },
formatInputTooShort: function (input, min) { return "Įrašykite dar" + character(min - input.length); },
formatInputTooLong: function (input, max) { return "Pašalinkite" + character(input.length - max); },
formatSelectionTooBig: function (limit) {
return "Jūs galite pasirinkti tik " + limit + " element" + ((limit%100 > 9 && limit%100 < 21) || limit%10 == 0 ? "ų" : limit%10 > 1 ? "us" : "ą");
},
formatLoadMore: function (pageNumber) { return "Kraunama daugiau rezultatų…"; },
formatSearching: function () { return "Ieškoma…"; }
});
function character (n) {
return " " + n + " simbol" + ((n%100 > 9 && n%100 < 21) || n%10 == 0 ? "ių" : n%10 > 1 ? "ius" : "į");
}
})(jQuery);

View File

@@ -0,0 +1,17 @@
/**
* Select2 Latvian translation.
*
* @author Uriy Efremochkin <efremochkin@uriy.me>
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "Sakritību nav"; },
formatInputTooShort: function (input, min) { var n = min - input.length; return "Lūdzu ievadiet vēl " + n + " simbol" + (n == 11 ? "us" : n%10 == 1 ? "u" : "us"); },
formatInputTooLong: function (input, max) { var n = input.length - max; return "Lūdzu ievadiet par " + n + " simbol" + (n == 11 ? "iem" : n%10 == 1 ? "u" : "iem") + " mazāk"; },
formatSelectionTooBig: function (limit) { return "Jūs varat izvēlēties ne vairāk kā " + limit + " element" + (limit == 11 ? "us" : limit%10 == 1 ? "u" : "us"); },
formatLoadMore: function (pageNumber) { return "Datu ielāde…"; },
formatSearching: function () { return "Meklēšana…"; }
});
})(jQuery);

View File

@@ -0,0 +1,17 @@
/**
* Select2 Macedonian translation.
*
* Author: Marko Aleksic <psybaron@gmail.com>
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "Нема пронајдено совпаѓања"; },
formatInputTooShort: function (input, min) { var n = min - input.length; return "Ве молиме внесете уште " + n + " карактер" + (n == 1 ? "" : "и"); },
formatInputTooLong: function (input, max) { var n = input.length - max; return "Ве молиме внесете " + n + " помалку карактер" + (n == 1? "" : "и"); },
formatSelectionTooBig: function (limit) { return "Можете да изберете само " + limit + " ставк" + (limit == 1 ? "а" : "и"); },
formatLoadMore: function (pageNumber) { return "Вчитување резултати…"; },
formatSearching: function () { return "Пребарување…"; }
});
})(jQuery);

View File

@@ -0,0 +1,17 @@
/**
* Select2 Malay translation.
*
* Author: Kepoweran <kepoweran@gmail.com>
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "Tiada padanan yang ditemui"; },
formatInputTooShort: function (input, min) { var n = min - input.length; return "Sila masukkan " + n + " aksara lagi"; },
formatInputTooLong: function (input, max) { var n = input.length - max; return "Sila hapuskan " + n + " aksara"; },
formatSelectionTooBig: function (limit) { return "Anda hanya boleh memilih " + limit + " pilihan"; },
formatLoadMore: function (pageNumber) { return "Sedang memuatkan keputusan…"; },
formatSearching: function () { return "Mencari…"; }
});
})(jQuery);

View File

@@ -0,0 +1,15 @@
/**
* Select2 Dutch translation
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "Geen resultaten gevonden"; },
formatInputTooShort: function (input, min) { var n = min - input.length; return "Vul " + n + " karakter" + (n == 1? "" : "s") + " meer in"; },
formatInputTooLong: function (input, max) { var n = input.length - max; return "Vul " + n + " karakter" + (n == 1? "" : "s") + " minder in"; },
formatSelectionTooBig: function (limit) { return "Maximaal " + limit + " item" + (limit == 1 ? "" : "s") + " toegestaan"; },
formatLoadMore: function (pageNumber) { return "Meer resultaten laden…"; },
formatSearching: function () { return "Zoeken…"; }
});
})(jQuery);

View File

@@ -0,0 +1,18 @@
/**
* Select2 Norwegian translation.
*
* Author: Torgeir Veimo <torgeir.veimo@gmail.com>
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "Ingen treff"; },
formatInputTooShort: function (input, min) { var n = min - input.length; return "Vennligst skriv inn " + n + (n>1 ? " flere tegn" : " tegn til"); },
formatInputTooLong: function (input, max) { var n = input.length - max; return "Vennligst fjern " + n + " tegn"; },
formatSelectionTooBig: function (limit) { return "Du kan velge maks " + limit + " elementer"; },
formatLoadMore: function (pageNumber) { return "Laster flere resultater…"; },
formatSearching: function () { return "Søker…"; }
});
})(jQuery);

View File

@@ -0,0 +1,22 @@
/**
* Select2 Polish translation.
*
* @author Jan Kondratowicz <jan@kondratowicz.pl>
* @author Uriy Efremochkin <efremochkin@uriy.me>
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "Brak wyników"; },
formatInputTooShort: function (input, min) { return "Wpisz jeszcze" + character(min - input.length, "znak", "i"); },
formatInputTooLong: function (input, max) { return "Wpisana fraza jest za długa o" + character(input.length - max, "znak", "i"); },
formatSelectionTooBig: function (limit) { return "Możesz zaznaczyć najwyżej" + character(limit, "element", "y"); },
formatLoadMore: function (pageNumber) { return "Ładowanie wyników…"; },
formatSearching: function () { return "Szukanie…"; }
});
function character (n, word, pluralSuffix) {
return " " + n + " " + word + (n == 1 ? "" : n%10 < 5 && n%10 > 1 && (n%100 < 5 || n%100 > 20) ? pluralSuffix : "ów");
}
})(jQuery);

View File

@@ -0,0 +1,15 @@
/**
* Select2 Brazilian Portuguese translation
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "Nenhum resultado encontrado"; },
formatInputTooShort: function (input, min) { var n = min - input.length; return "Digite mais " + n + " caracter" + (n == 1? "" : "es"); },
formatInputTooLong: function (input, max) { var n = input.length - max; return "Apague " + n + " caracter" + (n == 1? "" : "es"); },
formatSelectionTooBig: function (limit) { return "Só é possível selecionar " + limit + " elemento" + (limit == 1 ? "" : "s"); },
formatLoadMore: function (pageNumber) { return "Carregando mais resultados…"; },
formatSearching: function () { return "Buscando…"; }
});
})(jQuery);

View File

@@ -0,0 +1,15 @@
/**
* Select2 Portuguese (Portugal) translation
*/
(function ($) {
"use strict";
$.extend($.fn.select2.defaults, {
formatNoMatches: function () { return "Nenhum resultado encontrado"; },
formatInputTooShort: function (input, min) { var n = min - input.length; return "Introduza " + n + " car" + (n == 1 ? "ácter" : "acteres"); },
formatInputTooLong: function (input, max) { var n = input.length - max; return "Apague " + n + " car" + (n == 1 ? "ácter" : "acteres"); },
formatSelectionTooBig: function (limit) { return "Só é possível selecionar " + limit + " elemento" + (limit == 1 ? "" : "s"); },
formatLoadMore: function (pageNumber) { return "A carregar mais resultados…"; },
formatSearching: function () { return "A pesquisar…"; }
});
})(jQuery);

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