1
0
mirror of https://github.com/chylex/Nextcloud-Desktop.git synced 2026-04-05 05:34:18 +02:00

Compare commits

...

129 Commits

Author SHA1 Message Date
Olivier Goffart
458f336405 PropagateDownload: Read the mtime from the file system after writing it
Because file system like FAT only have two second accuracy and would result
in a upload if the mtime in the database is not the same as the one that was
downloaded

Issue #3103
2015-04-15 15:50:20 +02:00
Daniel Molkentin
3f3f27d4d3 1.8.1 beta 1 2015-04-15 15:33:17 +02:00
Markus Goetz
7c9cffa5ae ConfigFile: Remove unused functions 2015-04-15 14:58:27 +02:00
Markus Goetz
996223197c Translations: Attempt two for Serbian #3083 2015-04-15 12:31:25 +02:00
Jenkins for ownCloud
b8e7555977 [tx-robot] updated from transifex 2015-04-15 02:18:35 -04:00
Daniel Molkentin
ed80a712ab Sort folder sizes SelectiveSyncTreeView numerically
Fixes #3112
2015-04-14 20:00:42 +02:00
Markus Goetz
2866e56c51 LsColXMLParser: More testing 2 2015-04-14 14:56:25 +02:00
Markus Goetz
2074bdbb19 LsColXMLParser: More testing 2015-04-14 14:41:48 +02:00
Klaas Freitag
d212ac7d16 test xmlparser: Verify call to parse() 2015-04-14 13:45:09 +02:00
Klaas Freitag
d2bae21b14 Added unit test for XML Parser class. 2015-04-14 13:43:05 +02:00
Klaas Freitag
4283ab3b44 LsColJob: Create a XML parser object for better unit testability. 2015-04-14 13:43:05 +02:00
Klaas Freitag
c579069071 LsColXMLParser: let parse return bool. 2015-04-14 13:41:51 +02:00
Jenkins for ownCloud
88488c695c [tx-robot] updated from transifex 2015-04-14 02:18:33 -04:00
Markus Goetz
21594e9aa9 Translations: Try to add Serbian #3083 2015-04-13 18:27:28 +02:00
Markus Goetz
9ffacd4ecd Discovery: Explicitly check for XML parser errors
..instead of relying that our state machine does not do anything in that case.
2015-04-13 16:04:24 +02:00
Markus Goetz
9d5f5ea3bc Discovery: Initialize error with EIO in constructor
This is safer, initializing it in remote_vio_opendir_hook was enough though.
2015-04-13 15:54:08 +02:00
Markus Goetz
2dbd27af76 Discovery: Initialize error with EIO 2015-04-13 15:36:07 +02:00
Markus Goetz
0634a4d0c6 Discovery: Add a sanity check when results are parsed 2015-04-13 15:10:04 +02:00
Markus Goetz
fa80a006b8 CSync: Log if file_id is too long 2015-04-13 14:58:25 +02:00
Olivier Goffart
9d88ef5432 Restore submodule 2015-04-13 13:03:46 +02:00
Klaas Freitag
7b99877c68 owncloudcmd: Filter out empty lines in selectivesync 2015-04-12 12:59:25 +02:00
Klaas Freitag
ec81cdefb0 Networkjobs: Only log a subset of the account url.
This avoids disclosing of user and password in the logfile which can
happen in some cases.
2015-04-12 12:37:14 +02:00
Jenkins for ownCloud
454d5b575c [tx-robot] updated from transifex 2015-04-12 02:18:27 -04:00
Jenkins for ownCloud
785b59e6d1 [tx-robot] updated from transifex 2015-04-11 02:18:26 -04:00
Christian Kamm
9d8fc4aa4d ProtocolWidget: Fix adding of seconds. #2535 2015-04-10 12:11:35 +02:00
Christian Kamm
57ac1d9ea2 AuthRedirect: Use the configured DAV path. #3082 2015-04-10 09:24:25 +02:00
Christian Kamm
d9ea6936ab Handle redirect of auth request. #3082 2015-04-10 09:18:15 +02:00
Olivier Goffart
c917251e9e Reconcile: Fix clang warning
csync_reconcile.c:159:26: warning: address of array 'tmp->path' will always evaluate to 'true' [-Wpointer-bool-conversion]
                if( tmp->path ) {
                ~~  ~~~~~^~~~

csync_file_stat_s::path is an array so it is never null
What was meant here is to check if the string was not empty
2015-04-09 15:06:48 +02:00
Jenkins for ownCloud
c805c5d6e9 [tx-robot] updated from transifex 2015-04-09 02:18:32 -04:00
Christian Kamm
adcf40afc3 Discovery: Speed up initial run. #2796 2015-04-08 15:43:49 +02:00
Christian Kamm
d986011067 Sync: Fix sync of deletions during 503. #2894 2015-04-08 10:50:08 +02:00
Roeland Jago Douma
5a83636f81 Only show share dialog if we are connected. 2015-04-08 09:53:57 +02:00
Jocelyn Turcotte
d475628c70 SyncEngine: Fix a crash in csync_vio_file_stat_copy #3051
In some cryptic cases where the getetag property wasn't returned by
the server, we might be trying to c_strdup a null pointer in
csync_vio_file_stat_copy.

At least avoid crashing in this case by looking for
CSYNC_VIO_FILE_STAT_FIELDS_ETAG, like csync_vio_file_stat_destroy
does.
2015-04-08 09:35:43 +02:00
Jocelyn Turcotte
4a890eae38 SyncEngine: Fix a crash caused by an invalid DiscoveryDirectoryResult::iterator #3051
The default constructor of the iterator points to NULL, which makes
it != end() but invalid to dereference.

Use an integer index instead to keep 0 as a valid default value that
can always correctly be checked against size().

Also make sure that no data is shared between threads by making the
csync_vio_file_stat_t copyable and passing it as const.
2015-04-08 09:35:43 +02:00
Christian Kamm
760e11bc5d Sharedialog: Fix compiler warnings. 2015-04-08 08:59:36 +02:00
Jenkins for ownCloud
96ebf2b519 [tx-robot] updated from transifex 2015-04-08 02:18:30 -04:00
Klaas Freitag
4a6f4919d7 More GUI refinements. 2015-04-07 13:38:01 +02:00
Klaas Freitag
b98040c7d5 ShareDialog: handle resize properly with elided text 2015-04-07 13:38:01 +02:00
Klaas Freitag
1240a8163d ShareDialog: Some GUI rework requested by Jan. 2015-04-07 13:38:01 +02:00
Olivier Goffart
e15b9b5358 Merge remote-tracking branch into 1.8 2015-04-07 10:42:27 +02:00
Olivier Goffart
1617c9d482 PropfindJob: fix xml parsing
It would only find the first property
2015-04-07 10:35:27 +02:00
Jenkins for ownCloud
16600fe86a [tx-robot] updated from transifex 2015-04-07 02:18:46 -04:00
Olivier Goffart
50ba73860c Merge remote-tracking branch into 1.8 2015-04-07 08:02:55 +02:00
Markus Goetz
750cdc1910 AbstractSslErrorHandler: Also give QSslConfiguration 2015-04-06 21:46:03 +02:00
Olivier Goffart
f4e2c84111 AccountState: Fix uninitialized memory access spotted by valgrind
QuotaInfo's constructor uses the AccountState's _state which is
initialized after
2015-04-06 16:21:05 +02:00
Jenkins for ownCloud
4f27750711 [tx-robot] updated from transifex 2015-04-04 02:18:40 -04:00
Olivier Goffart
71d9f23068 theme: fix compilation of libsync without QtGui 2015-04-03 11:27:06 +02:00
Jenkins for ownCloud
9f7aed7602 [tx-robot] updated from transifex 2015-04-03 02:18:33 -04:00
Markus Goetz
7f2213416a Discovery: Add warning if returned etag is 0
There will be another bugfix which fixes
https://gist.github.com/jturcotte/3d5a7874d26bc27b1be9
directory.
2015-04-02 16:57:53 +02:00
Markus Goetz
9b9f0bdd4d SyncEngine: Show more timing measurements #3064 2015-04-02 15:18:46 +02:00
Jenkins for ownCloud
ee0aec514f [tx-robot] updated from transifex 2015-04-02 02:18:44 -04:00
Jocelyn Turcotte
c2fd7d6ebd Clean up remains of SOCKETAPI_TCP 2015-04-01 15:03:42 +02:00
Jocelyn Turcotte
4a893c5267 Fix a crash on shutdown in ~SocketApi #3057
Deleting the QLocalSocket while iterating the QList with qDeleteAll
would trigger onLostConnection, which would modify the list mid-air
and leave dangling pointers in it.
2015-04-01 15:03:42 +02:00
Jocelyn Turcotte
2473183f19 Windows: Add version information for owncloud.exe
This should help us know what version or build number a crash report was generated with.
2015-04-01 15:03:41 +02:00
Jenkins for ownCloud
7d7142d7d8 [tx-robot] updated from transifex 2015-04-01 02:18:37 -04:00
Jenkins for ownCloud
cb57cda87a [tx-robot] updated from transifex 2015-03-31 02:18:45 -04:00
Daniel Molkentin
f2fa812b0b Updater: Give context as to which app is about to be updated
Fixes #3040
2015-03-30 14:44:34 +02:00
Markus Goetz
ef89582d7e Propagator: Fix compile 2015-03-30 08:41:53 +02:00
Jenkins for ownCloud
ae74a21305 [tx-robot] updated from transifex 2015-03-29 02:18:47 -04:00
Jenkins for ownCloud
32af63764c [tx-robot] updated from transifex 2015-03-29 01:15:23 -04:00
Jenkins for ownCloud
61ff90409d [tx-robot] updated from transifex 2015-03-28 02:18:42 -04:00
Christian Kamm
ba0c3256fa Remove unused HttpConfigFile. 2015-03-27 13:20:10 +01:00
Markus Goetz
b6fe5d2cff Propagator: Debug output regarding OC-ETag
We can remove this in some time, but currently it is interesting
to see for what server setup is no ETag but an OC-ETag.
2015-03-27 13:16:11 +01:00
Markus Goetz
9123fac545 owncloudcmd: Always trail path with /
Else the csync code vs the Qt code get confused.
2015-03-27 13:15:43 +01:00
Markus Goetz
c6bc388001 Proxy: More debug, always set returned system proxy 2015-03-27 11:53:58 +01:00
Christian Kamm
ea985a85af ProtocolWidget: Always add seconds to the DateTime locale. #2535 2015-03-27 11:25:30 +01:00
Christian Kamm
2578832002 Fix clang warnings about deleting incomplete 'Account'. 2015-03-27 11:11:44 +01:00
Markus Goetz
cfada67aa6 Proxy: Fix compile harder 2015-03-27 11:02:19 +01:00
Christian Kamm
5483682281 CookieJar: Don't accidentally overwrite cookies. #2808
Calling save() in the CookieJar destructor was problematic. For instance
we sometimes create a new QNAM with a new CookieJar and then call
setCookieJar() on it to assign some other jar. That destroy the fresh
jar and potentially overwrite cookies.

Also explicitly saving the account's cookies when the account is saved
is more explicit and thus more reliable than counting on the Account
destructor to do it.
2015-03-27 10:49:24 +01:00
Christian Kamm
2a8c23aac3 Account: Destroy on exit.
During shutdown we want the account object to be deleted and
therefore we need to be able to remove the strong reference
in AccountManager.
2015-03-27 10:43:14 +01:00
Christian Kamm
88bc96fc4c ConValidator: Delete instance if no credentials. 2015-03-27 10:43:14 +01:00
Christian Kamm
588129d852 HttpCreds: Delete password from old location. #2186 2015-03-27 10:40:19 +01:00
Jenkins for ownCloud
0889991c38 [tx-robot] updated from transifex 2015-03-27 02:18:47 -04:00
Markus Goetz
5c87a35fe4 Proxy: Fix compile 2015-03-26 18:36:37 +01:00
Markus Goetz
418185af9a Qt4: Fix compile 2015-03-26 15:17:16 +01:00
Roeland Jago Douma
4b56cc6e08 On creation of a share always retrieve the share
This makes sure that if a default expiration date is set this is reflected in
the dialog. #2889
2015-03-26 13:48:33 +01:00
Christian Kamm
3cef771868 HttpCreds: Fill pw dialog with previous password. #2848 #2879 2015-03-26 09:25:45 +01:00
Jenkins for ownCloud
59b20de7cd [tx-robot] updated from transifex 2015-03-26 02:18:43 -04:00
Markus Goetz
e0ae34f01b SslButton: Make menu creation lazy
Saves ~200msec on my not-so-old MBP on OS X.
For #3007 #2990
2015-03-25 15:41:23 +01:00
Christian Kamm
a9a24c96fc Themes: Cache icons instead of rebuilding a lot. 2015-03-25 14:59:28 +01:00
Markus Goetz
a202203325 Proxy: Fix issues with previous patch
This is for #2993 and #2802
2015-03-25 12:25:49 +01:00
Markus Goetz
83c3d76966 Proxy: Look up system proxy from different thread
We should actually upstream this into QNAM.

This is for #2993 and #2802
2015-03-25 08:52:23 +01:00
Markus Goetz
99734f8d72 Account: Unusued variable 2015-03-25 08:52:23 +01:00
Jenkins for ownCloud
570a0bb586 [tx-robot] updated from transifex 2015-03-25 02:18:53 -04:00
Daniel Molkentin
450a815d61 Add user id param 2015-03-24 22:24:09 +01:00
Olivier Goffart
dafc2d2b73 Sync engine: Check the blacklist for the right tree
When the operation is download, we have a INSTRUCTION_NONE for the local
tree, but we should not check the blacklist just yet.
2015-03-24 12:23:04 +01:00
Jocelyn Turcotte
0bd2edd33a Revert "Switch back to an existing sha"
This reverts commit 48c9222578.
The submodule repository now has the required commit.
2015-03-24 10:24:25 +01:00
Jenkins for ownCloud
807267cfdb [tx-robot] updated from transifex 2015-03-24 02:18:42 -04:00
Daniel Molkentin
48c9222578 Switch back to an existing sha 2015-03-23 22:40:57 +01:00
Daniel Molkentin
b5ea56df73 Add docker buildscript for win32 2015-03-23 22:24:43 +01:00
Carla Schroder
2fdf6dd8f2 Merge pull request #3008 from owncloud/passman
add note re password managers
2015-03-23 10:55:24 -07:00
Carla Schroder
5b8c9eb16f add note re password managers 2015-03-23 10:52:57 -07:00
Olivier Goffart
9c05150c12 SSLButton: Fix a crash
Made with danimo.
Attempt to fix a crash seen on breakpad reports.
(cc06b990-0c10-40eb-bcec-4d3902150320)
2015-03-23 18:30:53 +01:00
Daniel Molkentin
c7eb85ef78 Activity: Correctly restore column sizes
Fixes: #3005
2015-03-23 18:22:25 +01:00
Olivier Goffart
4df455f2e0 Add-folder Wizard: Select the newly created folder 2015-03-23 16:50:37 +01:00
Olivier Goffart
653a00d63d Add-folder wizard: Make sure there is a scrollbar if folder names are too long
Fixes #2962
2015-03-23 16:32:41 +01:00
Jocelyn Turcotte
3c9acdf724 Fix a crash when accessing a dangling UploadDevice pointer #2984
This is largely a guess, but this is the only place where we use
a QIODevice to push data through QNAM and that the QIODevice isn't
a direct child of the QNetworkReply.

Fix the issue by making sure that we don't go back to the event loop
and possibly handle network events between the destruction of the
upload QIODevice and the QNetworkReply, which might lead to QNAM
dereferencing a dangling QIODevice pointer.
2015-03-23 16:14:54 +01:00
Olivier Goffart
e81d1ab9b8 application: --confdir option with invalid direcotry now exit
Show an error and exit if an invalid directory (eg, a file) is passed to --confdir

Fixes: #2453
2015-03-23 15:02:27 +01:00
Jocelyn Turcotte
ad5620efb5 Disable asserts in official builds
Make sure that we define NDEBUG in all configurations.
Also remove inconsistent defines:
WIN32: We don't use
_DEBUG;_WINDOWS;_USRDLL: Should be defined by the compiler if necessary
OCCONTEXTMENU_EXPORTS: We currently don't use dllimport anyway

This also update the binary submodule with an updated build.
2015-03-23 13:53:09 +01:00
Daniel Molkentin
f455c71338 Merge pull request #2997 from owncloud/fix_shell-integration-python3
fix python3 syntax errors
2015-03-23 11:28:28 +01:00
Olivier Goffart
033f2cd231 Merge pull request #2998 from owncloud/remove-old-mirall-translation
Remove forgotten file.
2015-03-23 11:06:14 +01:00
Hefee
c9eccd729d Remove forgotten file. 2015-03-22 18:01:25 +01:00
Hefee
b1100cd9e5 fix python3 syntax errors 2015-03-22 17:49:09 +01:00
Jenkins for ownCloud
8f728ddfb2 [tx-robot] updated from transifex 2015-03-20 02:18:41 -04:00
Christian Kamm
4ef0ce112c CookieJar: Session cookies should *not* be stored in cookies.db. 2015-03-19 11:57:25 +01:00
Christian Kamm
57c14a0eba Windows: Reset QNAM as a workaround. #2899 #2895 #2973
The QNetworkAccessManager is reset when we are disconnected, just
before attempting to fetch the server's status.php.

This may help fix the problem described in various issues where we
get 'Connection closed' or timeout errors after the OS has woken
from sleep.
2015-03-19 11:40:47 +01:00
Christian Kamm
89f831e7d4 Remote delete: Consider 404 a success. #2919 2015-03-19 10:04:02 +01:00
Jenkins for ownCloud
917b8409ae [tx-robot] updated from transifex 2015-03-19 02:18:50 -04:00
Jenkins for ownCloud
86fd39e3a9 [tx-robot] updated from transifex 2015-03-18 02:18:42 -04:00
Jenkins for ownCloud
04db332051 [tx-robot] updated from transifex 2015-03-18 01:15:17 -04:00
Markus Goetz
06a2f58c51 Propagator: Introduce custom property to make error soft
This can be set by a custom credential QNAM.
2015-03-17 23:31:30 +01:00
Jenkins for ownCloud
b87d55758b [tx-robot] updated from transifex 2015-03-17 02:18:44 -04:00
Klaas Freitag
38ef525d5e Push version to final 1.8.0 2015-03-16 15:28:58 +01:00
Jenkins for ownCloud
367b1fcc33 [tx-robot] updated from transifex 2015-03-16 02:18:44 -04:00
Jenkins for ownCloud
f5c930968e [tx-robot] updated from transifex 2015-03-14 02:18:44 -04:00
Jocelyn Turcotte
5264a8c7f6 shell_integration: Fix disappearing context menus on Windows #2898
Since each new connection to the socket API would trigger a broadcast
of REGISTER_PATH to all existing connections, opening the context menu
would trigger a SHChangeNotify call of the root directory through
the overlay icon extension, which is currently also connected to the
socket API, waiting for changes.

Fix the issue by sending the initial REGISTER_PATH automatic response
only to the connecting socket.
2015-03-13 20:53:59 +01:00
Markus Goetz
6c4b7f1479 OS X: Always return 0 from pre_install.sh 2015-03-13 16:35:44 +01:00
Markus Goetz
c42c9f0002 Propagator: Add comment 2015-03-13 15:48:35 +01:00
Christian Kamm
95f299f865 Remote folder wizard: Add optional manual entry #2613 2015-03-13 09:52:21 +01:00
Jenkins for ownCloud
09749e2c7f [tx-robot] updated from transifex 2015-03-13 02:18:46 -04:00
Carla Schroder
dc33784a76 spelling corrections 2015-03-12 09:48:00 -07:00
Carla Schroder
961df1fc44 fix server side permissions table 2015-03-12 09:46:27 -07:00
Jocelyn Turcotte
e93c1ccb73 Install the crash handler earlier during startup
This moves the crash handler installation during the OCC::Application
contruction. This still leaves a window where crashes wouldn't be
caught, leaving the QtSingleApplication and theme initialization
code unreported, but isn't requiring any refactoring for now.

Issue #2952
2015-03-12 17:16:05 +01:00
Klaas Freitag
286ad0c478 Doc: Formatting fixes 2015-03-12 16:59:12 +01:00
Klaas Freitag
e30970ff90 Some ChangeLog corrections. 2015-03-12 16:49:41 +01:00
Daniel Molkentin
14e0e4a072 Win32: More reserved file names to ignore, including Recycle Bin
Addresses #2955
2015-03-12 16:25:32 +01:00
Jocelyn Turcotte
60da0a15e6 shell_integration: Remove the incorrect usage of the MIIM_BITMAP flag
This flag should only be specified if the hbmpItem member of the
MENUITEMINFO has been set.
2015-03-12 15:22:29 +01:00
Jocelyn Turcotte
0f84510e6f Fix the build with GCC 4.7
Disable bitfields completely in SyncFileItem with that compiler.
2015-03-12 14:54:11 +01:00
Christian Kamm
1dd3488973 Uploads: Fix big seeks on Windows. #2954 2015-03-12 13:18:08 +01:00
99 changed files with 1981 additions and 1168 deletions

View File

@@ -1,6 +1,6 @@
ChangeLog ChangeLog
========= =========
version 1.8.0 (release 2015-02-xx) version 1.8.0 (release 2015-03-xx)
* Mac OS: HIDPI support * Mac OS: HIDPI support
* Support Sharing from desktop: Added a share dialog that can be * Support Sharing from desktop: Added a share dialog that can be
opened by context menu in the file managers (Win, Mac, Nautilus) opened by context menu in the file managers (Win, Mac, Nautilus)
@@ -12,7 +12,7 @@ version 1.8.0 (release 2015-02-xx)
* Added ability to build on Windows utilizing MingGW * Added ability to build on Windows utilizing MingGW
* SQLite database fixes if running on FAT filesystems * SQLite database fixes if running on FAT filesystems
* Improved detection of changing files to upload from local * Improved detection of changing files to upload from local
* Preparations for the muli-account feature * Preparations for the multi-account feature
* Fixed experience for Window manager without system tray * Fixed experience for Window manager without system tray
* Build with Qt 5.4 * Build with Qt 5.4
* Dropped libneon dependency if Qt 5.4 is available * Dropped libneon dependency if Qt 5.4 is available
@@ -24,8 +24,7 @@ version 1.8.0 (release 2015-02-xx)
* Prepared direct download * Prepared direct download
* Added Crashreporter feature to be switched on on demand * Added Crashreporter feature to be switched on on demand
* A huge amount of bug fixes in all areas of the client. * A huge amount of bug fixes in all areas of the client.
* almost 700 commits since 1.7.1
* more than 7000 commits since 1.7.0
version 1.7.1 (release 2014-12-18) version 1.7.1 (release 2014-12-18)
* Documentation fixes and updates * Documentation fixes and updates

View File

@@ -1,10 +1,10 @@
set( MIRALL_VERSION_MAJOR 1 ) set( MIRALL_VERSION_MAJOR 1 )
set( MIRALL_VERSION_MINOR 8 ) set( MIRALL_VERSION_MINOR 8 )
set( MIRALL_VERSION_PATCH 0 ) set( MIRALL_VERSION_PATCH 1 )
set( MIRALL_SOVERSION 0 ) set( MIRALL_SOVERSION 0 )
if ( NOT DEFINED MIRALL_VERSION_SUFFIX ) if ( NOT DEFINED MIRALL_VERSION_SUFFIX )
set( MIRALL_VERSION_SUFFIX "rc1") #e.g. beta1, beta2, rc1 set( MIRALL_VERSION_SUFFIX "beta1") #e.g. beta1, beta2, rc1
endif( NOT DEFINED MIRALL_VERSION_SUFFIX ) endif( NOT DEFINED MIRALL_VERSION_SUFFIX )
if( NOT DEFINED MIRALL_VERSION_BUILD ) if( NOT DEFINED MIRALL_VERSION_BUILD )

View File

@@ -6,3 +6,4 @@ killall @APPLICATION_EXECUTABLE@
# Unload the Finder plugin. see issue #2105 # Unload the Finder plugin. see issue #2105
killall Finder killall Finder
exit 0

19
admin/win/docker/build.sh Executable file
View File

@@ -0,0 +1,19 @@
#!/bin/bash
if [ $# -lt 1 ]; then
echo "Usage: $(basename $0) directory_relative_to_home [uid]"
exit
fi
useradd user -u ${2:-1000}
su - user << EOF
cd /home/user/$1
rm -rf build-win32
mkdir build-win32
cd build-win32
../admin/win/download_runtimes.sh
cmake .. -DCMAKE_TOOLCHAIN_FILE=../admin/win/Toolchain-mingw32-openSUSE.cmake -DWITH_CRASHREPORTER=ON
make -j4
make package
ctest .
EOF

View File

@@ -2,7 +2,7 @@
#VS2013 #VS2013
base_url=http://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3 base_url=http://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3
tmp_path=/tmp/.vcredist tmp_path=${1:-/tmp/.vcredist}
mkdir -p $tmp_path mkdir -p $tmp_path

View File

@@ -15,6 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "Desinstal.lar ${APPLICATION_NAME}"
StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstal.lar ${APPLICATION_NAME}" StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstal.lar ${APPLICATION_NAME}"
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Escolliu l'opció de manteniment per executar-ho." StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Escolliu l'opció de manteniment per executar-ho."
StrCpy $SEC_APPLICATION_DETAILS "Instal·lant ${APPLICATION_NAME} essencial." StrCpy $SEC_APPLICATION_DETAILS "Instal·lant ${APPLICATION_NAME} essencial."
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Integració per Windows Explorer"
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Instal·lant integració per Windows Explorer"
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Accés directe del programa al menú d'inici" StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Accés directe del programa al menú d'inici"
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Afegint la drecera per ${APPLICATION_NAME} al menú d'inici." StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Afegint la drecera per ${APPLICATION_NAME} al menú d'inici."
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Drecera a l'escriptori" StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Drecera a l'escriptori"
@@ -42,5 +44,3 @@ StrCpy $INIT_INSTALLER_RUNNING "L'instal·lador ja s'està executant."
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Aquest desinstal·lador requereix accés d'administrador, intenteu-ho de nou." StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Aquest desinstal·lador requereix accés d'administrador, intenteu-ho de nou."
StrCpy $INIT_UNINSTALLER_RUNNING "El desinstal·lador ja s'està executant." StrCpy $INIT_UNINSTALLER_RUNNING "El desinstal·lador ja s'està executant."
StrCpy $SectionGroup_Shortcuts "Dreceres" StrCpy $SectionGroup_Shortcuts "Dreceres"
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Integration for Windows Explorer"
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Installing Integration for Windows Explorer"

View File

@@ -1,6 +1,6 @@
# Auto-generated - do not modify # Auto-generated - do not modify
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Afficher les notes de version" StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Afficher les notes de version"
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Le(s) processus en cours dexécution ${APPLICATION_EXECUTABLE} doit (doivent) être stoppé(s) afin de poursuivre.$\nVoulez-vous que le programme dinstallation sen charge pour vous ?" StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Les processus ${APPLICATION_EXECUTABLE} en cours dexécution doivent être stoppés avant de poursuivre.$\nVoulez-vous que le programme dinstallation sen charge pour vous ?"
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Fermeture des processus ${APPLICATION_EXECUTABLE}." StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Fermeture des processus ${APPLICATION_EXECUTABLE}."
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Le processus à stopper n'a pas été trouvé !" StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Le processus à stopper n'a pas été trouvé !"
StrCpy $PageReinstall_NEW_Field_1 "Une ancienne version de ${APPLICATION_NAME} est installée sur votre système. Il est recommandé de désinstaller cette version avant de continuer. Sélectionnez l'opération que vous voulez exécuter et cliquez sur Suivant pour continuer." StrCpy $PageReinstall_NEW_Field_1 "Une ancienne version de ${APPLICATION_NAME} est installée sur votre système. Il est recommandé de désinstaller cette version avant de continuer. Sélectionnez l'opération que vous voulez exécuter et cliquez sur Suivant pour continuer."

2
binary

Submodule binary updated: 01d73965dc...1fb9ddfa9a

View File

@@ -576,7 +576,8 @@ int csync_commit(CSYNC *ctx) {
_csync_clean_ctx(ctx); _csync_clean_ctx(ctx);
ctx->remote.read_from_db = 0; ctx->remote.read_from_db = 0;
ctx->read_from_db_disabled = 0; ctx->read_remote_from_db = true;
ctx->db_is_empty = false;
/* Create new trees */ /* Create new trees */
@@ -773,10 +774,3 @@ int csync_set_module_property(CSYNC* ctx, const char* key, void* value)
#endif #endif
} }
int csync_set_read_from_db(CSYNC* ctx, int enabled)
{
ctx->read_from_db_disabled = !enabled;
return 0;
}

View File

@@ -550,11 +550,6 @@ void csync_resume(CSYNC *ctx);
*/ */
int csync_abort_requested(CSYNC *ctx); int csync_abort_requested(CSYNC *ctx);
/**
* Specify if it is allowed to read the remote tree from the DB (default to enabled)
*/
int csync_set_read_from_db(CSYNC* ctx, int enabled);
char *csync_normalize_etag(const char *); char *csync_normalize_etag(const char *);
time_t oc_httpdate_parse( const char *date ); time_t oc_httpdate_parse( const char *date );

View File

@@ -151,11 +151,12 @@ CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path, int filetype) {
return match; return match;
} }
// See http://support.microsoft.com/kb/74496 // See http://support.microsoft.com/kb/74496 and
static const char *win_reserved_words[] = {"CON","PRN","AUX", "NUL", // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
"COM1", "COM2", "COM3", "COM4", // Additionally, we ignore '$Recycle.Bin', see https://github.com/owncloud/client/issues/2955
"LPT1", "LPT2", "LPT3", "CLOCK$" }; static const char* win_reserved_words[] = {"CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5",
"COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4",
"LPT5", "LPT6", "LPT7", "LPT8", "LPT9", "CLOCK$", "$Recycle.Bin" };
bool csync_is_windows_reserved_word(const char* filename) { bool csync_is_windows_reserved_word(const char* filename) {

View File

@@ -151,7 +151,17 @@ struct csync_s {
int status; int status;
volatile int abort; volatile int abort;
void *rename_info; void *rename_info;
int read_from_db_disabled;
/**
* Specify if it is allowed to read the remote tree from the DB (default to enabled)
*/
bool read_remote_from_db;
/**
* If true, the DB is considered empty and all reads are skipped. (default is false)
* This is useful during the initial local discovery as it speeds it up significantly.
*/
bool db_is_empty;
struct csync_owncloud_ctx_s *owncloud_context; struct csync_owncloud_ctx_s *owncloud_context;

View File

@@ -156,8 +156,8 @@ static int _csync_merge_algorithm_visitor(void *obj, void *data) {
} }
if( tmp ) { if( tmp ) {
if( tmp->path ) { len = strlen( tmp->path );
len = strlen( tmp->path ); if( len > 0 ) {
h = c_jhash64((uint8_t *) tmp->path, len, 0); h = c_jhash64((uint8_t *) tmp->path, len, 0);
/* First, check that the file is NOT in our tree (another file with the same name was added) */ /* First, check that the file is NOT in our tree (another file with the same name was added) */
node = c_rbtree_find(ctx->current == REMOTE_REPLICA ? ctx->remote.tree : ctx->local.tree, &h); node = c_rbtree_find(ctx->current == REMOTE_REPLICA ? ctx->remote.tree : ctx->local.tree, &h);

View File

@@ -298,7 +298,7 @@ csync_file_stat_t *csync_statedb_get_stat_by_hash(CSYNC *ctx,
csync_file_stat_t *st = NULL; csync_file_stat_t *st = NULL;
int rc; int rc;
if( !ctx ) { if( !ctx || ctx->db_is_empty ) {
return NULL; return NULL;
} }
@@ -341,7 +341,7 @@ csync_file_stat_t *csync_statedb_get_stat_by_file_id(CSYNC *ctx,
return 0; return 0;
} }
if( !ctx ) { if( !ctx || ctx->db_is_empty ) {
return NULL; return NULL;
} }
@@ -381,7 +381,7 @@ csync_file_stat_t *csync_statedb_get_stat_by_inode(CSYNC *ctx,
return NULL; return NULL;
} }
if( !ctx ) { if( !ctx || ctx->db_is_empty ) {
return NULL; return NULL;
} }
@@ -448,7 +448,7 @@ int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
return -1; return -1;
} }
if( !ctx ) { if( !ctx || ctx->db_is_empty ) {
return -1; return -1;
} }

View File

@@ -306,7 +306,7 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|| !c_streq(fs->remotePerm, tmp->remotePerm))) || !c_streq(fs->remotePerm, tmp->remotePerm)))
|| (ctx->current == LOCAL_REPLICA && fs->inode != tmp->inode); || (ctx->current == LOCAL_REPLICA && fs->inode != tmp->inode);
if (type == CSYNC_FTW_TYPE_DIR && ctx->current == REMOTE_REPLICA if (type == CSYNC_FTW_TYPE_DIR && ctx->current == REMOTE_REPLICA
&& !metadata_differ && !ctx->read_from_db_disabled) { && !metadata_differ && ctx->read_remote_from_db) {
/* If both etag and file id are equal for a directory, read all contents from /* If both etag and file id are equal for a directory, read all contents from
* the database. * the database.
* The metadata comparison ensure that we fetch all the file id or permission when * The metadata comparison ensure that we fetch all the file id or permission when

View File

@@ -20,6 +20,7 @@
#include "c_lib.h" #include "c_lib.h"
#include "csync.h" #include "csync.h"
#include "csync_log.h"
csync_vio_file_stat_t *csync_vio_file_stat_new(void) { csync_vio_file_stat_t *csync_vio_file_stat_new(void) {
csync_vio_file_stat_t *file_stat = (csync_vio_file_stat_t *) c_malloc(sizeof(csync_vio_file_stat_t)); csync_vio_file_stat_t *file_stat = (csync_vio_file_stat_t *) c_malloc(sizeof(csync_vio_file_stat_t));
@@ -30,7 +31,9 @@ csync_vio_file_stat_t *csync_vio_file_stat_new(void) {
csync_vio_file_stat_t* csync_vio_file_stat_copy(csync_vio_file_stat_t *file_stat) { csync_vio_file_stat_t* csync_vio_file_stat_copy(csync_vio_file_stat_t *file_stat) {
csync_vio_file_stat_t *file_stat_cpy = csync_vio_file_stat_new(); csync_vio_file_stat_t *file_stat_cpy = csync_vio_file_stat_new();
memcpy(file_stat_cpy, file_stat, sizeof(csync_vio_file_stat_t)); memcpy(file_stat_cpy, file_stat, sizeof(csync_vio_file_stat_t));
file_stat_cpy->etag = c_strdup(file_stat_cpy->etag); if (file_stat_cpy->fields & CSYNC_VIO_FILE_STAT_FIELDS_ETAG) {
file_stat_cpy->etag = c_strdup(file_stat_cpy->etag);
}
if (file_stat_cpy->directDownloadCookies) { if (file_stat_cpy->directDownloadCookies) {
file_stat_cpy->directDownloadCookies = c_strdup(file_stat_cpy->directDownloadCookies); file_stat_cpy->directDownloadCookies = c_strdup(file_stat_cpy->directDownloadCookies);
} }
@@ -68,6 +71,7 @@ void csync_vio_file_stat_set_file_id( csync_vio_file_stat_t *dst, const char* sr
void csync_vio_set_file_id( char* dst, const char *src ) { void csync_vio_set_file_id( char* dst, const char *src ) {
if( src && dst ) { if( src && dst ) {
if( strlen(src) > FILE_ID_BUF_SIZE ) { if( strlen(src) > FILE_ID_BUF_SIZE ) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Ignoring file_id because it is too long: %s", src);
strcpy(dst, ""); strcpy(dst, "");
} else { } else {
strcpy(dst, src); strcpy(dst, src);

View File

@@ -151,9 +151,9 @@ ownCloud Client provides the ability to add custom patterns.
By default, the ownCloud Client ignores the following files: By default, the ownCloud Client ignores the following files:
- Files matched by one of the patterns defined in :ref:`ignoredFilesEditor-label`. * Files matched by one of the patterns defined in the Ignored Files Editor
- Files containing characters that do not work on certain file systems (`\, /, :, ?, *, ", >, <, |`). * Files containing characters that do not work on certain file systems ``(`\, /, :, ?, *, ", >, <, |`)``.
* Files starting in ``.csync_journal.db*``, as these files are reserved for journalling. * Files starting in ``.csync_journal.db``, as these files are reserved for journalling.
If a pattern selected using a checkbox in the `ignoredFilesEditor-label` (or if If a pattern selected using a checkbox in the `ignoredFilesEditor-label` (or if
a line in the exclude file starts with the character `]` directly followed by a line in the exclude file starts with the character `]` directly followed by
@@ -212,62 +212,61 @@ In the communication between client and server a couple of custom WebDAV propert
were introduced. They are either needed for sync functionality or help have a positive were introduced. They are either needed for sync functionality or help have a positive
effect on synchronization performance. effect on synchronization performance.
This chapter describes additional xml elemeents which the server returns in response This chapter describes additional xml elements which the server returns in response
to a successful PROPFIND request on a file or directory. The elemnts are returned in to a successful PROPFIND request on a file or directory. The elements are returned in
the namespace oc. the namespace oc.
###Server Side Permissions Server Side Permissions
------------------------
The XML element <oc:permissions> represents the permission- and sharing state of the The XML element ``<oc:permissions>`` represents the permission- and sharing state of the
item. It is a list of characters, and each of the chars has a meaning as outlined item. It is a list of characters, and each of the chars has a meaning as outlined
in the table below: in the table below:
+------+-------------+-------------------------------------------+ +----+----------------+-------------------------------------------+
| Code | Resource | Description | |Code| Resource | Description |
|======+=============+===========================================| +----+----------------+-------------------------------------------+
| S | File or Folder | is shared | | S | File or Folder | is shared |
+---+----------------+-------------------------------------------| +----+----------------+-------------------------------------------+
| R | File or Folder | can share (includes reshare) | | R | File or Folder | can share (includes reshare) |
+---+----------------+-------------------------------------------| +----+----------------+-------------------------------------------+
| M | File or Folder | is mounted (like on DropBox, Samba, etc.) | | M | File or Folder | is mounted (like on DropBox, Samba, etc.) |
+---+----------------+-------------------------------------------| +----+----------------+-------------------------------------------+
| W | File | can write file | | W | File | can write file |
+---+----------------+-------------------------------------------| +----+----------------+-------------------------------------------+
| C | Folder |can create file in folder | | C | Folder |can create file in folder |
+---+----------------+-------------------------------------------| +----+----------------+-------------------------------------------+
| K | Folder | can create folder (mkdir) | | K | Folder | can create folder (mkdir) |
+---+----------------+-------------------------------------------| +----+----------------+-------------------------------------------+
| D | File or Folder |can delete file or folder | | D | File or Folder |can delete file or folder |
+---+----------------+-------------------------------------------| +----+----------------+-------------------------------------------+
| N | File or Folder | can rename file or folder | | N | File or Folder | can rename file or folder |
+---+----------------+-------------------------------------------| +----+----------------+-------------------------------------------+
| V | File or Folder | can move file or folder | | V | File or Folder | can move file or folder |
+---+----------------+-------------------------------------------| +----+----------------+-------------------------------------------+
Example: Example:
```
<oc:permissions>RDNVCK</oc:permissions>
```
###File- or Directory Size <oc:permissions>RDNVCK</oc:permissions>
The XML element <oc:size> represents the file- or directory size in bytes. For File- or Directory Size
-----------------------
The XML element ``<oc:size>`` represents the file- or directory size in bytes. For
directories, the size of the whole file tree underneath the directory is accumulated. directories, the size of the whole file tree underneath the directory is accumulated.
Example: Example:
```
<oc:size>2429176697</oc:size>
```
###FileID <oc:size>2429176697</oc:size>
FileID
------
The XML element <oc:id> represents the so called file ID. It is a non volatile string id The XML element ``<oc:id>`` represents the so called file ID. It is a non volatile string id
that stays constant as long as the file exists. It is not changed if the file changes or that stays constant as long as the file exists. It is not changed if the file changes or
is renamed or moved. is renamed or moved.
Example: Example:
```
<oc:id>00000020oc5cfy6qqizm</oc:id> <oc:id>00000020oc5cfy6qqizm</oc:id>
```

View File

@@ -18,6 +18,9 @@ and then use their package managers to install the desktop sync client. Linux
users will also update their sync clients via package manager, and the client users will also update their sync clients via package manager, and the client
will display a notification when an update is available. will display a notification when an update is available.
Linux users must also have a password manager enabled, such as GNOME Keyring or
KWallet, so that the sync client can login automatically.
Improvements and New Features Improvements and New Features
----------------------------- -----------------------------

View File

@@ -67,7 +67,7 @@ class SocketConnect(GObject.GObject):
print("Sending failed.") print("Sending failed.")
self.reconnect() self.reconnect()
else: else:
print "Cannot send, not connected!" print("Cannot send, not connected!")
def addListener(self, listener): def addListener(self, listener):
self._listeners.append(listener) self._listeners.append(listener)
@@ -85,7 +85,7 @@ class SocketConnect(GObject.GObject):
self.connected = True self.connected = True
print("Setting connected to %r" % self.connected ) print("Setting connected to %r" % self.connected )
self._watch_id = GObject.io_add_watch(self._sock, GObject.IO_IN, self._handle_notify) self._watch_id = GObject.io_add_watch(self._sock, GObject.IO_IN, self._handle_notify)
print "Socket watch id: "+str(self._watch_id) print("Socket watch id: "+str(self._watch_id))
return False # don't run again return False # don't run again
except Exception as e: except Exception as e:
print("Could not connect to unix socket." + str(e)) print("Could not connect to unix socket." + str(e))
@@ -175,7 +175,7 @@ class MenuExtension(GObject.GObject, Nautilus.MenuProvider):
def menu_share(self, menu, file): def menu_share(self, menu, file):
filename = get_local_path(file.get_uri()) filename = get_local_path(file.get_uri())
print "Share file "+filename print("Share file "+filename)
socketConnect.sendCommand("SHARE:"+filename+"\n") socketConnect.sendCommand("SHARE:"+filename+"\n")

View File

@@ -168,7 +168,7 @@ IFACEMETHODIMP OCContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT
assert(!info.shareMenuTitle.empty()); assert(!info.shareMenuTitle.empty());
MENUITEMINFO mii = { sizeof(mii) }; MENUITEMINFO mii = { sizeof(mii) };
mii.fMask = MIIM_BITMAP | MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_STATE; mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_STATE;
mii.wID = idCmdFirst + IDM_SHARE; mii.wID = idCmdFirst + IDM_SHARE;
mii.fType = MFT_STRING; mii.fType = MFT_STRING;
mii.dwTypeData = &info.shareMenuTitle[0]; mii.dwTypeData = &info.shareMenuTitle[0];

View File

@@ -83,7 +83,6 @@
<PrecompiledHeader>Use</PrecompiledHeader> <PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;OCCONTEXTMENU_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\OCUtil;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\OCUtil;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
@@ -101,8 +100,8 @@
<Optimization>MaxSpeed</Optimization> <Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;OCCONTEXTMENU_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\OCUtil;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\OCUtil;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;_USING_V110_SDK71_;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
@@ -132,6 +131,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile> <ClCompile>
<AdditionalIncludeDirectories>..\OCUtil;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\OCUtil;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;_USING_V110_SDK71_;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalLibraryDirectories>..\$(Configuration)\$(Platform);</AdditionalLibraryDirectories> <AdditionalLibraryDirectories>..\$(Configuration)\$(Platform);</AdditionalLibraryDirectories>

View File

@@ -127,6 +127,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\OCUtil;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\OCUtil;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;_USING_V110_SDK71_;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@@ -145,6 +146,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\OCUtil;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\OCUtil;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;_USING_V110_SDK71_;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>

View File

@@ -120,6 +120,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<PrecompiledHeader>Use</PrecompiledHeader> <PrecompiledHeader>Use</PrecompiledHeader>
<PreprocessorDefinitions>NDEBUG;_USING_V110_SDK71_;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@@ -136,6 +137,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<PrecompiledHeader>Use</PrecompiledHeader> <PrecompiledHeader>Use</PrecompiledHeader>
<PreprocessorDefinitions>NDEBUG;_USING_V110_SDK71_;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>

View File

@@ -194,6 +194,9 @@ void parseOptions( const QStringList& app_args, CmdOptions *options )
if (options->target_url.startsWith("http")) if (options->target_url.startsWith("http"))
options->target_url.replace(0, 4, "owncloud"); options->target_url.replace(0, 4, "owncloud");
options->source_dir = args.takeLast(); options->source_dir = args.takeLast();
if (!options->source_dir.endsWith('/')) {
options->source_dir.append('/');
}
if( !QFile::exists( options->source_dir )) { if( !QFile::exists( options->source_dir )) {
std::cerr << "Source dir '" << qPrintable(options->source_dir) << "' does not exist." << std::endl; std::cerr << "Source dir '" << qPrintable(options->source_dir) << "' does not exist." << std::endl;
exit(1); exit(1);
@@ -442,7 +445,9 @@ restart_sync:
if (!f.open(QFile::ReadOnly)) { if (!f.open(QFile::ReadOnly)) {
qCritical() << "Could not open file containing the list of unsynced folders: " << options.unsyncedfolders; qCritical() << "Could not open file containing the list of unsynced folders: " << options.unsyncedfolders;
} else { } else {
selectiveSyncList = QString::fromUtf8(f.readAll()).split('\n'); // filter out empty lines and comments
selectiveSyncList = QString::fromUtf8(f.readAll()).split('\n').filter(QRegExp("\\S+")).filter(QRegExp("^[^#]"));
for (int i = 0; i < selectiveSyncList.count(); ++i) { for (int i = 0; i < selectiveSyncList.count(); ++i) {
if (!selectiveSyncList.at(i).endsWith(QLatin1Char('/'))) { if (!selectiveSyncList.at(i).endsWith(QLatin1Char('/'))) {
selectiveSyncList[i].append(QLatin1Char('/')); selectiveSyncList[i].append(QLatin1Char('/'));

View File

@@ -15,9 +15,10 @@
#include "account.h" #include "account.h"
#include "simplesslerrorhandler.h" #include "simplesslerrorhandler.h"
bool SimpleSslErrorHandler::handleErrors(QList<QSslError> errors, QList<QSslCertificate> *certs, OCC::AccountPtr account) bool SimpleSslErrorHandler::handleErrors(QList<QSslError> errors, const QSslConfiguration &conf, QList<QSslCertificate> *certs, OCC::AccountPtr account)
{ {
(void) account; (void) account;
(void) conf;
if (!certs) { if (!certs) {
qDebug() << "Certs parameter required but is NULL!"; qDebug() << "Certs parameter required but is NULL!";

View File

@@ -20,7 +20,7 @@ class QSslCertificate;
class SimpleSslErrorHandler : public OCC::AbstractSslErrorHandler { class SimpleSslErrorHandler : public OCC::AbstractSslErrorHandler {
public: public:
bool handleErrors(QList<QSslError> errors, QList<QSslCertificate> *certs, OCC::AccountPtr) Q_DECL_OVERRIDE; bool handleErrors(QList<QSslError> errors, const QSslConfiguration &conf, QList<QSslCertificate> *certs, OCC::AccountPtr) Q_DECL_OVERRIDE;
}; };
#endif // SIMPLESSLERRORHANDLER_H #endif // SIMPLESSLERRORHANDLER_H

View File

@@ -154,10 +154,19 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}
qt_add_translation(client_I18N ${TRANSLATIONS}) qt_add_translation(client_I18N ${TRANSLATIONS})
IF( WIN32 )
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/version.rc.in
${CMAKE_CURRENT_BINARY_DIR}/version.rc
@ONLY)
set(client_version ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
ENDIF()
set( final_src set( final_src
${MIRALL_RC_SRC} ${MIRALL_RC_SRC}
${client_SRCS} ${client_SRCS}
${client_UI_SRCS} ${client_UI_SRCS}
${client_version}
${guiMoc} ${guiMoc}
${client_I18N} ${client_I18N}
${3rdparty_SRC} ${3rdparty_SRC}

View File

@@ -43,7 +43,9 @@ void AccountStateManager::setAccountState(AccountState *accountState)
emit accountStateRemoved(_accountState); emit accountStateRemoved(_accountState);
} }
_accountState = accountState; _accountState = accountState;
emit accountStateAdded(accountState); if (accountState) {
emit accountStateAdded(accountState);
}
} }
void AccountStateManager::slotAccountAdded(AccountPtr account) void AccountStateManager::slotAccountAdded(AccountPtr account)
@@ -54,13 +56,15 @@ void AccountStateManager::slotAccountAdded(AccountPtr account)
AccountState::AccountState(AccountPtr account) AccountState::AccountState(AccountPtr account)
: QObject(account.data()) : QObject(account.data())
, _account(account) , _account(account)
, _quotaInfo(new QuotaInfo(this)) , _quotaInfo(0)
, _state(AccountState::Disconnected) , _state(AccountState::Disconnected)
, _connectionStatus(ConnectionValidator::Undefined) , _connectionStatus(ConnectionValidator::Undefined)
, _waitingForNewCredentials(false) , _waitingForNewCredentials(false)
{ {
qRegisterMetaType<AccountState*>("AccountState*"); qRegisterMetaType<AccountState*>("AccountState*");
_quotaInfo = new QuotaInfo(this); // Need to be initialized when 'this' is fully initialized
connect(account.data(), SIGNAL(invalidCredentials()), connect(account.data(), SIGNAL(invalidCredentials()),
SLOT(slotInvalidCredentials())); SLOT(slotInvalidCredentials()));
connect(account.data(), SIGNAL(credentialsFetched(AbstractCredentials*)), connect(account.data(), SIGNAL(credentialsFetched(AbstractCredentials*)),
@@ -179,6 +183,15 @@ void AccountState::checkConnectivity()
conValidator->checkAuthentication(); conValidator->checkAuthentication();
} else { } else {
// Check the server and then the auth. // Check the server and then the auth.
#ifdef Q_OS_WIN
// There seems to be a bug in Qt on Windows where QNAM sometimes stops
// working correctly after the computer woke up from sleep. See #2895 #2899
// and #2973.
// As an attempted workaround, reset the QNAM regularly if the account is
// disconnected.
account()->resetNetworkAccessManager();
#endif
conValidator->checkServerAndAuth(); conValidator->checkServerAndAuth();
} }
} }

View File

@@ -42,6 +42,10 @@
#include <windows.h> #include <windows.h>
#endif #endif
#if defined(WITH_CRASHREPORTER)
#include <libcrashreporter-handler/Handler.h>
#endif
#include <QTranslator> #include <QTranslator>
#include <QMenu> #include <QMenu>
#include <QMessageBox> #include <QMessageBox>
@@ -106,6 +110,11 @@ Application::Application(int &argc, char **argv) :
if (isRunning()) if (isRunning())
return; return;
#if defined(WITH_CRASHREPORTER)
if (ConfigFile().crashReporter())
_crashHandler.reset(new CrashReporter::Handler( QDir::tempPath(), true, CRASHREPORTER_EXECUTABLE ));
#endif
setupLogging(); setupLogging();
setupTranslations(); setupTranslations();
@@ -171,7 +180,8 @@ Application::Application(int &argc, char **argv) :
Application::~Application() Application::~Application()
{ {
// qDebug() << "* OCC shutdown"; // Remove the account from the account manager so it can be deleted.
AccountManager::instance()->setAccount(AccountPtr());
} }
void Application::slotLogin() void Application::slotLogin()
@@ -394,7 +404,10 @@ void Application::parseOptions(const QStringList &options)
} else if (option == QLatin1String("--confdir")) { } else if (option == QLatin1String("--confdir")) {
if (it.hasNext() && !it.peekNext().startsWith(QLatin1String("--"))) { if (it.hasNext() && !it.peekNext().startsWith(QLatin1String("--"))) {
QString confDir = it.next(); QString confDir = it.next();
ConfigFile::setConfDir( confDir ); if (!ConfigFile::setConfDir( confDir )) {
std::cerr << "Invalid path passed to --confdir" << std::endl;
std::exit(1);
}
} else { } else {
showHelp(); showHelp();
} }

View File

@@ -34,6 +34,10 @@ class QMessageBox;
class QSystemTrayIcon; class QSystemTrayIcon;
class QSocket; class QSocket;
namespace CrashReporter {
class Handler;
}
namespace OCC { namespace OCC {
class Theme; class Theme;
class Folder; class Folder;
@@ -109,6 +113,9 @@ private:
QTimer _checkConnectionTimer; QTimer _checkConnectionTimer;
#if defined(WITH_CRASHREPORTER)
QScopedPointer<CrashReporter::Handler> _crashHandler;
#endif
QScopedPointer<FolderMan> _folderManager; QScopedPointer<FolderMan> _folderManager;
friend class ownCloudGui; // for _startupNetworkError friend class ownCloudGui; // for _startupNetworkError

View File

@@ -873,6 +873,13 @@ void FolderMan::setDirtyProxy(bool value)
foreach( Folder *f, _folderMap.values() ) { foreach( Folder *f, _folderMap.values() ) {
if(f) { if(f) {
f->setProxyDirty(value); f->setProxyDirty(value);
if (f->accountState() && f->accountState()->account()
&& f->accountState()->account()->networkAccessManager()) {
// Need to do this have us not use the old determined system proxy
f->accountState()->account()->networkAccessManager()->setProxy(
QNetworkProxy(QNetworkProxy::DefaultProxy));
}
} }
} }
} }

View File

@@ -239,10 +239,19 @@ FolderWizardRemotePath::FolderWizardRemotePath(AccountPtr account)
connect(_ui.addFolderButton, SIGNAL(clicked()), SLOT(slotAddRemoteFolder())); connect(_ui.addFolderButton, SIGNAL(clicked()), SLOT(slotAddRemoteFolder()));
connect(_ui.refreshButton, SIGNAL(clicked()), SLOT(slotRefreshFolders())); connect(_ui.refreshButton, SIGNAL(clicked()), SLOT(slotRefreshFolders()));
connect(_ui.folderTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem*,int)), SIGNAL(completeChanged()));
connect(_ui.folderTreeWidget, SIGNAL(itemActivated(QTreeWidgetItem*,int)), SIGNAL(completeChanged()));
connect(_ui.folderTreeWidget, SIGNAL(itemExpanded(QTreeWidgetItem*)), SLOT(slotItemExpanded(QTreeWidgetItem*))); connect(_ui.folderTreeWidget, SIGNAL(itemExpanded(QTreeWidgetItem*)), SLOT(slotItemExpanded(QTreeWidgetItem*)));
connect(_ui.folderTreeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(slotCurrentItemChanged(QTreeWidgetItem*)));
connect(_ui.folderEntry, SIGNAL(textEdited(QString)), SLOT(slotFolderEntryEdited(QString)));
_lscolTimer.setInterval(500);
_lscolTimer.setSingleShot(true);
connect(&_lscolTimer, SIGNAL(timeout()), SLOT(slotLsColFolderEntry()));
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
_ui.folderTreeWidget->header()->setSectionResizeMode(0,QHeaderView::ResizeToContents);
// Make sure that there will be a scrollbar when the contents is too wide
_ui.folderTreeWidget->header()->setStretchLastSection(false);
#endif
} }
void FolderWizardRemotePath::slotAddRemoteFolder() void FolderWizardRemotePath::slotAddRemoteFolder()
@@ -288,6 +297,8 @@ void FolderWizardRemotePath::slotCreateRemoteFolderFinished(QNetworkReply::Netwo
qDebug() << "** webdav mkdir request finished"; qDebug() << "** webdav mkdir request finished";
showWarn(tr("Folder was successfully created on %1.").arg(Theme::instance()->appNameGUI())); showWarn(tr("Folder was successfully created on %1.").arg(Theme::instance()->appNameGUI()));
slotRefreshFolders(); slotRefreshFolders();
_ui.folderEntry->setText(static_cast<MkColJob *>(sender())->path());
slotLsColFolderEntry();
} }
} }
@@ -315,27 +326,58 @@ static QTreeWidgetItem* findFirstChild(QTreeWidgetItem *parent, const QString& t
void FolderWizardRemotePath::recursiveInsert(QTreeWidgetItem *parent, QStringList pathTrail, QString path) void FolderWizardRemotePath::recursiveInsert(QTreeWidgetItem *parent, QStringList pathTrail, QString path)
{ {
QFileIconProvider prov; if (pathTrail.isEmpty())
QIcon folderIcon = prov.icon(QFileIconProvider::Folder); return;
if (pathTrail.size() == 0) {
if (path.endsWith('/')) {
path.chop(1);
}
parent->setToolTip(0, path);
parent->setData(0, Qt::UserRole, path);
} else {
QTreeWidgetItem *item = findFirstChild(parent, pathTrail.first());
if (!item) {
item = new QTreeWidgetItem(parent);
item->setIcon(0, folderIcon);
item->setText(0, pathTrail.first());
item->setData(0, Qt::UserRole, pathTrail.first());
item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
}
pathTrail.removeFirst(); const QString parentPath = parent->data(0, Qt::UserRole).toString();
recursiveInsert(item, pathTrail, path); const QString folderName = pathTrail.first();
QString folderPath;
if (parentPath == QLatin1String("/")) {
folderPath = folderName;
} else {
folderPath = parentPath + "/" + folderName;
} }
QTreeWidgetItem *item = findFirstChild(parent, folderName);
if (!item) {
item = new QTreeWidgetItem(parent);
QFileIconProvider prov;
QIcon folderIcon = prov.icon(QFileIconProvider::Folder);
item->setIcon(0, folderIcon);
item->setText(0, folderName);
item->setData(0, Qt::UserRole, folderPath);
item->setToolTip(0, folderPath);
item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
}
pathTrail.removeFirst();
recursiveInsert(item, pathTrail, path);
}
bool FolderWizardRemotePath::selectByPath(QString path)
{
if (path.startsWith(QLatin1Char('/'))) {
path = path.mid(1);
}
if (path.endsWith(QLatin1Char('/'))) {
path.chop(1);
}
QTreeWidgetItem *it = _ui.folderTreeWidget->topLevelItem(0);
if (!path.isEmpty()) {
const QStringList pathTrail = path.split(QLatin1Char('/'));
foreach (const QString& path, pathTrail) {
if (!it) {
return false;
}
it = findFirstChild(it, path);
}
}
if (!it) {
return false;
}
_ui.folderTreeWidget->setCurrentItem(it);
return true;
} }
void FolderWizardRemotePath::slotUpdateDirectories(const QStringList &list) void FolderWizardRemotePath::slotUpdateDirectories(const QStringList &list)
@@ -367,6 +409,7 @@ void FolderWizardRemotePath::slotRefreshFolders()
SLOT(slotUpdateDirectories(QStringList))); SLOT(slotUpdateDirectories(QStringList)));
job->start(); job->start();
_ui.folderTreeWidget->clear(); _ui.folderTreeWidget->clear();
_ui.folderEntry->clear();
} }
void FolderWizardRemotePath::slotItemExpanded(QTreeWidgetItem *item) void FolderWizardRemotePath::slotItemExpanded(QTreeWidgetItem *item)
@@ -379,6 +422,49 @@ void FolderWizardRemotePath::slotItemExpanded(QTreeWidgetItem *item)
job->start(); job->start();
} }
void FolderWizardRemotePath::slotCurrentItemChanged(QTreeWidgetItem *item)
{
if (item) {
QString dir = item->data(0, Qt::UserRole).toString();
if (!dir.startsWith(QLatin1Char('/'))) {
dir.prepend(QLatin1Char('/'));
}
_ui.folderEntry->setText(dir);
}
emit completeChanged();
}
void FolderWizardRemotePath::slotFolderEntryEdited(const QString& text)
{
if (selectByPath(text)) {
_lscolTimer.stop();
return;
}
_ui.folderTreeWidget->setCurrentItem(0);
_lscolTimer.start(); // avoid sending a request on each keystroke
}
void FolderWizardRemotePath::slotLsColFolderEntry()
{
QString path = _ui.folderEntry->text();
if (path.startsWith(QLatin1Char('/')))
path = path.mid(1);
LsColJob *job = new LsColJob(_account, path, this);
job->setProperties(QList<QByteArray>() << "resourcetype");
connect(job, SIGNAL(directoryListingSubfolders(QStringList)),
SLOT(slotTypedPathFound(QStringList)));
job->start();
}
void FolderWizardRemotePath::slotTypedPathFound(const QStringList& subpaths)
{
slotUpdateDirectories(subpaths);
selectByPath(_ui.folderEntry->text());
}
FolderWizardRemotePath::~FolderWizardRemotePath() FolderWizardRemotePath::~FolderWizardRemotePath()
{ {
} }

View File

@@ -86,11 +86,17 @@ protected slots:
void slotUpdateDirectories(const QStringList&); void slotUpdateDirectories(const QStringList&);
void slotRefreshFolders(); void slotRefreshFolders();
void slotItemExpanded(QTreeWidgetItem*); void slotItemExpanded(QTreeWidgetItem*);
void slotCurrentItemChanged(QTreeWidgetItem*);
void slotFolderEntryEdited(const QString& text);
void slotLsColFolderEntry();
void slotTypedPathFound(const QStringList& subpaths);
private: private:
void recursiveInsert(QTreeWidgetItem *parent, QStringList pathTrail, QString path); void recursiveInsert(QTreeWidgetItem *parent, QStringList pathTrail, QString path);
bool selectByPath(QString path);
Ui_FolderWizardTargetPage _ui; Ui_FolderWizardTargetPage _ui;
bool _warnWasVisible; bool _warnWasVisible;
AccountPtr _account; AccountPtr _account;
QTimer _lscolTimer;
}; };

View File

@@ -14,7 +14,10 @@
<string>Form</string> <string>Form</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_6"> <layout class="QGridLayout" name="gridLayout_6">
<item row="3" column="0"> <item row="1" column="0">
<widget class="QLineEdit" name="folderEntry"/>
</item>
<item row="2" column="0">
<widget class="QFrame" name="warnFrame"> <widget class="QFrame" name="warnFrame">
<property name="palette"> <property name="palette">
<palette> <palette>
@@ -179,7 +182,7 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="4" column="0"> <item row="3" column="0">
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>

View File

@@ -28,13 +28,6 @@
#include "updater/updater.h" #include "updater/updater.h"
#include "config.h"
#ifdef WITH_CRASHREPORTER
#include "configfile.h"
#include <libcrashreporter-handler/Handler.h>
#endif
#include <QTimer> #include <QTimer>
#include <QMessageBox> #include <QMessageBox>
@@ -59,12 +52,6 @@ int main(int argc, char **argv)
#endif #endif
OCC::Application app(argc, argv); OCC::Application app(argc, argv);
#ifdef WITH_CRASHREPORTER
if (ConfigFile().crashReporter())
new CrashReporter::Handler( QDir::tempPath(), true, CRASHREPORTER_EXECUTABLE );
#endif
#ifndef Q_OS_WIN #ifndef Q_OS_WIN
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
#endif #endif

View File

@@ -145,6 +145,9 @@ void OwncloudSetupWizard::slotDetermineAuthType(const QString &urlString)
} }
AccountPtr account = _ocWizard->account(); AccountPtr account = _ocWizard->account();
account->setUrl(url); account->setUrl(url);
// Reset the proxy which might had been determined previously in ConnectionValidator::checkServerAndAuth()
// when there was a previous account.
account->networkAccessManager()->setProxy(QNetworkProxy(QNetworkProxy::DefaultProxy));
// Set fake credentials beforfe we check what credential it actually is. // Set fake credentials beforfe we check what credential it actually is.
account->setCredentials(CredentialsFactory::create("dummy")); account->setCredentials(CredentialsFactory::create("dummy"));
CheckServerJob *job = new CheckServerJob(_ocWizard->account(), this); CheckServerJob *job = new CheckServerJob(_ocWizard->account(), this);
@@ -214,11 +217,53 @@ void OwncloudSetupWizard::testOwnCloudConnect()
auto *job = new PropfindJob(account, "/", this); auto *job = new PropfindJob(account, "/", this);
job->setIgnoreCredentialFailure(true); job->setIgnoreCredentialFailure(true);
job->setProperties(QList<QByteArray>() << "getlastmodified"); job->setProperties(QList<QByteArray>() << "getlastmodified");
connect(job, SIGNAL(result(QVariantMap)), _ocWizard, SLOT(successfulStep())); connect(job, SIGNAL(result(QVariantMap)), _ocWizard, SLOT(successfulStep()));
connect(job, SIGNAL(networkError(QNetworkReply*)), this, SLOT(slotConnectionCheck(QNetworkReply*))); connect(job, SIGNAL(finishedWithError()), this, SLOT(slotAuthError()));
connect(job, SIGNAL(networkError(QNetworkReply*)), this, SLOT(slotAuthNetworkError(QNetworkReply*)));
job->start(); job->start();
} }
void OwncloudSetupWizard::slotAuthError()
{
QString errorMsg;
PropfindJob* job = qobject_cast<PropfindJob*>(sender());
if (!job) {
qWarning() << "Can't check for authed redirects. This slot should be invoked from PropfindJob!";
return;
}
// If there were redirects on the *authed* requests, also store
// the updated server URL, similar to redirects on status.php.
QUrl redirectUrl = job->reply()->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
if (!redirectUrl.isEmpty()) {
qDebug() << "authed request was redirected to" << redirectUrl.toString();
// strip the expected path
QString path = redirectUrl.path();
static QString expectedPath = "/" + _ocWizard->account()->davPath();
if (path.endsWith(expectedPath)) {
path.chop(expectedPath.size());
redirectUrl.setPath(path);
qDebug() << "setting account url to" << redirectUrl.toString();
_ocWizard->account()->setUrl(redirectUrl);
testOwnCloudConnect();
return;
} else {
errorMsg = tr("The authenticated request to the server was redirected to "
"'%1'. The URL is bad, the server is misconfigured.")
.arg(redirectUrl.toString());
}
}
if (errorMsg.isEmpty()) {
errorMsg = tr("There was an invalid response to an authenticated webdav request");
}
_ocWizard->displayError(errorMsg, false);
_ocWizard->show();
}
bool OwncloudSetupWizard::checkDowngradeAdvised(QNetworkReply* reply) bool OwncloudSetupWizard::checkDowngradeAdvised(QNetworkReply* reply)
{ {
if(reply->url().scheme() != QLatin1String("https")) { if(reply->url().scheme() != QLatin1String("https")) {
@@ -242,7 +287,7 @@ bool OwncloudSetupWizard::checkDowngradeAdvised(QNetworkReply* reply)
return true; return true;
} }
void OwncloudSetupWizard::slotConnectionCheck(QNetworkReply* reply) void OwncloudSetupWizard::slotAuthNetworkError(QNetworkReply* reply)
{ {
QString msg = reply->errorString(); QString msg = reply->errorString();
switch (reply->error()) { switch (reply->error()) {
@@ -291,7 +336,7 @@ void OwncloudSetupWizard::slotCreateLocalAndRemoteFolders(const QString& localFo
} }
if (nextStep) { if (nextStep) {
EntityExistsJob *job = new EntityExistsJob(_ocWizard->account(), _ocWizard->account()->davPath() + remoteFolder, this); EntityExistsJob *job = new EntityExistsJob(_ocWizard->account(), _ocWizard->account()->davPath() + remoteFolder, this);
connect(job, SIGNAL(exists(QNetworkReply*)), SLOT(slotAuthCheckReply(QNetworkReply*))); connect(job, SIGNAL(exists(QNetworkReply*)), SLOT(slotRemoteFolderExists(QNetworkReply*)));
job->start(); job->start();
} else { } else {
finalizeSetup( false ); finalizeSetup( false );
@@ -299,7 +344,7 @@ void OwncloudSetupWizard::slotCreateLocalAndRemoteFolders(const QString& localFo
} }
// ### TODO move into EntityExistsJob once we decide if/how to return gui strings from jobs // ### TODO move into EntityExistsJob once we decide if/how to return gui strings from jobs
void OwncloudSetupWizard::slotAuthCheckReply(QNetworkReply *reply) void OwncloudSetupWizard::slotRemoteFolderExists(QNetworkReply *reply)
{ {
bool ok = true; bool ok = true;
QString error; QString error;
@@ -519,8 +564,10 @@ bool DetermineAuthTypeJob::finished()
} else if (redirection.toString().endsWith(account()->davPath())) { } else if (redirection.toString().endsWith(account()->davPath())) {
// do a new run // do a new run
_redirects++; _redirects++;
resetTimeout();
setReply(getRequest(redirection)); setReply(getRequest(redirection));
setupConnections(reply()); setupConnections(reply());
return false; // don't discard
} else { } else {
QRegExp shibbolethyWords("SAML|wayf"); QRegExp shibbolethyWords("SAML|wayf");

View File

@@ -62,10 +62,11 @@ private slots:
void slotNoOwnCloudFoundAuthTimeout(const QUrl&url); void slotNoOwnCloudFoundAuthTimeout(const QUrl&url);
void slotConnectToOCUrl(const QString&); void slotConnectToOCUrl(const QString&);
void slotConnectionCheck(QNetworkReply*); void slotAuthNetworkError(QNetworkReply*);
void slotAuthError();
void slotCreateLocalAndRemoteFolders(const QString&, const QString&); void slotCreateLocalAndRemoteFolders(const QString&, const QString&);
void slotAuthCheckReply(QNetworkReply*); void slotRemoteFolderExists(QNetworkReply*);
void slotCreateRemoteFolderFinished(QNetworkReply::NetworkError); void slotCreateRemoteFolderFinished(QNetworkReply::NetworkError);
void slotAssistantFinished( int ); void slotAssistantFinished( int );
void slotSkipFolderConfiguration(); void slotSkipFolderConfiguration();

View File

@@ -73,16 +73,10 @@ ProtocolWidget::ProtocolWidget(QWidget *parent) :
_copyBtn->setToolTip( tr("Copy the activity list to the clipboard.")); _copyBtn->setToolTip( tr("Copy the activity list to the clipboard."));
_copyBtn->setEnabled(false); _copyBtn->setEnabled(false);
connect(_copyBtn, SIGNAL(clicked()), SLOT(copyToClipboard())); connect(_copyBtn, SIGNAL(clicked()), SLOT(copyToClipboard()));
ConfigFile cfg;
cfg.restoreGeometryHeader(_ui->_treeWidget->header());
} }
ProtocolWidget::~ProtocolWidget() ProtocolWidget::~ProtocolWidget()
{ {
ConfigFile cfg;
cfg.saveGeometryHeader(_ui->_treeWidget->header() );
delete _ui; delete _ui;
} }
@@ -137,6 +131,20 @@ void ProtocolWidget::slotRetrySync()
folderMan->slotScheduleAllFolders(); folderMan->slotScheduleAllFolders();
} }
void ProtocolWidget::showEvent(QShowEvent *ev)
{
ConfigFile cfg;
cfg.restoreGeometryHeader(_ui->_treeWidget->header());
QWidget::showEvent(ev);
}
void ProtocolWidget::hideEvent(QHideEvent *ev)
{
ConfigFile cfg;
cfg.saveGeometryHeader(_ui->_treeWidget->header() );
QWidget::hideEvent(ev);
}
void ProtocolWidget::cleanIgnoreItems(const QString& folder) void ProtocolWidget::cleanIgnoreItems(const QString& folder)
{ {
int itemCnt = _ui->_treeWidget->topLevelItemCount(); int itemCnt = _ui->_treeWidget->topLevelItemCount();
@@ -159,16 +167,11 @@ void ProtocolWidget::cleanIgnoreItems(const QString& folder)
QString ProtocolWidget::timeString(QDateTime dt, QLocale::FormatType format) const QString ProtocolWidget::timeString(QDateTime dt, QLocale::FormatType format) const
{ {
QLocale loc = QLocale::system(); const QLocale loc = QLocale::system();
QString timeStr; QString dtFormat = loc.dateTimeFormat(format);
static const QRegExp re("(HH|H|hh|h):mm(?!:s)");
if( format == QLocale::NarrowFormat ) { dtFormat.replace(re, "\\1:mm:ss");
timeStr = loc.toString(dt, QLocale::NarrowFormat); return loc.toString(dt, dtFormat);
} else {
timeStr = loc.toString(dt, format);
}
return timeStr;
} }
void ProtocolWidget::slotOpenFile( QTreeWidgetItem *item, int ) void ProtocolWidget::slotOpenFile( QTreeWidgetItem *item, int )

View File

@@ -39,8 +39,6 @@ public:
explicit ProtocolWidget(QWidget *parent = 0); explicit ProtocolWidget(QWidget *parent = 0);
~ProtocolWidget(); ~ProtocolWidget();
signals:
public slots: public slots:
void slotProgressInfo( const QString& folder, const Progress::Info& progress ); void slotProgressInfo( const QString& folder, const Progress::Info& progress );
void slotOpenFile( QTreeWidgetItem* item, int ); void slotOpenFile( QTreeWidgetItem* item, int );
@@ -49,6 +47,10 @@ protected slots:
void copyToClipboard(); void copyToClipboard();
void slotRetrySync(); void slotRetrySync();
protected:
void showEvent(QShowEvent *);
void hideEvent(QHideEvent *);
signals: signals:
void guiLog(const QString&, const QString&); void guiLog(const QString&, const QString&);

View File

@@ -26,10 +26,33 @@
#include <QDebug> #include <QDebug>
#include <QSettings> #include <QSettings>
#include <QScopedValueRollback> #include <QScopedValueRollback>
#include <QTreeWidgetItem>
#include <QLabel> #include <QLabel>
namespace OCC { namespace OCC {
class SelectiveSyncTreeViewItem : public QTreeWidgetItem {
public:
SelectiveSyncTreeViewItem(int type = QTreeWidgetItem::Type)
: QTreeWidgetItem(type) { }
SelectiveSyncTreeViewItem(const QStringList &strings, int type = QTreeWidgetItem::Type)
: QTreeWidgetItem(strings, type) { }
SelectiveSyncTreeViewItem(QTreeWidget *view, int type = QTreeWidgetItem::Type)
: QTreeWidgetItem(view, type) { }
SelectiveSyncTreeViewItem(QTreeWidgetItem *parent, int type = QTreeWidgetItem::Type)
: QTreeWidgetItem(parent, type) { }
private:
bool operator<(const QTreeWidgetItem &other)const {
int column = treeWidget()->sortColumn();
if (column == 1) {
return data(1, Qt::UserRole).toLongLong() < other.data(1, Qt::UserRole).toLongLong();
}
return QTreeWidgetItem::operator <(other);
}
};
SelectiveSyncTreeView::SelectiveSyncTreeView(AccountPtr account, QWidget* parent) SelectiveSyncTreeView::SelectiveSyncTreeView(AccountPtr account, QWidget* parent)
: QTreeWidget(parent), _inserting(false), _account(account) : QTreeWidget(parent), _inserting(false), _account(account)
{ {
@@ -101,9 +124,9 @@ void SelectiveSyncTreeView::recursiveInsert(QTreeWidgetItem* parent, QStringList
parent->setToolTip(0, path); parent->setToolTip(0, path);
parent->setData(0, Qt::UserRole, path); parent->setData(0, Qt::UserRole, path);
} else { } else {
QTreeWidgetItem *item = findFirstChild(parent, pathTrail.first()); SelectiveSyncTreeViewItem *item = static_cast<SelectiveSyncTreeViewItem*>(findFirstChild(parent, pathTrail.first()));
if (!item) { if (!item) {
item = new QTreeWidgetItem(parent); item = new SelectiveSyncTreeViewItem(parent);
if (parent->checkState(0) == Qt::Checked if (parent->checkState(0) == Qt::Checked
|| parent->checkState(0) == Qt::PartiallyChecked) { || parent->checkState(0) == Qt::PartiallyChecked) {
item->setCheckState(0, Qt::Checked); item->setCheckState(0, Qt::Checked);
@@ -138,7 +161,7 @@ void SelectiveSyncTreeView::slotUpdateDirectories(const QStringList&list)
QScopedValueRollback<bool> isInserting(_inserting); QScopedValueRollback<bool> isInserting(_inserting);
_inserting = true; _inserting = true;
QTreeWidgetItem *root = topLevelItem(0); SelectiveSyncTreeViewItem *root = static_cast<SelectiveSyncTreeViewItem*>(topLevelItem(0));
if (!root && list.size() <= 1) { if (!root && list.size() <= 1) {
_loading->setText(tr("No subfolders currently on the server.")); _loading->setText(tr("No subfolders currently on the server."));
@@ -149,7 +172,7 @@ void SelectiveSyncTreeView::slotUpdateDirectories(const QStringList&list)
} }
if (!root) { if (!root) {
root = new QTreeWidgetItem(this); root = new SelectiveSyncTreeViewItem(this);
root->setText(0, _rootName); root->setText(0, _rootName);
root->setIcon(0, Theme::instance()->applicationIcon()); root->setIcon(0, Theme::instance()->applicationIcon());
root->setData(0, Qt::UserRole, QString()); root->setData(0, Qt::UserRole, QString());

View File

@@ -21,6 +21,7 @@
#include "folder.h" #include "folder.h"
#include "theme.h" #include "theme.h"
#include "syncresult.h" #include "syncresult.h"
#include "configfile.h"
#include "QProgressIndicator.h" #include "QProgressIndicator.h"
#include <QBuffer> #include <QBuffer>
@@ -44,6 +45,8 @@ ShareDialog::ShareDialog(AccountPtr account, const QString &sharePath, const QSt
_resharingAllowed(resharingAllowed) _resharingAllowed(resharingAllowed)
{ {
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
setObjectName("SharingDialog"); // required as group for saveGeometry call
_ui->setupUi(this); _ui->setupUi(this);
_ui->pushButton_copy->setIcon(QIcon::fromTheme("edit-copy")); _ui->pushButton_copy->setIcon(QIcon::fromTheme("edit-copy"));
_ui->pushButton_copy->setEnabled(false); _ui->pushButton_copy->setEnabled(false);
@@ -84,24 +87,31 @@ ShareDialog::ShareDialog(AccountPtr account, const QString &sharePath, const QSt
QIcon icon = icon_provider.icon(f_info); QIcon icon = icon_provider.icon(f_info);
_ui->label_icon->setPixmap(icon.pixmap(40,40)); _ui->label_icon->setPixmap(icon.pixmap(40,40));
QString name; QFileInfo lPath(_localPath);
if( f_info.isDir() ) { QString fileName = lPath.fileName();
name = tr("Share Directory"); _ui->label_name->setText(tr("%1").arg(fileName));
} else { QFont f( _ui->label_name->font());
name = tr("Share File"); f.setPointSize( f.pointSize() * 1.4 );
} _ui->label_name->setFont( f );
_ui->groupBox->setTitle(name);
QString lPath(_localPath);
if( lPath.length() > 50) {
lPath = QLatin1String("...")+lPath.right(50);
}
_ui->label_name->setText(tr("Local path: %1").arg(lPath));
_ui->label_sharePath->setWordWrap(true); _ui->label_sharePath->setWordWrap(true);
_ui->label_sharePath->setText(tr("%1 path: %2").arg(Theme::instance()->appNameGUI()).arg(_sharePath)); QString ocDir(_sharePath);
ocDir.truncate(ocDir.length()-fileName.length());
if( ocDir == QLatin1String("/")) {
_ui->label_sharePath->setText(QString());
} else {
if( ocDir.startsWith(QLatin1Char('/')) ) {
ocDir = ocDir.mid(1, -1);
}
if( ocDir.endsWith(QLatin1Char('/')) ) {
ocDir.chop(1);
}
_ui->label_sharePath->setText(tr("Folder: %2").arg(ocDir));
}
this->setWindowTitle(tr("%1 Sharing").arg(Theme::instance()->appNameGUI())); this->setWindowTitle(tr("%1 Sharing").arg(Theme::instance()->appNameGUI()));
_ui->label_password->setText(tr("Set p&assword")); _ui->checkBox_password->setText(tr("P&assword protect"));
// check if the file is already inside of a synced folder // check if the file is already inside of a synced folder
if( sharePath.isEmpty() ) { if( sharePath.isEmpty() ) {
// The file is not yet in an ownCloud synced folder. We could automatically // The file is not yet in an ownCloud synced folder. We could automatically
@@ -128,6 +138,12 @@ ShareDialog::ShareDialog(AccountPtr account, const QString &sharePath, const QSt
_ui->errorLabel->hide(); _ui->errorLabel->hide();
} }
void ShareDialog::done( int r ) {
ConfigFile cfg;
cfg.saveGeometry(this);
QDialog::done(r);
}
void ShareDialog::setExpireDate(const QDate &date) void ShareDialog::setExpireDate(const QDate &date)
{ {
if( _public_share_id == 0 ) { if( _public_share_id == 0 ) {
@@ -331,19 +347,40 @@ void ShareDialog::slotSharesFetched(const QString &reply)
} }
} }
void ShareDialog::resizeEvent(QResizeEvent *e)
{
QDialog::resizeEvent(e);
redrawElidedUrl();
}
void ShareDialog::redrawElidedUrl()
{
QString u;
if( !_shareUrl.isEmpty() ) {
QFontMetrics fm( _ui->_labelShareLink->font() );
int linkLengthPixel = _ui->_labelShareLink->width();
const QUrl realUrl(_shareUrl);
QString elidedUrl = fm.elidedText(_shareUrl, Qt::ElideRight, linkLengthPixel);
u = QString("<a href=\"%1\">%2</a>").arg(realUrl.toString(QUrl::None)).arg(elidedUrl);
}
_ui->_labelShareLink->setText(u);
}
void ShareDialog::setShareLink( const QString& url ) void ShareDialog::setShareLink( const QString& url )
{ {
// FIXME: shorten the url for output. // FIXME: shorten the url for output.
const QUrl realUrl(url); const QUrl realUrl(url);
if( realUrl.isValid() ) { if( realUrl.isValid() ) {
const QString u = QString("<a href=\"%1\">%2</a>").arg(realUrl.toString(QUrl::None)).arg(url);
_ui->_labelShareLink->setText(u);
_shareUrl = url; _shareUrl = url;
_ui->pushButton_copy->setEnabled(true); _ui->pushButton_copy->setEnabled(true);
} else { } else {
_shareUrl.clear(); _shareUrl.clear();
_ui->_labelShareLink->setText(QString::null); _ui->_labelShareLink->setText(QString::null);
} }
redrawElidedUrl();
} }
@@ -407,7 +444,7 @@ void ShareDialog::slotCreateShareFetched(const QString &reply)
// there needs to be a password // there needs to be a password
_ui->checkBox_password->setChecked(true); _ui->checkBox_password->setChecked(true);
_ui->checkBox_password->setVisible(false); _ui->checkBox_password->setVisible(false);
_ui->label_password->setText(tr("Public sh&aring requires a password:")); _ui->checkBox_password->setText(tr("Public sh&aring requires a password:"));
_ui->lineEdit_password->setFocus(); _ui->lineEdit_password->setFocus();
_ui->widget_shareLink->show(); _ui->widget_shareLink->show();
@@ -421,13 +458,7 @@ void ShareDialog::slotCreateShareFetched(const QString &reply)
bool success; bool success;
QVariantMap json = QtJson::parse(reply, success).toMap(); QVariantMap json = QtJson::parse(reply, success).toMap();
_public_share_id = json.value("ocs").toMap().values("data")[0].toMap().value("id").toULongLong(); _public_share_id = json.value("ocs").toMap().values("data")[0].toMap().value("id").toULongLong();
QString url = json.value("ocs").toMap().values("data")[0].toMap().value("url").toString(); getShares();
setShareLink(url);
setShareCheckBoxTitle(true);
_ui->widget_shareLink->show();
} }
void ShareDialog::slotCheckBoxPasswordClicked() void ShareDialog::slotCheckBoxPasswordClicked()
@@ -487,8 +518,8 @@ int ShareDialog::checkJsonReturnCode(const QString &reply, QString &message)
void ShareDialog::setShareCheckBoxTitle(bool haveShares) void ShareDialog::setShareCheckBoxTitle(bool haveShares)
{ {
const QString noSharesTitle(tr("Check to &share by public link")); const QString noSharesTitle(tr("&Share link"));
const QString haveSharesTitle(tr("&Shared by public link (uncheck to delete share)")); const QString haveSharesTitle(tr("&Share link"));
if( haveShares ) { if( haveShares ) {
_ui->checkBox_shareLink->setText( haveSharesTitle ); _ui->checkBox_shareLink->setText( haveSharesTitle );

View File

@@ -76,11 +76,15 @@ private slots:
void slotPasswordChanged(const QString& newText); void slotPasswordChanged(const QString& newText);
void slotPushButtonCopyLinkPressed(); void slotPushButtonCopyLinkPressed();
void slotThumbnailFetched(const int &statusCode, const QByteArray &reply); void slotThumbnailFetched(const int &statusCode, const QByteArray &reply);
void done( int r );
private: private:
void setShareCheckBoxTitle(bool haveShares); void setShareCheckBoxTitle(bool haveShares);
void displayError(int code); void displayError(int code);
void displayError(const QString& errMsg); void displayError(const QString& errMsg);
void setShareLink( const QString& url ); void setShareLink( const QString& url );
void resizeEvent(QResizeEvent *e);
void redrawElidedUrl();
Ui::ShareDialog *_ui; Ui::ShareDialog *_ui;
AccountPtr _account; AccountPtr _account;

View File

@@ -6,23 +6,71 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>403</width> <width>372</width>
<height>296</height> <height>241</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Share NewDocument.odt</string> <string>Share NewDocument.odt</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_4"> <layout class="QGridLayout" name="gridLayout_3">
<item row="4" column="0"> <item row="0" column="0" colspan="2">
<widget class="QLabel" name="errorLabel"> <layout class="QGridLayout" name="gridLayout">
<property name="text"> <item row="0" column="0" rowspan="2">
<string>TextLabel</string> <widget class="QLabel" name="label_icon">
</property> <property name="text">
</widget> <string>TextLabel</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_name">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>share label</string>
</property>
</widget>
</item>
<item row="0" column="2" rowspan="2">
<widget class="QProgressIndicator" name="pi_share" native="true"/>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_sharePath">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>ownCloud Path:</string>
</property>
</widget>
</item>
</layout>
</item> </item>
<item row="1" column="0"> <item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_shareLink"> <layout class="QHBoxLayout" name="horizontalLayout_shareLink">
<property name="topMargin">
<number>10</number>
</property>
<item> <item>
<widget class="QCheckBox" name="checkBox_shareLink"> <widget class="QCheckBox" name="checkBox_shareLink">
<property name="text"> <property name="text">
@@ -34,8 +82,14 @@
</item> </item>
<item row="2" column="0" colspan="2"> <item row="2" column="0" colspan="2">
<widget class="QWidget" name="widget_shareLink" native="true"> <widget class="QWidget" name="widget_shareLink" native="true">
<layout class="QGridLayout" name="gridLayout_3"> <layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>20</number>
</property>
<property name="topMargin"> <property name="topMargin">
<number>1</number>
</property>
<property name="rightMargin">
<number>0</number> <number>0</number>
</property> </property>
<item row="0" column="0"> <item row="0" column="0">
@@ -68,7 +122,7 @@
<item> <item>
<widget class="QPushButton" name="pushButton_copy"> <widget class="QPushButton" name="pushButton_copy">
<property name="text"> <property name="text">
<string>Copy &amp;Link</string> <string>Copy &amp;link</string>
</property> </property>
</widget> </widget>
</item> </item>
@@ -79,30 +133,36 @@
<item> <item>
<widget class="QCheckBox" name="checkBox_password"> <widget class="QCheckBox" name="checkBox_password">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="text"> <property name="text">
<string/> <string>Set password</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="label_password"> <spacer name="horizontalSpacer_3">
<property name="text"> <property name="orientation">
<string>Set p&amp;assword</string> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="buddy"> <property name="sizeHint" stdset="0">
<cstring>checkBox_password</cstring> <size>
<width>40</width>
<height>20</height>
</size>
</property> </property>
</widget> </spacer>
</item> </item>
</layout> </layout>
</item> </item>
<item row="2" column="0"> <item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_14"> <layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>20</number>
</property>
<item> <item>
<widget class="QLineEdit" name="lineEdit_password"> <widget class="QLineEdit" name="lineEdit_password">
<property name="echoMode"> <property name="echoMode">
@@ -112,15 +172,24 @@
</item> </item>
<item> <item>
<widget class="QPushButton" name="pushButton_setPassword"> <widget class="QPushButton" name="pushButton_setPassword">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text"> <property name="text">
<string>Set &amp;Password</string> <string>Set &amp;password </string>
</property> </property>
</widget> </widget>
</item> </item>
</layout> </layout>
</item> </item>
<item row="3" column="0"> <item row="3" column="0">
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<item> <item>
<widget class="QCheckBox" name="checkBox_expire"> <widget class="QCheckBox" name="checkBox_expire">
<property name="text"> <property name="text">
@@ -140,80 +209,6 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="5" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Share Info</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" rowspan="2">
<widget class="QLabel" name="label_icon">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_name">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>share label</string>
</property>
</widget>
</item>
<item row="0" column="2" rowspan="2">
<widget class="QProgressIndicator" name="pi_share" native="true"/>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_sharePath">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>ownCloud Path:</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="3" column="1"> <item row="3" column="1">
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
@@ -227,7 +222,37 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="4" column="0">
<widget class="QLabel" name="errorLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout> </layout>
<zorder>errorLabel</zorder>
<zorder>widget_shareLink</zorder>
<zorder>buttonBox</zorder>
<zorder>checkBox_password</zorder>
</widget> </widget>
<layoutdefault spacing="6" margin="11"/> <layoutdefault spacing="6" margin="11"/>
<customwidgets> <customwidgets>

View File

@@ -1,6 +1,7 @@
/* /*
* Copyright (C) by Dominik Schmidt <dev@dominik-schmidt.de> * Copyright (C) by Dominik Schmidt <dev@dominik-schmidt.de>
* Copyright (C) by Klaas Freitag <freitag@owncloud.com> * Copyright (C) by Klaas Freitag <freitag@owncloud.com>
* Copyright (C) by Roeland Jago Douma <roeland@famdouma.nl>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -24,6 +25,7 @@
#include "syncfileitem.h" #include "syncfileitem.h"
#include "filesystem.h" #include "filesystem.h"
#include "version.h" #include "version.h"
#include "accountstate.h"
#include <QDebug> #include <QDebug>
#include <QUrl> #include <QUrl>
@@ -136,7 +138,9 @@ SocketApi::~SocketApi()
{ {
DEBUG << "dtor"; DEBUG << "dtor";
_localServer.close(); _localServer.close();
qDeleteAll(_listeners); // All remaining sockets will be destroyed with _localServer, their parent
Q_ASSERT(_listeners.isEmpty() || _listeners.first()->parent() == &_localServer);
_listeners.clear();
slotClearExcludesList(); slotClearExcludesList();
} }
@@ -163,7 +167,7 @@ void SocketApi::slotReadExcludes()
void SocketApi::slotNewConnection() void SocketApi::slotNewConnection()
{ {
SocketType* socket = _localServer.nextPendingConnection(); QLocalSocket* socket = _localServer.nextPendingConnection();
if( ! socket ) { if( ! socket ) {
return; return;
@@ -185,8 +189,9 @@ void SocketApi::slotNewConnection()
broadcastMessage(QLatin1String("ICON_PATH"), iconPath ); broadcastMessage(QLatin1String("ICON_PATH"), iconPath );
#endif #endif
foreach( QString alias, FolderMan::instance()->map().keys() ) { foreach( Folder *f, FolderMan::instance()->map() ) {
slotRegisterPath(alias); QString message = buildRegisterPathMessage(f->path());
sendMessage(socket, message);
} }
} }
@@ -194,7 +199,7 @@ void SocketApi::onLostConnection()
{ {
DEBUG << "Lost connection " << sender(); DEBUG << "Lost connection " << sender();
SocketType* socket = qobject_cast<SocketType*>(sender()); QLocalSocket* socket = qobject_cast<QLocalSocket*>(sender());
_listeners.removeAll(socket); _listeners.removeAll(socket);
socket->deleteLater(); socket->deleteLater();
} }
@@ -202,7 +207,7 @@ void SocketApi::onLostConnection()
void SocketApi::slotReadSocket() void SocketApi::slotReadSocket()
{ {
SocketType* socket = qobject_cast<SocketType*>(sender()); QLocalSocket* socket = qobject_cast<QLocalSocket*>(sender());
Q_ASSERT(socket); Q_ASSERT(socket);
while(socket->canReadLine()) { while(socket->canReadLine()) {
@@ -210,12 +215,12 @@ void SocketApi::slotReadSocket()
QString command = line.split(":").first(); QString command = line.split(":").first();
QString function = QString(QLatin1String("command_")).append(command); QString function = QString(QLatin1String("command_")).append(command);
QString functionWithArguments = function + QLatin1String("(QString,SocketType*)"); QString functionWithArguments = function + QLatin1String("(QString,QLocalSocket*)");
int indexOfMethod = this->metaObject()->indexOfMethod(functionWithArguments.toAscii()); int indexOfMethod = this->metaObject()->indexOfMethod(functionWithArguments.toAscii());
QString argument = line.remove(0, command.length()+1).trimmed(); QString argument = line.remove(0, command.length()+1).trimmed();
if(indexOfMethod != -1) { if(indexOfMethod != -1) {
QMetaObject::invokeMethod(this, function.toAscii(), Q_ARG(QString, argument), Q_ARG(SocketType*, socket)); QMetaObject::invokeMethod(this, function.toAscii(), Q_ARG(QString, argument), Q_ARG(QLocalSocket*, socket));
} else { } else {
DEBUG << "The command is not supported by this version of the client:" << command << "with argument:" << argument; DEBUG << "The command is not supported by this version of the client:" << command << "with argument:" << argument;
} }
@@ -226,7 +231,10 @@ void SocketApi::slotRegisterPath( const QString& alias )
{ {
Folder *f = FolderMan::instance()->folder(alias); Folder *f = FolderMan::instance()->folder(alias);
if (f) { if (f) {
broadcastMessage(QLatin1String("REGISTER_PATH"), f->path() ); QString message = buildRegisterPathMessage(f->path());
foreach(QLocalSocket *socket, _listeners) {
sendMessage(socket, message);
}
} }
} }
@@ -329,7 +337,7 @@ void SocketApi::slotSyncItemDiscovered(const QString &folder, const SyncFileItem
void SocketApi::sendMessage(SocketType *socket, const QString& message, bool doWait) void SocketApi::sendMessage(QLocalSocket *socket, const QString& message, bool doWait)
{ {
DEBUG << "Sending message: " << message; DEBUG << "Sending message: " << message;
QString localMessage = message; QString localMessage = message;
@@ -364,12 +372,12 @@ void SocketApi::broadcastMessage( const QString& verb, const QString& path, cons
// sendMessage already has a debug output // sendMessage already has a debug output
//DEBUG << "Broadcasting to" << _listeners.count() << "listeners: " << msg; //DEBUG << "Broadcasting to" << _listeners.count() << "listeners: " << msg;
foreach(SocketType *socket, _listeners) { foreach(QLocalSocket *socket, _listeners) {
sendMessage(socket, msg, doWait); sendMessage(socket, msg, doWait);
} }
} }
void SocketApi::command_RETRIEVE_FOLDER_STATUS(const QString& argument, SocketType* socket) void SocketApi::command_RETRIEVE_FOLDER_STATUS(const QString& argument, QLocalSocket* socket)
{ {
// This command is the same as RETRIEVE_FILE_STATUS // This command is the same as RETRIEVE_FILE_STATUS
@@ -377,7 +385,7 @@ void SocketApi::command_RETRIEVE_FOLDER_STATUS(const QString& argument, SocketTy
command_RETRIEVE_FILE_STATUS(argument, socket); command_RETRIEVE_FILE_STATUS(argument, socket);
} }
void SocketApi::command_RETRIEVE_FILE_STATUS(const QString& argument, SocketType* socket) void SocketApi::command_RETRIEVE_FILE_STATUS(const QString& argument, QLocalSocket* socket)
{ {
if( !socket ) { if( !socket ) {
qDebug() << "No valid socket object."; qDebug() << "No valid socket object.";
@@ -405,7 +413,7 @@ void SocketApi::command_RETRIEVE_FILE_STATUS(const QString& argument, SocketType
sendMessage(socket, message); sendMessage(socket, message);
} }
void SocketApi::command_SHARE(const QString& localFile, SocketType* socket) void SocketApi::command_SHARE(const QString& localFile, QLocalSocket* socket)
{ {
if (!socket) { if (!socket) {
qDebug() << Q_FUNC_INFO << "No valid socket object."; qDebug() << Q_FUNC_INFO << "No valid socket object.";
@@ -419,6 +427,10 @@ void SocketApi::command_SHARE(const QString& localFile, SocketType* socket)
const QString message = QLatin1String("SHARE:NOP:")+QDir::toNativeSeparators(localFile); const QString message = QLatin1String("SHARE:NOP:")+QDir::toNativeSeparators(localFile);
// files that are not within a sync folder are not synced. // files that are not within a sync folder are not synced.
sendMessage(socket, message); sendMessage(socket, message);
} else if (!shareFolder->accountState()->isConnected()) {
const QString message = QLatin1String("SHARE:NOTCONNECTED:")+QDir::toNativeSeparators(localFile);
// if the folder isn't connected, don't open the share dialog
sendMessage(socket, message);
} else { } else {
const QString folderForPath = shareFolder->path(); const QString folderForPath = shareFolder->path();
const QString remotePath = shareFolder->remotePath() + localFile.right(localFile.count()-folderForPath.count()+1); const QString remotePath = shareFolder->remotePath() + localFile.right(localFile.count()-folderForPath.count()+1);
@@ -439,16 +451,24 @@ void SocketApi::command_SHARE(const QString& localFile, SocketType* socket)
} }
} }
void SocketApi::command_VERSION(const QString&, SocketType* socket) void SocketApi::command_VERSION(const QString&, QLocalSocket* socket)
{ {
sendMessage(socket, QLatin1String("VERSION:" MIRALL_VERSION_STRING ":" MIRALL_SOCKET_API_VERSION)); sendMessage(socket, QLatin1String("VERSION:" MIRALL_VERSION_STRING ":" MIRALL_SOCKET_API_VERSION));
} }
void SocketApi::command_SHARE_MENU_TITLE(const QString &, SocketType* socket) void SocketApi::command_SHARE_MENU_TITLE(const QString &, QLocalSocket* socket)
{ {
sendMessage(socket, QLatin1String("SHARE_MENU_TITLE:") + tr("Share with %1", "parameter is ownCloud").arg(Theme::instance()->appNameGUI())); sendMessage(socket, QLatin1String("SHARE_MENU_TITLE:") + tr("Share with %1", "parameter is ownCloud").arg(Theme::instance()->appNameGUI()));
} }
QString SocketApi::buildRegisterPathMessage(const QString& path)
{
QFileInfo fi(path);
QString message = QLatin1String("REGISTER_PATH:");
message.append(QDir::toNativeSeparators(fi.absoluteFilePath()));
return message;
}
SqlQuery* SocketApi::getSqlQuery( Folder *folder ) SqlQuery* SocketApi::getSqlQuery( Folder *folder )
{ {
if( !folder ) { if( !folder ) {

View File

@@ -37,8 +37,6 @@ class QStringList;
namespace OCC { namespace OCC {
typedef QLocalSocket SocketType;
class SyncFileStatus; class SyncFileStatus;
class Folder; class Folder;
@@ -72,23 +70,20 @@ private:
SyncJournalFileRecord dbFileRecord_capi( Folder *folder, QString fileName ); SyncJournalFileRecord dbFileRecord_capi( Folder *folder, QString fileName );
SqlQuery *getSqlQuery( Folder *folder ); SqlQuery *getSqlQuery( Folder *folder );
void sendMessage(SocketType* socket, const QString& message, bool doWait = false); void sendMessage(QLocalSocket* socket, const QString& message, bool doWait = false);
void broadcastMessage(const QString& verb, const QString &path, const QString &status = QString::null, bool doWait = false); void broadcastMessage(const QString& verb, const QString &path, const QString &status = QString::null, bool doWait = false);
Q_INVOKABLE void command_RETRIEVE_FOLDER_STATUS(const QString& argument, SocketType* socket); Q_INVOKABLE void command_RETRIEVE_FOLDER_STATUS(const QString& argument, QLocalSocket* socket);
Q_INVOKABLE void command_RETRIEVE_FILE_STATUS(const QString& argument, SocketType* socket); Q_INVOKABLE void command_RETRIEVE_FILE_STATUS(const QString& argument, QLocalSocket* socket);
Q_INVOKABLE void command_SHARE(const QString& localFile, SocketType* socket); Q_INVOKABLE void command_SHARE(const QString& localFile, QLocalSocket* socket);
Q_INVOKABLE void command_VERSION(const QString& argument, SocketType* socket); Q_INVOKABLE void command_VERSION(const QString& argument, QLocalSocket* socket);
Q_INVOKABLE void command_SHARE_MENU_TITLE(const QString& argument, SocketType* socket); Q_INVOKABLE void command_SHARE_MENU_TITLE(const QString& argument, QLocalSocket* socket);
QString buildRegisterPathMessage(const QString& path);
#ifdef SOCKETAPI_TCP
QTcpServer _localServer;
#else
QLocalServer _localServer; QLocalServer _localServer;
#endif QList<QLocalSocket*> _listeners;
QList<SocketType*> _listeners;
c_strlist_t *_excludes; c_strlist_t *_excludes;
QHash<Folder*, SqlQuery*> _dbQueries; QHash<Folder*, SqlQuery*> _dbQueries;
QHash<Folder*, SqlDatabase*> _openDbs; QHash<Folder*, SqlDatabase*> _openDbs;

View File

@@ -31,6 +31,10 @@ SslButton::SslButton(QWidget *parent) :
{ {
setPopupMode(QToolButton::InstantPopup); setPopupMode(QToolButton::InstantPopup);
setAutoRaise(true); setAutoRaise(true);
setMenu(new QMenu(this));
QObject::connect(menu(), SIGNAL(aboutToShow()),
this, SLOT(slotUpdateMenu()));
} }
QString SslButton::protoToString(QSsl::SslProtocol proto) QString SslButton::protoToString(QSsl::SslProtocol proto)
@@ -178,19 +182,39 @@ void SslButton::updateAccountState(AccountState *accountState)
} else { } else {
setVisible(true); setVisible(true);
} }
AccountPtr account = accountState->account(); _accountState = accountState;
if(QMenu *oldMenu = menu()) {
oldMenu->hide(); // Need to be hidden because the QToolButton would be left in invalid state if the menu is deleted while it is visible AccountPtr account = _accountState->account();
setMenu(0);
oldMenu->deleteLater(); // setMenu do not delete the previous menu.
}
if (account->url().scheme() == QLatin1String("https")) { if (account->url().scheme() == QLatin1String("https")) {
setIcon(QIcon(QPixmap(Theme::hidpiFileName(":/client/resources/lock-https.png")))); QPixmap pm(Theme::hidpiFileName(":/client/resources/lock-https.png"));
setIcon(QIcon(pm));
QSslCipher cipher = account->sslConfiguration().sessionCipher(); QSslCipher cipher = account->sslConfiguration().sessionCipher();
setToolTip(tr("This connection is encrypted using %1 bit %2.\n").arg(cipher.usedBits()).arg(cipher.name())); setToolTip(tr("This connection is encrypted using %1 bit %2.\n").arg(cipher.usedBits()).arg(cipher.name()));
QMenu *menu = new QMenu(this); } else {
setIcon(QIcon(QPixmap(Theme::hidpiFileName(":/client/resources/lock-http.png"))));
setToolTip(tr("This connection is NOT secure as it is not encrypted.\n"));
}
}
void SslButton::slotUpdateMenu() {
menu()->clear();
if (!_accountState) {
return;
}
AccountPtr account = _accountState->account();
if (account->url().scheme() == QLatin1String("https")) {
QList<QSslCertificate> chain = account->sslConfiguration().peerCertificateChain(); QList<QSslCertificate> chain = account->sslConfiguration().peerCertificateChain();
menu->addAction(tr("Certificate information:"))->setEnabled(false);
if (chain.isEmpty()) {
qWarning() << "empty certificate chain";
return;
}
menu()->addAction(tr("Certificate information:"))->setEnabled(false);
QList<QSslCertificate> tmpChain; QList<QSslCertificate> tmpChain;
foreach(QSslCertificate cert, chain) { foreach(QSslCertificate cert, chain) {
@@ -213,13 +237,9 @@ void SslButton::updateAccountState(AccountState *accountState)
it.toBack(); it.toBack();
int i = 0; int i = 0;
while (it.hasPrevious()) { while (it.hasPrevious()) {
menu->addMenu(buildCertMenu(menu, it.previous(), account->approvedCerts(), i)); menu()->addMenu(buildCertMenu(menu(), it.previous(), account->approvedCerts(), i));
i++; i++;
} }
setMenu(menu);
} else {
setIcon(QIcon(QPixmap(Theme::hidpiFileName(":/client/resources/lock-http.png"))));
setToolTip(tr("This connection is NOT secure as it is not encrypted.\n"));
} }
} }

View File

@@ -24,7 +24,6 @@ class QSslConfiguration;
namespace OCC { namespace OCC {
class Account;
class AccountState; class AccountState;
class SslButton : public QToolButton class SslButton : public QToolButton
@@ -35,9 +34,13 @@ public:
QString protoToString(QSsl::SslProtocol proto); QString protoToString(QSsl::SslProtocol proto);
void updateAccountState(AccountState *accountState); void updateAccountState(AccountState *accountState);
public slots:
void slotUpdateMenu();
private: private:
QMenu* buildCertMenu(QMenu *parent, const QSslCertificate& cert, QMenu* buildCertMenu(QMenu *parent, const QSslCertificate& cert,
const QList<QSslCertificate>& userApproved, int pos); const QList<QSslCertificate>& userApproved, int pos);
QPointer<AccountState> _accountState;
}; };
} // namespace OCC } // namespace OCC

View File

@@ -34,8 +34,9 @@ namespace Utility {
} }
#endif #endif
bool SslDialogErrorHandler::handleErrors(QList<QSslError> errors, QList<QSslCertificate> *certs, AccountPtr account) bool SslDialogErrorHandler::handleErrors(QList<QSslError> errors, const QSslConfiguration &conf, QList<QSslCertificate> *certs, AccountPtr account)
{ {
(void) conf;
if (!certs) { if (!certs) {
qDebug() << "Certs parameter required but is NULL!"; qDebug() << "Certs parameter required but is NULL!";
return false; return false;

View File

@@ -33,7 +33,7 @@ class SslErrorDialog;
class SslDialogErrorHandler : public AbstractSslErrorHandler { class SslDialogErrorHandler : public AbstractSslErrorHandler {
public: public:
bool handleErrors(QList<QSslError> errors, QList<QSslCertificate> *certs, AccountPtr) Q_DECL_OVERRIDE; bool handleErrors(QList<QSslError> errors, const QSslConfiguration &conf, QList<QSslCertificate> *certs, AccountPtr) Q_DECL_OVERRIDE;
}; };
class SslErrorDialog : public QDialog class SslErrorDialog : public QDialog

View File

@@ -52,9 +52,10 @@ bool OCUpdater::performUpdate()
QSettings settings(cfg.configFile(), QSettings::IniFormat); QSettings settings(cfg.configFile(), QSettings::IniFormat);
QString updateFile = settings.value(updateAvailableC).toString(); QString updateFile = settings.value(updateAvailableC).toString();
if (!updateFile.isEmpty() && QFile(updateFile).exists()) { if (!updateFile.isEmpty() && QFile(updateFile).exists()) {
if (QMessageBox::information(0, tr("New Update Ready"), const QString name = Theme::instance()->appNameGUI();
tr("A new update is about to be installed. The updater may ask\n" if (QMessageBox::information(0, tr("New %1 Update Ready").arg(name),
"for additional privileges during the process."), QMessageBox::Ok)) { tr("A new update for %1 is about to be installed. The updater may ask\n"
"for additional privileges during the process.").arg(name), QMessageBox::Ok)) {
slotStartInstaller(); slotStartInstaller();
return true; return true;
} }

25
src/gui/version.rc.in Normal file
View File

@@ -0,0 +1,25 @@
#include "winresrc.h"
#define VER_FILEVERSION @MIRALL_VERSION_MAJOR@,@MIRALL_VERSION_MINOR@,@MIRALL_VERSION_PATCH@,@MIRALL_VERSION_BUILD@
#define VER_FILEVERSION_STR "@MIRALL_VERSION_MAJOR@.@MIRALL_VERSION_MINOR@.@MIRALL_VERSION_PATCH@.@MIRALL_VERSION_BUILD@\0"
#define VER_PRODUCTVERSION @MIRALL_VERSION_MAJOR@,@MIRALL_VERSION_MINOR@,@MIRALL_VERSION_PATCH@,@MIRALL_VERSION_BUILD@
#define VER_PRODUCTVERSION_STR "@MIRALL_VERSION_MAJOR@.@MIRALL_VERSION_MINOR@.@MIRALL_VERSION_PATCH@.@MIRALL_VERSION_BUILD@\0"
VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILEVERSION
PRODUCTVERSION VER_PRODUCTVERSION
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "080904b0"
BEGIN
VALUE "FileVersion", VER_FILEVERSION_STR
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x809, 1200
END
END

View File

@@ -64,7 +64,6 @@ set(libsync_SRCS
creds/dummycredentials.cpp creds/dummycredentials.cpp
creds/abstractcredentials.cpp creds/abstractcredentials.cpp
creds/credentialsfactory.cpp creds/credentialsfactory.cpp
creds/http/httpconfigfile.cpp
creds/credentialscommon.cpp creds/credentialscommon.cpp
../3rdparty/qjson/json.cpp ../3rdparty/qjson/json.cpp
../3rdparty/certificates/p12topem.cpp ../3rdparty/certificates/p12topem.cpp

View File

@@ -63,7 +63,9 @@ void AccountManager::setAccount(AccountPtr account)
emit accountRemoved(_account); emit accountRemoved(_account);
} }
_account = account; _account = account;
emit accountAdded(account); if (account) {
emit accountAdded(account);
}
} }
@@ -129,6 +131,15 @@ void Account::save()
if (!certs.isEmpty()) { if (!certs.isEmpty()) {
settings->setValue( QLatin1String(caCertsKeyC), certs ); settings->setValue( QLatin1String(caCertsKeyC), certs );
} }
// Save cookies.
if (_am) {
CookieJar* jar = qobject_cast<CookieJar*>(_am->cookieJar());
if (jar) {
qDebug() << "Saving cookies.";
jar->save();
}
}
} }
AccountPtr Account::restore() AccountPtr Account::restore()
@@ -271,6 +282,21 @@ void Account::clearCookieJar()
_am->setCookieJar(new CookieJar); _am->setCookieJar(new CookieJar);
} }
void Account::resetNetworkAccessManager()
{
if (!_credentials || !_am) {
return;
}
qDebug() << "Resetting QNAM";
QNetworkCookieJar* jar = _am->cookieJar();
_am->deleteLater();
_am = _credentials->getQNAM();
_am->setCookieJar(jar); // takes ownership of the old cookie jar
connect(_am, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
SLOT(slotHandleErrors(QNetworkReply*,QList<QSslError>)));
}
QNetworkAccessManager *Account::networkAccessManager() QNetworkAccessManager *Account::networkAccessManager()
{ {
return _am; return _am;
@@ -460,7 +486,7 @@ void Account::slotHandleErrors(QNetworkReply *reply , QList<QSslError> errors)
return; return;
} }
if (_sslErrorHandler->handleErrors(errors, &approvedCerts, sharedFromThis())) { if (_sslErrorHandler->handleErrors(errors, reply->sslConfiguration(), &approvedCerts, sharedFromThis())) {
QSslSocket::addDefaultCaCertificates(approvedCerts); QSslSocket::addDefaultCaCertificates(approvedCerts);
addApprovedCerts(approvedCerts); addApprovedCerts(approvedCerts);
// all ssl certs are known and accepted. We can ignore the problems right away. // all ssl certs are known and accepted. We can ignore the problems right away.

View File

@@ -62,7 +62,7 @@ private:
class AbstractSslErrorHandler { class AbstractSslErrorHandler {
public: public:
virtual ~AbstractSslErrorHandler() {} virtual ~AbstractSslErrorHandler() {}
virtual bool handleErrors(QList<QSslError>, QList<QSslCertificate>*, AccountPtr) = 0; virtual bool handleErrors(QList<QSslError>, const QSslConfiguration &conf, QList<QSslCertificate>*, AccountPtr) = 0;
}; };
/** /**
@@ -156,6 +156,7 @@ public:
void clearCookieJar(); void clearCookieJar();
void resetNetworkAccessManager();
QNetworkAccessManager* networkAccessManager(); QNetworkAccessManager* networkAccessManager();
/// Called by network jobs on credential errors. /// Called by network jobs on credential errors.
@@ -185,7 +186,6 @@ private:
QNetworkAccessManager *_am; QNetworkAccessManager *_am;
AbstractCredentials* _credentials; AbstractCredentials* _credentials;
bool _treatSslErrorsAsFailure; bool _treatSslErrorsAsFailure;
int _state;
static QString _configFileName; static QString _configFileName;
QByteArray _pemCertificate; QByteArray _pemCertificate;
QString _pemPrivateKey; QString _pemPrivateKey;

View File

@@ -15,6 +15,7 @@
#include "configfile.h" #include "configfile.h"
#include <QUrl> #include <QUrl>
#include <QThreadPool>
namespace OCC { namespace OCC {
@@ -23,7 +24,7 @@ ClientProxy::ClientProxy(QObject *parent) :
{ {
} }
QNetworkProxy ClientProxy::proxyFromConfig(const ConfigFile& cfg) static QNetworkProxy proxyFromConfig(const ConfigFile& cfg)
{ {
QNetworkProxy proxy; QNetworkProxy proxy;
@@ -39,6 +40,22 @@ QNetworkProxy ClientProxy::proxyFromConfig(const ConfigFile& cfg)
return proxy; return proxy;
} }
bool ClientProxy::isUsingSystemDefault() {
OCC::ConfigFile cfg;
// if there is no config file, default to system proxy.
if( cfg.exists() ) {
return cfg.proxyType() == QNetworkProxy::DefaultProxy;
}
return false;
}
QString printQNetworkProxy(const QNetworkProxy &proxy)
{
return QString("%1://%2:%3").arg(proxy.type()).arg(proxy.hostName()).arg(proxy.port());
}
void ClientProxy::setupQtProxyFromConfig() void ClientProxy::setupQtProxyFromConfig()
{ {
OCC::ConfigFile cfg; OCC::ConfigFile cfg;
@@ -53,19 +70,23 @@ void ClientProxy::setupQtProxyFromConfig()
switch(proxyType) { switch(proxyType) {
case QNetworkProxy::NoProxy: case QNetworkProxy::NoProxy:
qDebug() << "Set proxy configuration to use NO proxy";
QNetworkProxyFactory::setUseSystemConfiguration(false); QNetworkProxyFactory::setUseSystemConfiguration(false);
QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy); QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy);
break; break;
case QNetworkProxy::DefaultProxy: case QNetworkProxy::DefaultProxy:
qDebug() << "Set proxy configuration to use system configuration";
QNetworkProxyFactory::setUseSystemConfiguration(true); QNetworkProxyFactory::setUseSystemConfiguration(true);
break; break;
case QNetworkProxy::Socks5Proxy: case QNetworkProxy::Socks5Proxy:
proxy.setType(QNetworkProxy::Socks5Proxy); proxy.setType(QNetworkProxy::Socks5Proxy);
qDebug() << "Set proxy configuration to SOCKS5" << printQNetworkProxy(proxy);
QNetworkProxyFactory::setUseSystemConfiguration(false); QNetworkProxyFactory::setUseSystemConfiguration(false);
QNetworkProxy::setApplicationProxy(proxy); QNetworkProxy::setApplicationProxy(proxy);
break; break;
case QNetworkProxy::HttpProxy: case QNetworkProxy::HttpProxy:
proxy.setType(QNetworkProxy::HttpProxy); proxy.setType(QNetworkProxy::HttpProxy);
qDebug() << "Set proxy configuration to HTTP" << printQNetworkProxy(proxy);
QNetworkProxyFactory::setUseSystemConfiguration(false); QNetworkProxyFactory::setUseSystemConfiguration(false);
QNetworkProxy::setApplicationProxy(proxy); QNetworkProxy::setApplicationProxy(proxy);
break; break;
@@ -96,6 +117,7 @@ const char* ClientProxy::proxyTypeToCStr(QNetworkProxy::ProxyType type)
void ClientProxy::setCSyncProxy( const QUrl& url, CSYNC *csync_ctx ) void ClientProxy::setCSyncProxy( const QUrl& url, CSYNC *csync_ctx )
{ {
#ifdef USE_NEON
/* Store proxy */ /* Store proxy */
QList<QNetworkProxy> proxies = QNetworkProxyFactory::proxyForQuery(QNetworkProxyQuery(url)); QList<QNetworkProxy> proxies = QNetworkProxyFactory::proxyForQuery(QNetworkProxyQuery(url));
// We set at least one in Application // We set at least one in Application
@@ -118,7 +140,38 @@ void ClientProxy::setCSyncProxy( const QUrl& url, CSYNC *csync_ctx )
csync_set_module_property( csync_ctx, "proxy_port", &proxy_port ); csync_set_module_property( csync_ctx, "proxy_port", &proxy_port );
csync_set_module_property( csync_ctx, "proxy_user", proxy.user().toUtf8().data()); csync_set_module_property( csync_ctx, "proxy_user", proxy.user().toUtf8().data());
csync_set_module_property( csync_ctx, "proxy_pwd", proxy.password().toUtf8().data()); csync_set_module_property( csync_ctx, "proxy_pwd", proxy.password().toUtf8().data());
#else
Q_UNUSED(url);
Q_UNUSED(csync_ctx);
#endif
}
void ClientProxy::lookupSystemProxyAsync(const QUrl &url, QObject *dst, const char *slot)
{
SystemProxyRunnable *runnable = new SystemProxyRunnable(url);
QObject::connect(runnable, SIGNAL(systemProxyLookedUp(QNetworkProxy)), dst, slot);
QThreadPool::globalInstance()->start(runnable); // takes ownership and deletes
}
SystemProxyRunnable::SystemProxyRunnable(const QUrl &url) : QObject(), QRunnable(), _url(url)
{
} }
void SystemProxyRunnable::run()
{
qDebug() << Q_FUNC_INFO << "Starting system proxy lookup";
QList<QNetworkProxy> proxies = QNetworkProxyFactory::systemProxyForQuery(QNetworkProxyQuery(_url));
if (proxies.isEmpty()) {
emit systemProxyLookedUp(QNetworkProxy(QNetworkProxy::NoProxy));
} else {
emit systemProxyLookedUp(proxies.first());
// FIXME Would we really ever return more?
}
}
} }

View File

@@ -16,6 +16,8 @@
#include <QObject> #include <QObject>
#include <QNetworkProxy> #include <QNetworkProxy>
#include <QRunnable>
#include <QUrl>
#include <csync.h> #include <csync.h>
#include "utility.h" #include "utility.h"
@@ -30,17 +32,31 @@ class OWNCLOUDSYNC_EXPORT ClientProxy : public QObject
public: public:
explicit ClientProxy(QObject *parent = 0); explicit ClientProxy(QObject *parent = 0);
signals: static bool isUsingSystemDefault();
static void lookupSystemProxyAsync(const QUrl &url, QObject *dst, const char *slot);
public slots: public slots:
void setCSyncProxy( const QUrl& url, CSYNC *csync_ctx ); void setCSyncProxy( const QUrl& url, CSYNC *csync_ctx );
void setupQtProxyFromConfig(); void setupQtProxyFromConfig();
private: private:
QNetworkProxy proxyFromConfig(const ConfigFile& cfg);
const char* proxyTypeToCStr(QNetworkProxy::ProxyType type); const char* proxyTypeToCStr(QNetworkProxy::ProxyType type);
}; };
class SystemProxyRunnable : public QObject, public QRunnable {
Q_OBJECT
public:
SystemProxyRunnable(const QUrl &url);
void run();
signals:
void systemProxyLookedUp(const QNetworkProxy &url);
private:
QUrl _url;
};
QString printQNetworkProxy(const QNetworkProxy &proxy);
} }
#endif // CLIENTPROXY_H #endif // CLIENTPROXY_H

View File

@@ -40,7 +40,7 @@
namespace OCC { namespace OCC {
static const char caCertsKeyC[] = "CaCertificates"; //static const char caCertsKeyC[] = "CaCertificates"; only used from account.cpp
static const char remotePollIntervalC[] = "remotePollInterval"; static const char remotePollIntervalC[] = "remotePollInterval";
static const char forceSyncIntervalC[] = "forceSyncInterval"; static const char forceSyncIntervalC[] = "forceSyncInterval";
static const char monoIconsC[] = "monoIcons"; static const char monoIconsC[] = "monoIcons";
@@ -85,10 +85,10 @@ ConfigFile::ConfigFile()
// qDebug() << Q_FUNC_INFO << "Loading config: " << config << " (URL is " << settings.value("url").toString() << ")"; // qDebug() << Q_FUNC_INFO << "Loading config: " << config << " (URL is " << settings.value("url").toString() << ")";
} }
void ConfigFile::setConfDir(const QString &value) bool ConfigFile::setConfDir(const QString &value)
{ {
QString dirPath = value; QString dirPath = value;
if( dirPath.isEmpty() ) return; if( dirPath.isEmpty() ) return false;
QFileInfo fi(dirPath); QFileInfo fi(dirPath);
if ( !fi.exists() && !fi.isAbsolute() ) { if ( !fi.exists() && !fi.isAbsolute() ) {
@@ -101,7 +101,9 @@ void ConfigFile::setConfDir(const QString &value)
dirPath = fi.absoluteFilePath(); dirPath = fi.absoluteFilePath();
qDebug() << "** Using custom config dir " << dirPath; qDebug() << "** Using custom config dir " << dirPath;
_confDir=dirPath; _confDir=dirPath;
return true;
} }
return false;
} }
bool ConfigFile::optionalDesktopNotifications() const bool ConfigFile::optionalDesktopNotifications() const
@@ -145,7 +147,7 @@ void ConfigFile::saveGeometryHeader(QHeaderView *header)
{ {
#ifndef TOKEN_AUTH_ONLY #ifndef TOKEN_AUTH_ONLY
if(!header) return; if(!header) return;
Q_ASSERT(!header->objectName().isNull()); Q_ASSERT(!header->objectName().isEmpty());
QSettings settings(configFile(), QSettings::IniFormat); QSettings settings(configFile(), QSettings::IniFormat);
settings.beginGroup(header->objectName()); settings.beginGroup(header->objectName());
@@ -162,7 +164,7 @@ void ConfigFile::restoreGeometryHeader(QHeaderView *header)
QSettings settings(configFile(), QSettings::IniFormat); QSettings settings(configFile(), QSettings::IniFormat);
settings.beginGroup(header->objectName()); settings.beginGroup(header->objectName());
header->restoreState(getValue(geometryC, header->objectName()).toByteArray()); header->restoreState(settings.value(geometryC).toByteArray());
#endif #endif
} }
@@ -315,20 +317,6 @@ bool ConfigFile::dataExists(const QString& group, const QString& key) const
return settings.contains(key); return settings.contains(key);
} }
QByteArray ConfigFile::caCerts( )
{
QSettings settings(configFile(), QSettings::IniFormat);
return settings.value( QLatin1String(caCertsKeyC) ).toByteArray();
}
void ConfigFile::setCaCerts( const QByteArray & certs )
{
QSettings settings(configFile(), QSettings::IniFormat);
settings.setValue( QLatin1String(caCertsKeyC), certs );
settings.sync();
}
int ConfigFile::remotePollInterval( const QString& connection ) const int ConfigFile::remotePollInterval( const QString& connection ) const
{ {
QString con( connection ); QString con( connection );

View File

@@ -96,7 +96,7 @@ public:
void setUploadLimit(int kbytes); void setUploadLimit(int kbytes);
void setDownloadLimit(int kbytes); void setDownloadLimit(int kbytes);
static void setConfDir(const QString &value); static bool setConfDir(const QString &value);
bool optionalDesktopNotifications() const; bool optionalDesktopNotifications() const;
void setOptionalDesktopNotifications(bool show); void setOptionalDesktopNotifications(bool show);

View File

@@ -13,11 +13,13 @@
#include <QtCore> #include <QtCore>
#include <QNetworkReply> #include <QNetworkReply>
#include <QNetworkProxyFactory>
#include "connectionvalidator.h" #include "connectionvalidator.h"
#include "theme.h" #include "theme.h"
#include "account.h" #include "account.h"
#include "networkjobs.h" #include "networkjobs.h"
#include "clientproxy.h"
#include <creds/abstractcredentials.h> #include <creds/abstractcredentials.h>
namespace OCC { namespace OCC {
@@ -61,8 +63,38 @@ void ConnectionValidator::checkServerAndAuth()
reportResult( NotConfigured ); reportResult( NotConfigured );
return; return;
} }
qDebug() << "Checking server and authentication";
_isCheckingServerAndAuth = true; _isCheckingServerAndAuth = true;
// Lookup system proxy in a thread https://github.com/owncloud/client/issues/2993
if (ClientProxy::isUsingSystemDefault()) {
qDebug() << "Trying to look up system proxy";
ClientProxy::lookupSystemProxyAsync(_account->url(),
this, SLOT(systemProxyLookupDone(QNetworkProxy)));
} else {
// We want to reset the QNAM proxy so that the global proxy settings are used (via ClientProxy settings)
_account->networkAccessManager()->setProxy(QNetworkProxy(QNetworkProxy::DefaultProxy));
// use a queued invocation so we're as asynchronous as with the other code path
QMetaObject::invokeMethod(this, "slotCheckServerAndAuth", Qt::QueuedConnection);
}
}
void ConnectionValidator::systemProxyLookupDone(const QNetworkProxy &proxy) {
if (!_account) {
qDebug() << "Bailing out, Account had been deleted";
return;
}
qDebug() << Q_FUNC_INFO << "Setting QNAM proxy to be system proxy" << printQNetworkProxy(proxy);
_account->networkAccessManager()->setProxy(proxy);
slotCheckServerAndAuth();
}
// The actual check
void ConnectionValidator::slotCheckServerAndAuth()
{
CheckServerJob *checkJob = new CheckServerJob(_account, this); CheckServerJob *checkJob = new CheckServerJob(_account, this);
checkJob->setIgnoreCredentialFailure(true); checkJob->setIgnoreCredentialFailure(true);
connect(checkJob, SIGNAL(instanceFound(QUrl,QVariantMap)), SLOT(slotStatusFound(QUrl,QVariantMap))); connect(checkJob, SIGNAL(instanceFound(QUrl,QVariantMap)), SLOT(slotStatusFound(QUrl,QVariantMap)));
@@ -98,12 +130,16 @@ void ConnectionValidator::slotStatusFound(const QUrl&url, const QVariantMap &inf
// Fetch them now! Once fetched, a new connectivity check will be // Fetch them now! Once fetched, a new connectivity check will be
// initiated anyway. // initiated anyway.
creds->fetch(); creds->fetch();
// no result is reported
deleteLater();
} }
} }
// status.php could not be loaded (network or server issue!). // status.php could not be loaded (network or server issue!).
void ConnectionValidator::slotNoStatusFound(QNetworkReply *reply) void ConnectionValidator::slotNoStatusFound(QNetworkReply *reply)
{ {
qDebug() << Q_FUNC_INFO << reply->error() << reply->errorString();
if( reply && ! _account->credentials()->stillValid(reply)) { if( reply && ! _account->credentials()->stillValid(reply)) {
_errors.append(tr("Authentication error: Either username or password are wrong.")); _errors.append(tr("Authentication error: Either username or password are wrong."));
} else { } else {

View File

@@ -36,6 +36,8 @@ namespace OCC {
*---> checkServerAndAuth (check status.php) *---> checkServerAndAuth (check status.php)
Will asynchronously check for system proxy (if using system proxy)
And then invoke slotCheckServerAndAuth
CheckServerJob CheckServerJob
| |
+-> slotNoStatusFound --> X +-> slotNoStatusFound --> X
@@ -85,6 +87,7 @@ public:
public slots: public slots:
/// Checks the server and the authentication. /// Checks the server and the authentication.
void checkServerAndAuth(); void checkServerAndAuth();
void systemProxyLookupDone(const QNetworkProxy &proxy);
/// Checks authentication only. /// Checks authentication only.
void checkAuthentication(); void checkAuthentication();
@@ -93,6 +96,8 @@ signals:
void connectionResult( ConnectionValidator::Status status, QStringList errors ); void connectionResult( ConnectionValidator::Status status, QStringList errors );
protected slots: protected slots:
void slotCheckServerAndAuth();
void slotStatusFound(const QUrl&url, const QVariantMap &info); void slotStatusFound(const QUrl&url, const QVariantMap &info);
void slotNoStatusFound(QNetworkReply *reply); void slotNoStatusFound(QNetworkReply *reply);
void slotJobTimeout(const QUrl& url); void slotJobTimeout(const QUrl& url);

View File

@@ -71,7 +71,6 @@ CookieJar::CookieJar(QObject *parent) :
CookieJar::~CookieJar() CookieJar::~CookieJar()
{ {
save();
} }
bool CookieJar::setCookiesFromUrl(const QList<QNetworkCookie>& cookieList, const QUrl& url) bool CookieJar::setCookiesFromUrl(const QList<QNetworkCookie>& cookieList, const QUrl& url)
@@ -103,7 +102,7 @@ void CookieJar::save()
qDebug() << storagePath(); qDebug() << storagePath();
file.open(QIODevice::WriteOnly); file.open(QIODevice::WriteOnly);
QDataStream stream(&file); QDataStream stream(&file);
stream << allCookies(); stream << removeExpired(allCookies());
file.close(); file.close();
} }

View File

@@ -34,10 +34,11 @@ public:
using QNetworkCookieJar::setAllCookies; using QNetworkCookieJar::setAllCookies;
using QNetworkCookieJar::allCookies; using QNetworkCookieJar::allCookies;
void save();
signals: signals:
void newCookiesForUrl(const QList<QNetworkCookie>& cookieList, const QUrl& url); void newCookiesForUrl(const QList<QNetworkCookie>& cookieList, const QUrl& url);
private: private:
void save();
void restore(); void restore();
QList<QNetworkCookie> removeExpired(const QList<QNetworkCookie> &cookies); QList<QNetworkCookie> removeExpired(const QList<QNetworkCookie> &cookies);
QString storagePath() const; QString storagePath() const;

View File

@@ -1,81 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "creds/http/httpconfigfile.h"
namespace OCC
{
namespace
{
const char userC[] = "user";
const char passwdC[] = "passwd";
const char oldPasswdC[] = "password";
} // ns
QString HttpConfigFile::user() const
{
return retrieveData(QString(), QLatin1String(userC)).toString();
}
void HttpConfigFile::setUser(const QString& user)
{
storeData(QString(), QLatin1String(userC), QVariant(user));
}
QString HttpConfigFile::password() const
{
const QVariant passwd(retrieveData(QString(), QLatin1String(passwdC)));
if (passwd.isValid()) {
return QString::fromUtf8(QByteArray::fromBase64(passwd.toByteArray()));
}
return QString();
}
void HttpConfigFile::setPassword(const QString& password)
{
QByteArray pwdba = password.toUtf8();
storeData( QString(), QLatin1String(passwdC), QVariant(pwdba.toBase64()) );
removeOldPassword();
}
bool HttpConfigFile::passwordExists() const
{
return dataExists(QString(), QLatin1String(passwdC));
}
void HttpConfigFile::removePassword()
{
removeOldPassword();
removeData(QString(), QLatin1String(passwdC));
}
void HttpConfigFile::fixupOldPassword()
{
const QString old(QString::fromLatin1(oldPasswdC));
if (dataExists(QString(), old)) {
setPassword(retrieveData(QString(), old).toString());
}
}
void HttpConfigFile::removeOldPassword()
{
removeData(QString(), QLatin1String(oldPasswdC));
}
} // namespace OCC

View File

@@ -1,44 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef MIRALL_CREDS_HTTP_CONFIG_FILE_H
#define MIRALL_CREDS_HTTP_CONFIG_FILE_H
#include "configfile.h"
namespace OCC
{
class HttpConfigFile : public ConfigFile
{
public:
QString user() const;
void setUser(const QString& user);
QString password() const;
void setPassword(const QString& password);
bool passwordExists() const;
void removePassword();
void fixupOldPassword();
QString certificatePath() const;
void setCertificatePath(const QString& cPath);
QString certificatePasswd() const;
void setCertificatePasswd(const QString& cPasswd);
private:
void removeOldPassword();
};
} // namespace OCC
#endif

View File

@@ -313,6 +313,9 @@ void HttpCredentials::slotReadJobDone(QKeychain::Job *job)
void HttpCredentials::invalidateToken() void HttpCredentials::invalidateToken()
{ {
if (! _password.isEmpty()) {
_previousPassword = _password;
}
_password = QString(); _password = QString();
_ready = false; _ready = false;
@@ -333,6 +336,14 @@ void HttpCredentials::invalidateToken()
job->setKey(kck); job->setKey(kck);
job->start(); job->start();
// Also ensure the password is deleted from the deprecated place
// otherwise we'd possibly read and use it again and again.
DeletePasswordJob *job2 = new DeletePasswordJob(Theme::instance()->appName());
// no job2->setSettings() call here, to make it use the deprecated location.
job2->setInsecureFallback(true);
job2->setKey(kck);
job2->start();
_account->clearCookieJar(); _account->clearCookieJar();
} }
@@ -387,7 +398,7 @@ QString HttpCredentialsGui::queryPassword(bool *ok)
QString str = QInputDialog::getText(0, tr("Enter Password"), QString str = QInputDialog::getText(0, tr("Enter Password"),
tr("Please enter %1 password for user '%2':") tr("Please enter %1 password for user '%2':")
.arg(Theme::instance()->appNameGUI(), _user), .arg(Theme::instance()->appNameGUI(), _user),
QLineEdit::Password, QString(), ok); QLineEdit::Password, _previousPassword, ok);
return str; return str;
} else { } else {
return QString(); return QString();

View File

@@ -64,6 +64,7 @@ private Q_SLOTS:
protected: protected:
QString _user; QString _user;
QString _password; QString _password;
QString _previousPassword;
private: private:
QString _certificatePath; QString _certificatePath;

View File

@@ -268,8 +268,11 @@ void DiscoverySingleDirectoryJob::directoryListingIteratedSlot(QString file,QMap
} }
csync_vio_file_stat_t *file_stat = propertyMapToFileStat(map); FileStatPointer file_stat(propertyMapToFileStat(map));
file_stat->name = strdup(file.toUtf8()); file_stat->name = strdup(file.toUtf8());
if (!file_stat->etag || strlen(file_stat->etag) == 0) {
qDebug() << "WARNING: etag of" << file_stat->name << "is" << file_stat->etag << " This must not happen.";
}
//qDebug() << "!!!!" << file_stat << file_stat->name << file_stat->file_id << map.count(); //qDebug() << "!!!!" << file_stat << file_stat->name << file_stat->file_id << map.count();
_results.append(file_stat); _results.append(file_stat);
} }
@@ -282,6 +285,13 @@ void DiscoverySingleDirectoryJob::directoryListingIteratedSlot(QString file,QMap
void DiscoverySingleDirectoryJob::lsJobFinishedWithoutErrorSlot() void DiscoverySingleDirectoryJob::lsJobFinishedWithoutErrorSlot()
{ {
if (!_ignoredFirst) {
// This is a sanity check, if we haven't _ignoredFirst then it means we never received any directoryListingIteratedSlot
// which means somehow the server XML was bogus
emit finishedWithError(ERRNO_WRONG_CONTENT, QLatin1String("Server error: PROPFIND reply is not XML formatted!"));
deleteLater();
return;
}
emit etagConcatenation(_etagConcatenation); emit etagConcatenation(_etagConcatenation);
emit finishedWithResult(_results); emit finishedWithResult(_results);
deleteLater(); deleteLater();
@@ -293,7 +303,7 @@ void DiscoverySingleDirectoryJob::lsJobFinishedWithErrorSlot(QNetworkReply *r)
int httpCode = r->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); int httpCode = r->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QString httpReason = r->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString(); QString httpReason = r->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
QString msg = r->errorString(); QString msg = r->errorString();
int errnoCode = 0; int errnoCode = EIO; // Something went wrong
qDebug() << Q_FUNC_INFO << r->errorString() << httpCode << r->error(); qDebug() << Q_FUNC_INFO << r->errorString() << httpCode << r->error();
if (httpCode != 0 && httpCode != 207) { if (httpCode != 0 && httpCode != 207) {
errnoCode = get_errno_from_http_errcode(httpCode, httpReason); errnoCode = get_errno_from_http_errcode(httpCode, httpReason);
@@ -302,6 +312,8 @@ void DiscoverySingleDirectoryJob::lsJobFinishedWithErrorSlot(QNetworkReply *r)
} else if (!contentType.contains("application/xml; charset=utf-8")) { } else if (!contentType.contains("application/xml; charset=utf-8")) {
msg = QLatin1String("Server error: PROPFIND reply is not XML formatted!"); msg = QLatin1String("Server error: PROPFIND reply is not XML formatted!");
errnoCode = ERRNO_WRONG_CONTENT; errnoCode = ERRNO_WRONG_CONTENT;
} else {
// Default keep at EIO, see above
} }
emit finishedWithError(errnoCode, msg); emit finishedWithError(errnoCode, msg);
@@ -316,15 +328,6 @@ void DiscoveryMainThread::setupHooks(DiscoveryJob *discoveryJob, const QString &
connect(discoveryJob, SIGNAL(doOpendirSignal(QString,DiscoveryDirectoryResult*)), connect(discoveryJob, SIGNAL(doOpendirSignal(QString,DiscoveryDirectoryResult*)),
this, SLOT(doOpendirSlot(QString,DiscoveryDirectoryResult*)), this, SLOT(doOpendirSlot(QString,DiscoveryDirectoryResult*)),
Qt::QueuedConnection); Qt::QueuedConnection);
connect(discoveryJob, SIGNAL(doClosedirSignal(QString)),
this, SLOT(doClosedirSlot(QString)),
Qt::QueuedConnection);
}
void DiscoveryMainThread::doClosedirSlot(QString path)
{
//qDebug() << Q_FUNC_INFO << "Invalidating" << path;
deleteCacheEntry(path);
} }
// Coming from owncloud_opendir -> DiscoveryJob::vio_opendir_hook -> doOpendirSignal // Coming from owncloud_opendir -> DiscoveryJob::vio_opendir_hook -> doOpendirSignal
@@ -349,8 +352,8 @@ void DiscoveryMainThread::doOpendirSlot(QString subPath, DiscoveryDirectoryResul
// Schedule the DiscoverySingleDirectoryJob // Schedule the DiscoverySingleDirectoryJob
_singleDirJob = new DiscoverySingleDirectoryJob(_account, fullPath, this); _singleDirJob = new DiscoverySingleDirectoryJob(_account, fullPath, this);
QObject::connect(_singleDirJob, SIGNAL(finishedWithResult(QLinkedList<csync_vio_file_stat_t *>)), QObject::connect(_singleDirJob, SIGNAL(finishedWithResult(const QList<FileStatPointer> &)),
this, SLOT(singleDirectoryJobResultSlot(QLinkedList<csync_vio_file_stat_t*>))); this, SLOT(singleDirectoryJobResultSlot(const QList<FileStatPointer> &)));
QObject::connect(_singleDirJob, SIGNAL(finishedWithError(int,QString)), QObject::connect(_singleDirJob, SIGNAL(finishedWithError(int,QString)),
this, SLOT(singleDirectoryJobFinishedWithErrorSlot(int,QString))); this, SLOT(singleDirectoryJobFinishedWithErrorSlot(int,QString)));
QObject::connect(_singleDirJob, SIGNAL(firstDirectoryPermissions(QString)), QObject::connect(_singleDirJob, SIGNAL(firstDirectoryPermissions(QString)),
@@ -361,7 +364,7 @@ void DiscoveryMainThread::doOpendirSlot(QString subPath, DiscoveryDirectoryResul
} }
void DiscoveryMainThread::singleDirectoryJobResultSlot(QLinkedList<csync_vio_file_stat_t *> result) void DiscoveryMainThread::singleDirectoryJobResultSlot(const QList<FileStatPointer> & result)
{ {
if (!_currentDiscoveryDirectoryResult) { if (!_currentDiscoveryDirectoryResult) {
return; // possibly aborted return; // possibly aborted
@@ -369,11 +372,9 @@ void DiscoveryMainThread::singleDirectoryJobResultSlot(QLinkedList<csync_vio_fil
qDebug() << Q_FUNC_INFO << "Have" << result.count() << "results for " << _currentDiscoveryDirectoryResult->path; qDebug() << Q_FUNC_INFO << "Have" << result.count() << "results for " << _currentDiscoveryDirectoryResult->path;
_directoryContents.insert(_currentDiscoveryDirectoryResult->path, result);
_currentDiscoveryDirectoryResult->list = result; _currentDiscoveryDirectoryResult->list = result;
_currentDiscoveryDirectoryResult->code = 0; _currentDiscoveryDirectoryResult->code = 0;
_currentDiscoveryDirectoryResult->iterator = _currentDiscoveryDirectoryResult->list.begin(); _currentDiscoveryDirectoryResult->listIndex = 0;
_currentDiscoveryDirectoryResult = 0; // the sync thread owns it now _currentDiscoveryDirectoryResult = 0; // the sync thread owns it now
_discoveryJob->_vioMutex.lock(); _discoveryJob->_vioMutex.lock();
@@ -411,7 +412,7 @@ void DiscoveryMainThread::abort() {
if (_singleDirJob) { if (_singleDirJob) {
_singleDirJob->disconnect(SIGNAL(finishedWithError(int,QString)), this); _singleDirJob->disconnect(SIGNAL(finishedWithError(int,QString)), this);
_singleDirJob->disconnect(SIGNAL(firstDirectoryPermissions(QString)), this); _singleDirJob->disconnect(SIGNAL(firstDirectoryPermissions(QString)), this);
_singleDirJob->disconnect(SIGNAL(finishedWithResult(QLinkedList<csync_vio_file_stat_t*>)), this); _singleDirJob->disconnect(SIGNAL(finishedWithResult(const QList<FileStatPointer> &)), this);
_singleDirJob->abort(); _singleDirJob->abort();
} }
if (_currentDiscoveryDirectoryResult) { if (_currentDiscoveryDirectoryResult) {
@@ -466,9 +467,8 @@ csync_vio_file_stat_t* DiscoveryJob::remote_vio_readdir_hook (csync_vio_handle_t
DiscoveryJob *discoveryJob = static_cast<DiscoveryJob*>(userdata); DiscoveryJob *discoveryJob = static_cast<DiscoveryJob*>(userdata);
if (discoveryJob) { if (discoveryJob) {
DiscoveryDirectoryResult *directoryResult = static_cast<DiscoveryDirectoryResult*>(dhandle); DiscoveryDirectoryResult *directoryResult = static_cast<DiscoveryDirectoryResult*>(dhandle);
if (directoryResult->iterator != directoryResult->list.end()) { if (directoryResult->listIndex < directoryResult->list.size()) {
csync_vio_file_stat_t *file_stat = *(directoryResult->iterator); csync_vio_file_stat_t *file_stat = directoryResult->list.at(directoryResult->listIndex++).data();
directoryResult->iterator++;
// Make a copy, csync_update will delete the copy // Make a copy, csync_update will delete the copy
return csync_vio_file_stat_copy(file_stat); return csync_vio_file_stat_copy(file_stat);
} }
@@ -484,7 +484,6 @@ void DiscoveryJob::remote_vio_closedir_hook (csync_vio_handle_t *dhandle, void
QString path = directoryResult->path; QString path = directoryResult->path;
qDebug() << Q_FUNC_INFO << discoveryJob << path; qDebug() << Q_FUNC_INFO << discoveryJob << path;
delete directoryResult; // just deletes the struct and the iterator, the data itself is owned by the SyncEngine/DiscoveryMainThread delete directoryResult; // just deletes the struct and the iterator, the data itself is owned by the SyncEngine/DiscoveryMainThread
emit discoveryJob->doClosedirSignal(path);
} }
} }

View File

@@ -34,12 +34,36 @@ class Account;
* if the files are new, or changed. * if the files are new, or changed.
*/ */
class FileStatPointer {
public:
FileStatPointer(csync_vio_file_stat_t *stat)
: _stat(stat)
{ }
FileStatPointer(const FileStatPointer &other)
: _stat(csync_vio_file_stat_copy(other._stat))
{ }
~FileStatPointer() {
csync_vio_file_stat_destroy(_stat);
}
FileStatPointer &operator=(const FileStatPointer &other) {
csync_vio_file_stat_destroy(_stat);
_stat = csync_vio_file_stat_copy(other._stat);
return *this;
}
inline csync_vio_file_stat_t *data() const { return _stat; }
inline csync_vio_file_stat_t *operator->() const { return _stat; }
private:
csync_vio_file_stat_t *_stat;
};
struct DiscoveryDirectoryResult { struct DiscoveryDirectoryResult {
QString path; QString path;
QString msg; QString msg;
int code; int code;
QLinkedList<csync_vio_file_stat_t*>::iterator iterator; QList<FileStatPointer> list;
QLinkedList<csync_vio_file_stat_t *> list; int listIndex;
DiscoveryDirectoryResult() : code(EIO), listIndex(0) { }
}; };
// Run in the main thread, reporting to the DiscoveryJobMainThread object // Run in the main thread, reporting to the DiscoveryJobMainThread object
@@ -53,14 +77,14 @@ public:
signals: signals:
void firstDirectoryPermissions(const QString &); void firstDirectoryPermissions(const QString &);
void etagConcatenation(const QString &); void etagConcatenation(const QString &);
void finishedWithResult(QLinkedList<csync_vio_file_stat_t*>); void finishedWithResult(const QList<FileStatPointer> &);
void finishedWithError(int csyncErrnoCode, QString msg); void finishedWithError(int csyncErrnoCode, QString msg);
private slots: private slots:
void directoryListingIteratedSlot(QString,QMap<QString,QString>); void directoryListingIteratedSlot(QString,QMap<QString,QString>);
void lsJobFinishedWithoutErrorSlot(); void lsJobFinishedWithoutErrorSlot();
void lsJobFinishedWithErrorSlot(QNetworkReply*); void lsJobFinishedWithErrorSlot(QNetworkReply*);
private: private:
QLinkedList<csync_vio_file_stat_t*> _results; QList<FileStatPointer> _results;
QString _subPath; QString _subPath;
QString _etagConcatenation; QString _etagConcatenation;
AccountPtr _account; AccountPtr _account;
@@ -73,11 +97,6 @@ class DiscoveryJob;
class DiscoveryMainThread : public QObject { class DiscoveryMainThread : public QObject {
Q_OBJECT Q_OBJECT
// For non-recursive and recursive
// If it is not in this map it needs to be requested
QMap<QString, QLinkedList<csync_vio_file_stat_t*> > _directoryContents;
QPointer<DiscoveryJob> _discoveryJob; QPointer<DiscoveryJob> _discoveryJob;
QPointer<DiscoverySingleDirectoryJob> _singleDirJob; QPointer<DiscoverySingleDirectoryJob> _singleDirJob;
QString _pathPrefix; QString _pathPrefix;
@@ -87,22 +106,6 @@ class DiscoveryMainThread : public QObject {
public: public:
DiscoveryMainThread(AccountPtr account) : QObject(), _account(account), _currentDiscoveryDirectoryResult(0) { DiscoveryMainThread(AccountPtr account) : QObject(), _account(account), _currentDiscoveryDirectoryResult(0) {
}
void deleteCacheEntry(QString path) {
//qDebug() << path << _directoryContents.value(path).count();
foreach (csync_vio_file_stat_t* stat, _directoryContents.value(path)) {
csync_vio_file_stat_destroy(stat);
}
_directoryContents.remove(path);
}
~DiscoveryMainThread() {
// Delete the _contents_ of the list-map explicitly:
foreach (const QLinkedList<csync_vio_file_stat_t*> & list, _directoryContents) {
foreach (csync_vio_file_stat_t* stat, list) {
csync_vio_file_stat_destroy(stat);
}
}
} }
void abort(); void abort();
@@ -110,10 +113,9 @@ public:
public slots: public slots:
// From DiscoveryJob: // From DiscoveryJob:
void doOpendirSlot(QString url, DiscoveryDirectoryResult* ); void doOpendirSlot(QString url, DiscoveryDirectoryResult* );
void doClosedirSlot(QString path);
// From Job: // From Job:
void singleDirectoryJobResultSlot(QLinkedList<csync_vio_file_stat_t*>); void singleDirectoryJobResultSlot(const QList<FileStatPointer> &);
void singleDirectoryJobFinishedWithErrorSlot(int csyncErrnoCode, QString msg); void singleDirectoryJobFinishedWithErrorSlot(int csyncErrnoCode, QString msg);
void singleDirectoryJobFirstDirectoryPermissionsSlot(QString); void singleDirectoryJobFirstDirectoryPermissionsSlot(QString);
signals: signals:
@@ -175,8 +177,6 @@ signals:
// After the discovery job has been woken up again (_vioWaitCondition) // After the discovery job has been woken up again (_vioWaitCondition)
void doOpendirSignal(QString url, DiscoveryDirectoryResult*); void doOpendirSignal(QString url, DiscoveryDirectoryResult*);
// to tell the main thread to invalidate its directory data
void doClosedirSignal(QString path);
}; };
} }

View File

@@ -204,12 +204,12 @@ bool FileSystem::renameReplace(const QString& originFileName, const QString& des
return true; return true;
} }
bool FileSystem::openFileSharedRead(QFile* file, QString* error) bool FileSystem::openAndSeekFileSharedRead(QFile* file, QString* errorOrNull, qint64 seek)
{ {
bool ok = false; QString errorDummy;
if (error) { // avoid many if (errorOrNull) later.
error->clear(); QString& error = errorOrNull ? *errorOrNull : errorDummy;
} error.clear();
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
// //
@@ -236,9 +236,7 @@ bool FileSystem::openFileSharedRead(QFile* file, QString* error)
// Bail out on error. // Bail out on error.
if (fileHandle == INVALID_HANDLE_VALUE) { if (fileHandle == INVALID_HANDLE_VALUE) {
if (error) { error = qt_error_string();
*error = qt_error_string();
}
return false; return false;
} }
@@ -247,19 +245,34 @@ bool FileSystem::openFileSharedRead(QFile* file, QString* error)
// the fd the handle will be closed too. // the fd the handle will be closed too.
int fd = _open_osfhandle((intptr_t)fileHandle, _O_RDONLY); int fd = _open_osfhandle((intptr_t)fileHandle, _O_RDONLY);
if (fd == -1) { if (fd == -1) {
if (error) { error = "could not make fd from handle";
*error = "could not make fd from handle";
}
return false; return false;
} }
ok = file->open(fd, QIODevice::ReadOnly, QFile::AutoCloseHandle); if (!file->open(fd, QIODevice::ReadOnly, QFile::AutoCloseHandle)) {
#else error = file->errorString();
ok = file->open(QFile::ReadOnly); return false;
#endif
if (! ok && error) {
*error = file->errorString();
} }
return ok;
// Seek to the right spot
LARGE_INTEGER *li = reinterpret_cast<LARGE_INTEGER*>(&seek);
DWORD newFilePointer = SetFilePointer(fileHandle, li->LowPart, &li->HighPart, FILE_BEGIN);
if (newFilePointer == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
error = qt_error_string();
return false;
}
return true;
#else
if (!file->open(QFile::ReadOnly)) {
error = file->errorString();
return false;
}
if (!file->seek(seek)) {
error = file->errorString();
return false;
}
return true;
#endif
} }
#ifdef Q_OS_WIN #ifdef Q_OS_WIN

View File

@@ -75,13 +75,13 @@ bool renameReplace(const QString &originFileName, const QString &destinationFile
QString *errorString); QString *errorString);
/** /**
* Replacement for QFile::open(ReadOnly) that sets a more permissive sharing mode * Replacement for QFile::open(ReadOnly) followed by a seek().
* on Windows. * This version sets a more permissive sharing mode on Windows.
* *
* Warning: The resuting file may have an empty fileName and be unsuitable for use * Warning: The resuting file may have an empty fileName and be unsuitable for use
* with QFileInfo! * with QFileInfo! Calling seek() on the QFile with >32bit signed values will fail!
*/ */
bool openFileSharedRead(QFile* file, QString* error); bool openAndSeekFileSharedRead(QFile* file, QString* error, qint64 seek);
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
/** /**

View File

@@ -68,11 +68,12 @@ AbstractNetworkJob::AbstractNetworkJob(AccountPtr account, const QString &path,
void AbstractNetworkJob::setReply(QNetworkReply *reply) void AbstractNetworkJob::setReply(QNetworkReply *reply)
{ {
if (_reply) { if (reply)
_reply->deleteLater(); reply->setProperty("doNotHandleAuth", true);
}
reply->setProperty("doNotHandleAuth", true); QNetworkReply *old = _reply;
_reply = reply; _reply = reply;
delete old;
} }
void AbstractNetworkJob::setTimeout(qint64 msec) void AbstractNetworkJob::setTimeout(qint64 msec)
@@ -213,9 +214,7 @@ QByteArray AbstractNetworkJob::responseTimestamp()
AbstractNetworkJob::~AbstractNetworkJob() AbstractNetworkJob::~AbstractNetworkJob()
{ {
if (_reply) { setReply(0);
_reply->deleteLater();
}
} }
void AbstractNetworkJob::start() void AbstractNetworkJob::start()
@@ -224,7 +223,10 @@ void AbstractNetworkJob::start()
_durationTimer.start(); _durationTimer.start();
_duration = 0; _duration = 0;
qDebug() << "!!!" << metaObject()->className() << "created for" << account()->url() << "querying" << path(); const QUrl url = account()->url();
const QString displayUrl = QString( "%1://%2%3").arg(url.scheme()).arg(url.host()).arg(url.path());
qDebug() << "!!!" << metaObject()->className() << "created for" << displayUrl << "+" << path();
} }
void AbstractNetworkJob::slotTimeout() void AbstractNetworkJob::slotTimeout()
@@ -318,6 +320,131 @@ bool MkColJob::finished()
return true; return true;
} }
/*********************************************************************************************/
// supposed to read <D:collection> when pointing to <D:resourcetype><D:collection></D:resourcetype>..
static QString readContentsAsString(QXmlStreamReader &reader) {
QString result;
int level = 0;
do {
QXmlStreamReader::TokenType type = reader.readNext();
if (type == QXmlStreamReader::StartElement) {
level++;
result += "<" + reader.name().toString() + ">";
} else if (type == QXmlStreamReader::Characters) {
result += reader.text();
} else if (type == QXmlStreamReader::EndElement) {
level--;
if (level < 0) {
break;
}
result += "</" + reader.name().toString() + ">";
}
} while (!reader.atEnd());
return result;
}
LsColXMLParser::LsColXMLParser()
{
}
bool LsColXMLParser::parse( const QByteArray& xml, QHash<QString, qint64> *sizes)
{
// Parse DAV response
QXmlStreamReader reader(xml);
reader.addExtraNamespaceDeclaration(QXmlStreamNamespaceDeclaration("d", "DAV:"));
QStringList folders;
QString currentHref;
QMap<QString, QString> currentTmpProperties;
QMap<QString, QString> currentHttp200Properties;
bool currentPropsHaveHttp200 = false;
bool insidePropstat = false;
bool insideProp = false;
bool insideMultiStatus = false;
while (!reader.atEnd()) {
QXmlStreamReader::TokenType type = reader.readNext();
QString name = reader.name().toString();
// Start elements with DAV:
if (type == QXmlStreamReader::StartElement && reader.namespaceUri() == QLatin1String("DAV:")) {
if (name == QLatin1String("href")) {
currentHref = QUrl::fromPercentEncoding(reader.readElementText().toUtf8());
} else if (name == QLatin1String("response")) {
} else if (name == QLatin1String("propstat")) {
insidePropstat = true;
} else if (name == QLatin1String("status") && insidePropstat) {
QString httpStatus = reader.readElementText();
if (httpStatus.startsWith("HTTP/1.1 200")) {
currentPropsHaveHttp200 = true;
} else {
currentPropsHaveHttp200 = false;
}
} else if (name == QLatin1String("prop")) {
insideProp = true;
continue;
} else if (name == QLatin1String("multistatus")) {
insideMultiStatus = true;
continue;
}
}
if (type == QXmlStreamReader::StartElement && insidePropstat && insideProp) {
// All those elements are properties
QString propertyContent = readContentsAsString(reader);
if (name == QLatin1String("resourcetype") && propertyContent.contains("collection")) {
folders.append(currentHref);
} else if (name == QLatin1String("quota-used-bytes")) {
bool ok = false;
auto s = propertyContent.toLongLong(&ok);
if (ok && sizes) {
sizes->insert(currentHref, s);
}
}
currentTmpProperties.insert(reader.name().toString(), propertyContent);
}
// End elements with DAV:
if (type == QXmlStreamReader::EndElement) {
if (reader.namespaceUri() == QLatin1String("DAV:")) {
if (reader.name() == "response") {
if (currentHref.endsWith('/')) {
currentHref.chop(1);
}
emit directoryListingIterated(currentHref, currentHttp200Properties);
currentHref.clear();
currentHttp200Properties.clear();
} else if (reader.name() == "propstat") {
insidePropstat = false;
if (currentPropsHaveHttp200) {
currentHttp200Properties = QMap<QString,QString>(currentTmpProperties);
}
currentTmpProperties.clear();
currentPropsHaveHttp200 = false;
} else if (reader.name() == "prop") {
insideProp = false;
}
}
}
}
if (reader.hasError()) {
// XML Parser error? Whatever had been emitted before will come as directoryListingIterated
qDebug() << "ERROR" << reader.errorString() << xml;
return false;
} else if (!insideMultiStatus) {
qDebug() << "ERROR no WebDAV response?" << xml;
return false;
} else {
emit directoryListingSubfolders(folders);
emit finishedWithoutError();
}
return true;
}
/*********************************************************************************************/ /*********************************************************************************************/
LsColJob::LsColJob(AccountPtr account, const QString &path, QObject *parent) LsColJob::LsColJob(AccountPtr account, const QString &path, QObject *parent)
@@ -375,117 +502,36 @@ void LsColJob::start()
AbstractNetworkJob::start(); AbstractNetworkJob::start();
} }
// supposed to read <D:collection> when pointing to <D:resourcetype><D:collection></D:resourcetype>.. // TODO: Instead of doing all in this slot, we should iteratively parse in readyRead(). This
static QString readContentsAsString(QXmlStreamReader &reader) { // would allow us to be more asynchronous in processing while data is coming from the network,
QString result; // not in all in one big blobb at the end.
int level = 0;
do {
QXmlStreamReader::TokenType type = reader.readNext();
if (type == QXmlStreamReader::StartElement) {
level++;
result += "<" + reader.name().toString() + ">";
} else if (type == QXmlStreamReader::Characters) {
result += reader.text();
} else if (type == QXmlStreamReader::EndElement) {
level--;
if (level < 0) {
break;
}
result += "</" + reader.name().toString() + ">";
}
} while (!reader.atEnd());
return result;
}
bool LsColJob::finished() bool LsColJob::finished()
{ {
QString contentType = reply()->header(QNetworkRequest::ContentTypeHeader).toString(); QString contentType = reply()->header(QNetworkRequest::ContentTypeHeader).toString();
int httpCode = reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); int httpCode = reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (httpCode == 207 && contentType.contains("application/xml; charset=utf-8")) { if (httpCode == 207 && contentType.contains("application/xml; charset=utf-8")) {
// Parse DAV response LsColXMLParser parser;
QByteArray xml = reply()->readAll(); connect( &parser, SIGNAL(directoryListingSubfolders(const QStringList&)),
QXmlStreamReader reader(xml); this, SIGNAL(directoryListingSubfolders(const QStringList&)) );
reader.addExtraNamespaceDeclaration(QXmlStreamNamespaceDeclaration("d", "DAV:")); connect( &parser, SIGNAL(directoryListingIterated(const QString&, const QMap<QString,QString>&)),
this, SIGNAL(directoryListingIterated(const QString&, const QMap<QString,QString>&)) );
connect( &parser, SIGNAL(finishedWithError(QNetworkReply *)),
this, SIGNAL(finishedWithError(QNetworkReply *)) );
connect( &parser, SIGNAL(finishedWithoutError()),
this, SIGNAL(finishedWithoutError()) );
QStringList folders; if( !parser.parse( reply()->readAll(), &_sizes ) ) {
QString currentHref; // XML parse error
QMap<QString, QString> currentTmpProperties; emit finishedWithError(reply());
QMap<QString, QString> currentHttp200Properties;
bool currentPropsHaveHttp200 = false;
bool insidePropstat = false;
bool insideProp = false;
while (!reader.atEnd()) {
QXmlStreamReader::TokenType type = reader.readNext();
QString name = reader.name().toString();
// Start elements with DAV:
if (type == QXmlStreamReader::StartElement && reader.namespaceUri() == QLatin1String("DAV:")) {
if (name == QLatin1String("href")) {
currentHref = QUrl::fromPercentEncoding(reader.readElementText().toUtf8());
} else if (name == QLatin1String("response")) {
} else if (name == QLatin1String("propstat")) {
insidePropstat = true;
} else if (name == QLatin1String("status") && insidePropstat) {
QString httpStatus = reader.readElementText();
if (httpStatus.startsWith("HTTP/1.1 200")) {
currentPropsHaveHttp200 = true;
} else {
currentPropsHaveHttp200 = false;
}
} else if (name == QLatin1String("prop")) {
insideProp = true;
continue;
}
}
if (type == QXmlStreamReader::StartElement && insidePropstat && insideProp) {
// All those elements are properties
QString propertyContent = readContentsAsString(reader);
if (name == QLatin1String("resourcetype") && propertyContent.contains("collection")) {
folders.append(currentHref);
} else if (name == QLatin1String("quota-used-bytes")) {
bool ok = false;
auto s = propertyContent.toLongLong(&ok);
if (ok) {
_sizes[currentHref] = s;
}
}
currentTmpProperties.insert(reader.name().toString(), propertyContent);
}
// End elements with DAV:
if (type == QXmlStreamReader::EndElement) {
if (reader.namespaceUri() == QLatin1String("DAV:")) {
if (reader.name() == "response") {
if (currentHref.endsWith('/')) {
currentHref.chop(1);
}
emit directoryListingIterated(currentHref, currentHttp200Properties);
currentHref.clear();
currentHttp200Properties.clear();
} else if (reader.name() == "propstat") {
insidePropstat = false;
if (currentPropsHaveHttp200) {
currentHttp200Properties = QMap<QString,QString>(currentTmpProperties);
}
currentTmpProperties.clear();
currentPropsHaveHttp200 = false;
} else if (reader.name() == "prop") {
insideProp = false;
}
}
}
} }
emit directoryListingSubfolders(folders);
emit finishedWithoutError();
} else if (httpCode == 207) { } else if (httpCode == 207) {
// wrong content type // wrong content type
emit finishedWithError(reply()); emit finishedWithError(reply());
} else { } else {
// wrong HTTP code // wrong HTTP code or any other network error
emit finishedWithError(reply()); emit finishedWithError(reply());
} }
return true; return true;
} }
@@ -648,8 +694,9 @@ bool PropfindJob::finished()
if (type == QXmlStreamReader::StartElement) { if (type == QXmlStreamReader::StartElement) {
if (!curElement.isEmpty() && curElement.top() == QLatin1String("prop")) { if (!curElement.isEmpty() && curElement.top() == QLatin1String("prop")) {
items.insert(reader.name().toString(), reader.readElementText()); items.insert(reader.name().toString(), reader.readElementText());
} else {
curElement.push(reader.name().toString());
} }
curElement.push(reader.name().toString());
} }
if (type == QXmlStreamReader::EndElement) { if (type == QXmlStreamReader::EndElement) {
if(curElement.top() == reader.name()) { if(curElement.top() == reader.name()) {

View File

@@ -94,6 +94,9 @@ protected:
QElapsedTimer _durationTimer; QElapsedTimer _durationTimer;
quint64 _duration; quint64 _duration;
bool _timedout; // set to true when the timeout slot is recieved bool _timedout; // set to true when the timeout slot is recieved
// Automatically follows redirects. Note that this only works for
// GET requests that don't set up any HTTP body or other flags.
bool _followRedirects; bool _followRedirects;
private slots: private slots:
@@ -129,6 +132,21 @@ private slots:
/** /**
* @brief The LsColJob class * @brief The LsColJob class
*/ */
class OWNCLOUDSYNC_EXPORT LsColXMLParser : public QObject {
Q_OBJECT
public:
explicit LsColXMLParser();
bool parse(const QByteArray &xml, QHash<QString, qint64> *sizes);
signals:
void directoryListingSubfolders(const QStringList &items);
void directoryListingIterated(const QString &name, const QMap<QString,QString> &properties);
void finishedWithError(QNetworkReply *reply);
void finishedWithoutError();
};
class OWNCLOUDSYNC_EXPORT LsColJob : public AbstractNetworkJob { class OWNCLOUDSYNC_EXPORT LsColJob : public AbstractNetworkJob {
Q_OBJECT Q_OBJECT
public: public:

View File

@@ -27,6 +27,7 @@
#endif #endif
#include "configfile.h" #include "configfile.h"
#include "utility.h" #include "utility.h"
#include "account.h"
#include <json.h> #include <json.h>
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
@@ -40,9 +41,13 @@
#include <QTimer> #include <QTimer>
#include <QObject> #include <QObject>
#include <QTimerEvent> #include <QTimerEvent>
#include <QDebug>
namespace OCC { namespace OCC {
OwncloudPropagator::~OwncloudPropagator()
{}
/* The maximum number of active job in parallel */ /* The maximum number of active job in parallel */
int OwncloudPropagator::maximumActiveJob() int OwncloudPropagator::maximumActiveJob()
{ {
@@ -631,6 +636,9 @@ void PropagateDirectory::finalize()
emit finished(_hasError == SyncFileItem::NoStatus ? SyncFileItem::Success : _hasError); emit finished(_hasError == SyncFileItem::NoStatus ? SyncFileItem::Success : _hasError);
} }
CleanupPollsJob::~CleanupPollsJob()
{}
void CleanupPollsJob::start() void CleanupPollsJob::start()
{ {
if (_pollInfos.empty()) { if (_pollInfos.empty()) {

View File

@@ -270,6 +270,8 @@ public:
, _account(account) , _account(account)
{ } { }
~OwncloudPropagator();
void start(const SyncFileItemVector &_syncedItems); void start(const SyncFileItemVector &_syncedItems);
QAtomicInt _downloadLimit; QAtomicInt _downloadLimit;
@@ -359,6 +361,8 @@ public:
SyncJournalDb *journal, const QString &localPath, QObject* parent = 0) SyncJournalDb *journal, const QString &localPath, QObject* parent = 0)
: QObject(parent), _pollInfos(pollInfos), _account(account), _journal(journal), _localPath(localPath) {} : QObject(parent), _pollInfos(pollInfos), _account(account), _journal(journal), _localPath(localPath) {}
~CleanupPollsJob();
void start(); void start();
signals: signals:
void finished(); void finished();

View File

@@ -16,6 +16,7 @@
#pragma once #pragma once
#include <QNetworkReply> #include <QNetworkReply>
#include <QDebug>
#include "syncfileitem.h" #include "syncfileitem.h"
namespace OCC { namespace OCC {
@@ -33,9 +34,14 @@ inline QByteArray parseEtag(const char *header) {
inline QByteArray getEtagFromReply(QNetworkReply *reply) inline QByteArray getEtagFromReply(QNetworkReply *reply)
{ {
QByteArray ret = parseEtag(reply->rawHeader("OC-ETag")); QByteArray ocEtag = parseEtag(reply->rawHeader("OC-ETag"));
QByteArray etag = parseEtag(reply->rawHeader("ETag"));
QByteArray ret = ocEtag;
if (ret.isEmpty()) { if (ret.isEmpty()) {
ret = parseEtag(reply->rawHeader("ETag")); ret = etag;
}
if (ocEtag.length() > 0 && ocEtag != etag) {
qDebug() << "Quite peculiar, we have an etag != OC-Etag [no problem!]" << etag << ocEtag;
} }
return ret; return ret;
} }

View File

@@ -25,6 +25,7 @@
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QFileInfo> #include <QFileInfo>
#include <QDir> #include <QDir>
#include <QDebug>
#include <cmath> #include <cmath>
namespace OCC { namespace OCC {
@@ -368,6 +369,7 @@ void PropagateDownloadFileQNAM::start()
_job->start(); _job->start();
} }
const char owncloudCustomSoftErrorStringC[] = "owncloud-custom-soft-error-string";
void PropagateDownloadFileQNAM::slotGetFinished() void PropagateDownloadFileQNAM::slotGetFinished()
{ {
_propagator->_activeJobs--; _propagator->_activeJobs--;
@@ -407,7 +409,18 @@ void PropagateDownloadFileQNAM::slotGetFinished()
return; return;
} }
// This gives a custom QNAM (by the user of libowncloudsync) to abort() a QNetworkReply in its metaDataChanged() slot and
// set a custom error string to make this a soft error. In contrast to the default hard error this won't bring down
// the whole sync and allows for a custom error message.
QNetworkReply *reply = job->reply();
if (err == QNetworkReply::OperationCanceledError && reply->property(owncloudCustomSoftErrorStringC).isValid()) {
job->setErrorString(reply->property(owncloudCustomSoftErrorStringC).toString());
job->setErrorStatus(SyncFileItem::SoftError);
}
SyncFileItem::Status status = job->errorStatus(); SyncFileItem::Status status = job->errorStatus();
if (status == SyncFileItem::NoStatus) { if (status == SyncFileItem::NoStatus) {
status = classifyError(err, _item._httpErrorCode); status = classifyError(err, _item._httpErrorCode);
} }
@@ -506,10 +519,14 @@ void PropagateDownloadFileQNAM::downloadFinished()
_tmpFile.setPermissions(existingFile.permissions()); _tmpFile.setPermissions(existingFile.permissions());
} }
FileSystem::setFileHidden(_tmpFile.fileName(), false); FileSystem::setModTime(_tmpFile.fileName(), _item._modtime);
// We need to fetch the time again because some file system such as FAT have a less than a second
// Accuracy, and we really need the time from the file system. (#3103)
_item._modtime = FileSystem::getModTime(_tmpFile.fileName());
QString error; QString error;
_propagator->addTouchedFile(fn); _propagator->addTouchedFile(fn);
FileSystem::setFileHidden(_tmpFile.fileName(), false);
if (!FileSystem::renameReplace(_tmpFile.fileName(), fn, &error)) { if (!FileSystem::renameReplace(_tmpFile.fileName(), fn, &error)) {
qDebug() << Q_FUNC_INFO << QString("Rename failed: %1 => %2").arg(_tmpFile.fileName()).arg(fn); qDebug() << Q_FUNC_INFO << QString("Rename failed: %1 => %2").arg(_tmpFile.fileName()).arg(fn);
// If we moved away the original file due to a conflict but can't // If we moved away the original file due to a conflict but can't
@@ -530,7 +547,6 @@ void PropagateDownloadFileQNAM::downloadFinished()
// Maybe we downloaded a newer version of the file than we thought we would... // Maybe we downloaded a newer version of the file than we thought we would...
// Get up to date information for the journal. // Get up to date information for the journal.
FileSystem::setModTime(fn, _item._modtime);
_item._size = FileSystem::getSize(fn); _item._size = FileSystem::getSize(fn);
_propagator->_journal->setFileRecord(SyncJournalFileRecord(_item, fn)); _propagator->_journal->setFileRecord(SyncJournalFileRecord(_item, fn));

View File

@@ -78,8 +78,10 @@ public:
qint64 currentDownloadPosition(); qint64 currentDownloadPosition();
QString errorString() const; QString errorString() const;
void setErrorString(const QString& s) { _errorString = s; }
SyncFileItem::Status errorStatus() { return _errorStatus; } SyncFileItem::Status errorStatus() { return _errorStatus; }
void setErrorStatus(const SyncFileItem::Status & s) { _errorStatus = s; }
virtual void slotTimeout() Q_DECL_OVERRIDE; virtual void slotTimeout() Q_DECL_OVERRIDE;

View File

@@ -85,9 +85,10 @@ void PropagateRemoteDelete::slotDeleteJobFinished()
<< (_job->reply()->error() == QNetworkReply::NoError ? QLatin1String("") : _job->reply()->errorString()); << (_job->reply()->error() == QNetworkReply::NoError ? QLatin1String("") : _job->reply()->errorString());
QNetworkReply::NetworkError err = _job->reply()->error(); QNetworkReply::NetworkError err = _job->reply()->error();
_item._httpErrorCode = _job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); const int httpStatus = _job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
_item._httpErrorCode = httpStatus;
if (err != QNetworkReply::NoError) { if (err != QNetworkReply::NoError && err != QNetworkReply::ContentNotFoundError) {
if( checkForProblemsWithShared(_item._httpErrorCode, if( checkForProblemsWithShared(_item._httpErrorCode,
tr("The file has been removed from a read only share. It was restored.")) ) { tr("The file has been removed from a read only share. It was restored.")) ) {
@@ -102,7 +103,11 @@ void PropagateRemoteDelete::slotDeleteJobFinished()
_item._requestDuration = _job->duration(); _item._requestDuration = _job->duration();
_item._responseTimeStamp = _job->responseTimestamp(); _item._responseTimeStamp = _job->responseTimestamp();
if (_item._httpErrorCode != 204 ) { // A 404 reply is also considered a success here: We want to make sure
// a file is gone from the server. It not being there in the first place
// is ok. This will happen for files that are in the DB but not on
// the server or the local file system.
if (httpStatus != 204 && httpStatus != 404) {
// Normaly we expect "204 No Content" // Normaly we expect "204 No Content"
// If it is not the case, it might be because of a proxy or gateway intercepting the request, so we must // If it is not the case, it might be because of a proxy or gateway intercepting the request, so we must
// throw an error. // throw an error.

View File

@@ -64,6 +64,12 @@ static qint64 chunkSize() {
return chunkSize; return chunkSize;
} }
PUTFileJob::~PUTFileJob()
{
// Make sure that we destroy the QNetworkReply before our _device of which it keeps an internal pointer.
setReply(0);
}
void PUTFileJob::start() { void PUTFileJob::start() {
QNetworkRequest req; QNetworkRequest req;
for(QMap<QByteArray, QByteArray>::const_iterator it = _headers.begin(); it != _headers.end(); ++it) { for(QMap<QByteArray, QByteArray>::const_iterator it = _headers.begin(); it != _headers.end(); ++it) {
@@ -232,17 +238,13 @@ bool UploadDevice::prepareAndOpen(const QString& fileName, qint64 start, qint64
QFile file(fileName); QFile file(fileName);
QString openError; QString openError;
if (!FileSystem::openFileSharedRead(&file, &openError)) { if (!FileSystem::openAndSeekFileSharedRead(&file, &openError, start)) {
setErrorString(openError); setErrorString(openError);
return false; return false;
} }
size = qMin(FileSystem::getSize(fileName), size); size = qBound(0ll, size, FileSystem::getSize(fileName) - start);
_data.resize(size); _data.resize(size);
if (!file.seek(start)) {
setErrorString(file.errorString());
return false;
}
auto read = file.read(_data.data(), size); auto read = file.read(_data.data(), size);
if (read != size) { if (read != size) {
setErrorString(file.errorString()); setErrorString(file.errorString());
@@ -406,6 +408,7 @@ void PropagateUploadFileQNAM::startNextChunk()
return; return;
} }
// job takes ownership of device via a QScopedPointer. Job deletes itself when finishing
PUTFileJob* job = new PUTFileJob(_propagator->account(), _propagator->_remoteFolder + path, device, headers, _currentChunk); PUTFileJob* job = new PUTFileJob(_propagator->account(), _propagator->_remoteFolder + path, device, headers, _currentChunk);
_jobs.append(job); _jobs.append(job);
connect(job, SIGNAL(finishedSignal()), this, SLOT(slotPutFinished())); connect(job, SIGNAL(finishedSignal()), this, SLOT(slotPutFinished()));
@@ -521,8 +524,8 @@ void PropagateUploadFileQNAM::slotPutFinished()
// But if the upload is ongoing, because not all chunks were uploaded // But if the upload is ongoing, because not all chunks were uploaded
// yet, the upload can be stopped and an error can be displayed, because // yet, the upload can be stopped and an error can be displayed, because
// the server hasn't registered the new file yet. // the server hasn't registered the new file yet.
bool finished = job->reply()->hasRawHeader("ETag") QByteArray etag = getEtagFromReply(job->reply());
|| job->reply()->hasRawHeader("OC-ETag"); bool finished = etag.length() > 0;
// Check if the file still exists // Check if the file still exists
const QString fullFilePath(_propagator->getFilePath(_item._file)); const QString fullFilePath(_propagator->getFilePath(_item._file));
@@ -592,7 +595,6 @@ void PropagateUploadFileQNAM::slotPutFinished()
_item._fileId = fid; _item._fileId = fid;
} }
QByteArray etag = getEtagFromReply(job->reply());
_item._etag = etag; _item._etag = etag;
_item._responseTimeStamp = job->responseTimestamp(); _item._responseTimeStamp = job->responseTimestamp();

View File

@@ -74,6 +74,7 @@ public:
explicit PUTFileJob(AccountPtr account, const QString& path, QIODevice *device, explicit PUTFileJob(AccountPtr account, const QString& path, QIODevice *device,
const QMap<QByteArray, QByteArray> &headers, int chunk, QObject* parent = 0) const QMap<QByteArray, QByteArray> &headers, int chunk, QObject* parent = 0)
: AbstractNetworkJob(account, path, parent), _device(device), _headers(headers), _chunk(chunk) {} : AbstractNetworkJob(account, path, parent), _device(device), _headers(headers), _chunk(chunk) {}
~PUTFileJob();
int _chunk; int _chunk;

View File

@@ -384,6 +384,7 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
case CSYNC_STATUS_STORAGE_UNAVAILABLE: case CSYNC_STATUS_STORAGE_UNAVAILABLE:
item._errorString = QLatin1String("Directory temporarily not available on server."); item._errorString = QLatin1String("Directory temporarily not available on server.");
item._status = SyncFileItem::SoftError; item._status = SyncFileItem::SoftError;
_temporarilyUnavailablePaths.insert(item._file);
break; break;
default: default:
Q_ASSERT("Non handled error-status"); Q_ASSERT("Non handled error-status");
@@ -484,9 +485,11 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
} }
item._direction = dir; item._direction = dir;
// check for blacklisting of this item. if (instruction != CSYNC_INSTRUCTION_NONE) {
// if the item is on blacklist, the instruction was set to IGNORE // check for blacklisting of this item.
checkErrorBlacklisting( &item ); // if the item is on blacklist, the instruction was set to ERROR
checkErrorBlacklisting( &item );
}
if (!item._isDirectory) { if (!item._isDirectory) {
_progressInfo._totalFileCount++; _progressInfo._totalFileCount++;
@@ -605,11 +608,15 @@ void SyncEngine::startSync()
if (fileRecordCount >= 1 && isUpdateFrom_1_5) { if (fileRecordCount >= 1 && isUpdateFrom_1_5) {
qDebug() << "detected update from 1.5" << fileRecordCount << isUpdateFrom_1_5; qDebug() << "detected update from 1.5" << fileRecordCount << isUpdateFrom_1_5;
// Disable the read from DB to be sure to re-read all the fileid and etags. // Disable the read from DB to be sure to re-read all the fileid and etags.
csync_set_read_from_db(_csync_ctx, false); _csync_ctx->read_remote_from_db = false;
} else { } else {
csync_set_read_from_db(_csync_ctx, true); _csync_ctx->read_remote_from_db = true;
} }
// This tells csync to never read from the DB if it is empty
// thereby speeding up the initial discovery significantly.
_csync_ctx->db_is_empty = (fileRecordCount == 0);
bool usingSelectiveSync = (!_selectiveSyncBlackList.isEmpty()); bool usingSelectiveSync = (!_selectiveSyncBlackList.isEmpty());
qDebug() << (usingSelectiveSync ? "====Using Selective Sync" : "====NOT Using Selective Sync"); qDebug() << (usingSelectiveSync ? "====Using Selective Sync" : "====NOT Using Selective Sync");
if (fileRecordCount >= 0 && fileRecordCount < 50 && !usingSelectiveSync) { if (fileRecordCount >= 0 && fileRecordCount < 50 && !usingSelectiveSync) {
@@ -690,7 +697,7 @@ void SyncEngine::slotDiscoveryJobFinished(int discoveryResult)
return; return;
} }
_stopWatch.addLapTime(QLatin1String("Reconcile Finished")); qDebug() << "<<#### Reconcile end #################################################### " << _stopWatch.addLapTime(QLatin1String("Reconcile Finished"));
_progressInfo = Progress::Info(); _progressInfo = Progress::Info();
@@ -698,6 +705,7 @@ void SyncEngine::slotDiscoveryJobFinished(int discoveryResult)
_hasRemoveFile = false; _hasRemoveFile = false;
bool walkOk = true; bool walkOk = true;
_seenFiles.clear(); _seenFiles.clear();
_temporarilyUnavailablePaths.clear();
if( csync_walk_local_tree(_csync_ctx, &treewalkLocal, 0) < 0 ) { if( csync_walk_local_tree(_csync_ctx, &treewalkLocal, 0) < 0 ) {
qDebug() << "Error in local treewalk."; qDebug() << "Error in local treewalk.";
@@ -791,6 +799,8 @@ void SyncEngine::slotDiscoveryJobFinished(int discoveryResult)
emit(started()); emit(started());
_propagator->start(_syncedItems); _propagator->start(_syncedItems);
qDebug() << "<<#### Post-Reconcile end #################################################### " << _stopWatch.addLapTime(QLatin1String("Post-Reconcile Finished"));
} }
void SyncEngine::slotCleanPollsJobAborted(const QString &error) void SyncEngine::slotCleanPollsJobAborted(const QString &error)
@@ -859,7 +869,7 @@ void SyncEngine::slotFinished()
_anotherSyncNeeded = _anotherSyncNeeded || _propagator->_anotherSyncNeeded; _anotherSyncNeeded = _anotherSyncNeeded || _propagator->_anotherSyncNeeded;
// emit the treewalk results. // emit the treewalk results.
if( ! _journal->postSyncCleanup( _seenFiles ) ) { if( ! _journal->postSyncCleanup( _seenFiles, _temporarilyUnavailablePaths ) ) {
qDebug() << "Cleaning of synced "; qDebug() << "Cleaning of synced ";
} }

View File

@@ -159,7 +159,21 @@ private:
QPointer<DiscoveryMainThread> _discoveryMainThread; QPointer<DiscoveryMainThread> _discoveryMainThread;
QSharedPointer <OwncloudPropagator> _propagator; QSharedPointer <OwncloudPropagator> _propagator;
QString _lastDeleted; // if the last item was a path and it has been deleted QString _lastDeleted; // if the last item was a path and it has been deleted
// After a sync, only the syncdb entries whose filenames appear in this
// set will be kept. See _temporarilyUnavailablePaths.
QSet<QString> _seenFiles; QSet<QString> _seenFiles;
// Some paths might be temporarily unavailable on the server, for
// example due to 503 Storage not available. Deleting information
// about the files from the database in these cases would lead to
// incorrect synchronization.
// Therefore all syncdb entries whose filename starts with one of
// the paths in this set will be kept.
// The specific case that fails otherwise is deleting a local file
// while the remote says storage not available.
QSet<QString> _temporarilyUnavailablePaths;
QThread _thread; QThread _thread;
Progress::Info _progressInfo; Progress::Info _progressInfo;

View File

@@ -21,6 +21,13 @@
#include <csync.h> #include <csync.h>
#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG) && (__GNUC__ * 100 + __GNUC_MINOR__ < 408)
// openSuse 12.3 didn't like enum bitfields.
#define BITFIELD(size)
#else
#define BITFIELD(size) :size
#endif
namespace OCC { namespace OCC {
class SyncFileItem { class SyncFileItem {
@@ -114,19 +121,19 @@ public:
// Variables usefull for everybody // Variables usefull for everybody
QString _file; QString _file;
QString _renameTarget; QString _renameTarget;
Type _type:3; Type _type BITFIELD(3);
Direction _direction:2; Direction _direction BITFIELD(2);
bool _isDirectory:1; bool _isDirectory BITFIELD(1);
/// Whether there's an entry in the blacklist table. /// Whether there's an entry in the blacklist table.
/// Note: that entry may have retries left, so this can be true /// Note: that entry may have retries left, so this can be true
/// without the status being FileIgnored. /// without the status being FileIgnored.
bool _hasBlacklistEntry:1; bool _hasBlacklistEntry BITFIELD(1);
// Variables usefull to report to the user // Variables usefull to report to the user
Status _status:4; Status _status BITFIELD(4);
bool _isRestoration:1; // The original operation was forbidden, and this is a restoration bool _isRestoration BITFIELD(1); // The original operation was forbidden, and this is a restoration
bool _should_update_etag:1; bool _should_update_etag BITFIELD(1);
quint16 _httpErrorCode; quint16 _httpErrorCode;
QString _errorString; // Contains a string only in case of error QString _errorString; // Contains a string only in case of error
QByteArray _responseTimeStamp; QByteArray _responseTimeStamp;
@@ -155,8 +162,8 @@ public:
time_t _other_modtime; time_t _other_modtime;
QByteArray _other_etag; QByteArray _other_etag;
QByteArray _other_fileId; QByteArray _other_fileId;
enum csync_instructions_e _instruction:16; enum csync_instructions_e _instruction BITFIELD(16);
enum csync_instructions_e _other_instruction:16; enum csync_instructions_e _other_instruction BITFIELD(16);
} log; } log;
}; };

View File

@@ -698,7 +698,8 @@ SyncJournalFileRecord SyncJournalDb::getFileRecord( const QString& filename )
return rec; return rec;
} }
bool SyncJournalDb::postSyncCleanup(const QSet<QString> &items ) bool SyncJournalDb::postSyncCleanup(const QSet<QString>& filepathsToKeep,
const QSet<QString>& prefixesToKeep)
{ {
QMutexLocker locker(&_mutex); QMutexLocker locker(&_mutex);
@@ -719,8 +720,16 @@ bool SyncJournalDb::postSyncCleanup(const QSet<QString> &items )
while(query.next()) { while(query.next()) {
const QString file = query.stringValue(1); const QString file = query.stringValue(1);
bool contained = items.contains(file); bool keep = filepathsToKeep.contains(file);
if( !contained ) { if( !keep ) {
foreach( const QString & prefix, prefixesToKeep ) {
if( file.startsWith(prefix) ) {
keep = true;
break;
}
}
}
if( !keep ) {
superfluousItems.append(query.stringValue(0)); superfluousItems.append(query.stringValue(0));
} }
} }

View File

@@ -97,7 +97,8 @@ public:
*/ */
void avoidReadFromDbOnNextSync(const QString& fileName); void avoidReadFromDbOnNextSync(const QString& fileName);
bool postSyncCleanup( const QSet<QString>& items ); bool postSyncCleanup(const QSet<QString>& filepathsToKeep,
const QSet<QString>& prefixesToKeep);
/* Because sqlite transactions is really slow, we encapsulate everything in big transactions /* Because sqlite transactions is really slow, we encapsulate everything in big transactions
* Commit will actually commit the transaction and create a new one. * Commit will actually commit the transaction and create a new one.

View File

@@ -122,11 +122,14 @@ QIcon Theme::themeIcon( const QString& name, bool sysTray ) const
flavor = QLatin1String("colored"); flavor = QLatin1String("colored");
} }
QIcon icon;
if( QIcon::hasThemeIcon( name )) { if( QIcon::hasThemeIcon( name )) {
// use from theme // use from theme
icon = QIcon::fromTheme( name ); return QIcon::fromTheme( name );
} else { }
QString key = name + "," + flavor;
QIcon & cached = _iconCache[key];
if (cached.isNull()) {
QList<int> sizes; QList<int> sizes;
sizes <<16 << 22 << 32 << 48 << 64 << 128 << 256; sizes <<16 << 22 << 32 << 48 << 64 << 128 << 256;
foreach (int size, sizes) { foreach (int size, sizes) {
@@ -140,19 +143,20 @@ QIcon Theme::themeIcon( const QString& name, bool sysTray ) const
p.setPen(QColor("#dfdbd2")); p.setPen(QColor("#dfdbd2"));
p.drawPixmap(px.rect(), mask, mask.rect()); p.drawPixmap(px.rect(), mask, mask.rect());
} }
icon.addPixmap(px); cached.addPixmap(px);
} }
} }
if (icon.isNull()) { if (cached.isNull()) {
foreach (int size, sizes) { foreach (int size, sizes) {
QString pixmapName = QString::fromLatin1(":/client/resources/%1-%2.png").arg(name).arg(size); QString pixmapName = QString::fromLatin1(":/client/resources/%1-%2.png").arg(name).arg(size);
if (QFile::exists(pixmapName)) { if (QFile::exists(pixmapName)) {
icon.addFile(pixmapName); cached.addFile(pixmapName);
} }
} }
} }
} }
return icon;
return cached;
} }
QString Theme::hidpiFileName(const QString &fileName, QPaintDevice *dev) QString Theme::hidpiFileName(const QString &fileName, QPaintDevice *dev)

View File

@@ -196,7 +196,9 @@ public:
virtual bool wizardSelectiveSyncDefaultNothing() const; virtual bool wizardSelectiveSyncDefaultNothing() const;
protected: protected:
#ifndef TOKEN_AUTH_ONLY
QIcon themeIcon(const QString& name, bool sysTray = false) const; QIcon themeIcon(const QString& name, bool sysTray = false) const;
#endif
Theme(); Theme();
signals: signals:
@@ -208,7 +210,9 @@ private:
static Theme* _instance; static Theme* _instance;
bool _mono; bool _mono;
#ifndef TOKEN_AUTH_ONLY
mutable QHash<QString, QIcon> _iconCache;
#endif
}; };
} }

View File

@@ -32,5 +32,5 @@ owncloud_add_test(SyncJournalDB "")
owncloud_add_test(SyncFileItem "") owncloud_add_test(SyncFileItem "")
owncloud_add_test(ConcatUrl "") owncloud_add_test(ConcatUrl "")
owncloud_add_test(XmlParse "")

245
test/testxmlparse.h Normal file
View File

@@ -0,0 +1,245 @@
/*
* This software is in the public domain, furnished "as is", without technical
* support, and with no warranty, express or implied, as to its usefulness for
* any purpose.
* */
#ifndef MIRALL_TESTXMLPARSE_H
#define MIRALL_TESTXMLPARSE_H
#include <QtTest>
#include "networkjobs.h"
using namespace OCC;
class TestXmlParse : public QObject
{
Q_OBJECT
private:
bool _success;
QStringList _subdirs;
QStringList _items;
public slots:
void slotDirectoryListingSubFolders(const QStringList& list)
{
qDebug() << "subfolders: " << list;
_subdirs.append(list);
}
void slotDirectoryListingIterated(const QString& item, const QMap<QString,QString>& )
{
qDebug() << " item: " << item;
_items.append(item);
}
void slotFinishedSuccessfully()
{
_success = true;
}
private slots:
void init() {
qDebug() << Q_FUNC_INFO;
_success = false;
_subdirs.clear();
_items.clear();
}
void cleanup() {
}
void testParser1() {
const QByteArray testXml = "<?xml version='1.0' encoding='utf-8'?>"
"<d:multistatus xmlns:d=\"DAV:\" xmlns:s=\"http://sabredav.org/ns\" xmlns:oc=\"http://owncloud.org/ns\">"
"<d:response>"
"<d:href>/oc/remote.php/webdav/sharefolder/</d:href>"
"<d:propstat>"
"<d:prop>"
"<oc:id>00004213ocobzus5kn6s</oc:id>"
"<oc:permissions>RDNVCK</oc:permissions>"
"<oc:size>121780</oc:size>"
"<d:getetag>\"5527beb0400b0\"</d:getetag>"
"<d:resourcetype>"
"<d:collection/>"
"</d:resourcetype>"
"<d:getlastmodified>Fri, 06 Feb 2015 13:49:55 GMT</d:getlastmodified>"
"</d:prop>"
"<d:status>HTTP/1.1 200 OK</d:status>"
"</d:propstat>"
"<d:propstat>"
"<d:prop>"
"<d:getcontentlength/>"
"<oc:downloadURL/>"
"<oc:dDC/>"
"</d:prop>"
"<d:status>HTTP/1.1 404 Not Found</d:status>"
"</d:propstat>"
"</d:response>"
"<d:response>"
"<d:href>/oc/remote.php/webdav/sharefolder/quitte.pdf</d:href>"
"<d:propstat>"
"<d:prop>"
"<oc:id>00004215ocobzus5kn6s</oc:id>"
"<oc:permissions>RDNVW</oc:permissions>"
"<d:getetag>\"2fa2f0d9ed49ea0c3e409d49e652dea0\"</d:getetag>"
"<d:resourcetype/>"
"<d:getlastmodified>Fri, 06 Feb 2015 13:49:55 GMT</d:getlastmodified>"
"<d:getcontentlength>121780</d:getcontentlength>"
"</d:prop>"
"<d:status>HTTP/1.1 200 OK</d:status>"
"</d:propstat>"
"<d:propstat>"
"<d:prop>"
"<oc:downloadURL/>"
"<oc:dDC/>"
"</d:prop>"
"<d:status>HTTP/1.1 404 Not Found</d:status>"
"</d:propstat>"
"</d:response>"
"</d:multistatus>";
LsColXMLParser parser;
connect( &parser, SIGNAL(directoryListingSubfolders(const QStringList&)),
this, SLOT(slotDirectoryListingSubFolders(const QStringList&)) );
connect( &parser, SIGNAL(directoryListingIterated(const QString&, const QMap<QString,QString>&)),
this, SLOT(slotDirectoryListingIterated(const QString&, const QMap<QString,QString>&)) );
connect( &parser, SIGNAL(finishedWithoutError()),
this, SLOT(slotFinishedSuccessfully()) );
QHash <QString, qint64> sizes;
QVERIFY(parser.parse( testXml, &sizes ));
QVERIFY(_success);
QVERIFY(sizes.size() == 0 ); // No quota info in the XML
QVERIFY(_items.contains("/oc/remote.php/webdav/sharefolder/quitte.pdf"));
QVERIFY(_items.contains("/oc/remote.php/webdav/sharefolder"));
QVERIFY(_items.size() == 2 );
QVERIFY(_subdirs.contains("/oc/remote.php/webdav/sharefolder/"));
QVERIFY(_subdirs.size() == 1);
}
void testParserBrokenXml() {
const QByteArray testXml = "X<?xml version='1.0' encoding='utf-8'?>"
"<d:multistatus xmlns:d=\"DAV:\" xmlns:s=\"http://sabredav.org/ns\" xmlns:oc=\"http://owncloud.org/ns\">"
"<d:response>"
"<d:href>/oc/remote.php/webdav/sharefolder/</d:href>"
"<d:propstat>"
"<d:prop>"
"<oc:id>00004213ocobzus5kn6s</oc:id>"
"<oc:permissions>RDNVCK</oc:permissions>"
"<oc:size>121780</oc:size>"
"<d:getetag>\"5527beb0400b0\"</d:getetag>"
"<d:resourcetype>"
"<d:collection/>"
"</d:resourcetype>"
"<d:getlastmodified>Fri, 06 Feb 2015 13:49:55 GMT</d:getlastmodified>"
"</d:prop>"
"<d:status>HTTP/1.1 200 OK</d:status>"
"</d:propstat>"
"<d:propstat>"
"<d:prop>"
"<d:getcontentlength/>"
"<oc:downloadURL/>"
"<oc:dDC/>"
"</d:prop>"
"<d:status>HTTP/1.1 404 Not Found</d:status>"
"</d:propstat>"
"</d:response>"
"<d:response>"
"<d:href>/oc/remote.php/webdav/sharefolder/quitte.pdf</d:href>"
"<d:propstat>"
"<d:prop>"
"<oc:id>00004215ocobzus5kn6s</oc:id>"
"<oc:permissions>RDNVW</oc:permissions>"
"<d:getetag>\"2fa2f0d9ed49ea0c3e409d49e652dea0\"</d:getetag>"
"<d:resourcetype/>"
"<d:getlastmodified>Fri, 06 Feb 2015 13:49:55 GMT</d:getlastmodified>"
"<d:getcontentlength>121780</d:getcontentlength>"
"</d:prop>"
"<d:status>HTTP/1.1 200 OK</d:status>"
"</d:propstat>"
"<d:propstat>"
"<d:prop>"
"<oc:downloadURL/>"
"<oc:dDC/>"
"</d:prop>"
"<d:status>HTTP/1.1 404 Not Found</d:status>"
"</d:propstat>"
"</d:response>"
"</d:multistatus>";
LsColXMLParser parser;
connect( &parser, SIGNAL(directoryListingSubfolders(const QStringList&)),
this, SLOT(slotDirectoryListingSubFolders(const QStringList&)) );
connect( &parser, SIGNAL(directoryListingIterated(const QString&, const QMap<QString,QString>&)),
this, SLOT(slotDirectoryListingIterated(const QString&, const QMap<QString,QString>&)) );
connect( &parser, SIGNAL(finishedWithoutError()),
this, SLOT(slotFinishedSuccessfully()) );
QHash <QString, qint64> sizes;
QVERIFY(false == parser.parse( testXml, &sizes )); // verify false
QVERIFY(!_success);
QVERIFY(sizes.size() == 0 ); // No quota info in the XML
QVERIFY(_items.size() == 0 ); // FIXME: We should change the parser to not emit during parsing but at the end
QVERIFY(_subdirs.size() == 0);
}
void testParserEmptyXmlNoDav() {
const QByteArray testXml = "<html><body>I am under construction</body></html>";
LsColXMLParser parser;
connect( &parser, SIGNAL(directoryListingSubfolders(const QStringList&)),
this, SLOT(slotDirectoryListingSubFolders(const QStringList&)) );
connect( &parser, SIGNAL(directoryListingIterated(const QString&, const QMap<QString,QString>&)),
this, SLOT(slotDirectoryListingIterated(const QString&, const QMap<QString,QString>&)) );
connect( &parser, SIGNAL(finishedWithoutError()),
this, SLOT(slotFinishedSuccessfully()) );
QHash <QString, qint64> sizes;
QVERIFY(false == parser.parse( testXml, &sizes )); // verify false
QVERIFY(!_success);
QVERIFY(sizes.size() == 0 ); // No quota info in the XML
QVERIFY(_items.size() == 0 ); // FIXME: We should change the parser to not emit during parsing but at the end
QVERIFY(_subdirs.size() == 0);
}
void testParserEmptyXml() {
const QByteArray testXml = "";
LsColXMLParser parser;
connect( &parser, SIGNAL(directoryListingSubfolders(const QStringList&)),
this, SLOT(slotDirectoryListingSubFolders(const QStringList&)) );
connect( &parser, SIGNAL(directoryListingIterated(const QString&, const QMap<QString,QString>&)),
this, SLOT(slotDirectoryListingIterated(const QString&, const QMap<QString,QString>&)) );
connect( &parser, SIGNAL(finishedWithoutError()),
this, SLOT(slotFinishedSuccessfully()) );
QHash <QString, qint64> sizes;
QVERIFY(false == parser.parse( testXml, &sizes )); // verify false
QVERIFY(!_success);
QVERIFY(sizes.size() == 0 ); // No quota info in the XML
QVERIFY(_items.size() == 0 ); // FIXME: We should change the parser to not emit during parsing but at the end
QVERIFY(_subdirs.size() == 0);
}
};
#endif

View File

@@ -22,6 +22,7 @@ trans.pt_BR = client_pt_BR.ts
trans.ru = client_ru.ts trans.ru = client_ru.ts
trans.sl = client_sl.ts trans.sl = client_sl.ts
trans.sv = client_sv.ts trans.sv = client_sv.ts
trans.sr = client_sr.ts
trans.tr = client_tr.ts trans.tr = client_tr.ts
trans.uk = client_uk.ts trans.uk = client_uk.ts
trans.zh_TW = client_zh_TW.ts trans.zh_TW = client_zh_TW.ts

View File

@@ -235,12 +235,12 @@ Total time left %5</source>
<message> <message>
<location filename="../src/gui/addcertificatedialog.ui" line="17"/> <location filename="../src/gui/addcertificatedialog.ui" line="17"/>
<source>SSL client certificate authentication</source> <source>SSL client certificate authentication</source>
<translation type="unfinished"/> <translation>Επικύρωση πιστοποιητικού χρήστη SSL</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/addcertificatedialog.ui" line="23"/> <location filename="../src/gui/addcertificatedialog.ui" line="23"/>
<source>This server probably requires a SSL client certificate.</source> <source>This server probably requires a SSL client certificate.</source>
<translation type="unfinished"/> <translation>Ο διακομιστής πιθανόν απαιτεί πιστοποιητικό χρήστη SSL </translation>
</message> </message>
<message> <message>
<location filename="../src/gui/addcertificatedialog.ui" line="35"/> <location filename="../src/gui/addcertificatedialog.ui" line="35"/>
@@ -250,7 +250,7 @@ Total time left %5</source>
<message> <message>
<location filename="../src/gui/addcertificatedialog.ui" line="51"/> <location filename="../src/gui/addcertificatedialog.ui" line="51"/>
<source>Browse...</source> <source>Browse...</source>
<translation type="unfinished"/> <translation>Περιήγηση...</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/addcertificatedialog.ui" line="60"/> <location filename="../src/gui/addcertificatedialog.ui" line="60"/>
@@ -669,7 +669,7 @@ Are you sure you want to perform this operation?</source>
<message> <message>
<location filename="../src/gui/folderwizard.cpp" line="444"/> <location filename="../src/gui/folderwizard.cpp" line="444"/>
<source>Choose What to Sync: You can optionally deselect remote subfolders you do not wish to synchronize.</source> <source>Choose What to Sync: You can optionally deselect remote subfolders you do not wish to synchronize.</source>
<translation type="unfinished"/> <translation>Επιλέξτε Τι θα Συγχρονιστεί: Μπορείτε προαιρετικά να καταργήστε την επιλογή υποφακέλων που δεν επιθυμείτε να συγχρονίσετε.</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -734,7 +734,7 @@ Are you sure you want to perform this operation?</source>
<message> <message>
<location filename="../src/gui/generalsettings.ui" line="47"/> <location filename="../src/gui/generalsettings.ui" line="47"/>
<source>Show crash reporter</source> <source>Show crash reporter</source>
<translation type="unfinished"/> <translation>Εμφάνιση αναφοράς κατάρρευσης</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/generalsettings.ui" line="57"/> <location filename="../src/gui/generalsettings.ui" line="57"/>
@@ -1203,7 +1203,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="193"/> <location filename="../src/gui/owncloudsetupwizard.cpp" line="193"/>
<source>Timeout while trying to connect to %1 at %2.</source> <source>Timeout while trying to connect to %1 at %2.</source>
<translation type="unfinished"/> <translation>Λήξη χρονικού ορίου κατά τη σύνδεση σε %1 σε %2.</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="204"/> <location filename="../src/gui/owncloudsetupwizard.cpp" line="204"/>
@@ -1213,7 +1213,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="253"/> <location filename="../src/gui/owncloudsetupwizard.cpp" line="253"/>
<source>Access forbidden by server. To verify that you have proper access, &lt;a href=&quot;%1&quot;&gt;click here&lt;/a&gt; to access the service with your browser.</source> <source>Access forbidden by server. To verify that you have proper access, &lt;a href=&quot;%1&quot;&gt;click here&lt;/a&gt; to access the service with your browser.</source>
<translation type="unfinished"/> <translation>Απαγόρευση πρόσβασης από τον διακομιστή. Για να επιβεβαιώσετε ότι έχετε δικαιώματα πρόσβασης, &lt;a href=&quot;%1&quot;&gt;πατήστε εδώ&lt;/a&gt; για να προσπελάσετε την υπηρεσία με το πρόγραμμα πλοήγησής σας.</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="275"/> <location filename="../src/gui/owncloudsetupwizard.cpp" line="275"/>
@@ -1362,7 +1362,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/libsync/propagateupload.cpp" line="121"/> <location filename="../src/libsync/propagateupload.cpp" line="121"/>
<source>Invalid JSON reply from the poll URL</source> <source>Invalid JSON reply from the poll URL</source>
<translation type="unfinished"/> <translation>Λανθασμένη απάντηση JSON από την ιστοσελίδα poll</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -1421,7 +1421,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/libsync/owncloudpropagator.cpp" line="104"/> <location filename="../src/libsync/owncloudpropagator.cpp" line="104"/>
<source>Continue blacklisting: </source> <source>Continue blacklisting: </source>
<translation type="unfinished"/> <translation>Συνέχεια μαύρη λίστα:</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/owncloudpropagator.cpp" line="200"/> <location filename="../src/libsync/owncloudpropagator.cpp" line="200"/>
@@ -1478,7 +1478,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/libsync/propagateremotedelete.cpp" line="103"/> <location filename="../src/libsync/propagateremotedelete.cpp" line="103"/>
<source>Wrong HTTP code returned by server. Expected 204, but recieved &quot;%1 %2&quot;.</source> <source>Wrong HTTP code returned by server. Expected 204, but recieved &quot;%1 %2&quot;.</source>
<translation type="unfinished"/> <translation>Ο διακομιστής επέστρεψε εσφαλμένο κωδικό HTTP. Αναμενόταν 204, ελήφθη &quot;%1 %2&quot;.</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -1486,7 +1486,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/libsync/propagateremotemkdir.cpp" line="67"/> <location filename="../src/libsync/propagateremotemkdir.cpp" line="67"/>
<source>Wrong HTTP code returned by server. Expected 201, but recieved &quot;%1 %2&quot;.</source> <source>Wrong HTTP code returned by server. Expected 201, but recieved &quot;%1 %2&quot;.</source>
<translation type="unfinished"/> <translation>Ο διακομιστής επέστρεψε εσφαλμένο κωδικό HTTP. Αναμενόταν 201, ελήφθη &quot;%1 %2&quot;.</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -1509,7 +1509,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/libsync/propagateremotemove.cpp" line="127"/> <location filename="../src/libsync/propagateremotemove.cpp" line="127"/>
<source>Wrong HTTP code returned by server. Expected 201, but recieved &quot;%1 %2&quot;.</source> <source>Wrong HTTP code returned by server. Expected 201, but recieved &quot;%1 %2&quot;.</source>
<translation type="unfinished"/> <translation>Ο διακομιστής επέστρεψε εσφαλμένο κωδικό HTTP. Αναμενόταν 201, ελήφθη &quot;%1 %2&quot;.</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -1552,7 +1552,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/libsync/propagateupload.cpp" line="468"/> <location filename="../src/libsync/propagateupload.cpp" line="468"/>
<source>Poll URL missing</source> <source>Poll URL missing</source>
<translation type="unfinished"/> <translation>Η διεύθυνση poll URL λείπει</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/propagateupload.cpp" line="493"/> <location filename="../src/libsync/propagateupload.cpp" line="493"/>
@@ -1646,13 +1646,19 @@ It is not advisable to use it.</source>
<location filename="../src/gui/protocolwidget.cpp" line="265"/> <location filename="../src/gui/protocolwidget.cpp" line="265"/>
<source>%n files are ignored because of previous errors. <source>%n files are ignored because of previous errors.
</source> </source>
<translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation> <translation><numerusform>%n αρχεία αγνοήθηκαν λόγω προηγούμενων σφαλμάτων.
</numerusform><numerusform>%n αρχεία αγνοήθηκαν λόγω προηγούμενων σφαλμάτων.
</numerusform></translation>
</message> </message>
<message numerus="yes"> <message numerus="yes">
<location filename="../src/gui/protocolwidget.cpp" line="266"/> <location filename="../src/gui/protocolwidget.cpp" line="266"/>
<source>%n files are partially downloaded. <source>%n files are partially downloaded.
</source> </source>
<translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation> <translation><numerusform>%n αρχεία λήφθηκαν μερικώς.
</numerusform><numerusform>%n αρχεία λήφθηκαν μερικώς.
</numerusform></translation>
</message> </message>
<message> <message>
<location filename="../src/gui/protocolwidget.cpp" line="267"/> <location filename="../src/gui/protocolwidget.cpp" line="267"/>
@@ -1670,12 +1676,12 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/selectivesyncdialog.cpp" line="318"/> <location filename="../src/gui/selectivesyncdialog.cpp" line="318"/>
<source>Choose What to Sync: Select remote subfolders you wish to synchronize.</source> <source>Choose What to Sync: Select remote subfolders you wish to synchronize.</source>
<translation type="unfinished"/> <translation>Επιλέξτε Τι θα Συγχρονιστεί: Επιλέξτε τους απομακρυσμένους υποφακέλους που επιθυμείτε να συγχρονίσετε.</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/selectivesyncdialog.cpp" line="319"/> <location filename="../src/gui/selectivesyncdialog.cpp" line="319"/>
<source>Choose What to Sync: Deselect remote subfolders you do not wish to synchronize.</source> <source>Choose What to Sync: Deselect remote subfolders you do not wish to synchronize.</source>
<translation type="unfinished"/> <translation>Επιλέξτε Τι θα Συγχρονιστεί: Επιλέξτε τους απομακρυσμένους υποφακέλους που δεν επιθυμείτε να συγχρονίσετε.</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/selectivesyncdialog.cpp" line="325"/> <location filename="../src/gui/selectivesyncdialog.cpp" line="325"/>
@@ -1778,12 +1784,12 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/sharedialog.ui" line="53"/> <location filename="../src/gui/sharedialog.ui" line="53"/>
<source>share label</source> <source>share label</source>
<translation type="unfinished"/> <translation>Διαμοιρασμός ετικέτας</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.ui" line="75"/> <location filename="../src/gui/sharedialog.ui" line="75"/>
<source>OwnCloud Path:</source> <source>OwnCloud Path:</source>
<translation type="unfinished"/> <translation>Διαδρομή ownCloud:</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.ui" line="89"/> <location filename="../src/gui/sharedialog.ui" line="89"/>
@@ -1804,7 +1810,7 @@ It is not advisable to use it.</source>
<location filename="../src/gui/sharedialog.cpp" line="67"/> <location filename="../src/gui/sharedialog.cpp" line="67"/>
<location filename="../src/gui/sharedialog.cpp" line="461"/> <location filename="../src/gui/sharedialog.cpp" line="461"/>
<source>%1 path: %2</source> <source>%1 path: %2</source>
<translation type="unfinished"/> <translation>%1 διαδρομή: %2</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="68"/> <location filename="../src/gui/sharedialog.cpp" line="68"/>
@@ -1824,7 +1830,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="351"/> <location filename="../src/gui/sharedialog.cpp" line="351"/>
<source>OCS API error code: %1</source> <source>OCS API error code: %1</source>
<translation type="unfinished"/> <translation>OCS API κωδικός λάθους: %1</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="374"/> <location filename="../src/gui/sharedialog.cpp" line="374"/>
@@ -1839,12 +1845,12 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="393"/> <location filename="../src/gui/sharedialog.cpp" line="393"/>
<source>Sharing of external directories is not yet working.</source> <source>Sharing of external directories is not yet working.</source>
<translation type="unfinished"/> <translation>Ο διαμοιρασμός εξωτερικών καταλόγων δεν λειτουργεί ακόμα.</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="408"/> <location filename="../src/gui/sharedialog.cpp" line="408"/>
<source>A sync file with the same name exists. The file can not be registered to sync.</source> <source>A sync file with the same name exists. The file can not be registered to sync.</source>
<translation type="unfinished"/> <translation>Ήδη υπάρχει αρχείο συγχρονισμού με το ίδιο όνομα. Το αρχείο δεν μπορεί να καταχωρηθεί προς συγχρονισμό.</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="420"/> <location filename="../src/gui/sharedialog.cpp" line="420"/>
@@ -1854,7 +1860,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="422"/> <location filename="../src/gui/sharedialog.cpp" line="422"/>
<source>Unable to register in sync space.</source> <source>Unable to register in sync space.</source>
<translation type="unfinished"/> <translation>Αδυναμία καταχώρησης στο χώρο συγχρονισμού.</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="453"/> <location filename="../src/gui/sharedialog.cpp" line="453"/>
@@ -1864,7 +1870,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="463"/> <location filename="../src/gui/sharedialog.cpp" line="463"/>
<source>Sync of registered file was not successful yet.</source> <source>Sync of registered file was not successful yet.</source>
<translation type="unfinished"/> <translation>Ο συγχρονισμός του καταχωρημένου αρχείου δεν πέτυχε ακόμη.</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -1909,7 +1915,7 @@ It is not advisable to use it.</source>
<location filename="../src/gui/socketapi.cpp" line="431"/> <location filename="../src/gui/socketapi.cpp" line="431"/>
<source>Share with %1</source> <source>Share with %1</source>
<comment>parameter is ownCloud</comment> <comment>parameter is ownCloud</comment>
<translation type="unfinished"/> <translation>Διαμοιρασμός με %1</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -2123,7 +2129,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/libsync/syncengine.cpp" line="99"/> <location filename="../src/libsync/syncengine.cpp" line="99"/>
<source>CSync failed to load the journal file. The journal file is corrupted.</source> <source>CSync failed to load the journal file. The journal file is corrupted.</source>
<translation type="unfinished"/> <translation>Το CSync απέτυχε να φορτώσει ο αρχείο καταλόγου. Το αρχείο καταλόγου έχει καταστραφεί.</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/syncengine.cpp" line="102"/> <location filename="../src/libsync/syncengine.cpp" line="102"/>
@@ -2218,7 +2224,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/libsync/syncengine.cpp" line="156"/> <location filename="../src/libsync/syncengine.cpp" line="156"/>
<source>The mounted directory is temporarily not available on the server</source> <source>The mounted directory is temporarily not available on the server</source>
<translation type="unfinished"/> <translation>Ο προσαρτημένος κατάλογος δεν είναι προσωρινά διαθέσιμος στον δικομιστή</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/syncengine.cpp" line="159"/> <location filename="../src/libsync/syncengine.cpp" line="159"/>
@@ -2346,7 +2352,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/libsync/theme.cpp" line="237"/> <location filename="../src/libsync/theme.cpp" line="237"/>
<source>&lt;p&gt;Copyright ownCloud, Incorporated&lt;/p&gt;</source> <source>&lt;p&gt;Copyright ownCloud, Incorporated&lt;/p&gt;</source>
<translation type="unfinished"/> <translation>&lt;p&gt;Πνευματικά δικαιώματα ownCloud, Ανώνυμη Εταιρία&lt;/p&gt;</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/theme.cpp" line="238"/> <location filename="../src/libsync/theme.cpp" line="238"/>
@@ -2454,7 +2460,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/owncloudgui.cpp" line="435"/> <location filename="../src/gui/owncloudgui.cpp" line="435"/>
<source>Crash now</source> <source>Crash now</source>
<translation type="unfinished"/> <translation>Κατάρρευση τώρα</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/owncloudgui.cpp" line="446"/> <location filename="../src/gui/owncloudgui.cpp" line="446"/>
@@ -2502,7 +2508,7 @@ It is not advisable to use it.</source>
<message utf8="true"> <message utf8="true">
<location filename="../src/libsync/owncloudtheme.cpp" line="48"/> <location filename="../src/libsync/owncloudtheme.cpp" line="48"/>
<source>&lt;p&gt;Version %2. For more information visit &lt;a href=&quot;%3&quot;&gt;%4&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;small&gt;By Klaas Freitag, Daniel Molkentin, Jan-Christoph Borchardt, Olivier Goffart, Markus Götz and others.&lt;/small&gt;&lt;/p&gt;&lt;p&gt;Copyright ownCloud, Inc.&lt;/p&gt;&lt;p&gt;Licensed under the GNU General Public License (GPL) Version 2.0&lt;br/&gt;ownCloud and the ownCloud Logo are registered trademarks of ownCloud, Inc. in the United States, other countries, or both.&lt;/p&gt;</source> <source>&lt;p&gt;Version %2. For more information visit &lt;a href=&quot;%3&quot;&gt;%4&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;small&gt;By Klaas Freitag, Daniel Molkentin, Jan-Christoph Borchardt, Olivier Goffart, Markus Götz and others.&lt;/small&gt;&lt;/p&gt;&lt;p&gt;Copyright ownCloud, Inc.&lt;/p&gt;&lt;p&gt;Licensed under the GNU General Public License (GPL) Version 2.0&lt;br/&gt;ownCloud and the ownCloud Logo are registered trademarks of ownCloud, Inc. in the United States, other countries, or both.&lt;/p&gt;</source>
<translation type="unfinished"/> <translation>&lt;p&gt;Έκδοση %2. Για περισσότερες πληροφορίες επισκεφθείτε &lt;a href=&quot;%3&quot;&gt;%4&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;small&gt;Των Klaas Freitag, Daniel Molkentin, Jan-Christoph Borchardt, Olivier Goffart, Markus Götz και άλλων.&lt;/small&gt;&lt;/p&gt;&lt;p&gt;Πνευματικά δικαιώματα ownCloud, Inc.&lt;/p&gt;&lt;p&gt;Αδειοδότηση υπό την GNU General Public License (GPL) Έκδοση 2.0&lt;br/&gt;το ownCloud και το λογότυπο ownCloud είναι σήματα κατατεθέντα της ownCloud, Inc. στις Η.Π.Α., σε άλλες χώρες ή και στα δύο&lt;/p&gt;</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -2561,7 +2567,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/wizard/owncloudadvancedsetuppage.ui" line="224"/> <location filename="../src/gui/wizard/owncloudadvancedsetuppage.ui" line="224"/>
<source>S&amp;ync everything from server</source> <source>S&amp;ync everything from server</source>
<translation type="unfinished"/> <translation>Σ&amp;υγχρονισμός όλων από τον διακομιστή</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/wizard/owncloudadvancedsetuppage.ui" line="306"/> <location filename="../src/gui/wizard/owncloudadvancedsetuppage.ui" line="306"/>
@@ -2579,7 +2585,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="43"/> <location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="43"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Failed to connect to the secure server address specified. How do you wish to proceed?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source> <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Failed to connect to the secure server address specified. How do you wish to proceed?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"/> <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Αποτυχία σύνδεσης στην ασφαλή διεύθυνση διακομιστή που ορίστηκε. Πώς θέλετε να συνεχίσετε;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="55"/> <location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="55"/>
@@ -2589,17 +2595,17 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="62"/> <location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="62"/>
<source>Retry unencrypted over HTTP (insecure)</source> <source>Retry unencrypted over HTTP (insecure)</source>
<translation type="unfinished"/> <translation>Επανάληψη χωρίς κρυπτογράφηση μέσω HTTP (ανασφαλής)</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="69"/> <location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="69"/>
<source>Configure client-side TLS certificate</source> <source>Configure client-side TLS certificate</source>
<translation type="unfinished"/> <translation>Διαμόρφωση πιστοποιητικού TLS του δέκτη</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/wizard/owncloudconnectionmethoddialog.cpp" line="18"/> <location filename="../src/gui/wizard/owncloudconnectionmethoddialog.cpp" line="18"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Failed to connect to the secure server address &lt;em&gt;%1&lt;/em&gt;. How do you wish to proceed?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source> <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Failed to connect to the secure server address &lt;em&gt;%1&lt;/em&gt;. How do you wish to proceed?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"/> <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt; Αποτυχία σύνδεσης με ασφαλή διεύθυνση του διακομιστή &lt;em&gt;%1&lt;/em&gt;. Πώς θέλετε να συνεχίσετε;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message> </message>
</context> </context>
<context> <context>

View File

@@ -695,7 +695,7 @@ Voulez-vous réellement effectuer cette opération ?</translation>
<message> <message>
<location filename="../src/libsync/propagatedownload.cpp" line="156"/> <location filename="../src/libsync/propagatedownload.cpp" line="156"/>
<source>Server returned wrong content-range</source> <source>Server returned wrong content-range</source>
<translation>Le serveur a retourné une gamme de contenu erronnée</translation> <translation>Le serveur a retourné une gamme de contenu erronée</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/propagatedownload.cpp" line="257"/> <location filename="../src/libsync/propagatedownload.cpp" line="257"/>
@@ -757,12 +757,12 @@ Voulez-vous réellement effectuer cette opération ?</translation>
<message> <message>
<location filename="../src/libsync/creds/httpcredentials.cpp" line="400"/> <location filename="../src/libsync/creds/httpcredentials.cpp" line="400"/>
<source>Enter Password</source> <source>Enter Password</source>
<translation>Entrez le mot de passe</translation> <translation>Saisissez le mot de passe</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/creds/httpcredentials.cpp" line="401"/> <location filename="../src/libsync/creds/httpcredentials.cpp" line="401"/>
<source>Please enter %1 password for user &apos;%2&apos;:</source> <source>Please enter %1 password for user &apos;%2&apos;:</source>
<translation>Veuillez entrer le mot de passe %1 pour l&apos;utilisateur &apos;%2&apos; :</translation> <translation>Veuillez saisir le mot de passe %1 pour l&apos;utilisateur &apos;%2&apos; :</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -770,7 +770,7 @@ Voulez-vous réellement effectuer cette opération ?</translation>
<message> <message>
<location filename="../src/gui/ignorelisteditor.ui" line="14"/> <location filename="../src/gui/ignorelisteditor.ui" line="14"/>
<source>Ignored Files Editor</source> <source>Ignored Files Editor</source>
<translation>Éditeur de modification des fichiers ignorés</translation> <translation>Éditeur de la liste des fichiers ignorés</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/ignorelisteditor.ui" line="53"/> <location filename="../src/gui/ignorelisteditor.ui" line="53"/>
@@ -789,7 +789,7 @@ Voulez-vous réellement effectuer cette opération ?</translation>
Checked items will also be deleted if they prevent a directory from being removed. This is useful for meta data.</source> Checked items will also be deleted if they prevent a directory from being removed. This is useful for meta data.</source>
<translation>Les fichiers ou dossiers correspondants à un motif ne seront pas synchronisés. <translation>Les fichiers ou dossiers correspondants à un motif ne seront pas synchronisés.
Les items cochés seront également supprimés s&apos;ils empêchent la suppression d&apos;un dossier. Cela est utile pour les meta-données.</translation> Les motifs cochés seront également supprimés s&apos;ils empêchent la suppression d&apos;un dossier. Cela est utile pour les meta-données.</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/ignorelisteditor.cpp" line="97"/> <location filename="../src/gui/ignorelisteditor.cpp" line="97"/>
@@ -809,22 +809,22 @@ Les items cochés seront également supprimés s&apos;ils empêchent la suppress
<message> <message>
<location filename="../src/gui/ignorelisteditor.cpp" line="106"/> <location filename="../src/gui/ignorelisteditor.cpp" line="106"/>
<source>Add a new ignore pattern:</source> <source>Add a new ignore pattern:</source>
<translation>Ajouter un nouveau modèle à ignorer :</translation> <translation>Ajoutez un nouveau motif à ignorer :</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/ignorelisteditor.cpp" line="128"/> <location filename="../src/gui/ignorelisteditor.cpp" line="128"/>
<source>Edit Ignore Pattern</source> <source>Edit Ignore Pattern</source>
<translation>Éditer le modèle</translation> <translation>Modifier le motif</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/ignorelisteditor.cpp" line="129"/> <location filename="../src/gui/ignorelisteditor.cpp" line="129"/>
<source>Edit ignore pattern:</source> <source>Edit ignore pattern:</source>
<translation>Éditer le modèle :</translation> <translation>Éditer le motif :</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/ignorelisteditor.cpp" line="140"/> <location filename="../src/gui/ignorelisteditor.cpp" line="140"/>
<source>This entry is provided by the system at &apos;%1&apos; and cannot be modified in this view.</source> <source>This entry is provided by the system at &apos;%1&apos; and cannot be modified in this view.</source>
<translation>Cette entrée est fournie par le système à &apos;%1&apos; et ne peut être modifiée dans cette vue.</translation> <translation>Cette entrée est fournie par le système dans &apos;%1&apos; et ne peut être modifiée dans cette vue.</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -916,7 +916,7 @@ Les items cochés seront également supprimés s&apos;ils empêchent la suppress
<message> <message>
<location filename="../src/gui/updater/ocupdater.cpp" line="275"/> <location filename="../src/gui/updater/ocupdater.cpp" line="275"/>
<source>Skip this version</source> <source>Skip this version</source>
<translation>Ignorer cette version.</translation> <translation>Ignorer cette version</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/updater/ocupdater.cpp" line="276"/> <location filename="../src/gui/updater/ocupdater.cpp" line="276"/>
@@ -1007,7 +1007,7 @@ Les items cochés seront également supprimés s&apos;ils empêchent la suppress
<message> <message>
<location filename="../src/gui/networksettings.cpp" line="34"/> <location filename="../src/gui/networksettings.cpp" line="34"/>
<source>Hostname of proxy server</source> <source>Hostname of proxy server</source>
<translation>Nom d&apos;hôte ou serveur mandataire</translation> <translation>Nom d&apos;hôte du serveur mandataire</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/networksettings.cpp" line="35"/> <location filename="../src/gui/networksettings.cpp" line="35"/>
@@ -1384,7 +1384,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message> <message>
<location filename="../src/libsync/propagator_legacy.cpp" line="516"/> <location filename="../src/libsync/propagator_legacy.cpp" line="516"/>
<source>Server returned wrong content-range</source> <source>Server returned wrong content-range</source>
<translation>Le serveur a retourné une gamme de contenu erronnée</translation> <translation>Le serveur a retourné une gamme de contenu erronée</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/propagator_legacy.cpp" line="567"/> <location filename="../src/libsync/propagator_legacy.cpp" line="567"/>
@@ -1420,12 +1420,12 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message> <message>
<location filename="../src/libsync/owncloudpropagator.cpp" line="104"/> <location filename="../src/libsync/owncloudpropagator.cpp" line="104"/>
<source>Continue blacklisting: </source> <source>Continue blacklisting: </source>
<translation>Poursuivre la liste noire :</translation> <translation>Poursuivre la mise sur liste noire :</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/owncloudpropagator.cpp" line="200"/> <location filename="../src/libsync/owncloudpropagator.cpp" line="200"/>
<source>A file or directory was removed from a read only share, but restoring failed: %1</source> <source>A file or directory was removed from a read only share, but restoring failed: %1</source>
<translation>Un fichier ou un dossier a é supprimé du partage en lecture seule, mais la restauration à échoué : %1</translation> <translation>Un fichier ou un dossier a é supprimé d&apos;un partage en lecture seule, mais la restauration a échoué : %1</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -1477,7 +1477,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message> <message>
<location filename="../src/libsync/propagateremotedelete.cpp" line="103"/> <location filename="../src/libsync/propagateremotedelete.cpp" line="103"/>
<source>Wrong HTTP code returned by server. Expected 204, but recieved &quot;%1 %2&quot;.</source> <source>Wrong HTTP code returned by server. Expected 204, but recieved &quot;%1 %2&quot;.</source>
<translation>Le code HTTP retourné par le serveur est invalide. La valeur attendue est 204 mais la valeur reçue est &quot;%1 %2&quot;.</translation> <translation>Le code HTTP retourné par le serveur n&apos;est pas valide. La valeur attendue est 204 mais la valeur reçue est &quot;%1 %2&quot;.</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -1485,7 +1485,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message> <message>
<location filename="../src/libsync/propagateremotemkdir.cpp" line="67"/> <location filename="../src/libsync/propagateremotemkdir.cpp" line="67"/>
<source>Wrong HTTP code returned by server. Expected 201, but recieved &quot;%1 %2&quot;.</source> <source>Wrong HTTP code returned by server. Expected 201, but recieved &quot;%1 %2&quot;.</source>
<translation>Le code HTTP retourné par le serveur est invalide. La valeur attendue est 201 mais la valeur reçue est &quot;%1 %2&quot;.</translation> <translation>Le code HTTP retourné par le serveur n&apos;est pas valide. La valeur attendue est 201 mais la valeur reçue est &quot;%1 %2&quot;.</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -1498,7 +1498,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message> <message>
<location filename="../src/libsync/propagateremotemove.cpp" line="75"/> <location filename="../src/libsync/propagateremotemove.cpp" line="75"/>
<source>This folder must not be renamed. Please name it back to Shared.</source> <source>This folder must not be renamed. Please name it back to Shared.</source>
<translation>Ce dossier ne doit pas être renommé. Veuillez le nommer Partagé uniquement.</translation> <translation>Ce dossier ne doit pas être renommé. Veuillez le renommer en Shared.</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/propagateremotemove.cpp" line="111"/> <location filename="../src/libsync/propagateremotemove.cpp" line="111"/>
@@ -1508,7 +1508,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message> <message>
<location filename="../src/libsync/propagateremotemove.cpp" line="127"/> <location filename="../src/libsync/propagateremotemove.cpp" line="127"/>
<source>Wrong HTTP code returned by server. Expected 201, but recieved &quot;%1 %2&quot;.</source> <source>Wrong HTTP code returned by server. Expected 201, but recieved &quot;%1 %2&quot;.</source>
<translation>Le code HTTP retourné par le serveur est invalide. La valeur attendue est 201 mais la valeur reçue est &quot;%1 %2&quot;.</translation> <translation>Le code HTTP retourné par le serveur n&apos;est pas valide. La valeur attendue est 201 mais la valeur reçue est &quot;%1 %2&quot;.</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -2123,7 +2123,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message> <message>
<location filename="../src/libsync/syncengine.cpp" line="95"/> <location filename="../src/libsync/syncengine.cpp" line="95"/>
<source>CSync failed to load or create the journal file. Make sure you have read and write permissions in the local sync directory.</source> <source>CSync failed to load or create the journal file. Make sure you have read and write permissions in the local sync directory.</source>
<translation>CSync na pu charger ou créer le fichier de journalisation. Veuillez vérifier que vous possédez les droits en lecture/écriture dans le répertoire de synchronisation local.</translation> <translation>CSync na pu charger ou créer le fichier de journalisation. Veuillez vérifier que vous possédez les droits en lecture et écriture dans le répertoire de synchronisation local.</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/syncengine.cpp" line="99"/> <location filename="../src/libsync/syncengine.cpp" line="99"/>
@@ -2158,17 +2158,17 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message> <message>
<location filename="../src/libsync/syncengine.cpp" line="117"/> <location filename="../src/libsync/syncengine.cpp" line="117"/>
<source>CSync processing step reconcile failed.</source> <source>CSync processing step reconcile failed.</source>
<translation>Erreur CSync lors de l&apos;opération d&apos;harmonisation</translation> <translation>Erreur CSync lors de l&apos;opération de réconciliation</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/syncengine.cpp" line="120"/> <location filename="../src/libsync/syncengine.cpp" line="120"/>
<source>CSync could not authenticate at the proxy.</source> <source>CSync could not authenticate at the proxy.</source>
<translation>CSync ne peut s&apos;authentifier auprès du proxy.</translation> <translation>CSync n&apos;a pu s&apos;authentifier auprès du proxy.</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/syncengine.cpp" line="123"/> <location filename="../src/libsync/syncengine.cpp" line="123"/>
<source>CSync failed to lookup proxy or server.</source> <source>CSync failed to lookup proxy or server.</source>
<translation>CSync n&apos;a pu trouver un proxy ou serveur auquel se connecter.</translation> <translation>CSync n&apos;a pu trouver le proxy ou serveur auquel se connecter.</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/syncengine.cpp" line="126"/> <location filename="../src/libsync/syncengine.cpp" line="126"/>
@@ -2183,7 +2183,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message> <message>
<location filename="../src/libsync/syncengine.cpp" line="132"/> <location filename="../src/libsync/syncengine.cpp" line="132"/>
<source>A network connection timeout happened.</source> <source>A network connection timeout happened.</source>
<translation>Le délai d&apos;attente pour la connexion réseau a é dépassé.</translation> <translation>Le délai d&apos;attente de la connexion réseau a é dépassé.</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/syncengine.cpp" line="135"/> <location filename="../src/libsync/syncengine.cpp" line="135"/>
@@ -2198,7 +2198,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message> <message>
<location filename="../src/libsync/syncengine.cpp" line="141"/> <location filename="../src/libsync/syncengine.cpp" line="141"/>
<source>CSync failed to access </source> <source>CSync failed to access </source>
<translation>Echec de CSync pour accéder</translation> <translation>CSync n&apos;a pu accéder à</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/syncengine.cpp" line="144"/> <location filename="../src/libsync/syncengine.cpp" line="144"/>
@@ -2279,7 +2279,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<location filename="../src/libsync/syncengine.cpp" line="895"/> <location filename="../src/libsync/syncengine.cpp" line="895"/>
<location filename="../src/libsync/syncengine.cpp" line="902"/> <location filename="../src/libsync/syncengine.cpp" line="902"/>
<source>Ignored because of the &quot;choose what to sync&quot; blacklist</source> <source>Ignored because of the &quot;choose what to sync&quot; blacklist</source>
<translation>Ignoré à cause de la liste noire du contenu à synchroniser.</translation> <translation>Ignoré à cause de la liste noire &quot;Choisir le contenu à synchroniser&quot;.</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/syncengine.cpp" line="920"/> <location filename="../src/libsync/syncengine.cpp" line="920"/>
@@ -2389,7 +2389,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message> <message>
<location filename="../src/gui/owncloudgui.cpp" line="295"/> <location filename="../src/gui/owncloudgui.cpp" line="295"/>
<source>None.</source> <source>None.</source>
<translation>Aucun.</translation> <translation>Aucune</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/owncloudgui.cpp" line="299"/> <location filename="../src/gui/owncloudgui.cpp" line="299"/>
@@ -2404,7 +2404,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message> <message>
<location filename="../src/gui/owncloudgui.cpp" line="326"/> <location filename="../src/gui/owncloudgui.cpp" line="326"/>
<source>Managed Folders:</source> <source>Managed Folders:</source>
<translation>Répertoires suivis :</translation> <translation>Répertoires configurés :</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/owncloudgui.cpp" line="335"/> <location filename="../src/gui/owncloudgui.cpp" line="335"/>
@@ -2464,7 +2464,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message> <message>
<location filename="../src/gui/owncloudgui.cpp" line="446"/> <location filename="../src/gui/owncloudgui.cpp" line="446"/>
<source>Quota n/a</source> <source>Quota n/a</source>
<translation>Quota n/a</translation> <translation>Quota non disponible ou non applicable</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/owncloudgui.cpp" line="453"/> <location filename="../src/gui/owncloudgui.cpp" line="453"/>
@@ -2474,7 +2474,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message> <message>
<location filename="../src/gui/owncloudgui.cpp" line="465"/> <location filename="../src/gui/owncloudgui.cpp" line="465"/>
<source>No items synced recently</source> <source>No items synced recently</source>
<translation>Aucun item synchronisé récemment</translation> <translation>Aucun élément synchronisé récemment</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/owncloudgui.cpp" line="477"/> <location filename="../src/gui/owncloudgui.cpp" line="477"/>
@@ -2484,12 +2484,12 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message> <message>
<location filename="../src/gui/owncloudgui.cpp" line="482"/> <location filename="../src/gui/owncloudgui.cpp" line="482"/>
<source>Syncing %1 of %2 (%3 left)</source> <source>Syncing %1 of %2 (%3 left)</source>
<translation>Synchronisation %1 de %2 (%3 restant)</translation> <translation>Synchronisation de %1 sur %2 (%3 restant)</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/owncloudgui.cpp" line="487"/> <location filename="../src/gui/owncloudgui.cpp" line="487"/>
<source>Syncing %1 (%2 left)</source> <source>Syncing %1 (%2 left)</source>
<translation>Synchronisation %1 (%2 restant)</translation> <translation>Synchronisation de %1 (%2 restant)</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/owncloudgui.cpp" line="507"/> <location filename="../src/gui/owncloudgui.cpp" line="507"/>
@@ -2566,7 +2566,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message> <message>
<location filename="../src/gui/wizard/owncloudadvancedsetuppage.ui" line="224"/> <location filename="../src/gui/wizard/owncloudadvancedsetuppage.ui" line="224"/>
<source>S&amp;ync everything from server</source> <source>S&amp;ync everything from server</source>
<translation>Synchroniser tout le contenu depuis le serveur</translation> <translation>S&amp;ynchroniser tout le contenu depuis le serveur</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/wizard/owncloudadvancedsetuppage.ui" line="306"/> <location filename="../src/gui/wizard/owncloudadvancedsetuppage.ui" line="306"/>
@@ -2584,17 +2584,17 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message> <message>
<location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="43"/> <location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="43"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Failed to connect to the secure server address specified. How do you wish to proceed?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source> <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Failed to connect to the secure server address specified. How do you wish to proceed?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Impossible de se connecter au serveur via l&apos;adresse sécurisée indiquée. Comment voulez-vous procéder ?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation> <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Impossible de se connecter au serveur via l&apos;adresse sécurisée indiquée. Que souhaitez-vous faire ?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="55"/> <location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="55"/>
<source>Select a different URL</source> <source>Select a different URL</source>
<translation>Sélectionner un URL différent</translation> <translation>Sélectionner une URL différente</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="62"/> <location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="62"/>
<source>Retry unencrypted over HTTP (insecure)</source> <source>Retry unencrypted over HTTP (insecure)</source>
<translation>Réessayer en clair sur HTTP (non sécurisé)</translation> <translation>Essayer en clair sur HTTP (non sécurisé)</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="69"/> <location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="69"/>
@@ -2604,7 +2604,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message> <message>
<location filename="../src/gui/wizard/owncloudconnectionmethoddialog.cpp" line="18"/> <location filename="../src/gui/wizard/owncloudconnectionmethoddialog.cpp" line="18"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Failed to connect to the secure server address &lt;em&gt;%1&lt;/em&gt;. How do you wish to proceed?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source> <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Failed to connect to the secure server address &lt;em&gt;%1&lt;/em&gt;. How do you wish to proceed?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Impossible de se connecter à l&apos;adresse sécurisée du serveur &lt;em&gt;%1&lt;/em&gt;. Comment voulez-vous procéder ?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation> <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Impossible de se connecter à l&apos;adresse sécurisée &lt;em&gt;%1&lt;/em&gt;. Que souhaitez-vous faire ?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -2696,7 +2696,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message> <message>
<location filename="../src/gui/owncloudsetuppage.ui" line="120"/> <location filename="../src/gui/owncloudsetuppage.ui" line="120"/>
<source>&amp;Do not store password on local machine</source> <source>&amp;Do not store password on local machine</source>
<translation>&amp;Ne pas mémoriser le mot de passe sur la machine locale</translation> <translation>Ne &amp;pas mémoriser le mot de passe sur la machine locale</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/owncloudsetuppage.ui" line="140"/> <location filename="../src/gui/owncloudsetuppage.ui" line="140"/>
@@ -2786,7 +2786,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message> <message>
<location filename="../src/gui/main.cpp" line="46"/> <location filename="../src/gui/main.cpp" line="46"/>
<source>%1 requires on a working system tray. If you are running XFCE, please follow &lt;a href=&quot;http://docs.xfce.org/xfce/xfce4-panel/systray&quot;&gt;these instructions&lt;/a&gt;. Otherwise, please install a system tray application such as &apos;trayer&apos; and try again.</source> <source>%1 requires on a working system tray. If you are running XFCE, please follow &lt;a href=&quot;http://docs.xfce.org/xfce/xfce4-panel/systray&quot;&gt;these instructions&lt;/a&gt;. Otherwise, please install a system tray application such as &apos;trayer&apos; and try again.</source>
<translation>%1 nécessite la présence d&apos;une zone de notification système (system tray). Si vous utilisez XFCE, veuillez suivre &lt;a href=&quot;http://docs.xfce.org/xfce/xfce4-panel/systray&quot;&gt;ces instructions&lt;/a&gt;. Sinon, installez une application mettant en place une zone de notification, telle que &apos;trayer&apos;, et essayez à nouveau.</translation> <translation>%1 nécessite la présence d&apos;une zone de notification système. Si vous utilisez XFCE, veuillez suivre &lt;a href=&quot;http://docs.xfce.org/xfce/xfce4-panel/systray&quot;&gt;ces instructions&lt;/a&gt;. Sinon, installez une application mettant en place une zone de notification, telle que &apos;trayer&apos;, et essayez à nouveau.</translation>
</message> </message>
</context> </context>
<context> <context>

View File

@@ -2265,7 +2265,7 @@ Recomendámoslle que non o use.</translation>
<message> <message>
<location filename="../src/libsync/syncengine.cpp" line="567"/> <location filename="../src/libsync/syncengine.cpp" line="567"/>
<source>Unable to initialize a sync journal.</source> <source>Unable to initialize a sync journal.</source>
<translation>Non é posíbel iniciar un rexistro de sincronización.</translation> <translation>Non é posíbel preparar un rexistro de sincronización.</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/syncengine.cpp" line="648"/> <location filename="../src/libsync/syncengine.cpp" line="648"/>

View File

@@ -1210,7 +1210,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="253"/> <location filename="../src/gui/owncloudsetupwizard.cpp" line="253"/>
<source>Access forbidden by server. To verify that you have proper access, &lt;a href=&quot;%1&quot;&gt;click here&lt;/a&gt; to access the service with your browser.</source> <source>Access forbidden by server. To verify that you have proper access, &lt;a href=&quot;%1&quot;&gt;click here&lt;/a&gt; to access the service with your browser.</source>
<translation>&lt;a href=&quot;%1&quot;&gt;&lt;/a&gt;</translation> <translation>&lt;a href=&quot;%1&quot;&gt;&lt;/a&gt;</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="275"/> <location filename="../src/gui/owncloudsetupwizard.cpp" line="275"/>
@@ -1828,12 +1828,12 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="374"/> <location filename="../src/gui/sharedialog.cpp" line="374"/>
<source>There is no sync folder configured.</source> <source>There is no sync folder configured.</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="386"/> <location filename="../src/gui/sharedialog.cpp" line="386"/>
<source>Can not find an folder to upload to.</source> <source>Can not find an folder to upload to.</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="393"/> <location filename="../src/gui/sharedialog.cpp" line="393"/>
@@ -1926,7 +1926,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/sslbutton.cpp" line="101"/> <location filename="../src/gui/sslbutton.cpp" line="101"/>
<source>Subject Alternative Names:</source> <source>Subject Alternative Names:</source>
<translation>Subject Alternative Names():</translation> <translation>:</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sslbutton.cpp" line="103"/> <location filename="../src/gui/sslbutton.cpp" line="103"/>
@@ -1971,7 +1971,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/sslbutton.cpp" line="115"/> <location filename="../src/gui/sslbutton.cpp" line="115"/>
<source>Expires on:</source> <source>Expires on:</source>
<translation>:</translation> <translation>:</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sslbutton.cpp" line="118"/> <location filename="../src/gui/sslbutton.cpp" line="118"/>
@@ -2237,7 +2237,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/libsync/syncengine.cpp" line="340"/> <location filename="../src/libsync/syncengine.cpp" line="340"/>
<source>Symbolic links are not supported in syncing.</source> <source>Symbolic links are not supported in syncing.</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/syncengine.cpp" line="343"/> <location filename="../src/libsync/syncengine.cpp" line="343"/>

View File

@@ -226,7 +226,7 @@ Skupaj še %5</translation>
<message> <message>
<location filename="../src/gui/accountsettings.cpp" line="820"/> <location filename="../src/gui/accountsettings.cpp" line="820"/>
<source>No %1 connection configured.</source> <source>No %1 connection configured.</source>
<translation>Ni nastavljenih %1 povezav.</translation> <translation>Ni nastavljene povezave %1.</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -234,7 +234,7 @@ Skupaj še %5</translation>
<message> <message>
<location filename="../src/gui/addcertificatedialog.ui" line="17"/> <location filename="../src/gui/addcertificatedialog.ui" line="17"/>
<source>SSL client certificate authentication</source> <source>SSL client certificate authentication</source>
<translation>SSL overjanje potrdila odjemalca</translation> <translation>Overitev odjemalca s potrdilom SSL</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/addcertificatedialog.ui" line="23"/> <location filename="../src/gui/addcertificatedialog.ui" line="23"/>
@@ -329,7 +329,7 @@ Skupaj še %5</translation>
<message> <message>
<location filename="../src/libsync/propagateremotedelete.cpp" line="41"/> <location filename="../src/libsync/propagateremotedelete.cpp" line="41"/>
<source>Connection timed out</source> <source>Connection timed out</source>
<translation>Povezava je potekla</translation> <translation>Povezava je časovno potekla</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -2473,7 +2473,7 @@ Uporaba ni priporočljiva.</translation>
<message> <message>
<location filename="../src/gui/owncloudgui.cpp" line="477"/> <location filename="../src/gui/owncloudgui.cpp" line="477"/>
<source>Discovering &apos;%1&apos;</source> <source>Discovering &apos;%1&apos;</source>
<translation>Poteka preučevanje %1</translation> <translation>Poteka preučevanje &apos;%1&apos;</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/owncloudgui.cpp" line="482"/> <location filename="../src/gui/owncloudgui.cpp" line="482"/>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.0" language="en_US">
</TS>

View File

@@ -244,27 +244,27 @@ Total tid kvar %5</translation>
<message> <message>
<location filename="../src/gui/addcertificatedialog.ui" line="35"/> <location filename="../src/gui/addcertificatedialog.ui" line="35"/>
<source>Certificate :</source> <source>Certificate :</source>
<translation type="unfinished"/> <translation>Certifikat :</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/addcertificatedialog.ui" line="51"/> <location filename="../src/gui/addcertificatedialog.ui" line="51"/>
<source>Browse...</source> <source>Browse...</source>
<translation type="unfinished"/> <translation>Bläddra...</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/addcertificatedialog.ui" line="60"/> <location filename="../src/gui/addcertificatedialog.ui" line="60"/>
<source>Certificate password :</source> <source>Certificate password :</source>
<translation type="unfinished"/> <translation>Certifikatlösenord :</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/addcertificatedialog.cpp" line="23"/> <location filename="../src/gui/addcertificatedialog.cpp" line="23"/>
<source>Select a certificate</source> <source>Select a certificate</source>
<translation type="unfinished"/> <translation>Välj ett certifikat</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/addcertificatedialog.cpp" line="23"/> <location filename="../src/gui/addcertificatedialog.cpp" line="23"/>
<source>Certificate files (*.p12 *.pfx)</source> <source>Certificate files (*.p12 *.pfx)</source>
<translation type="unfinished"/> <translation>Certifikatfiler (*.p12 *.pfx)</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -329,7 +329,7 @@ Total tid kvar %5</translation>
<message> <message>
<location filename="../src/libsync/propagateremotedelete.cpp" line="41"/> <location filename="../src/libsync/propagateremotedelete.cpp" line="41"/>
<source>Connection timed out</source> <source>Connection timed out</source>
<translation type="unfinished"/> <translation>Tidsgräns för anslutningen överskreds</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -668,7 +668,7 @@ Detta kan bero på att konfigurationen för mappen ändrats, eller att alla file
<message> <message>
<location filename="../src/gui/folderwizard.cpp" line="444"/> <location filename="../src/gui/folderwizard.cpp" line="444"/>
<source>Choose What to Sync: You can optionally deselect remote subfolders you do not wish to synchronize.</source> <source>Choose What to Sync: You can optionally deselect remote subfolders you do not wish to synchronize.</source>
<translation type="unfinished"/> <translation>Välj Vad du vill Synka: Du har även möjlighet att avmarkera mappar servern som du ej vill synkronisera.</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -733,7 +733,7 @@ Detta kan bero på att konfigurationen för mappen ändrats, eller att alla file
<message> <message>
<location filename="../src/gui/generalsettings.ui" line="47"/> <location filename="../src/gui/generalsettings.ui" line="47"/>
<source>Show crash reporter</source> <source>Show crash reporter</source>
<translation type="unfinished"/> <translation>Visa kraschrapporteringsverktyg</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/generalsettings.ui" line="57"/> <location filename="../src/gui/generalsettings.ui" line="57"/>
@@ -898,7 +898,7 @@ Valda objekt kommer också att raderas om dom hindrar en mapp från att tas bort
<message> <message>
<location filename="../src/libsync/propagateremotemove.cpp" line="45"/> <location filename="../src/libsync/propagateremotemove.cpp" line="45"/>
<source>Connection timed out</source> <source>Connection timed out</source>
<translation type="unfinished"/> <translation>Tidsgräns för anslutningen överskreds</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -1131,7 +1131,7 @@ efter ytterligare privilegier under processen.</translation>
<location filename="../src/gui/wizard/owncloudadvancedsetuppage.cpp" line="297"/> <location filename="../src/gui/wizard/owncloudadvancedsetuppage.cpp" line="297"/>
<location filename="../src/gui/wizard/owncloudadvancedsetuppage.cpp" line="318"/> <location filename="../src/gui/wizard/owncloudadvancedsetuppage.cpp" line="318"/>
<source>(%1)</source> <source>(%1)</source>
<translation type="unfinished"/> <translation>(%1)</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -1420,7 +1420,7 @@ Det är inte lämpligt använda den.</translation>
<message> <message>
<location filename="../src/libsync/owncloudpropagator.cpp" line="104"/> <location filename="../src/libsync/owncloudpropagator.cpp" line="104"/>
<source>Continue blacklisting: </source> <source>Continue blacklisting: </source>
<translation type="unfinished"/> <translation>Fortsätt svartlista:</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/owncloudpropagator.cpp" line="200"/> <location filename="../src/libsync/owncloudpropagator.cpp" line="200"/>
@@ -1477,7 +1477,7 @@ Det är inte lämpligt använda den.</translation>
<message> <message>
<location filename="../src/libsync/propagateremotedelete.cpp" line="103"/> <location filename="../src/libsync/propagateremotedelete.cpp" line="103"/>
<source>Wrong HTTP code returned by server. Expected 204, but recieved &quot;%1 %2&quot;.</source> <source>Wrong HTTP code returned by server. Expected 204, but recieved &quot;%1 %2&quot;.</source>
<translation type="unfinished"/> <translation>Fel HTTP-kod returnerades av servern. Förväntade 204, men tog emot &quot;%1 %2&quot;.</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -1535,7 +1535,7 @@ Det är inte lämpligt använda den.</translation>
<message> <message>
<location filename="../src/libsync/propagateupload.cpp" line="156"/> <location filename="../src/libsync/propagateupload.cpp" line="156"/>
<source>File Removed</source> <source>File Removed</source>
<translation type="unfinished"/> <translation>Filen Raderad</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/propagateupload.cpp" line="171"/> <location filename="../src/libsync/propagateupload.cpp" line="171"/>
@@ -1792,12 +1792,12 @@ Det är inte lämpligt använda den.</translation>
<message> <message>
<location filename="../src/gui/sharedialog.ui" line="127"/> <location filename="../src/gui/sharedialog.ui" line="127"/>
<source>Set password</source> <source>Set password</source>
<translation type="unfinished"/> <translation>Ange lösenord</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.ui" line="149"/> <location filename="../src/gui/sharedialog.ui" line="149"/>
<source>Set expiry date</source> <source>Set expiry date</source>
<translation type="unfinished"/> <translation>Sätt utgångsdatum</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="67"/> <location filename="../src/gui/sharedialog.cpp" line="67"/>
@@ -1813,7 +1813,7 @@ Det är inte lämpligt använda den.</translation>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="141"/> <location filename="../src/gui/sharedialog.cpp" line="141"/>
<source>Password Protected</source> <source>Password Protected</source>
<translation type="unfinished"/> <translation>Lösenordsskyddad</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="299"/> <location filename="../src/gui/sharedialog.cpp" line="299"/>
@@ -1858,7 +1858,7 @@ Det är inte lämpligt använda den.</translation>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="453"/> <location filename="../src/gui/sharedialog.cpp" line="453"/>
<source>The file can not be synced.</source> <source>The file can not be synced.</source>
<translation type="unfinished"/> <translation>Filen kan inte synkas.</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="463"/> <location filename="../src/gui/sharedialog.cpp" line="463"/>
@@ -1908,7 +1908,7 @@ Det är inte lämpligt använda den.</translation>
<location filename="../src/gui/socketapi.cpp" line="431"/> <location filename="../src/gui/socketapi.cpp" line="431"/>
<source>Share with %1</source> <source>Share with %1</source>
<comment>parameter is ownCloud</comment> <comment>parameter is ownCloud</comment>
<translation type="unfinished"/> <translation>Dela med %1</translation>
</message> </message>
</context> </context>
<context> <context>

View File

@@ -733,7 +733,7 @@ Are you sure you want to perform this operation?</source>
<message> <message>
<location filename="../src/gui/generalsettings.ui" line="47"/> <location filename="../src/gui/generalsettings.ui" line="47"/>
<source>Show crash reporter</source> <source>Show crash reporter</source>
<translation type="unfinished"/> <translation>Показати звіти про помилки</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/generalsettings.ui" line="57"/> <location filename="../src/gui/generalsettings.ui" line="57"/>
@@ -1202,7 +1202,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="193"/> <location filename="../src/gui/owncloudsetupwizard.cpp" line="193"/>
<source>Timeout while trying to connect to %1 at %2.</source> <source>Timeout while trying to connect to %1 at %2.</source>
<translation type="unfinished"/> <translation>Перевищено час очікування з&apos;єднання до %1 на %2.</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="204"/> <location filename="../src/gui/owncloudsetupwizard.cpp" line="204"/>
@@ -1212,7 +1212,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="253"/> <location filename="../src/gui/owncloudsetupwizard.cpp" line="253"/>
<source>Access forbidden by server. To verify that you have proper access, &lt;a href=&quot;%1&quot;&gt;click here&lt;/a&gt; to access the service with your browser.</source> <source>Access forbidden by server. To verify that you have proper access, &lt;a href=&quot;%1&quot;&gt;click here&lt;/a&gt; to access the service with your browser.</source>
<translation type="unfinished"/> <translation>Доступ заборонений сервером. Щоб довести, що у Вас є права доступу, &lt;a href=&quot;%1&quot;&gt;клікніть тут&lt;/a&gt; для входу через Ваш браузер.</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="275"/> <location filename="../src/gui/owncloudsetupwizard.cpp" line="275"/>
@@ -1361,7 +1361,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/libsync/propagateupload.cpp" line="121"/> <location filename="../src/libsync/propagateupload.cpp" line="121"/>
<source>Invalid JSON reply from the poll URL</source> <source>Invalid JSON reply from the poll URL</source>
<translation type="unfinished"/> <translation>Неправильна JSON відповідь на сформований URL</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -1420,7 +1420,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/libsync/owncloudpropagator.cpp" line="104"/> <location filename="../src/libsync/owncloudpropagator.cpp" line="104"/>
<source>Continue blacklisting: </source> <source>Continue blacklisting: </source>
<translation type="unfinished"/> <translation>Продовжити занесення до чорного списку:</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/owncloudpropagator.cpp" line="200"/> <location filename="../src/libsync/owncloudpropagator.cpp" line="200"/>
@@ -1477,7 +1477,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/libsync/propagateremotedelete.cpp" line="103"/> <location filename="../src/libsync/propagateremotedelete.cpp" line="103"/>
<source>Wrong HTTP code returned by server. Expected 204, but recieved &quot;%1 %2&quot;.</source> <source>Wrong HTTP code returned by server. Expected 204, but recieved &quot;%1 %2&quot;.</source>
<translation type="unfinished"/> <translation>Сервер відповів неправильним HTTP кодом. Очікувався 204, але отриманий &quot;%1 %2&quot;.</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -1485,7 +1485,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/libsync/propagateremotemkdir.cpp" line="67"/> <location filename="../src/libsync/propagateremotemkdir.cpp" line="67"/>
<source>Wrong HTTP code returned by server. Expected 201, but recieved &quot;%1 %2&quot;.</source> <source>Wrong HTTP code returned by server. Expected 201, but recieved &quot;%1 %2&quot;.</source>
<translation type="unfinished"/> <translation>Сервер відповів неправильним HTTP кодом. Очікувався 201, але отриманий &quot;%1 %2&quot;.</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -1508,7 +1508,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/libsync/propagateremotemove.cpp" line="127"/> <location filename="../src/libsync/propagateremotemove.cpp" line="127"/>
<source>Wrong HTTP code returned by server. Expected 201, but recieved &quot;%1 %2&quot;.</source> <source>Wrong HTTP code returned by server. Expected 201, but recieved &quot;%1 %2&quot;.</source>
<translation type="unfinished"/> <translation>Сервер відповів неправильним HTTP кодом. Очікувався 201, але отриманий &quot;%1 %2&quot;.</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -1551,7 +1551,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/libsync/propagateupload.cpp" line="468"/> <location filename="../src/libsync/propagateupload.cpp" line="468"/>
<source>Poll URL missing</source> <source>Poll URL missing</source>
<translation type="unfinished"/> <translation>Не вистачає сформованого URL</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/propagateupload.cpp" line="493"/> <location filename="../src/libsync/propagateupload.cpp" line="493"/>
@@ -1645,13 +1645,19 @@ It is not advisable to use it.</source>
<location filename="../src/gui/protocolwidget.cpp" line="265"/> <location filename="../src/gui/protocolwidget.cpp" line="265"/>
<source>%n files are ignored because of previous errors. <source>%n files are ignored because of previous errors.
</source> </source>
<translation type="unfinished"><numerusform></numerusform><numerusform></numerusform><numerusform></numerusform></translation> <translation><numerusform>%n файл пропущено через попередні помилки.
</numerusform><numerusform>%n файлів пропущено через попередні помилки.
</numerusform><numerusform>%n файлів пропущено через попередні помилки.
</numerusform></translation>
</message> </message>
<message numerus="yes"> <message numerus="yes">
<location filename="../src/gui/protocolwidget.cpp" line="266"/> <location filename="../src/gui/protocolwidget.cpp" line="266"/>
<source>%n files are partially downloaded. <source>%n files are partially downloaded.
</source> </source>
<translation type="unfinished"><numerusform></numerusform><numerusform></numerusform><numerusform></numerusform></translation> <translation><numerusform>%n файлів частково завантажений.
</numerusform><numerusform>%n файлів частково завантажені.
</numerusform><numerusform>%n файлів частково завантажено.
</numerusform></translation>
</message> </message>
<message> <message>
<location filename="../src/gui/protocolwidget.cpp" line="267"/> <location filename="../src/gui/protocolwidget.cpp" line="267"/>
@@ -1669,12 +1675,12 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/selectivesyncdialog.cpp" line="318"/> <location filename="../src/gui/selectivesyncdialog.cpp" line="318"/>
<source>Choose What to Sync: Select remote subfolders you wish to synchronize.</source> <source>Choose What to Sync: Select remote subfolders you wish to synchronize.</source>
<translation type="unfinished"/> <translation>Виберіть Що Синхронізувати: Виберіть папки на віддаленому сервері, які Ви хотіли б синхронізувати.</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/selectivesyncdialog.cpp" line="319"/> <location filename="../src/gui/selectivesyncdialog.cpp" line="319"/>
<source>Choose What to Sync: Deselect remote subfolders you do not wish to synchronize.</source> <source>Choose What to Sync: Deselect remote subfolders you do not wish to synchronize.</source>
<translation type="unfinished"/> <translation>Виберіть Що Синхронізувати: Зніміть вибір папок на віддаленому сервері, які Ви не хочете синхронізувати.</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/selectivesyncdialog.cpp" line="325"/> <location filename="../src/gui/selectivesyncdialog.cpp" line="325"/>
@@ -1761,12 +1767,12 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/sharedialog.ui" line="14"/> <location filename="../src/gui/sharedialog.ui" line="14"/>
<source>Share NewDocument.odt</source> <source>Share NewDocument.odt</source>
<translation type="unfinished"/> <translation>Поділитися NewDocument.odt</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.ui" line="26"/> <location filename="../src/gui/sharedialog.ui" line="26"/>
<source>Share Info</source> <source>Share Info</source>
<translation type="unfinished"/> <translation>Поділитися Інформацією</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.ui" line="34"/> <location filename="../src/gui/sharedialog.ui" line="34"/>
@@ -1777,12 +1783,12 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/sharedialog.ui" line="53"/> <location filename="../src/gui/sharedialog.ui" line="53"/>
<source>share label</source> <source>share label</source>
<translation type="unfinished"/> <translation>поділитися міткою</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.ui" line="75"/> <location filename="../src/gui/sharedialog.ui" line="75"/>
<source>OwnCloud Path:</source> <source>OwnCloud Path:</source>
<translation type="unfinished"/> <translation>Шлях до OwnCloud:</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.ui" line="89"/> <location filename="../src/gui/sharedialog.ui" line="89"/>
@@ -1803,12 +1809,12 @@ It is not advisable to use it.</source>
<location filename="../src/gui/sharedialog.cpp" line="67"/> <location filename="../src/gui/sharedialog.cpp" line="67"/>
<location filename="../src/gui/sharedialog.cpp" line="461"/> <location filename="../src/gui/sharedialog.cpp" line="461"/>
<source>%1 path: %2</source> <source>%1 path: %2</source>
<translation type="unfinished"/> <translation>%1 шлях: %2</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="68"/> <location filename="../src/gui/sharedialog.cpp" line="68"/>
<source>%1 Sharing</source> <source>%1 Sharing</source>
<translation type="unfinished"/> <translation>Ви поділилися %1</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="141"/> <location filename="../src/gui/sharedialog.cpp" line="141"/>
@@ -1823,27 +1829,27 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="351"/> <location filename="../src/gui/sharedialog.cpp" line="351"/>
<source>OCS API error code: %1</source> <source>OCS API error code: %1</source>
<translation type="unfinished"/> <translation>OCS API код помилки: %1</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="374"/> <location filename="../src/gui/sharedialog.cpp" line="374"/>
<source>There is no sync folder configured.</source> <source>There is no sync folder configured.</source>
<translation type="unfinished"/> <translation>Немає папок налаштованих для синхронізації.</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="386"/> <location filename="../src/gui/sharedialog.cpp" line="386"/>
<source>Can not find an folder to upload to.</source> <source>Can not find an folder to upload to.</source>
<translation type="unfinished"/> <translation>Неможливо знайти папку для завантаження в неї.</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="393"/> <location filename="../src/gui/sharedialog.cpp" line="393"/>
<source>Sharing of external directories is not yet working.</source> <source>Sharing of external directories is not yet working.</source>
<translation type="unfinished"/> <translation>Функція відкриття доступу до зовнішніх папок поки не працює.</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="408"/> <location filename="../src/gui/sharedialog.cpp" line="408"/>
<source>A sync file with the same name exists. The file can not be registered to sync.</source> <source>A sync file with the same name exists. The file can not be registered to sync.</source>
<translation type="unfinished"/> <translation>Існує файл з ім&apos;ям як у синхронізованого. Файл не може бути прийнятий до синхронізації.</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="420"/> <location filename="../src/gui/sharedialog.cpp" line="420"/>
@@ -1853,17 +1859,17 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="422"/> <location filename="../src/gui/sharedialog.cpp" line="422"/>
<source>Unable to register in sync space.</source> <source>Unable to register in sync space.</source>
<translation type="unfinished"/> <translation>Неможливо зареєструватися в синхронізованому просторі.</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="453"/> <location filename="../src/gui/sharedialog.cpp" line="453"/>
<source>The file can not be synced.</source> <source>The file can not be synced.</source>
<translation type="unfinished"/> <translation>Файл не може бути синхронізований.</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/sharedialog.cpp" line="463"/> <location filename="../src/gui/sharedialog.cpp" line="463"/>
<source>Sync of registered file was not successful yet.</source> <source>Sync of registered file was not successful yet.</source>
<translation type="unfinished"/> <translation>Синхронізація зареєстрованого файлу поки не була успішною.</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -1908,7 +1914,7 @@ It is not advisable to use it.</source>
<location filename="../src/gui/socketapi.cpp" line="431"/> <location filename="../src/gui/socketapi.cpp" line="431"/>
<source>Share with %1</source> <source>Share with %1</source>
<comment>parameter is ownCloud</comment> <comment>parameter is ownCloud</comment>
<translation type="unfinished"/> <translation>Поділитися з %1</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -2122,7 +2128,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/libsync/syncengine.cpp" line="99"/> <location filename="../src/libsync/syncengine.cpp" line="99"/>
<source>CSync failed to load the journal file. The journal file is corrupted.</source> <source>CSync failed to load the journal file. The journal file is corrupted.</source>
<translation type="unfinished"/> <translation>CSync не вдалося завантажити файл журналу. Файл журналу пошкоджений.</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/syncengine.cpp" line="102"/> <location filename="../src/libsync/syncengine.cpp" line="102"/>
@@ -2217,12 +2223,12 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/libsync/syncengine.cpp" line="156"/> <location filename="../src/libsync/syncengine.cpp" line="156"/>
<source>The mounted directory is temporarily not available on the server</source> <source>The mounted directory is temporarily not available on the server</source>
<translation type="unfinished"/> <translation>Приєднана тека тимчасово недоступна на сервері</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/syncengine.cpp" line="159"/> <location filename="../src/libsync/syncengine.cpp" line="159"/>
<source>An error opening a directory happened</source> <source>An error opening a directory happened</source>
<translation type="unfinished"/> <translation>Сталася помилка при відкритті теки</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/syncengine.cpp" line="162"/> <location filename="../src/libsync/syncengine.cpp" line="162"/>
@@ -2345,7 +2351,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/libsync/theme.cpp" line="237"/> <location filename="../src/libsync/theme.cpp" line="237"/>
<source>&lt;p&gt;Copyright ownCloud, Incorporated&lt;/p&gt;</source> <source>&lt;p&gt;Copyright ownCloud, Incorporated&lt;/p&gt;</source>
<translation type="unfinished"/> <translation>&lt;p&gt; Права належать ownCloud, Incorporated &lt;/p&gt;</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/theme.cpp" line="238"/> <location filename="../src/libsync/theme.cpp" line="238"/>
@@ -2453,7 +2459,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/owncloudgui.cpp" line="435"/> <location filename="../src/gui/owncloudgui.cpp" line="435"/>
<source>Crash now</source> <source>Crash now</source>
<translation type="unfinished"/> <translation>Критична помилка</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/owncloudgui.cpp" line="446"/> <location filename="../src/gui/owncloudgui.cpp" line="446"/>
@@ -2501,7 +2507,7 @@ It is not advisable to use it.</source>
<message utf8="true"> <message utf8="true">
<location filename="../src/libsync/owncloudtheme.cpp" line="48"/> <location filename="../src/libsync/owncloudtheme.cpp" line="48"/>
<source>&lt;p&gt;Version %2. For more information visit &lt;a href=&quot;%3&quot;&gt;%4&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;small&gt;By Klaas Freitag, Daniel Molkentin, Jan-Christoph Borchardt, Olivier Goffart, Markus Götz and others.&lt;/small&gt;&lt;/p&gt;&lt;p&gt;Copyright ownCloud, Inc.&lt;/p&gt;&lt;p&gt;Licensed under the GNU General Public License (GPL) Version 2.0&lt;br/&gt;ownCloud and the ownCloud Logo are registered trademarks of ownCloud, Inc. in the United States, other countries, or both.&lt;/p&gt;</source> <source>&lt;p&gt;Version %2. For more information visit &lt;a href=&quot;%3&quot;&gt;%4&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;small&gt;By Klaas Freitag, Daniel Molkentin, Jan-Christoph Borchardt, Olivier Goffart, Markus Götz and others.&lt;/small&gt;&lt;/p&gt;&lt;p&gt;Copyright ownCloud, Inc.&lt;/p&gt;&lt;p&gt;Licensed under the GNU General Public License (GPL) Version 2.0&lt;br/&gt;ownCloud and the ownCloud Logo are registered trademarks of ownCloud, Inc. in the United States, other countries, or both.&lt;/p&gt;</source>
<translation type="unfinished"/> <translation>&lt;p&gt;Версія %2. Для більш детальної інформації відвідайте &lt;a href=&quot;%3&quot;&gt;%4&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;small&gt; Klaas Freitag, Daniel Molkentin, Jan-Christoph Borchardt, Olivier Goffart, Markus Götz та інші.&lt;/ small&gt;&lt;/p&gt; &lt;p&gt; Права належать ownCloud, Inc. &lt;/p&gt; &lt;p&gt; Під ліцензією GNU General Public License (GPL) Version 2.0 &lt;br/&gt; ownCloud і логотип ownCloud є зареєстрованими товарними знаками ownCloud, Inc. в США та інших країнах. &lt;/p&gt;</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -2560,7 +2566,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/wizard/owncloudadvancedsetuppage.ui" line="224"/> <location filename="../src/gui/wizard/owncloudadvancedsetuppage.ui" line="224"/>
<source>S&amp;ync everything from server</source> <source>S&amp;ync everything from server</source>
<translation type="unfinished"/> <translation>Синхронізувати все з сервером</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/wizard/owncloudadvancedsetuppage.ui" line="306"/> <location filename="../src/gui/wizard/owncloudadvancedsetuppage.ui" line="306"/>
@@ -2578,7 +2584,7 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="43"/> <location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="43"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Failed to connect to the secure server address specified. How do you wish to proceed?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source> <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Failed to connect to the secure server address specified. How do you wish to proceed?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"/> <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt; Не вдалося підключитися до безпечного серверу за наданною адресою. Як Ви хочете продовжити? &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="55"/> <location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="55"/>
@@ -2588,17 +2594,17 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="62"/> <location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="62"/>
<source>Retry unencrypted over HTTP (insecure)</source> <source>Retry unencrypted over HTTP (insecure)</source>
<translation type="unfinished"/> <translation>Спробувати без шифрування через HTTP (небезпечно)</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="69"/> <location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="69"/>
<source>Configure client-side TLS certificate</source> <source>Configure client-side TLS certificate</source>
<translation type="unfinished"/> <translation>Налаштувати TLS сертифікат клієнта</translation>
</message> </message>
<message> <message>
<location filename="../src/gui/wizard/owncloudconnectionmethoddialog.cpp" line="18"/> <location filename="../src/gui/wizard/owncloudconnectionmethoddialog.cpp" line="18"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Failed to connect to the secure server address &lt;em&gt;%1&lt;/em&gt;. How do you wish to proceed?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source> <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Failed to connect to the secure server address &lt;em&gt;%1&lt;/em&gt;. How do you wish to proceed?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"/> <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Не вдалося підключитися до безпечного серверу за адресою &lt;em&gt;%1&lt;/em&gt;. Як Ви хочете продовжити?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -2747,22 +2753,22 @@ It is not advisable to use it.</source>
<message> <message>
<location filename="../src/libsync/utility.cpp" line="113"/> <location filename="../src/libsync/utility.cpp" line="113"/>
<source>%L1 TiB</source> <source>%L1 TiB</source>
<translation type="unfinished"/> <translation>%L1 Тіб</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/utility.cpp" line="116"/> <location filename="../src/libsync/utility.cpp" line="116"/>
<source>%L1 GiB</source> <source>%L1 GiB</source>
<translation type="unfinished"/> <translation>%L1 ГіБ</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/utility.cpp" line="119"/> <location filename="../src/libsync/utility.cpp" line="119"/>
<source>%L1 MiB</source> <source>%L1 MiB</source>
<translation type="unfinished"/> <translation>%L1 МіБ</translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/utility.cpp" line="122"/> <location filename="../src/libsync/utility.cpp" line="122"/>
<source>%L1 KiB</source> <source>%L1 KiB</source>
<translation type="unfinished"/> <translation>%L1 КіБ </translation>
</message> </message>
<message> <message>
<location filename="../src/libsync/utility.cpp" line="125"/> <location filename="../src/libsync/utility.cpp" line="125"/>

File diff suppressed because it is too large Load Diff