1
0
mirror of https://github.com/chylex/Nextcloud-Desktop.git synced 2026-04-16 15:44:08 +02:00

Compare commits

..

98 Commits

Author SHA1 Message Date
Klaas Freitag
398bca9fe4 Add OWNCLOUDSYNC_EXPORT prefix to make windows build. 2015-03-04 13:50:55 +01:00
Klaas Freitag
07e60b9161 Bump version to 1.8.0 beta2. 2015-03-04 12:29:17 +01:00
Olivier Goffart
46d5d22f72 PropagateUpload: also read the OC-ErrorString header from the poll job 2015-03-04 12:01:41 +01:00
Olivier Goffart
97c221d860 PropagateUpload: add a few comments 2015-03-04 12:00:55 +01:00
Jocelyn Turcotte
a5d29e6d56 Fix missing symbols on XP
Import a fix from libcrashreporter-qt that should remove
usage of symbols not available in XP's msvcrt.dll

This should help solving #2907 with the crash reporter enabled.
2015-03-04 09:51:54 +01:00
Jenkins for ownCloud
4662f59577 [tx-robot] updated from transifex 2015-03-04 02:18:30 -05:00
Markus Goetz
131cf63d8d Propagator: Don't use 0,0 progress signals.
They seemed to have messed up the calculation sometimes for
the last chunk.
2015-03-03 17:46:57 +01:00
Olivier Goffart
4d85f1daec setup wizard: use a PROPFIND instead of a GET on the webdav url
In order to initiate the conneciton, we should not send a GET on the
webdav URL because that is not a valid webdav command on a collection.

Issue #2911
2015-03-03 16:03:53 +01:00
Klaas Freitag
f913cd97ee DiscoveryJob: Fix progress display.
This fixes #2909
2015-03-03 16:01:17 +01:00
Olivier Goffart
ccbeb86140 Fix build of the legacy propagator 2015-03-03 10:05:38 +01:00
Olivier Goffart
b43e0f5ebd Do not ask for the password when the check server job times up
QNetworkReply::OperationCanceledError may be both because of anthentication
error (because the HTTPCredentials abort the reply) or because of a timeout
(the timer abort the reply). We should only ask for the password if the
reply was canceled because the password was wrong.
2015-03-03 09:21:24 +01:00
Jenkins for ownCloud
b3c82fd7b6 [tx-robot] updated from transifex 2015-03-03 02:18:28 -05:00
Jenkins for ownCloud
15a60bb359 [tx-robot] updated from transifex 2015-03-03 01:15:17 -05:00
Markus Goetz
fe574dbbf9 Discovery: Free some memory before propagate (#2902) 2015-03-02 15:08:21 +01:00
Markus Goetz
7595c7e697 Discovery: Free some memory on VIO dir close (#2902) 2015-03-02 14:09:01 +01:00
Olivier Goffart
bd6769a3fd LsColJob: one must now specify the properties
So the discovery phase don't ask for the quota, and the selective sync
don't ask for all the other properties

Issue #2906
2015-03-02 11:03:25 +01:00
Jenkins for ownCloud
dc2a919e75 [tx-robot] updated from transifex 2015-03-01 02:18:29 -05:00
Jenkins for ownCloud
c20fc24f4d [tx-robot] updated from transifex 2015-02-28 02:18:39 -05:00
Daniel Molkentin
5f8af4527e Update Windows cross build instructions for 1.8 2015-02-27 17:13:14 +01:00
Markus Goetz
80f3c7584b libowncloudsync: Don't link to Qt SQL and Qt XML
For issue #2901 ..
2015-02-27 16:20:25 +01:00
Klaas Freitag
05624e3fc8 FileSystem: Remove QFileInfo based implementations.
QFileInfo has to be refreshed if the underlying file has been
modified in between. That is dangerous so ckamm and me decided
to eliminate the QFileInfo based implementations.

This was triggered by a bug that the client uploaded files that
it should not have.
2015-02-27 15:27:49 +01:00
Christian Kamm
e381143a8f Ensure good sync state if in-progress folder is deleted. #2896
The slotFolderSyncFinished() didn't reliably trigger because
the folder was being deleted before the syncFinished signal could
fire.
2015-02-27 12:39:19 +01:00
Christian Kamm
b03209ccef Inform user about ignored long files. #2882 2015-02-27 12:12:39 +01:00
Markus Goetz
ec03ebd69f Token Auth: Allow empty token
Just username/password. The received token will automatically be stored
inside the QNetworkCookieJar.
2015-02-27 11:58:18 +01:00
Daniel Molkentin
ff68caac24 Merge pull request #2900 from rullzer/qt-4.8-fix
static member QFileInfo::exists is not available on 4.8
2015-02-27 08:56:40 +01:00
Roeland Jago Douma
51c617801d static member QFileInfo::exists is not available on 4.8 2015-02-27 08:43:33 +01:00
Jenkins for ownCloud
e53290088f [tx-robot] updated from transifex 2015-02-27 02:18:29 -05:00
Klaas Freitag
4f7c062f3f csync_exclude: Ignore files where the filename length is > 254 chars.
This is for example HFS+ and others. It fixes #2882
2015-02-26 17:09:49 +01:00
Klaas Freitag
8507aba9f8 SocketAPI: Append trailing slash for directories in UPDATE_VIEW.
This fixes #2233
2015-02-26 16:41:55 +01:00
Olivier Goffart
d8b6e00fe7 Propagator: Let network propagator job understand a new header OC-ErrorString
This allows the server to send a readable error string in many cases
2015-02-26 15:53:09 +01:00
Christian Kamm
c8167b77c9 Remove mention of allprop #2865 2015-02-26 12:36:11 +01:00
Christian Kamm
c37792f58f Propagator: Upload files with future timestamps. #2880 2015-02-26 11:00:06 +01:00
Christian Kamm
842e5ba5e0 Sharing: Fix for folders containing &. #2892 2015-02-26 09:58:09 +01:00
Jenkins for ownCloud
10d28292c6 [tx-robot] updated from transifex 2015-02-26 02:18:35 -05:00
Klaas Freitag
506cc3908a Add proper copyright headers to some files, fixes #2869 2015-02-25 17:00:27 +01:00
Klaas Freitag
ca00b02b0a ShareDialog: Improve some GUI, fix #2850
This improves some wording and fixes some show/hide issues with password
setting.
2015-02-25 13:44:27 +01:00
Klaas Freitag
201075827f Sharedialog: Add a Share button. 2015-02-25 13:44:27 +01:00
Daniel Molkentin
961623d388 Crash Reporter: fix submit URL 2015-02-25 12:33:16 +01:00
Jocelyn Turcotte
a98ab6f51d shell_integration: Remove OwnCloud from public strings on OSX
Also removed it from commented out logs just in case.
2015-02-25 12:13:28 +01:00
Christian Kamm
5c7fd24ea8 Handle 503 due to maintenance more gracefully. #2884 2015-02-25 12:02:10 +01:00
Christian Kamm
76ac628153 Discovery: Distinguish 503 Storage not available. #2884 2015-02-25 12:02:10 +01:00
Christian Kamm
6f71bd9353 SocketAPI: Don't mark .lnk files as ignored on windows. #2447 2015-02-25 11:55:48 +01:00
Christian Kamm
f88398e776 lnk files: Fix exists() calls. #2792 2015-02-25 11:50:32 +01:00
Jenkins for ownCloud
ed315f54e3 [tx-robot] updated from transifex 2015-02-25 02:18:31 -05:00
Christian Kamm
08c33cd1dc Discovery: Fix handling of 503 on a folder. #2884 2015-02-25 08:09:07 +01:00
Christian Kamm
0464947610 Remove extra ; to silence warning. 2015-02-25 07:14:05 +01:00
Klaas Freitag
1929040bb7 Discovery: Preserve the error message. 2015-02-24 22:02:31 +01:00
Klaas Freitag
3af936c8a1 Some minor cleanups. 2015-02-24 22:02:29 +01:00
Jenkins for ownCloud
3bd48c1b3f [tx-robot] updated from transifex 2015-02-24 02:18:32 -05:00
Jenkins for ownCloud
298ca552c8 [tx-robot] updated from transifex 2015-02-24 01:15:20 -05:00
Jenkins for ownCloud
5dcc6a16ee [tx-robot] updated from transifex 2015-02-23 02:18:25 -05:00
Jenkins for ownCloud
318b858ce6 [tx-robot] updated from transifex 2015-02-22 02:18:23 -05:00
Jenkins for ownCloud
6c09764b35 [tx-robot] updated from transifex 2015-02-22 01:15:16 -05:00
Jenkins for ownCloud
96501322fa [tx-robot] updated from transifex 2015-02-21 02:18:23 -05:00
Jenkins for ownCloud
b1e9a74cc2 [tx-robot] updated from transifex 2015-02-21 01:15:14 -05:00
Daniel Molkentin
f38aa698eb Don't translate dummy strings 2015-02-20 10:12:31 +01:00
Daniel Molkentin
366f3f68b8 Activity view: Always add date
Fixes #2223
2015-02-20 10:12:19 +01:00
Olivier Goffart
276dd50650 Update GetGitRevisionDescription.cmake
From https://github.com/rpavlik/cmake-modules
2015-02-20 10:11:30 +01:00
Jenkins for ownCloud
defd6180c6 [tx-robot] updated from transifex 2015-02-20 02:18:35 -05:00
Jocelyn Turcotte
03e23da6a3 Show the settings also when no arguments are passed
sendMessage would only be called if there were options to
be sent to the running application.
Fix the issue by having explicitly named messages and always
send the show settings message.

Issue #2374
2015-02-19 16:57:16 +01:00
Jocelyn Turcotte
2ddaf5a06a Add a NO_MSG_HANDLER cmake option
This allows QDebug to output to stdout or OutputDebugString
to ease development.
2015-02-19 16:57:16 +01:00
Olivier Goffart
5e1aa7d383 SyncEngine: Fix move would re-upload the file
Because SyncJournalDb::postSyncCleanup was deleting the entries in the database
2015-02-19 15:00:37 +01:00
Olivier Goffart
e1871eb325 libsync: Fix qWarning in SyncEngine::slotJobCompleted saying we cannot find the sync item when moving
We need to compare against the original file name, that's why it's there
2015-02-19 13:13:45 +01:00
Olivier Goffart
66fc8e9e27 Merge branch 'master' into 1.8 2015-02-19 11:32:16 +01:00
Jenkins for ownCloud
3259cf59f5 [tx-robot] updated from transifex 2015-02-19 02:19:25 -05:00
Jocelyn Turcotte
c6442f67c1 shell_integration: Fix a crash on explorer startup
There is a race condition that can initialize the RemotePathChecker
instance concurrently on the same address and cause a crash when locking
the mutex. The reason is that local static initialization is not
thread-safe with MSVC2013.

Fix the issue by using call_once to initialize a static unique_ptr
instead.

This could be related to some reports of issue #2836.
2015-02-18 17:33:46 +01:00
Olivier Goffart
1998b602b9 SyncEngine: better merge of the renames node
The same file is on the two sync trees under different names in case of a rename
We must therefore use the rename target as the key in the _syncItemMap to ensure
that the trees are correctly merged.

Also use the same UTF-8 decoding for the target than for the actual file in order
to catch invalid utf-8 in the rename target
2015-02-18 12:41:06 +01:00
Olivier Goffart
193fca4a8b SyncFileItem::operator<: must return false when two items are equal
Fixes #2852
2015-02-18 12:41:06 +01:00
Jenkins for ownCloud
9659d0bdc7 [tx-robot] updated from transifex 2015-02-18 02:18:34 -05:00
Jocelyn Turcotte
ccf4298c81 shell_integration: Cleanup our uses of NSLog
Remove info messages and make sure that error messages
have an OwnCloud prefix since they will be reported by
Finder's process.
2015-02-17 18:23:30 +01:00
Jocelyn Turcotte
0b461e2275 shell_integration: Fix the overlay icons in the column view
Based on 79a713ea643e13e95f52bfe2adbbaf4a5ca92f8a in upstream liferay-nativity.
2015-02-17 18:20:16 +01:00
Jocelyn Turcotte
4f4ae5861a Enable c++11 regardless of the compiler detection
CMake is using "c++" as the compiler and the clang detection fails.
Since we require C++11 at this point, enable it in all cases.

Removed the MSVC todos since we don't plan supporting it yet.
2015-02-17 18:20:15 +01:00
Daniel Molkentin
fedf368c7a Merge pull request #2849 from owncloud/nsis_shortcuts_all_users
Install shortcuts for all users
2015-02-17 18:13:11 +01:00
Daniel Molkentin
c5f78fab51 Make NSIS installer with /S fully silent
Addresses #2006
2015-02-17 17:59:14 +01:00
Daniel Molkentin
56a907128a Install shortcuts for all users
Implements #2413
2015-02-17 17:17:39 +01:00
Olivier Goffart
fb77cd5f7e SyncEngine: Fix detection of the server reconfiguration
Some files might be kept (like the default files)
The files should be considered as NONE only if they are NONE on both trees

issue #2847
2015-02-17 16:44:13 +01:00
Daniel Molkentin
99d674c346 Default shiboolethwebview to 900x700, remember last size
Also add host to the title

Addresses #2285
2015-02-17 15:28:14 +01:00
Daniel Molkentin
9690ca0198 Explain the "crash now" button to translators 2015-02-17 14:03:09 +01:00
Olivier Goffart
9351c7485f Try another way to fix the build 2015-02-17 14:04:16 +01:00
Olivier Goffart
d43b82dc82 Fix compilation with clang
The compilation error was

 account.h:140:113: error: expected ')'
 const QList< QPair<QString, QString> > &queryItems = QList< QPair<QString, QString> >());
                                                                                   ^
followed by more errors.

The problem is because the compiler has hard time disambiguiating the comma

int foo(const QPair<int, int> &p = QPair<int, int>());
                                            ^
It is indeed quite hard for the compiler to know if this comma is a separation
between complate arguments or the separation between arguments of the functions.

Use the C++11 construct instead which does not need commas
2015-02-17 11:09:45 +01:00
Olivier Goffart
ce195bd599 SyncEngine: add an getter to the journal 2015-02-17 11:08:16 +01:00
Olivier Goffart
c0c8a22fa3 SyncEngine: pass a non-const reference to the SyncFileItemVector in aboutToPropagate
That way, users of the library  can change the contents of the sync item vector.
2015-02-17 11:08:16 +01:00
Jenkins for ownCloud
93717c95fb [tx-robot] updated from transifex 2015-02-17 02:18:24 -05:00
Jocelyn Turcotte
a955defae5 Raise the share window to make sure that the user sees it 2015-02-16 16:47:00 +01:00
Jocelyn Turcotte
9579102541 shell_integration: Generate a .pdb in Release for OCContextMenu_x64.dll 2015-02-16 16:47:00 +01:00
Daniel Molkentin
2423aa592f Add new icons by Jan 2015-02-16 14:47:32 +01:00
Olivier Goffart
151228b2a6 Fix build when compiling libsync without QtGui
Utility must stay QtGui-free, move the hidpiFileName to the theme which
is the only part in libsync which uses it, and already has #ifdefs
2015-02-16 10:24:42 +01:00
Jenkins for ownCloud
025d74bbcd [tx-robot] updated from transifex 2015-02-16 02:18:23 -05:00
Jenkins for ownCloud
7626478165 [tx-robot] updated from transifex 2015-02-15 02:18:23 -05:00
Daniel Molkentin
3dea1eb173 Merge pull request #2785 from owncloud/typos
some typos, grammar and sentence fixes
2015-02-14 23:56:10 +01:00
Volkan Gezer
bd4f68233f some typos, grammar and sentence fixes 2015-02-14 23:47:07 +01:00
Olivier Goffart
d6bdbf9f34 Logger: use qFormatLogMessage with Qt 5.4 so it respects the Qt logging preferences 2015-02-14 14:23:01 +01:00
Jenkins for ownCloud
2ccfb8671e [tx-robot] updated from transifex 2015-02-14 02:18:27 -05:00
Olivier Goffart
04bb67ef45 Fix Qt4 build
The automatic registration of metatype only came with qt5
2015-02-13 21:41:09 +01:00
Jocelyn Turcotte
4b67429234 shell_integration: Wait longer for the Share menu title
50ms is sometimes not enough when the client is busy synchronizing.
Wait up to 500ms for the client to answer before we give up and show an
empty menu title.

Ideally we should request the title before the watched directory list, but
the list is currently sent implicitly on connect.
2015-02-13 17:18:39 +01:00
Jocelyn Turcotte
23e248b5d1 shell_integration: Fetch the share menu title from the client on Windows
The context menu will now show "Share with ownCloud" instead of "Share" as
it does on other platforms.

This also updates the submodule to point to matching binaries.
2015-02-13 16:08:39 +01:00
Christian Kamm
40dbc78407 concatUrl: Remove manual parsing, add test. #2817 2015-02-13 14:53:55 +01:00
Klaas Freitag
b159018f51 Changelog edited for 1.8.0 2015-02-13 12:54:27 +01:00
133 changed files with 1724 additions and 1058 deletions

View File

@@ -102,6 +102,11 @@ if(TOKEN_AUTH_ONLY)
add_definitions(-DTOKEN_AUTH_ONLY=1) add_definitions(-DTOKEN_AUTH_ONLY=1)
endif() endif()
option(NO_MSG_HANDLER "Don't redirect QDebug outputs to the log window/file" OFF)
if(NO_MSG_HANDLER)
add_definitions(-DNO_MSG_HANDLER=1)
endif()
# this option creates only libocsync and libowncloudsync # this option creates only libocsync and libowncloudsync
option(BUILD_LIBRARIES_ONLY "BUILD_LIBRARIES_ONLY" OFF) option(BUILD_LIBRARIES_ONLY "BUILD_LIBRARIES_ONLY" OFF)

View File

@@ -1,11 +1,38 @@
ChangeLog ChangeLog
========= =========
version 1.8.0 (release 2015-02-xx)
* Mac OS: HIDPI support
* Support Sharing from desktop: Added a share dialog that can be
opened by context menu in the file managers (Win, Mac, Nautilus)
Supports public links with password enforcement
* Enhanced usage of parallel HTTP requests for ownCloud 8 servers
* Renamed github repository from mirall to client.
* Mac OS: Use native notification support
* Selective Sync: allow to enforce selective sync in brandings.
* Added ability to build on Windows utilizing MingGW
* SQLite database fixes if running on FAT filesystems
* Improved detection of changing files to upload from local
* Preparations for the muli-account feature
* Fixed experience for Window manager without system tray
* Build with Qt 5.4
* Dropped libneon dependency if Qt 5.4 is available
* Keep files open very short, that avoid lock problems on Windows
especially with office software but also others.
* Merged some NetBSD patches
* Selective sync support for owncloudcmd
* Reorganize the source repository
* Prepared direct download
* Added Crashreporter feature to be switched on on demand
* A huge amount of bug fixes in all areas of the client.
* 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
* Nautilus Python plugin fixed for Python 3 * Nautilus Python plugin fixed for Python 3
* GUI wording fixes plus improved log messages * GUI wording fixes plus improved log messages
* Fix hidning of the database files in the sync directories * Fix hidning of the database files in the sync directories
* Compare http download size with the header value to avoid broken * Compare http download size with the header value to avoid broken
downloads, bug #2528 downloads, bug #2528
* Avoid initial ETag fetch job at startup, which is not needed. * Avoid initial ETag fetch job at startup, which is not needed.
* Add chunk size http header to PUT requests * Add chunk size http header to PUT requests
@@ -135,7 +162,7 @@ version 1.6.0 (release 2014-05-30 )
* Improve Cookie support (e.g. for cookie-based load-balancers) * Improve Cookie support (e.g. for cookie-based load-balancers)
* Introduce a general timeout of 300s for network operations * Introduce a general timeout of 300s for network operations
* Improve error handling, blacklisting * Improve error handling, blacklisting
* Job-based change propagation, enables faster parallel up/downloads * Job-based change propagation, enables faster parallel up/downloads
(right now only if no bandwidth limit is set and no proxy is used) (right now only if no bandwidth limit is set and no proxy is used)
* Significantly reduced CPU load when checking for local and remote changes * Significantly reduced CPU load when checking for local and remote changes
* Speed up file stat code on Windows * Speed up file stat code on Windows
@@ -148,7 +175,7 @@ version 1.6.0 (release 2014-05-30 )
Qt 5.2 or later Qt 5.2 or later
* Forward server exception messages to client error messages * Forward server exception messages to client error messages
* Mac OS X: Support Notification Center in OS X 10.8+ * Mac OS X: Support Notification Center in OS X 10.8+
* Mac OS X: Use native settings dialog * Mac OS X: Use native settings dialog
* Mac OS X: Fix UI inconsistencies on Mavericks * Mac OS X: Fix UI inconsistencies on Mavericks
* Shibboleth: Warn if authenticating with a different user * Shibboleth: Warn if authenticating with a different user
* Remove vio abstraction in csync * Remove vio abstraction in csync
@@ -183,7 +210,7 @@ version 1.5.2 (release 2014-02-26 )
* Shibboleth: Proper invalidation if timeout during sync * Shibboleth: Proper invalidation if timeout during sync
* Shibboleth: Do not pop up IdP login immediately when modifying account * Shibboleth: Do not pop up IdP login immediately when modifying account
* Shibboleth: Avoid auth on restart by storing cookies in the wallet * Shibboleth: Avoid auth on restart by storing cookies in the wallet
* Fix license headers * Fix license headers
version 1.5.1 (release 2014-02-13 ) version 1.5.1 (release 2014-02-13 )
* Added an auto updater that updates the client if a * Added an auto updater that updates the client if a
@@ -268,7 +295,7 @@ version 1.4.2 (release 2013-10-18 ), csync 0.90.4 required
version 1.4.1 (release 2013-09-24 ), csync 0.90.1 required version 1.4.1 (release 2013-09-24 ), csync 0.90.1 required
* Translation and documentation fixes. * Translation and documentation fixes.
* Fixed error display in settings/status dialog, displays multi * Fixed error display in settings/status dialog, displays multi
line error messages now correctly. line error messages now correctly.
* Wait up to 30 secs before complaining about missing systray * Wait up to 30 secs before complaining about missing systray
Fixes bug #949 Fixes bug #949
@@ -349,7 +376,7 @@ version 1.3.0 (release 2013-06-25 ), csync 0.80.0 required
version 1.2.5 (release 2013-04-23 ), csync 0.70.7 required version 1.2.5 (release 2013-04-23 ), csync 0.70.7 required
* [Fixes] NSIS installer fixes * [Fixes] NSIS installer fixes
* [Fixes] Fix crash race by making certificateChain() thread safe * [Fixes] Fix crash race by making certificateChain() thread safe
* [Fixes] Build with older CMake versions (CentOS/RHEL 6) * [Fixes] Build with older CMake versions (CentOS/RHEL 6)
* [Fixes] Wording in GUI * [Fixes] Wording in GUI
* [Fixes] Silently ignore "installed = true" status.php * [Fixes] Silently ignore "installed = true" status.php
* Set log verbosity before calling csync_init. * Set log verbosity before calling csync_init.
@@ -359,7 +386,7 @@ version 1.2.5 (release 2013-04-23 ), csync 0.70.7 required
version 1.2.4 (release 2013-04-11 ), csync 0.70.6 required version 1.2.4 (release 2013-04-11 ), csync 0.70.6 required
* [Fixes] Clarify string in folder wizard * [Fixes] Clarify string in folder wizard
* [Fixes] Fixed some valgrind warnings * [Fixes] Fixed some valgrind warnings
* [Fixes] Ensure that only one sync thread can ever run * [Fixes] Ensure that only one sync thread can ever run
* [Fixes] Fix default config storage path * [Fixes] Fix default config storage path
* [Fixes] Skip folders with no absolute path * [Fixes] Skip folders with no absolute path
* [Fixes] Allow setting the configuration directory on command line * [Fixes] Allow setting the configuration directory on command line

View File

@@ -14,5 +14,5 @@ set( MAC_INSTALLER_BACKGROUND_FILE "${CMAKE_SOURCE_DIR}/admin/osx/installer-back
# set( APPLICATION_LICENSE "${OEM_THEME_DIR}/license.txt ) # set( APPLICATION_LICENSE "${OEM_THEME_DIR}/license.txt )
option( WITH_CRASHREPORTER "Build crashreporter" OFF ) option( WITH_CRASHREPORTER "Build crashreporter" OFF )
set( CRASHREPORTER_SUBMIT_URL "https://crash-reports.owncloud.org/submit" CACHE string "URL for crash repoter" ) set( CRASHREPORTER_SUBMIT_URL "https://crash-reports.owncloud.com/submit" CACHE string "URL for crash repoter" )
set( CRASHREPORTER_ICON ":/owncloud-icon.png" ) set( CRASHREPORTER_ICON ":/owncloud-icon.png" )

View File

@@ -4,7 +4,7 @@ set( MIRALL_VERSION_PATCH 0 )
set( MIRALL_SOVERSION 0 ) set( MIRALL_SOVERSION 0 )
if ( NOT DEFINED MIRALL_VERSION_SUFFIX ) if ( NOT DEFINED MIRALL_VERSION_SUFFIX )
set( MIRALL_VERSION_SUFFIX "beta1") #e.g. beta1, beta2, rc1 set( MIRALL_VERSION_SUFFIX "beta2") #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

@@ -3,7 +3,7 @@ StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Amosar as notas de publicaci
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Atopáronse procesos ${APPLICATION_EXECUTABLE} que teñen que ser detidos.$\nQuere que sexa o instalador quen o(s) deteña?" StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Atopáronse procesos ${APPLICATION_EXECUTABLE} que teñen que ser detidos.$\nQuere que sexa o instalador quen o(s) deteña?"
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Matando os procesos ${APPLICATION_EXECUTABLE}." StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Matando os procesos ${APPLICATION_EXECUTABLE}."
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Non se atopou o proceso para matalo!" StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Non se atopou o proceso para matalo!"
StrCpy $PageReinstall_NEW_Field_1 "No seu sistema hai instalada unha versión anterior do ${APPLICATION_NAME}. Recomendámoslle que desinstale a versión actual antes de instalar. Seleccione a operación que quere realizar e prema en Seguinte para continuar." StrCpy $PageReinstall_NEW_Field_1 "No seu sistema hai instalada unha versión anterior de ${APPLICATION_NAME}. Recomendámoslle que desinstale a versión actual antes de instalar. Seleccione a operación que quere realizar e prema en Seguinte para continuar."
StrCpy $PageReinstall_NEW_Field_2 "Desinstalar antes de instalar" StrCpy $PageReinstall_NEW_Field_2 "Desinstalar antes de instalar"
StrCpy $PageReinstall_NEW_Field_3 "Non desinstalar" StrCpy $PageReinstall_NEW_Field_3 "Non desinstalar"
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Xa instalado" StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Xa instalado"
@@ -18,7 +18,7 @@ StrCpy $SEC_APPLICATION_DETAILS "Instalando ${APPLICATION_NAME} esenciais."
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Integración con Windows Explorer" StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Integración con Windows Explorer"
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Instalando a integración con Windows Explorer" StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Instalando a integración con Windows Explorer"
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Acceso directo ao programa no menú de inicio" StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Acceso directo ao programa no menú de inicio"
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Engadindo o acceso directo ao ${APPLICATION_NAME} no menú de inicio" StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Engadindo o acceso directo a ${APPLICATION_NAME} no menú de inicio"
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Acceso directo no escritorio" StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Acceso directo no escritorio"
StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Creando os accesos directos no escritorio" StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Creando os accesos directos no escritorio"
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Acceso de inicio rápido" StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Acceso de inicio rápido"

View File

@@ -15,6 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "卸载${APPLICATION_NAME}"
StrCpy $UNINSTALLER_APPDATA_TITLE "卸载${APPLICATION_NAME}" StrCpy $UNINSTALLER_APPDATA_TITLE "卸载${APPLICATION_NAME}"
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "选择需要执行的维护选项。" StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "选择需要执行的维护选项。"
StrCpy $SEC_APPLICATION_DETAILS "安装${APPLICATION_NAME}基本组件。" StrCpy $SEC_APPLICATION_DETAILS "安装${APPLICATION_NAME}基本组件。"
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "整合到 Windows 资源管理器"
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "正在整合到 Windows 资源管理器"
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "开始菜单程序快捷方式" StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "开始菜单程序快捷方式"
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "添加 ${APPLICATION_NAME} 快捷方式到开始菜单。" StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "添加 ${APPLICATION_NAME} 快捷方式到开始菜单。"
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "桌面快捷方式" StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "桌面快捷方式"
@@ -42,5 +44,3 @@ StrCpy $INIT_INSTALLER_RUNNING "安装程序已经运行。"
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "卸载程序需要管理员权限,请重试" StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "卸载程序需要管理员权限,请重试"
StrCpy $INIT_UNINSTALLER_RUNNING "卸载程序已经运行。" StrCpy $INIT_UNINSTALLER_RUNNING "卸载程序已经运行。"
StrCpy $SectionGroup_Shortcuts "快捷方式" StrCpy $SectionGroup_Shortcuts "快捷方式"
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

@@ -15,6 +15,8 @@ StrCpy $PageReinstall_SAME_Field_3 "Odstrani ${APPLICATION_NAME}"
StrCpy $UNINSTALLER_APPDATA_TITLE "Odstrani ${APPLICATION_NAME}" StrCpy $UNINSTALLER_APPDATA_TITLE "Odstrani ${APPLICATION_NAME}"
StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Izberite možnost vzdrževanja za izvedbo." StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Izberite možnost vzdrževanja za izvedbo."
StrCpy $SEC_APPLICATION_DETAILS "Poteka nameščanje ključnih paketov programa ${APPLICATION_NAME}." StrCpy $SEC_APPLICATION_DETAILS "Poteka nameščanje ključnih paketov programa ${APPLICATION_NAME}."
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Podpora programa Windows raziskovalca"
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Nameščanje podpore za program Windows Raziskovalec"
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Bližnjica programa v programskem meniju" StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Bližnjica programa v programskem meniju"
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Poteka dodajanje bližnjice programa ${APPLICATION_NAME} v programski meni." StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Poteka dodajanje bližnjice programa ${APPLICATION_NAME} v programski meni."
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Bližnica namizja" StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Bližnica namizja"
@@ -42,5 +44,3 @@ StrCpy $INIT_INSTALLER_RUNNING "Namestilnik je
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Program za odstranjevanje namestitve zahteva skrbniška dovoljenja." StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Program za odstranjevanje namestitve zahteva skrbniška dovoljenja."
StrCpy $INIT_UNINSTALLER_RUNNING "Program za odstranjevanje namestitve je že zagnan." StrCpy $INIT_UNINSTALLER_RUNNING "Program za odstranjevanje namestitve je že zagnan."
StrCpy $SectionGroup_Shortcuts "Bližnjice" StrCpy $SectionGroup_Shortcuts "Bližnjice"
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

@@ -20,8 +20,8 @@ StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Instalando la integraci
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Acceso directo al programa Menú de Inicio" StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Acceso directo al programa Menú de Inicio"
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Añadiendo accesos directos para ${APPLICATION_NAME} en el Menú de Inicio." StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Añadiendo accesos directos para ${APPLICATION_NAME} en el Menú de Inicio."
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Acceso directo de Escritorio" StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Acceso directo de Escritorio"
StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Creando Accesos Directos de Escritorio" StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Creando accesos directos de escritorio"
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Acceso Directo al Lanzador Rápido" StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Atajo de accceso rápido"
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Creando un Acceso Directo al Lanzador Rápido" StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Creando un Acceso Directo al Lanzador Rápido"
StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} esencial." StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} esencial."
StrCpy $OPTION_SECTION_SC_START_MENU_Desc "Acceso Directo de ${APPLICATION_NAME}" StrCpy $OPTION_SECTION_SC_START_MENU_Desc "Acceso Directo de ${APPLICATION_NAME}"
@@ -36,7 +36,7 @@ StrCpy $UNINSTALLER_REGISTRY_Detail "Escribiendo claves en el registro del insta
StrCpy $UNINSTALLER_FINISHED_Detail "Terminado" StrCpy $UNINSTALLER_FINISHED_Detail "Terminado"
StrCpy $UNINSTALL_MESSAGEBOX "Parece que ${APPLICATION_NAME} no está instalado en el directorio '$INSTDIR'.$$ ¿Continuar de todos modos? (No Recomendado)" StrCpy $UNINSTALL_MESSAGEBOX "Parece que ${APPLICATION_NAME} no está instalado en el directorio '$INSTDIR'.$$ ¿Continuar de todos modos? (No Recomendado)"
StrCpy $UNINSTALL_ABORT "Desinstalación cancelada por el usuario" StrCpy $UNINSTALL_ABORT "Desinstalación cancelada por el usuario"
StrCpy $INIT_NO_QUICK_LAUNCH "Acceso Directo al Lanzador Rápido (N/A)" StrCpy $INIT_NO_QUICK_LAUNCH "Atajo de inicio rápido (N/A)"
StrCpy $INIT_NO_DESKTOP "Atajo de escritorio (sobreescribe el existente)" StrCpy $INIT_NO_DESKTOP "Atajo de escritorio (sobreescribe el existente)"
StrCpy $UAC_ERROR_ELEVATE "No se ha podido elevar, error:" StrCpy $UAC_ERROR_ELEVATE "No se ha podido elevar, error:"
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "El instalador requiere acceso administrativo, inténtelo de nuevo" StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "El instalador requiere acceso administrativo, inténtelo de nuevo"

2
binary

Submodule binary updated: 96dd38811b...01d73965dc

View File

@@ -16,6 +16,6 @@
<file>resources/lock-http@2x.png</file> <file>resources/lock-http@2x.png</file>
<file>resources/lock-https.png</file> <file>resources/lock-https.png</file>
<file>resources/lock-https@2x.png</file> <file>resources/lock-https@2x.png</file>
<file>resources/accounts.png</file> <file>resources/account.png</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@@ -40,7 +40,7 @@ set(__get_git_revision_description YES)
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH) get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
function(get_git_head_revision _refspecvar _hashvar) function(get_git_head_revision _refspecvar _hashvar)
set(GIT_PARENT_DIR "${CMAKE_SOURCE_DIR}") set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(GIT_DIR "${GIT_PARENT_DIR}/.git") set(GIT_DIR "${GIT_PARENT_DIR}/.git")
while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories
set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}") set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}")
@@ -53,6 +53,13 @@ function(get_git_head_revision _refspecvar _hashvar)
endif() endif()
set(GIT_DIR "${GIT_PARENT_DIR}/.git") set(GIT_DIR "${GIT_PARENT_DIR}/.git")
endwhile() endwhile()
# check if this is a submodule
if(NOT IS_DIRECTORY ${GIT_DIR})
file(READ ${GIT_DIR} submodule)
string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule})
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE)
endif()
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
if(NOT EXISTS "${GIT_DATA}") if(NOT EXISTS "${GIT_DATA}")
file(MAKE_DIRECTORY "${GIT_DATA}") file(MAKE_DIRECTORY "${GIT_DATA}")

View File

@@ -264,7 +264,7 @@ FunctionEnd
!macro ConfirmEndProcess processName !macro ConfirmEndProcess processName
MessageBox MB_YESNO|MB_ICONEXCLAMATION \ MessageBox MB_YESNO|MB_ICONEXCLAMATION \
$ConfirmEndProcess_MESSAGEBOX_TEXT \ $ConfirmEndProcess_MESSAGEBOX_TEXT \
IDYES process_${processName}_kill IDNO process_${processName}_ended /SD IDYES IDYES process_${processName}_kill IDNO process_${processName}_ended
process_${processName}_kill: process_${processName}_kill:
DetailPrint $ConfirmEndProcess_KILLING_PROCESSES_TEXT DetailPrint $ConfirmEndProcess_KILLING_PROCESSES_TEXT
Processes::KillProcess ${processName} Processes::KillProcess ${processName}
@@ -512,7 +512,9 @@ SectionGroup $SectionGroup_Shortcuts
SetDetailsPrint textonly SetDetailsPrint textonly
DetailPrint $OPTION_SECTION_SC_DESKTOP_DetailPrint DetailPrint $OPTION_SECTION_SC_DESKTOP_DetailPrint
SetDetailsPrint listonly SetDetailsPrint listonly
SetShellVarContext all
CreateShortCut "$DESKTOP\${APPLICATION_NAME}.lnk" "$INSTDIR\${APPLICATION_EXECUTABLE}" CreateShortCut "$DESKTOP\${APPLICATION_NAME}.lnk" "$INSTDIR\${APPLICATION_EXECUTABLE}"
SetShellVarContext current
${MementoSectionEnd} ${MementoSectionEnd}
!endif !endif
@@ -521,8 +523,10 @@ SectionGroup $SectionGroup_Shortcuts
SectionIn 1 2 SectionIn 1 2
SetDetailsPrint textonly SetDetailsPrint textonly
DetailPrint $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint DetailPrint $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint
SetShellVarContext all
SetDetailsPrint listonly SetDetailsPrint listonly
CreateShortCut "$QUICKLAUNCH\${APPLICATION_NAME}.lnk" "$INSTDIR\${APPLICATION_EXECUTABLE}" CreateShortCut "$QUICKLAUNCH\${APPLICATION_NAME}.lnk" "$INSTDIR\${APPLICATION_EXECUTABLE}"
SetShellVarContext current
${MementoSectionEnd} ${MementoSectionEnd}
!endif !endif
@@ -672,18 +676,22 @@ Section Uninstall
;Desktop shortcut. ;Desktop shortcut.
!ifdef OPTION_SECTION_SC_DESKTOP !ifdef OPTION_SECTION_SC_DESKTOP
${If} ${HasSection} SEC_DESKTOP ${If} ${HasSection} SEC_DESKTOP
SetShellVarContext all
${If} ${FileExists} "$DESKTOP\${APPLICATION_NAME}.lnk" ${If} ${FileExists} "$DESKTOP\${APPLICATION_NAME}.lnk"
Delete "$DESKTOP\${APPLICATION_NAME}.lnk" Delete "$DESKTOP\${APPLICATION_NAME}.lnk"
${EndIf} ${EndIf}
SetShellVarContext current
${EndIf} ${EndIf}
!endif !endif
;Quick Launch shortcut. ;Quick Launch shortcut.
!ifdef OPTION_SECTION_SC_QUICK_LAUNCH !ifdef OPTION_SECTION_SC_QUICK_LAUNCH
${If} ${HasSection} SEC_QUICK_LAUNCH ${If} ${HasSection} SEC_QUICK_LAUNCH
SetShellVarContext all
${If} ${FileExists} "$QUICKLAUNCH\${APPLICATION_NAME}.lnk" ${If} ${FileExists} "$QUICKLAUNCH\${APPLICATION_NAME}.lnk"
Delete "$QUICKLAUNCH\${APPLICATION_NAME}.lnk" Delete "$QUICKLAUNCH\${APPLICATION_NAME}.lnk"
${EndIf} ${EndIf}
SetShellVarContext current
${EndIf} ${EndIf}
!endif !endif

View File

@@ -2,25 +2,21 @@
# Redistribution and use is allowed according to the terms of the BSD license. # Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING* file. # For details see the accompanying COPYING* file.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wno-long-long")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
if(CMAKE_COMPILER_IS_GNUCXX) if(CMAKE_COMPILER_IS_GNUCXX)
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
OUTPUT_VARIABLE GCC_VERSION) OUTPUT_VARIABLE GCC_VERSION)
if(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8) if(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic -Wno-long-long") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic")
else(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8) else(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wno-long-long") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
endif(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8) endif(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
endif(CMAKE_COMPILER_IS_GNUCXX) endif(CMAKE_COMPILER_IS_GNUCXX)
if(CMAKE_CXX_COMPILER MATCHES "clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wno-long-long")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
endif(CMAKE_CXX_COMPILER MATCHES "clang")
# TODO: handle msvc compilers warnings?
if(DEFINED MIRALL_FATAL_WARNINGS) if(DEFINED MIRALL_FATAL_WARNINGS)
if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER MATCHES "clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
endif (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER MATCHES "clang")
# TODO: handle msvc compilers warnings?
endif(DEFINED MIRALL_FATAL_WARNINGS) endif(DEFINED MIRALL_FATAL_WARNINGS)

View File

@@ -573,15 +573,6 @@ int csync_commit(CSYNC *ctx) {
} }
ctx->statedb.db = NULL; ctx->statedb.db = NULL;
#ifdef USE_NEON
rc = owncloud_commit(ctx);
if (rc < 0) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "commit failed: %s",
ctx->error_string ? ctx->error_string : "");
goto out;
}
#endif
_csync_clean_ctx(ctx); _csync_clean_ctx(ctx);
ctx->remote.read_from_db = 0; ctx->remote.read_from_db = 0;

View File

@@ -91,6 +91,7 @@ enum csync_status_codes_e {
CSYNC_STATUS_OUT_OF_SPACE, CSYNC_STATUS_OUT_OF_SPACE,
CSYNC_STATUS_QUOTA_EXCEEDED, /* UNUSED */ CSYNC_STATUS_QUOTA_EXCEEDED, /* UNUSED */
CSYNC_STATUS_SERVICE_UNAVAILABLE, CSYNC_STATUS_SERVICE_UNAVAILABLE,
CSYNC_STATUS_STORAGE_UNAVAILABLE,
CSYNC_STATUS_FILE_SIZE_ERROR, CSYNC_STATUS_FILE_SIZE_ERROR,
CSYNC_STATUS_CONTEXT_LOST, CSYNC_STATUS_CONTEXT_LOST,
CSYNC_STATUS_MERGE_FILETREE_ERROR, CSYNC_STATUS_MERGE_FILETREE_ERROR,
@@ -104,6 +105,7 @@ enum csync_status_codes_e {
CSYNC_STATUS_INDIVIDUAL_IS_HARDLINK, CSYNC_STATUS_INDIVIDUAL_IS_HARDLINK,
CSYNC_STATUS_INDIVIDUAL_IGNORE_LIST, CSYNC_STATUS_INDIVIDUAL_IGNORE_LIST,
CSYNC_STATUS_INDIVIDUAL_IS_INVALID_CHARS, CSYNC_STATUS_INDIVIDUAL_IS_INVALID_CHARS,
CSYNC_STATUS_INDIVIDUAL_EXCLUDE_LONG_FILENAME,
CYSNC_STATUS_FILE_LOCKED_OR_OPEN CYSNC_STATUS_FILE_LOCKED_OR_OPEN
}; };
@@ -335,7 +337,7 @@ int csync_update(CSYNC *ctx);
int csync_reconcile(CSYNC *ctx); int csync_reconcile(CSYNC *ctx);
/** /**
* @brief Commit the sync results to journal * @brief Re-initializes the csync context
* *
* @param ctx The context to commit. * @param ctx The context to commit.
* *

View File

@@ -231,6 +231,14 @@ CSYNC_EXCLUDE_TYPE csync_excluded_no_ctx(c_strlist_t *excludes, const char *path
goto out; goto out;
} }
// check the strlen and ignore the file if its name is longer than 254 chars.
if (strlen(bname) > 254) {
match = CSYNC_FILE_EXCLUDE_LONG_FILENAME;
SAFE_FREE(bname);
SAFE_FREE(dname);
goto out;
}
#ifdef _WIN32 #ifdef _WIN32
// Windows cannot sync files ending in spaces (#2176). It also cannot // Windows cannot sync files ending in spaces (#2176). It also cannot
// distinguish files ending in '.' from files without an ending, // distinguish files ending in '.' from files without an ending,

View File

@@ -26,7 +26,8 @@ enum csync_exclude_type_e {
CSYNC_FILE_SILENTLY_EXCLUDED, CSYNC_FILE_SILENTLY_EXCLUDED,
CSYNC_FILE_EXCLUDE_AND_REMOVE, CSYNC_FILE_EXCLUDE_AND_REMOVE,
CSYNC_FILE_EXCLUDE_LIST, CSYNC_FILE_EXCLUDE_LIST,
CSYNC_FILE_EXCLUDE_INVALID_CHAR CSYNC_FILE_EXCLUDE_INVALID_CHAR,
CSYNC_FILE_EXCLUDE_LONG_FILENAME
}; };
typedef enum csync_exclude_type_e CSYNC_EXCLUDE_TYPE; typedef enum csync_exclude_type_e CSYNC_EXCLUDE_TYPE;

View File

@@ -45,6 +45,7 @@
#define ERRNO_ERROR_STRING CSYNC_CUSTOM_ERRNO_BASE+13 #define ERRNO_ERROR_STRING CSYNC_CUSTOM_ERRNO_BASE+13
#define ERRNO_SERVICE_UNAVAILABLE CSYNC_CUSTOM_ERRNO_BASE+14 #define ERRNO_SERVICE_UNAVAILABLE CSYNC_CUSTOM_ERRNO_BASE+14
#define ERRNO_USER_ABORT CSYNC_CUSTOM_ERRNO_BASE+16 #define ERRNO_USER_ABORT CSYNC_CUSTOM_ERRNO_BASE+16
#define ERRNO_STORAGE_UNAVAILABLE CSYNC_CUSTOM_ERRNO_BASE+17
#endif /* _CSYNC_MACROS_H */ #endif /* _CSYNC_MACROS_H */
/* vim: set ft=c.doxygen ts=8 sw=2 et cindent: */ /* vim: set ft=c.doxygen ts=8 sw=2 et cindent: */

View File

@@ -108,6 +108,9 @@ CSYNC_STATUS csync_errno_to_status(int error, CSYNC_STATUS default_status)
case ERRNO_SERVICE_UNAVAILABLE: case ERRNO_SERVICE_UNAVAILABLE:
status = CSYNC_STATUS_SERVICE_UNAVAILABLE; /* Service temporarily down */ status = CSYNC_STATUS_SERVICE_UNAVAILABLE; /* Service temporarily down */
break; break;
case ERRNO_STORAGE_UNAVAILABLE:
status = CSYNC_STATUS_STORAGE_UNAVAILABLE; /* Storage temporarily unavailable */
break;
case EFBIG: case EFBIG:
status = CSYNC_STATUS_FILE_SIZE_ERROR; /* File larger than 2MB */ status = CSYNC_STATUS_FILE_SIZE_ERROR; /* File larger than 2MB */
break; break;

View File

@@ -416,6 +416,8 @@ out:
st->error_status = CSYNC_STATUS_INDIVIDUAL_IGNORE_LIST; /* File listed on ignore list. */ st->error_status = CSYNC_STATUS_INDIVIDUAL_IGNORE_LIST; /* File listed on ignore list. */
} else if (excluded == CSYNC_FILE_EXCLUDE_INVALID_CHAR) { } else if (excluded == CSYNC_FILE_EXCLUDE_INVALID_CHAR) {
st->error_status = CSYNC_STATUS_INDIVIDUAL_IS_INVALID_CHARS; /* File contains invalid characters. */ st->error_status = CSYNC_STATUS_INDIVIDUAL_IS_INVALID_CHARS; /* File contains invalid characters. */
} else if (excluded == CSYNC_FILE_EXCLUDE_LONG_FILENAME) {
st->error_status = CSYNC_STATUS_INDIVIDUAL_EXCLUDE_LONG_FILENAME; /* File name is too long. */
} }
} }
if (st->instruction != CSYNC_INSTRUCTION_NONE && st->instruction != CSYNC_INSTRUCTION_IGNORE if (st->instruction != CSYNC_INSTRUCTION_NONE && st->instruction != CSYNC_INSTRUCTION_IGNORE
@@ -619,11 +621,11 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
if (asp < 0) { if (asp < 0) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "asprintf failed!"); CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "asprintf failed!");
} }
} else if(errno == ERRNO_SERVICE_UNAVAILABLE) { } else if(errno == ERRNO_STORAGE_UNAVAILABLE) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Service was not available!"); CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Storage was not available!");
if (ctx->current_fs) { if (ctx->current_fs) {
ctx->current_fs->instruction = CSYNC_INSTRUCTION_IGNORE; ctx->current_fs->instruction = CSYNC_INSTRUCTION_IGNORE;
ctx->current_fs->error_status = CSYNC_STATUS_SERVICE_UNAVAILABLE; ctx->current_fs->error_status = CSYNC_STATUS_STORAGE_UNAVAILABLE;
/* If a directory has ignored files, put the flag on the parent directory as well */ /* If a directory has ignored files, put the flag on the parent directory as well */
if( previous_fs ) { if( previous_fs ) {
previous_fs->has_ignored_files = true; previous_fs->has_ignored_files = true;

View File

@@ -50,7 +50,7 @@ csync_vio_handle_t *csync_vio_opendir(CSYNC *ctx, const char *name) {
break; break;
case LOCAL_REPLICA: case LOCAL_REPLICA:
if( ctx->callbacks.update_callback ) { if( ctx->callbacks.update_callback ) {
ctx->callbacks.update_callback(ctx->replica, name, ctx->callbacks.update_callback_userdata); ctx->callbacks.update_callback(ctx->replica, name, ctx->callbacks.update_callback_userdata);
} }
return csync_vio_local_opendir(name); return csync_vio_local_opendir(name);
break; break;

View File

@@ -129,30 +129,23 @@ Windows Installer Build (Cross-Compile)
Due to the large number of dependencies, building the client installer for Windows Due to the large number of dependencies, building the client installer for Windows
is **currently only officially supported on openSUSE**, by using the MinGW cross compiler. is **currently only officially supported on openSUSE**, by using the MinGW cross compiler.
You can set up openSUSE 12.1, 12.2, or 13.1 in a virtual machine if you do not You can set up openSUSE 13.1, 13.2 or openSUSE Factory in a virtual machine if you do not
have it installed already. have it installed already.
To cross-compile: To cross-compile:
1. Add the following repositories using YaST or ``zypper ar`` (adjust when using openSUSE 12.2 or 13.1):: 1. Add the following repositories using YaST or ``zypper ar`` (adjust when using another openSUSE version)::
zypper ar http://download.opensuse.org/repositories/windows:/mingw:/win32/openSUSE_13.1/windows:mingw:win32.repo zypper ar http://download.opensuse.org/repositories/windows:/mingw/openSUSE_13.2/windows:mingw.repo
zypper ar http://download.opensuse.org/repositories/windows:/mingw/openSUSE_13.1/windows:mingw.repo zypper ar http://download.opensuse.org/repositories/windows:/mingw:/win32/openSUSE_13.2/windows:mingw:win32.repo
2. Install the cross-compiler packages and the cross-compiled dependencies:: 2. Install the cross-compiler packages and the cross-compiled dependencies::
zypper install cmake make mingw32-cross-binutils mingw32-cross-cpp mingw32-cross-gcc \ zypper install cmake make mingw32-cross-binutils mingw32-cross-cpp mingw32-cross-gcc \
mingw32-cross-gcc-c++ mingw32-cross-pkg-config mingw32-filesystem \ mingw32-cross-gcc-c++ mingw32-cross-pkg-config mingw32-filesystem \
mingw32-headers mingw32-runtime site-config mingw32-libqt4-sql \ mingw32-headers mingw32-runtime site-config \
mingw32-libqt4-sql-sqlite mingw32-sqlite mingw32-libsqlite-devel \ mingw32-cross-libqt5-qmake mingw32-cross-libqt5-qttools mingw32-libqt5* \
mingw32-dlfcn-devel mingw32-libssh2-devel kdewin-png2ico \ mingw32-cross-nsis
mingw32-libqt4 mingw32-libqt4-devel mingw32-libgcrypt \
mingw32-libgnutls mingw32-libneon-openssl mingw32-libneon-devel \
mingw32-libbeecrypt mingw32-libopenssl mingw32-openssl \
mingw32-libpng-devel mingw32-libsqlite mingw32-qtkeychain \
mingw32-qtkeychain-devel mingw32-dlfcn mingw32-libintl-devel \
mingw32-libneon-devel mingw32-libopenssl-devel mingw32-libproxy-devel \
mingw32-libxml2-devel mingw32-zlib-devel
3. For the installer, install the NSIS installer package:: 3. For the installer, install the NSIS installer package::
@@ -170,24 +163,43 @@ To cross-compile:
.. note:: These files also work for more recent openSUSE versions! .. note:: These files also work for more recent openSUSE versions!
:: ::
# RPM depends on curl for installs from HTTP
zypper install curl
rpm -ivh http://download.tomahawk-player.org/packman/mingw:32/openSUSE_12.1/x86_64/mingw32-cross-nsis-plugin-processes-0-1.1.x86_64.rpm rpm -ivh http://download.tomahawk-player.org/packman/mingw:32/openSUSE_12.1/x86_64/mingw32-cross-nsis-plugin-processes-0-1.1.x86_64.rpm
rpm -ivh http://download.tomahawk-player.org/packman/mingw:32/openSUSE_12.1/x86_64/mingw32-cross-nsis-plugin-uac-0-3.1.x86_64.rpm rpm -ivh http://download.tomahawk-player.org/packman/mingw:32/openSUSE_12.1/x86_64/mingw32-cross-nsis-plugin-uac-0-3.1.x86_64.rpm
6. Follow the `generic build instructions`_ 6. Follow the `generic build instructions`_
.. note:: When building for Windows platforms, you must specify a special .. note:: When building for Windows platforms, you must specify a special
toolchain file that enables cmake to locate the platform-specific tools. To add toolchain file that enables cmake to locate the platform-specific tools. To add
this parameter to the call to cmake, enter this parameter to the call to cmake, enter
``-DCMAKE_TOOLCHAIN_FILE=../client/admin/win/Toolchain-mingw32-openSUSE.cmake``. ``-DCMAKE_TOOLCHAIN_FILE=../client/admin/win/Toolchain-mingw32-openSUSE.cmake``.
7. Build by running ``make``. 7. Build by running ``make``.
.. note:: Using ``make package`` produces an NSIS-based installer, provided .. note:: Using ``make package`` produces an NSIS-based installer, provided
the NSIS mingw32 packages are installed. the NSIS mingw32 packages are installed.
.. _`generic build instructions`: 8. If you want to sign the installer, acquire a `Microsoft Authenticode`_ Certificate and install ``osslsigncode`` to sign the installer::
zypper install osslsigncode
9. Sign the package::
osslsigncode -pkcs12 $HOME/.codesign/packages.pfx -h sha1 \
-pass yourpass \
-n "ACME Client" \
-i "http://acme.com" \
-ts "http://timestamp.server/" \
-in ${unsigned_file} \
-out ${installer_file}
for ``-in``, use URL to the time stamping server provided by your CA along with the Authenticode certificate. Alternatively,
you may use the official Microsoft ``signtool`` utility on Microsoft Windows.
.. _`generic build instructions`:
Generic Build Instructions Generic Build Instructions
-------------------------- --------------------------
@@ -243,4 +255,5 @@ The following are known cmake parameters:
.. _Homebrew: http://mxcl.github.com/homebrew/ .. _Homebrew: http://mxcl.github.com/homebrew/
.. _`OpenSSL Windows Build`: http://slproweb.com/products/Win32OpenSSL.html .. _`OpenSSL Windows Build`: http://slproweb.com/products/Win32OpenSSL.html
.. _Qt: http://www.qt.io/download .. _Qt: http://www.qt.io/download
.. _`Microsoft Authenticode`: https://msdn.microsoft.com/en-us/library/ie/ms537361%28v=vs.85%29.aspx
.. _QtKeychain: https://github.com/frankosterfeld/qtkeychain .. _QtKeychain: https://github.com/frankosterfeld/qtkeychain

View File

@@ -81,7 +81,7 @@ file manager integration works.
.. image:: images/client8.png .. image:: images/client8.png
When you are in your local ownCloud folder you can right-click any file or When you are in your local ownCloud folder you can right-click any file or
folder, and then left-click Share to create a share link. Note that Windows folder, and then left-click "Share with ownCloud" to create a share link. Note that Windows
may also have a Share With option. This is not the ownCloud Share option. The may also have a Share With option. This is not the ownCloud Share option. The
ownCloud share dialog looks like the following example: ownCloud share dialog looks like the following example:

BIN
resources/account.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

10
resources/account.svg Normal file
View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="64" width="64" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs>
<linearGradient id="a" y2="69.127" gradientUnits="userSpaceOnUse" x2="-18.398" gradientTransform="matrix(.93749 0 0 .93750 48.705 -2.957)" y1="5.2866" x1="-18.398">
<stop offset="0"/>
<stop stop-color="#363636" offset="1"/>
</linearGradient>
</defs>
<path opacity=".7" style="block-progression:tb;color:#000000;text-transform:none;text-indent:0" d="m32.014 2.0032c-6.4921 0-12 4.7474-12 10.874 0.04608 1.9365 0.21927 4.3246 1.3749 9.3745v0.125l0.12499 0.125c0.37098 1.0626 0.91084 1.6705 1.6249 2.4999 0.71405 0.82937 1.5653 1.8055 2.3749 2.6249 0.09524 0.0964 0.15627 0.15612 0.24995 0.25003 0.16055 0.69862 0.35503 1.4505 0.49998 2.1249 0.38566 1.7943 0.34611 3.065 0.25003 3.4998-2.7899 0.97997-6.2601 2.1463-9.3744 3.5003-1.7483 0.75997-3.3307 1.4404-4.625 2.2483-1.2943 0.81109-2.5815 1.4239-2.9998 3.2498-0.00516 0.08324-0.00516 0.16675 0 0.25003-0.40882 3.7538-1.0272 9.2737-1.4999 13-0.10204 0.78425 0.31131 1.611 0.99996 1.9999 5.6546 3.0543 14.34 4.2835 22.999 4.2499 8.6584-0.0336 17.275-1.3353 22.749-4.2499 0.68865-0.38891 1.102-1.2156 0.99996-1.9999-0.15092-1.1646-0.33631-3.7907-0.49998-6.3746-0.16367-2.584-0.30575-5.1258-0.49994-6.6246-0.06775-0.37155-0.24343-0.72281-0.49998-0.99996-1.7388-2.0763-4.3366-3.3456-7.3745-4.6246-2.7736-1.1679-6.0249-2.3806-9.2496-3.7498-0.18047-0.40203-0.35975-1.5717 0-3.3748 0.0984-0.48318 0.24959-1.002 0.37678-1.4991 0.30279-0.33919 0.53918-0.61678 0.87476-0.99996 0.71597-0.81717 1.4859-1.6747 2.1259-2.4999 0.63997-0.82517 1.16-1.5327 1.4999-2.4999l0.124-0.1248c1.3065-5.273 1.3072-7.4733 1.3749-9.3745v-0.12852c0-6.127-5.5074-10.874-12-10.874z" fill="url(#a)"/>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

10
resources/activity.svg Normal file
View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="64" width="64" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs>
<linearGradient id="a" y2="62.102" gradientUnits="userSpaceOnUse" x2="32" y1="2.1695" x1="32">
<stop offset="0"/>
<stop stop-color="#363636" offset="1"/>
</linearGradient>
</defs>
<path opacity=".7" d="m32 2-20 36h22l-2 24 20-36h-22z" fill="url(#a)"/>
</svg>

After

Width:  |  Height:  |  Size: 597 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 739 B

After

Width:  |  Height:  |  Size: 479 B

5
resources/lock-http.svg Normal file
View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="64" width="64" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
<path fill="#909090" d="m32 6c-8.284 0-15 6.716-15 15v10h-5v28h40v-28h-5v-10c0-8.284-6.716-15-15-15zm0 6c4.9706 0 9 4.0294 9 9v10h-18v-10c0-4.9706 4.0294-9 9-9z"/>
<path d="m26 45h36l-18-30z" fill="#dfae19"/>
</svg>

After

Width:  |  Height:  |  Size: 493 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 583 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 478 B

After

Width:  |  Height:  |  Size: 291 B

4
resources/lock-https.svg Normal file
View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="64" width="64" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
<path fill="#60a149" d="m32 6c-8.284 0-15 6.716-15 15v10h-5v28h40v-28h-5v-10c0-8.284-6.716-15-15-15zm0 6c4.9706 0 9 4.0294 9 9v10h-18v-10c0-4.9706 4.0294-9 9-9z"/>
</svg>

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 731 B

After

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

10
resources/network.svg Normal file
View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="64" width="64" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs>
<linearGradient id="a" y2="62" gradientUnits="userSpaceOnUse" x2="32" gradientTransform="translate(0,1)" x1="32">
<stop offset="0"/>
<stop stop-color="#363636" offset="1"/>
</linearGradient>
</defs>
<path opacity=".7" d="m20 1-20 20h12v14h16v-14h12zm16 28v14h-12l20 20 20-20h-12v-14z" fill="url(#a)"/>
</svg>

After

Width:  |  Height:  |  Size: 647 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

14
resources/settings.svg Normal file
View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="64" width="64" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs>
<linearGradient id="d" x1="7.2236" xlink:href="#a" gradientUnits="userSpaceOnUse" x2="7.2236" y1=".019012" y2="15.035"/>
<linearGradient id="a">
<stop offset="0"/>
<stop stop-color="#363636" offset="1"/>
</linearGradient>
<linearGradient id="e" x1="7.493" xlink:href="#a" gradientUnits="userSpaceOnUse" x2="7.493" y1=".0035527" y2="14.998"/>
</defs>
<g opacity=".7" fill="url(#d)" transform="matrix(3.7332 0 0 3.7333 2.1334 3.7931)">
<path fill="url(#e)" d="m6.9375 0.056c-0.2484 0-0.4375 0.18908-0.4375 0.4375v1.25c-0.5539 0.1422-1.0512 0.3719-1.5312 0.6563l-0.9063-0.9063c-0.17566-0.17566-0.44934-0.17566-0.625 0l-1.5 1.5c-0.17566 0.17566-0.17566 0.44934 0 0.625l0.9063 0.9063c-0.2844 0.48-0.5141 0.9773-0.6563 1.5312h-1.25c-0.24842 0-0.4375 0.1891-0.4375 0.4375v2.125c1e-8 0.24842 0.18908 0.4375 0.4375 0.4375h1.25c0.1422 0.5539 0.37188 1.0512 0.65625 1.5312l-0.9063 0.907c-0.17566 0.17566-0.17566 0.44934 0 0.625l1.5 1.5c0.17566 0.17566 0.44934 0.17566 0.625 0l0.9063-0.907c0.48 0.285 0.9773 0.514 1.5312 0.656v1.25c1e-7 0.24842 0.18908 0.4375 0.4375 0.4375h2.125c0.2484 0 0.4375-0.189 0.4375-0.438v-1.25c0.5539-0.1422 1.0512-0.37188 1.5312-0.65625l0.90625 0.90625c0.17566 0.17566 0.44934 0.17566 0.625 0l1.5-1.5c0.17566-0.17566 0.17566-0.44934 0-0.625l-0.906-0.906c0.285-0.48 0.514-0.9771 0.656-1.531h1.25c0.249 0 0.438-0.1891 0.438-0.4375v-2.125c0-0.2484-0.189-0.4375-0.438-0.4375h-1.25c-0.142-0.5539-0.371-1.0512-0.656-1.5312l0.906-0.9063c0.17566-0.17566 0.17566-0.44934 0-0.625l-1.5-1.5c-0.17566-0.17566-0.44934-0.17566-0.625 0l-0.906 0.9063c-0.48-0.2844-0.977-0.5141-1.531-0.6563v-1.25c0.0004-0.24872-0.1887-0.4378-0.4371-0.4378zm1.0625 4.1573c1.8451 0 3.3427 1.4975 3.3427 3.3427 0 1.8451-1.4975 3.3427-3.3427 3.3427-1.8451 0-3.3427-1.4979-3.3427-3.343s1.4976-3.3427 3.3427-3.3427z" display="block"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -72,7 +72,7 @@ static ContentManager* sharedInstance = nil;
_icnWarnSwm = [[IconCache sharedInstance] registerIcon:[base stringByAppendingPathComponent:@"warning_swm.icns"]]; _icnWarnSwm = [[IconCache sharedInstance] registerIcon:[base stringByAppendingPathComponent:@"warning_swm.icns"]];
_icnErrSwm = [[IconCache sharedInstance] registerIcon:[base stringByAppendingPathComponent:@"error_swm.icns"]]; _icnErrSwm = [[IconCache sharedInstance] registerIcon:[base stringByAppendingPathComponent:@"error_swm.icns"]];
NSLog(@"Icon ok identifier: %d from %@", [_icnOk intValue], [base stringByAppendingString:@"ok.icns"]); // NSLog(@"Icon ok identifier: %d from %@", [_icnOk intValue], [base stringByAppendingString:@"ok.icns"]);
} }
- (void)enableFileIcons:(BOOL)enable - (void)enableFileIcons:(BOOL)enable
@@ -111,7 +111,7 @@ static ContentManager* sharedInstance = nil;
}else if( [result isEqualToString:@"NOP"]) { }else if( [result isEqualToString:@"NOP"]) {
// Nothing. // Nothing.
} else { } else {
NSLog(@"Unknown status code %@", result); NSLog(@"SyncState: Unknown status code %@", result);
} }
NSString* normalizedPath = [path decomposedStringWithCanonicalMapping]; NSString* normalizedPath = [path decomposedStringWithCanonicalMapping];
@@ -129,7 +129,7 @@ static ContentManager* sharedInstance = nil;
//NSLog(@"%@ %@", NSStringFromSelector(_cmd), path); //NSLog(@"%@ %@", NSStringFromSelector(_cmd), path);
if (!_fileIconsEnabled) if (!_fileIconsEnabled)
{ {
NSLog(@"Icons are NOT ENABLED!"); NSLog(@"SyncState: Icons are NOT ENABLED!");
// return nil; // return nil;
} }
@@ -284,7 +284,7 @@ static ContentManager* sharedInstance = nil;
} }
else else
{ {
NSLog(@"OwnCloudFinder: refreshing icon badges failed"); NSLog(@"SyncState: refreshing icon badges failed");
return; return;
} }
@@ -333,7 +333,7 @@ static ContentManager* sharedInstance = nil;
} }
else else
{ {
NSLog(@"OwnCloudFinder: refreshing icon badges failed"); NSLog(@"SyncState: refreshing icon badges failed");
return; return;
} }

View File

@@ -44,12 +44,12 @@ static BOOL installed = NO;
{ {
if (installed) if (installed)
{ {
NSLog(@"OwnCloudFinder: already installed"); // NSLog(@"SyncStateFinder: already installed");
return; return;
} }
NSLog(@"OwnCloudFinder: installing ownCloud Shell extension"); // NSLog(@"SyncStateFinder: installing SyncState Shell extension");
[RequestManager sharedInstance]; [RequestManager sharedInstance];
@@ -58,7 +58,7 @@ static BOOL installed = NO;
[self hookMethod:@selector(drawImage:) inClass:@"IKFinderReflectiveIconCell" toCallToTheNewMethod:@selector(OCIconOverlayHandlers_IKFinderReflectiveIconCell_drawImage:)]; // 10.7 & 10.8 & 10.9 (Icon View arrange by everything else) [self hookMethod:@selector(drawImage:) inClass:@"IKFinderReflectiveIconCell" toCallToTheNewMethod:@selector(OCIconOverlayHandlers_IKFinderReflectiveIconCell_drawImage:)]; // 10.7 & 10.8 & 10.9 (Icon View arrange by everything else)
[self hookMethod:@selector(drawIconWithFrame:) inClass:@"TListViewIconAndTextCell" toCallToTheNewMethod:@selector(OCIconOverlayHandlers_drawIconWithFrame:)]; // 10.7 & 10.8 & 10.9 Column View [self hookMethod:@selector(drawIconWithFrame:) inClass:@"TColumnCell" toCallToTheNewMethod:@selector(OCIconOverlayHandlers_drawIconWithFrame:)]; // 10.7 & 10.8 & 10.9 Column View
[self hookMethod:@selector(drawRect:) inClass:@"TDimmableIconImageView" toCallToTheNewMethod:@selector(OCIconOverlayHandlers_drawRect:)]; // 10.9 (List and Coverflow Views) [self hookMethod:@selector(drawRect:) inClass:@"TDimmableIconImageView" toCallToTheNewMethod:@selector(OCIconOverlayHandlers_drawRect:)]; // 10.9 (List and Coverflow Views)
@@ -81,19 +81,19 @@ static BOOL installed = NO;
installed = YES; installed = YES;
NSLog(@"OwnCloudFinder: installed"); // NSLog(@"SyncStateFinder: installed");
} }
+ (void)uninstall + (void)uninstall
{ {
if (!installed) if (!installed)
{ {
NSLog(@"OwnCloudFinder: not installed"); // NSLog(@"SyncStateFinder: not installed");
return; return;
} }
NSLog(@"OwnCloudFinder: uninstalling"); // NSLog(@"SyncStateFinder: uninstalling");
[[ContentManager sharedInstance] dealloc]; [[ContentManager sharedInstance] dealloc];
@@ -119,7 +119,7 @@ static BOOL installed = NO;
installed = NO; installed = NO;
NSLog(@"OwnCloudFinder: uninstalled"); // NSLog(@"SyncStateFinder: uninstalled");
} }
@end @end

View File

@@ -21,7 +21,7 @@
@implementation NSObject (IconOverlayHandlers) @implementation NSObject (IconOverlayHandlers)
- (void)IconOverlayHandlers_drawIconWithFrame:(struct CGRect)arg1 - (void)OCIconOverlayHandlers_drawIconWithFrame:(struct CGRect)arg1
{ {
[self OCIconOverlayHandlers_drawIconWithFrame:arg1]; [self OCIconOverlayHandlers_drawIconWithFrame:arg1];

View File

@@ -138,7 +138,7 @@ static RequestManager* sharedInstance = nil;
ContentManager *contentman = [ContentManager sharedInstance]; ContentManager *contentman = [ContentManager sharedInstance];
if( chunks && [chunks count] > 0 && tag == READ_TAG ) { if( chunks && [chunks count] > 0 && tag == READ_TAG ) {
NSLog(@"READ from socket (%ld): <%@>", tag, answer); // NSLog(@"READ from socket (%ld): <%@>", tag, answer);
if( [[chunks objectAtIndex:0] isEqualToString:@"STATUS"] ) { if( [[chunks objectAtIndex:0] isEqualToString:@"STATUS"] ) {
NSString *path = [chunks objectAtIndex:2]; NSString *path = [chunks objectAtIndex:2];
if( [chunks count] > 3 ) { if( [chunks count] > 3 ) {
@@ -154,7 +154,7 @@ static RequestManager* sharedInstance = nil;
} else if( [[chunks objectAtIndex:0 ] isEqualToString:@"REGISTER_PATH"] ) { } else if( [[chunks objectAtIndex:0 ] isEqualToString:@"REGISTER_PATH"] ) {
NSNumber *one = [NSNumber numberWithInt:1]; NSNumber *one = [NSNumber numberWithInt:1];
NSString *path = [chunks objectAtIndex:1]; NSString *path = [chunks objectAtIndex:1];
NSLog(@"Registering path: %@", path); // NSLog(@"Registering path: %@", path);
[_registeredPathes setObject:one forKey:path]; [_registeredPathes setObject:one forKey:path];
[contentman repaintAllWindows]; [contentman repaintAllWindows];
@@ -168,12 +168,12 @@ static RequestManager* sharedInstance = nil;
[[ContentManager sharedInstance] loadIconResourcePath:path]; [[ContentManager sharedInstance] loadIconResourcePath:path];
} else if( [[chunks objectAtIndex:0 ] isEqualToString:@"SHARE_MENU_TITLE"] ) { } else if( [[chunks objectAtIndex:0 ] isEqualToString:@"SHARE_MENU_TITLE"] ) {
_shareMenuTitle = [[chunks objectAtIndex:1] copy]; _shareMenuTitle = [[chunks objectAtIndex:1] copy];
NSLog(@"Received shar menu title: %@", _shareMenuTitle); // NSLog(@"Received shar menu title: %@", _shareMenuTitle);
} else { } else {
NSLog(@"Unknown command %@", [chunks objectAtIndex:0]); NSLog(@"SyncState: Unknown command %@", [chunks objectAtIndex:0]);
} }
} else if (tag != READ_TAG) { } else if (tag != READ_TAG) {
NSLog(@"Received unknown tag %ld <%@>", tag, answer); NSLog(@"SyncState: Received unknown tag %ld <%@>", tag, answer);
} }
// Read on and on // Read on and on
NSData* stop = [@"\n" dataUsingEncoding:NSUTF8StringEncoding]; NSData* stop = [@"\n" dataUsingEncoding:NSUTF8StringEncoding];
@@ -188,13 +188,13 @@ static RequestManager* sharedInstance = nil;
} }
-(void)socket:(GCDAsyncSocket*)socket didConnectToUrl:(NSURL *)url { -(void)socket:(GCDAsyncSocket*)socket didConnectToUrl:(NSURL *)url {
NSLog( @"Connected to sync client successfully on %@", url); // NSLog( @"Connected to sync client successfully on %@", url);
_isConnected = YES; _isConnected = YES;
[self askOnSocket:@"" query:@"SHARE_MENU_TITLE"]; [self askOnSocket:@"" query:@"SHARE_MENU_TITLE"];
if( [_requestQueue count] > 0 ) { if( [_requestQueue count] > 0 ) {
NSLog( @"We have to empty the queue"); // NSLog( @"We have to empty the queue");
for( NSString *path in _requestQueue ) { for( NSString *path in _requestQueue ) {
[self askOnSocket:path query:@"RETRIEVE_FILE_STATUS"]; [self askOnSocket:path query:@"RETRIEVE_FILE_STATUS"];
} }
@@ -211,7 +211,7 @@ static RequestManager* sharedInstance = nil;
- (void)socketDidDisconnect:(GCDAsyncSocket*)socket withError:(NSError*)err - (void)socketDidDisconnect:(GCDAsyncSocket*)socket withError:(NSError*)err
{ {
NSLog(@"Socket DISconnected! %@", [err localizedDescription]); // NSLog(@"Socket DISconnected! %@", [err localizedDescription]);
_isConnected = NO; _isConnected = NO;
@@ -272,7 +272,7 @@ static RequestManager* sharedInstance = nil;
if (!pnsError && paths && [paths count] > 0) { if (!pnsError && paths && [paths count] > 0) {
NSString *currentLatestPath = nil; NSString *currentLatestPath = nil;
if (paths.count > 1) { if (paths.count > 1) {
NSLog(@"Possible paths: %@", paths); // NSLog(@"Possible paths: %@", paths);
} }
for (int i = 0; i < paths.count; i++) { for (int i = 0; i < paths.count; i++) {
NSString *currentPath = [syncStateHelperDir stringByAppendingPathComponent:[paths objectAtIndex:i]]; NSString *currentPath = [syncStateHelperDir stringByAppendingPathComponent:[paths objectAtIndex:i]];
@@ -288,7 +288,7 @@ static RequestManager* sharedInstance = nil;
} }
} }
if (url) { if (url) {
NSLog(@"Connect Socket to %@", url); // NSLog(@"Connect Socket to %@", url);
[_socket connectToUrl:url withTimeout:1 error:&err]; [_socket connectToUrl:url withTimeout:1 error:&err];
} }
} }
@@ -296,7 +296,7 @@ static RequestManager* sharedInstance = nil;
- (void)menuItemClicked:(NSDictionary*)actionDictionary - (void)menuItemClicked:(NSDictionary*)actionDictionary
{ {
NSLog(@"RequestManager menuItemClicked %@", actionDictionary); // NSLog(@"RequestManager menuItemClicked %@", actionDictionary);
NSArray *filePaths = [actionDictionary valueForKey:@"files"]; NSArray *filePaths = [actionDictionary valueForKey:@"files"];
for (int i = 0; i < filePaths.count; i++) { for (int i = 0; i < filePaths.count; i++) {
[self askOnSocket:[filePaths objectAtIndex:i] query:@"SHARE"]; [self askOnSocket:[filePaths objectAtIndex:i] query:@"SHARE"];

View File

@@ -7,7 +7,7 @@
#define WAIT_FOR_APPLE_EVENT_TO_ENTER_HANDLER_IN_SECONDS 1.0 #define WAIT_FOR_APPLE_EVENT_TO_ENTER_HANDLER_IN_SECONDS 1.0
#define FINDER_MIN_TESTED_VERSION @"10.7" #define FINDER_MIN_TESTED_VERSION @"10.7"
#define FINDER_MAX_TESTED_VERSION @"10.8.5" #define FINDER_MAX_TESTED_VERSION @"10.8.5"
#define LIFERAYNATIVITY_INJECTED_NOTIFICATION @"OwnCloudInjectedNotification" #define LIFERAYNATIVITY_INJECTED_NOTIFICATION @"SyncStateInjectedNotification"
EXPORT OSErr HandleLoadEvent(const AppleEvent* ev, AppleEvent* reply, long refcon); EXPORT OSErr HandleLoadEvent(const AppleEvent* ev, AppleEvent* reply, long refcon);
@@ -78,14 +78,14 @@ static OSErr loadBundle(LNBundleType type, AppleEvent* reply, long refcon) {
minVersion = FINDER_MIN_TESTED_VERSION; minVersion = FINDER_MIN_TESTED_VERSION;
break; break;
default: default:
NSLog(@"Failed to load bundle for type %d", type); NSLog(@"SyncStateInjector: Failed to load bundle for type %d", type);
return 8; return 8;
break; break;
} }
if (isLoaded) { if (isLoaded) {
NSLog(@"OwnCloudInjector: %@ already loaded.", bundleName); // NSLog(@"SyncStateInjector: %@ already loaded.", bundleName);
return noErr; return noErr;
} }
@@ -149,7 +149,7 @@ static OSErr loadBundle(LNBundleType type, AppleEvent* reply, long refcon) {
} }
id principalClassObject = NSClassFromString(NSStringFromClass(principalClass)); id principalClassObject = NSClassFromString(NSStringFromClass(principalClass));
if ([principalClassObject respondsToSelector:@selector(install)]) { if ([principalClassObject respondsToSelector:@selector(install)]) {
NSLog(@"LiferayNativityInjector: Installing %@ ...", bundleName); // NSLog(@"SyncStateInjector: Installing %@ ...", bundleName);
[principalClassObject install]; [principalClassObject install];
} }
@@ -186,7 +186,7 @@ EXPORT OSErr HandleLoadEvent(const AppleEvent* ev, AppleEvent* reply, long refco
NSString* injectorVersion = [injectorBundle objectForInfoDictionaryKey:@"CFBundleVersion"]; NSString* injectorVersion = [injectorBundle objectForInfoDictionaryKey:@"CFBundleVersion"];
if (!injectorVersion || ![injectorVersion isKindOfClass:[NSString class]]) { if (!injectorVersion || ![injectorVersion isKindOfClass:[NSString class]]) {
reportError(reply, [NSString stringWithFormat:@"Unable to determine OwnCloudInjector version!"]); reportError(reply, [NSString stringWithFormat:@"Unable to determine SyncStateInjector version!"]);
return 7; return 7;
} }
@@ -232,7 +232,7 @@ EXPORT OSErr HandleUnloadEvent(const AppleEvent* ev, AppleEvent* reply, long ref
@autoreleasepool { @autoreleasepool {
@try { @try {
if (!liferayNativityLoaded) { if (!liferayNativityLoaded) {
NSLog(@"OwnCloudInjector: not loaded."); // NSLog(@"SyncStateInjector: not loaded.");
return noErr; return noErr;
} }
@@ -253,7 +253,7 @@ EXPORT OSErr HandleUnloadEvent(const AppleEvent* ev, AppleEvent* reply, long ref
} }
id principalClassObject = NSClassFromString(NSStringFromClass(principalClass)); id principalClassObject = NSClassFromString(NSStringFromClass(principalClass));
if ([principalClassObject respondsToSelector:@selector(uninstall)]) { if ([principalClassObject respondsToSelector:@selector(uninstall)]) {
NSLog(@"LiferayNativityInjector: Uninstalling %@ ...", bundleName); // NSLog(@"SyncStateInjector: Uninstalling %@ ...", bundleName);
[principalClassObject uninstall]; [principalClassObject uninstall];
} }

View File

@@ -21,8 +21,10 @@ from gi.repository import GObject, Nautilus
# do not touch the following line. # do not touch the following line.
appname = 'ownCloud' appname = 'ownCloud'
def get_local_path(path): def get_local_path(url):
return path.replace("file://", "") if url[0:7] == 'file://':
url = url[7:]
return urllib.unquote(url)
def get_runtime_dir(): def get_runtime_dir():
"""Returns the value of $XDG_RUNTIME_DIR, a directory path. """Returns the value of $XDG_RUNTIME_DIR, a directory path.
@@ -254,7 +256,7 @@ class SyncStateExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.Info
if item.get_uri_scheme() != 'file': if item.get_uri_scheme() != 'file':
return return
filename = urllib.unquote(item.get_uri()[7:]) filename = get_local_path(item.get_uri())
if item.is_directory(): if item.is_directory():
filename += '/' filename += '/'

View File

@@ -34,28 +34,40 @@ using namespace std;
#define PIPE_TIMEOUT 5*1000 //ms #define PIPE_TIMEOUT 5*1000 //ms
#define SOCK_BUFFER 4096 #define SOCK_BUFFER 4096
std::vector<std::wstring> OCClientInterface::WatchedDirectories() OCClientInterface::ContextMenuInfo OCClientInterface::FetchInfo()
{ {
auto pipename = std::wstring(L"\\\\.\\pipe\\"); auto pipename = std::wstring(L"\\\\.\\pipe\\");
pipename += L"ownCloud"; pipename += L"ownCloud";
CommunicationSocket socket; CommunicationSocket socket;
if (!WaitNamedPipe(pipename.data(), PIPE_TIMEOUT)) { if (!WaitNamedPipe(pipename.data(), PIPE_TIMEOUT)) {
return std::vector<std::wstring>(); return {};
} }
if (!socket.Connect(pipename)) { if (!socket.Connect(pipename)) {
return std::vector<std::wstring>(); return {};
} }
std::vector<std::wstring> watchedDirectories; socket.SendMsg(L"SHARE_MENU_TITLE\n");
ContextMenuInfo info;
std::wstring response; std::wstring response;
Sleep(50); int sleptCount = 0;
while (socket.ReadLine(&response)) { while (sleptCount < 5) {
if (StringUtil::begins_with(response, wstring(L"REGISTER_PATH:"))) { if (socket.ReadLine(&response)) {
wstring responsePath = response.substr(14); // length of REGISTER_PATH if (StringUtil::begins_with(response, wstring(L"REGISTER_PATH:"))) {
watchedDirectories.push_back(responsePath); wstring responsePath = response.substr(14); // length of REGISTER_PATH
info.watchedDirectories.push_back(responsePath);
}
else if (StringUtil::begins_with(response, wstring(L"SHARE_MENU_TITLE:"))) {
info.shareMenuTitle = response.substr(17); // length of SHARE_MENU_TITLE:
break; // Stop once we received the last sent request
}
}
else {
Sleep(50);
++sleptCount;
} }
} }
return watchedDirectories; return info;
} }
void OCClientInterface::ShareObject(const std::wstring &path) void OCClientInterface::ShareObject(const std::wstring &path)

View File

@@ -43,7 +43,11 @@ class CommunicationSocket;
class OCClientInterface class OCClientInterface
{ {
public: public:
static std::vector<std::wstring> WatchedDirectories(); struct ContextMenuInfo {
std::vector<std::wstring> watchedDirectories;
std::wstring shareMenuTitle;
};
static ContextMenuInfo FetchInfo();
static void ShareObject(const std::wstring &path); static void ShareObject(const std::wstring &path);
}; };

View File

@@ -150,8 +150,9 @@ IFACEMETHODIMP OCContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0)); return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0));
} }
OCClientInterface::ContextMenuInfo info = OCClientInterface::FetchInfo();
bool skip = true; bool skip = true;
for (const std::wstring path : OCClientInterface::WatchedDirectories()) { for (const std::wstring path : info.watchedDirectories) {
if (StringUtil::begins_with(std::wstring(m_szSelectedFile), path)) { if (StringUtil::begins_with(std::wstring(m_szSelectedFile), path)) {
skip = false; skip = false;
break; break;
@@ -165,11 +166,12 @@ IFACEMETHODIMP OCContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT
InsertSeperator(hMenu, indexMenu); InsertSeperator(hMenu, indexMenu);
indexMenu++; indexMenu++;
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_BITMAP | 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 = m_pszMenuText; mii.dwTypeData = &info.shareMenuTitle[0];
mii.fState = MFS_ENABLED; mii.fState = MFS_ENABLED;
if (!InsertMenuItem(hMenu, indexMenu, TRUE, &mii)) if (!InsertMenuItem(hMenu, indexMenu, TRUE, &mii))
{ {

View File

@@ -138,6 +138,7 @@
<AdditionalDependencies>OCUtil_x64.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>OCUtil_x64.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>OCContextMenu.def</ModuleDefinitionFile> <ModuleDefinitionFile>OCContextMenu.def</ModuleDefinitionFile>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>

View File

@@ -28,6 +28,7 @@
#include <algorithm> #include <algorithm>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <memory>
using namespace std; using namespace std;
@@ -38,9 +39,24 @@ extern HINSTANCE instanceHandle;
#define IDM_DISPLAY 0 #define IDM_DISPLAY 0
#define IDB_OK 101 #define IDB_OK 101
namespace {
unique_ptr<RemotePathChecker> s_instance;
RemotePathChecker *getGlobalChecker()
{
// On Vista we'll run into issue #2680 if we try to create the thread+pipe connection
// on any DllGetClassObject of our registered classes.
// Work around the issue by creating the static RemotePathChecker only once actually needed.
static once_flag s_onceFlag;
call_once(s_onceFlag, [] { s_instance.reset(new RemotePathChecker); });
return s_instance.get();
}
}
OCOverlay::OCOverlay(int state) OCOverlay::OCOverlay(int state)
: _referenceCount(1) : _referenceCount(1)
, _checker(nullptr)
, _state(state) , _state(state)
{ {
} }
@@ -49,16 +65,6 @@ OCOverlay::~OCOverlay(void)
{ {
} }
void OCOverlay::lazyInit()
{
// On Vista we'll run into issue #2680 if we try to create the thread+pipe connection
// on any DllGetClassObject of our registered classes.
// Work around the issue by creating the static RemotePathChecker only once actually needed.
if (_checker)
return;
static RemotePathChecker s_remotePathChecker;
_checker = &s_remotePathChecker;
}
IFACEMETHODIMP_(ULONG) OCOverlay::AddRef() IFACEMETHODIMP_(ULONG) OCOverlay::AddRef()
{ {
@@ -128,9 +134,8 @@ IFACEMETHODIMP OCOverlay::GetPriority(int *pPriority)
IFACEMETHODIMP OCOverlay::IsMemberOf(PCWSTR pwszPath, DWORD dwAttrib) IFACEMETHODIMP OCOverlay::IsMemberOf(PCWSTR pwszPath, DWORD dwAttrib)
{ {
lazyInit(); RemotePathChecker* checker = getGlobalChecker();
assert(_checker); auto watchedDirectories = checker->WatchedDirectories();
auto watchedDirectories = _checker->WatchedDirectories();
wstring wpath(pwszPath); wstring wpath(pwszPath);
wpath.append(L"\\"); wpath.append(L"\\");
@@ -147,7 +152,7 @@ IFACEMETHODIMP OCOverlay::GetPriority(int *pPriority)
} }
int state = 0; int state = 0;
if (!_checker->IsMonitoredPath(pwszPath, &state)) { if (!checker->IsMonitoredPath(pwszPath, &state)) {
return MAKE_HRESULT(S_FALSE, 0, 0); return MAKE_HRESULT(S_FALSE, 0, 0);
} }
return MAKE_HRESULT(state == _state ? S_OK : S_FALSE, 0, 0); return MAKE_HRESULT(state == _state ? S_OK : S_FALSE, 0, 0);

View File

@@ -17,8 +17,6 @@
#pragma once #pragma once
class RemotePathChecker;
class OCOverlay : public IShellIconOverlayIdentifier class OCOverlay : public IShellIconOverlayIdentifier
{ {
@@ -36,12 +34,8 @@ protected:
~OCOverlay(); ~OCOverlay();
private: private:
//bool _GenerateMessage(const wchar_t*, std::wstring*);
void lazyInit();
bool _IsOverlaysEnabled(); bool _IsOverlaysEnabled();
long _referenceCount; long _referenceCount;
RemotePathChecker* _checker;
int _state; int _state;
}; };

View File

@@ -156,7 +156,7 @@ void AccountSettings::slotFolderActivated( const QModelIndex& indx )
} else { } else {
ui->_buttonAdd->setVisible(true); ui->_buttonAdd->setVisible(true);
} }
bool isConnected = _accountState && _accountState->state() == AccountState::Connected; bool isConnected = _accountState && _accountState->isConnected();
ui->_buttonAdd->setEnabled(isConnected); ui->_buttonAdd->setEnabled(isConnected);
ui->_buttonEnable->setEnabled( isValid ); ui->_buttonEnable->setEnabled( isValid );
ui->_buttonSelectiveSync->setEnabled(isConnected && isValid); ui->_buttonSelectiveSync->setEnabled(isConnected && isValid);
@@ -168,7 +168,7 @@ void AccountSettings::slotFolderActivated( const QModelIndex& indx )
} else { } else {
ui->_buttonEnable->setText( tr( "Resume" ) ); ui->_buttonEnable->setText( tr( "Resume" ) );
} }
ui->_buttonEnable->setEnabled( _accountState && _accountState->state() == AccountState::Connected); ui->_buttonEnable->setEnabled(isConnected);
} }
} }
@@ -234,11 +234,7 @@ void AccountSettings::slotAddFolder( Folder *folder )
if( ! folder || folder->alias().isEmpty() ) return; if( ! folder || folder->alias().isEmpty() ) return;
QStandardItem *item = new QStandardItem(); QStandardItem *item = new QStandardItem();
bool isConnected = false; folderToModelItem( item, folder, _accountState && _accountState->isConnectedOrMaintenance());
if (_accountState) {
isConnected = (_accountState->state() == AccountState::Connected);
}
folderToModelItem( item, folder, isConnected);
_model->appendRow( item ); _model->appendRow( item );
// in order to update the enabled state of the "Sync now" button // in order to update the enabled state of the "Sync now" button
connect(folder, SIGNAL(syncStateChange()), this, SLOT(slotFolderSyncStateChange()), Qt::UniqueConnection); connect(folder, SIGNAL(syncStateChange()), this, SLOT(slotFolderSyncStateChange()), Qt::UniqueConnection);
@@ -541,7 +537,7 @@ void AccountSettings::slotUpdateFolderState( Folder *folder )
} }
if( item ) { if( item ) {
folderToModelItem( item, folder, _accountState->state() == AccountState::Connected ); folderToModelItem( item, folder, _accountState->isConnectedOrMaintenance() );
} else { } else {
// the dialog is not visible. // the dialog is not visible.
} }
@@ -798,7 +794,7 @@ void AccountSettings::slotAccountStateChanged(int state)
foreach (Folder *folder, folderMan->map().values()) { foreach (Folder *folder, folderMan->map().values()) {
slotUpdateFolderState(folder); slotUpdateFolderState(folder);
} }
if (state == AccountState::Connected) { if (state == AccountState::Connected || state == AccountState::ServerMaintenance) {
QString user; QString user;
if (AbstractCredentials *cred = account->credentials()) { if (AbstractCredentials *cred = account->credentials()) {
user = cred->user(); user = cred->user();

View File

@@ -125,6 +125,8 @@ QString AccountState::stateString(State state)
return QLatin1String("Disconnected"); return QLatin1String("Disconnected");
case Connected: case Connected:
return QLatin1String("Connected"); return QLatin1String("Connected");
case ServerMaintenance:
return QLatin1String("ServerMaintenance");
case NetworkError: case NetworkError:
return QLatin1String("NetworkError"); return QLatin1String("NetworkError");
case ConfigurationError: case ConfigurationError:
@@ -152,6 +154,11 @@ bool AccountState::isConnected() const
return _state == Connected; return _state == Connected;
} }
bool AccountState::isConnectedOrMaintenance() const
{
return isConnected() || _state == ServerMaintenance;
}
QuotaInfo *AccountState::quotaInfo() QuotaInfo *AccountState::quotaInfo()
{ {
return _quotaInfo; return _quotaInfo;
@@ -214,6 +221,9 @@ void AccountState::slotConnectionValidatorResult(ConnectionValidator::Status sta
case ConnectionValidator::UserCanceledCredentials: case ConnectionValidator::UserCanceledCredentials:
setState(SignedOut); setState(SignedOut);
break; break;
case ConnectionValidator::ServerMaintenance:
setState(ServerMaintenance);
break;
case ConnectionValidator::Timeout: case ConnectionValidator::Timeout:
setState(NetworkError); setState(NetworkError);
break; break;

View File

@@ -67,6 +67,10 @@ public:
/// The account is successfully talking to the server. /// The account is successfully talking to the server.
Connected, Connected,
/// The account is talking to the server, but the server is in
/// maintenance mode.
ServerMaintenance,
/// Could not communicate with the server for some reason. /// Could not communicate with the server for some reason.
/// We assume this may resolve itself over time and will try /// We assume this may resolve itself over time and will try
/// again automatically. /// again automatically.
@@ -96,6 +100,7 @@ public:
void setSignedOut(bool signedOut); void setSignedOut(bool signedOut);
bool isConnected() const; bool isConnected() const;
bool isConnectedOrMaintenance() const;
QuotaInfo *quotaInfo(); QuotaInfo *quotaInfo();

View File

@@ -1,3 +1,17 @@
/*
* Copyright (C) 2015 by nocteau
* Copyright (C) 2015 by Daniel Molkentin <danimo@owncloud.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 "ui_addcertificatedialog.h" #include "ui_addcertificatedialog.h"
#include "addcertificatedialog.h" #include "addcertificatedialog.h"
#include <QFileDialog> #include <QFileDialog>

View File

@@ -1,3 +1,17 @@
/*
* Copyright (C) 2015 by nocteau
* Copyright (C) 2015 by Daniel Molkentin <danimo@owncloud.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 ADDCERTIFICATEDIALOG_H #ifndef ADDCERTIFICATEDIALOG_H
#define ADDCERTIFICATEDIALOG_H #define ADDCERTIFICATEDIALOG_H

View File

@@ -111,7 +111,7 @@ Application::Application(int &argc, char **argv) :
_folderManager.reset(new FolderMan); _folderManager.reset(new FolderMan);
connect( this, SIGNAL(messageReceived(QString, QObject*)), SLOT(slotParseOptions(QString, QObject*))); connect(this, SIGNAL(messageReceived(QString, QObject*)), SLOT(slotParseMessage(QString, QObject*)));
// Create the account info manager to ensure it's listening to the // Create the account info manager to ensure it's listening to the
// account manager. // account manager.
@@ -224,7 +224,7 @@ void Application::slotCleanup()
if (account) { if (account) {
account->save(); account->save();
} }
FolderMan::instance()->unloadAllFolders(); FolderMan::instance()->unloadAndDeleteAllFolders();
_gui->slotShutdown(); _gui->slotShutdown();
_gui->deleteLater(); _gui->deleteLater();
@@ -260,6 +260,7 @@ void Application::slotAccountStateChanged(int state)
folderMan->setSyncEnabled(true); folderMan->setSyncEnabled(true);
folderMan->slotScheduleAllFolders(); folderMan->slotScheduleAllFolders();
break; break;
case AccountState::ServerMaintenance:
case AccountState::SignedOut: case AccountState::SignedOut:
case AccountState::ConfigurationError: case AccountState::ConfigurationError:
case AccountState::NetworkError: case AccountState::NetworkError:
@@ -343,15 +344,16 @@ void Application::slotUseMonoIconsChanged(bool)
_gui->slotComputeOverallSyncStatus(); _gui->slotComputeOverallSyncStatus();
} }
void Application::slotParseOptions(const QString &opts, QObject*) void Application::slotParseMessage(const QString &msg, QObject*)
{ {
QStringList options = opts.split(QLatin1Char('|')); if (msg.startsWith(QLatin1String("MSG_PARSEOPTIONS:"))) {
parseOptions(options); const int lengthOfMsgPrefix = 17;
setupLogging(); QStringList options = msg.mid(lengthOfMsgPrefix).split(QLatin1Char('|'));
parseOptions(options);
//This function is calld happens when someone tries to run another instance of ownCloud setupLogging();
// show the settings dialog } else if (msg.startsWith(QLatin1String("MSG_SHOWSETTINGS"))) {
showSettingsDialog(); showSettingsDialog();
}
} }
void Application::parseOptions(const QStringList &options) void Application::parseOptions(const QStringList &options)

View File

@@ -73,7 +73,7 @@ signals:
void folderStateChanged(Folder*); void folderStateChanged(Folder*);
protected slots: protected slots:
void slotParseOptions( const QString&, QObject* ); void slotParseMessage(const QString&, QObject*);
void slotCheckConnection(); void slotCheckConnection();
void slotUpdateConnectionErrors(int accountState); void slotUpdateConnectionErrors(int accountState);
void slotStartUpdateDetector(); void slotStartUpdateDetector();

View File

@@ -29,6 +29,7 @@
#include "syncengine.h" #include "syncengine.h"
#include "syncrunfilelog.h" #include "syncrunfilelog.h"
#include "theme.h" #include "theme.h"
#include "filesystem.h"
#include "creds/abstractcredentials.h" #include "creds/abstractcredentials.h"
@@ -145,12 +146,12 @@ AccountState* Folder::accountState() const
void Folder::checkLocalPath() void Folder::checkLocalPath()
{ {
QFileInfo fi(_path); const QFileInfo fi(_path);
if( fi.isDir() && fi.isReadable() ) { if( fi.isDir() && fi.isReadable() ) {
qDebug() << "Checked local path ok"; qDebug() << "Checked local path ok";
} else { } else {
if( !fi.exists() ) { if( !FileSystem::fileExists(_path) ) {
// try to create the local dir // try to create the local dir
QDir d(_path); QDir d(_path);
if( d.mkpath(_path) ) { if( d.mkpath(_path) ) {
@@ -158,7 +159,7 @@ void Folder::checkLocalPath()
} }
} }
// Check directory again // Check directory again
if( !fi.exists() ) { if( !FileSystem::fileExists(_path) ) {
_syncResult.setErrorString(tr("Local folder %1 does not exist.").arg(_path)); _syncResult.setErrorString(tr("Local folder %1 does not exist.").arg(_path));
_syncResult.setStatus( SyncResult::SetupError ); _syncResult.setStatus( SyncResult::SetupError );
} else if( !fi.isDir() ) { } else if( !fi.isDir() ) {
@@ -590,7 +591,7 @@ void Folder::slotThreadTreeWalkResult(const SyncFileItemVector& items)
_syncResult.setSyncFileItemVector(items); _syncResult.setSyncFileItemVector(items);
} }
void Folder::slotAboutToPropagate(const SyncFileItemVector& items) void Folder::slotAboutToPropagate(SyncFileItemVector& items)
{ {
// empty the tainted list since the status generation code will use the _syncedItems // empty the tainted list since the status generation code will use the _syncedItems
// (which imply the folder) to generate the syncing state icon now. // (which imply the folder) to generate the syncing state icon now.
@@ -791,8 +792,8 @@ void Folder::startSync(const QStringList &pathList)
connect(_engine.data(), SIGNAL(rootEtag(QString)), this, SLOT(etagRetreivedFromSyncEngine(QString))); connect(_engine.data(), SIGNAL(rootEtag(QString)), this, SLOT(etagRetreivedFromSyncEngine(QString)));
connect( _engine.data(), SIGNAL(treeWalkResult(const SyncFileItemVector&)), connect( _engine.data(), SIGNAL(treeWalkResult(const SyncFileItemVector&)),
this, SLOT(slotThreadTreeWalkResult(const SyncFileItemVector&)), Qt::QueuedConnection); this, SLOT(slotThreadTreeWalkResult(const SyncFileItemVector&)), Qt::QueuedConnection);
connect( _engine.data(), SIGNAL(aboutToPropagate(const SyncFileItemVector&)), connect( _engine.data(), SIGNAL(aboutToPropagate(SyncFileItemVector&)),
this, SLOT(slotAboutToPropagate(const SyncFileItemVector&)), Qt::QueuedConnection); this, SLOT(slotAboutToPropagate(SyncFileItemVector&)));
connect(_engine.data(), SIGNAL(started()), SLOT(slotSyncStarted()), Qt::QueuedConnection); connect(_engine.data(), SIGNAL(started()), SLOT(slotSyncStarted()), Qt::QueuedConnection);
connect(_engine.data(), SIGNAL(finished()), SLOT(slotSyncFinished()), Qt::QueuedConnection); connect(_engine.data(), SIGNAL(finished()), SLOT(slotSyncFinished()), Qt::QueuedConnection);

View File

@@ -189,7 +189,7 @@ private slots:
void etagRetreived(const QString &); void etagRetreived(const QString &);
void etagRetreivedFromSyncEngine(const QString &); void etagRetreivedFromSyncEngine(const QString &);
void slotAboutToPropagate(const SyncFileItemVector& ); void slotAboutToPropagate(SyncFileItemVector& );
void slotThreadTreeWalkResult(const SyncFileItemVector& ); // after sync is done void slotThreadTreeWalkResult(const SyncFileItemVector& ); // after sync is done
void slotEmitFinishedDelayed(); void slotEmitFinishedDelayed();

View File

@@ -43,8 +43,9 @@ FolderMan* FolderMan::_instance = 0;
* The minimum time between a sync being requested and it * The minimum time between a sync being requested and it
* being executed in milliseconds. * being executed in milliseconds.
* *
* This delay must be larger than the minFileAgeForUpload in * This delay must be large enough to ensure fileIsStillChanging()
* the propagator. * in the upload propagator doesn't decide to skip the file because
* the modification was too recent.
*/ */
static qint64 msBetweenRequestAndSync = 2000; static qint64 msBetweenRequestAndSync = 2000;
@@ -93,27 +94,25 @@ OCC::Folder::Map FolderMan::map()
return _folderMap; return _folderMap;
} }
// Attention: this function deletes the folder object to which
// the alias refers. Do NOT USE the folder pointer any more after
// having this called.
void FolderMan::unloadFolder( const QString& alias ) void FolderMan::unloadFolder( const QString& alias )
{ {
Folder *f = folder(alias); Folder* f = folder(alias);
if( f ) { if( !f ) {
if( _socketApi ) { return;
_socketApi->slotUnregisterPath(alias);
}
_folderChangeSignalMapper->removeMappings(f);
if( _folderWatchers.contains(alias)) {
_folderWatchers.remove(alias);
}
_folderMap.remove( alias );
delete f;
} }
if( _socketApi ) {
_socketApi->slotUnregisterPath(alias);
}
_folderChangeSignalMapper->removeMappings(f);
if( _folderWatchers.contains(alias)) {
_folderWatchers.remove(alias);
}
_folderMap.remove( alias );
} }
int FolderMan::unloadAllFolders() int FolderMan::unloadAndDeleteAllFolders()
{ {
int cnt = 0; int cnt = 0;
@@ -121,7 +120,9 @@ int FolderMan::unloadAllFolders()
Folder::MapIterator i(_folderMap); Folder::MapIterator i(_folderMap);
while (i.hasNext()) { while (i.hasNext()) {
i.next(); i.next();
Folder* f = i.value();
unloadFolder(i.key()); unloadFolder(i.key());
delete f;
cnt++; cnt++;
} }
_lastSyncFolder.clear(); _lastSyncFolder.clear();
@@ -187,7 +188,7 @@ int FolderMan::setupFolders()
{ {
qDebug() << "* Setup folders from " << _folderConfigPath; qDebug() << "* Setup folders from " << _folderConfigPath;
unloadAllFolders(); unloadAndDeleteAllFolders();
ConfigFile cfg; ConfigFile cfg;
QDir storageDir(cfg.configPath()); QDir storageDir(cfg.configPath());
@@ -760,48 +761,37 @@ void FolderMan::removeAllFolderDefinitions()
void FolderMan::slotRemoveFolder( const QString& alias ) void FolderMan::slotRemoveFolder( const QString& alias )
{ {
if( alias.isEmpty() ) return; Folder *f = folder(alias);
if( !f ) {
qDebug() << "!! Can not remove " << alias << ", not in folderMap.";
return;
}
if( _currentSyncFolder == alias ) { qDebug() << "Removing " << alias;
// terminate if the sync is currently underway.
const bool currentlyRunning = (_currentSyncFolder == alias);
if( currentlyRunning ) {
// let the folder delete itself when done and
// abort the sync now
connect(f, SIGNAL(syncFinished(SyncResult)), f, SLOT(deleteLater()));
terminateSyncProcess(); terminateSyncProcess();
} }
removeFolder(alias);
}
// remove a folder from the map. Should be sure n
void FolderMan::removeFolder( const QString& alias )
{
Folder *f = 0;
_scheduleQueue.removeAll(alias); _scheduleQueue.removeAll(alias);
if( _folderMap.contains( alias )) { f->wipe();
qDebug() << "Removing " << alias; f->setSyncPaused(true);
f = _folderMap[alias]; // do not remove from the map, that is done in unloadFolder.
} else { // remove the folder configuration
qDebug() << "!! Can not remove " << alias << ", not in folderMap."; QFile file(f->configFile() );
if( file.exists() ) {
qDebug() << "Remove folder config file " << file.fileName();
file.remove();
} }
if( f ) { unloadFolder( alias );
f->wipe(); if( !currentlyRunning ) {
delete f;
// can be removed if we are able to delete the folder object.
f->setSyncPaused(true);
// remove the folder configuration
QFile file(f->configFile() );
if( file.exists() ) {
qDebug() << "Remove folder config file " << file.fileName();
file.remove();
}
unloadFolder( alias ); // now the folder object is gone.
// FIXME: this is a temporar dirty fix against a crash happening because
// the csync owncloud module still has static components. Activate the
// delete once the module is fixed.
// f->deleteLater();
} }
} }

View File

@@ -121,10 +121,8 @@ public slots:
*/ */
void terminateSyncProcess(); void terminateSyncProcess();
/* unload and delete on folder object */
void unloadFolder( const QString& alias );
/* delete all folder objects */ /* delete all folder objects */
int unloadAllFolders(); int unloadAndDeleteAllFolders();
// if enabled is set to false, no new folders will start to sync. // if enabled is set to false, no new folders will start to sync.
// the current one will finish. // the current one will finish.
@@ -150,6 +148,9 @@ private slots:
void slotRemoveFoldersForAccount(AccountState* accountState); void slotRemoveFoldersForAccount(AccountState* accountState);
private: private:
/* unloads a folder object, does not delete it */
void unloadFolder( const QString& alias );
/** Will start a sync after a bit of delay. */ /** Will start a sync after a bit of delay. */
void startScheduledSyncSoon(qint64 msMinimumDelay = 0); void startScheduledSyncSoon(qint64 msMinimumDelay = 0);
@@ -160,8 +161,6 @@ private:
QString unescapeAlias( const QString& ) const; QString unescapeAlias( const QString& ) const;
void removeFolder( const QString& );
QSet<Folder*> _disabledFolders; QSet<Folder*> _disabledFolders;
Folder::Map _folderMap; Folder::Map _folderMap;
QString _folderConfigPath; QString _folderConfigPath;

View File

@@ -42,9 +42,9 @@ QString FormatWarningsWizardPage::formatWarnings(const QStringList &warnings) co
{ {
QString ret; QString ret;
if (warnings.count() == 1) { if (warnings.count() == 1) {
ret = tr("<b>Warning:</b> ") + warnings.first(); ret = tr("<b>Warning:</b> %1").arg(warnings.first());
} else if (warnings.count() > 1) { } else if (warnings.count() > 1) {
ret = tr("<b>Warning:</b> ") + "<ul>"; ret = tr("<b>Warning:</b>") + " <ul>";
Q_FOREACH(QString warning, warnings) { Q_FOREACH(QString warning, warnings) {
ret += QString::fromLatin1("<li>%1</li>").arg(warning); ret += QString::fromLatin1("<li>%1</li>").arg(warning);
} }
@@ -357,6 +357,7 @@ void FolderWizardRemotePath::slotUpdateDirectories(const QStringList &list)
void FolderWizardRemotePath::slotRefreshFolders() void FolderWizardRemotePath::slotRefreshFolders()
{ {
LsColJob *job = new LsColJob(_account, "/", this); LsColJob *job = new LsColJob(_account, "/", this);
job->setProperties(QList<QByteArray>() << "resourcetype");
connect(job, SIGNAL(directoryListingSubfolders(QStringList)), connect(job, SIGNAL(directoryListingSubfolders(QStringList)),
SLOT(slotUpdateDirectories(QStringList))); SLOT(slotUpdateDirectories(QStringList)));
job->start(); job->start();
@@ -367,6 +368,7 @@ void FolderWizardRemotePath::slotItemExpanded(QTreeWidgetItem *item)
{ {
QString dir = item->data(0, Qt::UserRole).toString(); QString dir = item->data(0, Qt::UserRole).toString();
LsColJob *job = new LsColJob(_account, dir, this); LsColJob *job = new LsColJob(_account, dir, this);
job->setProperties(QList<QByteArray>() << "resourcetype");
connect(job, SIGNAL(directoryListingSubfolders(QStringList)), connect(job, SIGNAL(directoryListingSubfolders(QStringList)),
SLOT(slotUpdateDirectories(QStringList))); SLOT(slotUpdateDirectories(QStringList)));
job->start(); job->start();

View File

@@ -68,7 +68,7 @@ LogBrowser::LogBrowser(QWidget *parent) :
mainLayout->addLayout( toolLayout ); mainLayout->addLayout( toolLayout );
// Search input field // Search input field
QLabel *lab = new QLabel(tr("&Search: ")); QLabel *lab = new QLabel(tr("&Search:") + " ");
_findTermEdit = new QLineEdit; _findTermEdit = new QLineEdit;
lab->setBuddy( _findTermEdit ); lab->setBuddy( _findTermEdit );
toolLayout->addWidget(lab); toolLayout->addWidget(lab);
@@ -191,7 +191,7 @@ void LogBrowser::slotSave()
stream << _logWidget->toPlainText(); stream << _logWidget->toPlainText();
file.close(); file.close();
} else { } else {
QMessageBox::critical(this, tr("Error"), tr("Could not write to log file ")+ saveFile); QMessageBox::critical(this, tr("Error"), tr("Could not write to log file %1").arg(saveFile));
} }
} }
_saveBtn->setEnabled(true); _saveBtn->setEnabled(true);

View File

@@ -96,14 +96,16 @@ int main(int argc, char **argv)
} }
// if the application is already running, notify it. // if the application is already running, notify it.
if( app.isRunning() ) { if(app.isRunning()) {
qDebug() << Q_FUNC_INFO << "Already running, exiting..."; qDebug() << Q_FUNC_INFO << "Already running, exiting...";
QStringList args = app.arguments(); QStringList args = app.arguments();
if ( args.size() > 1 && ! app.giveHelp() ) { if (args.size() > 1) {
QString msg = args.join( QLatin1String("|") ); QString msg = args.join(QLatin1String("|"));
if( ! app.sendMessage( msg ) ) if(!app.sendMessage(QLatin1String("MSG_PARSEOPTIONS:") + msg))
return -1; return -1;
} }
if(!app.sendMessage(QLatin1String("MSG_SHOWSETTINGS")))
return -1;
return 0; return 0;
} else { } else {
if (!QSystemTrayIcon::isSystemTrayAvailable()) { if (!QSystemTrayIcon::isSystemTrayAvailable()) {

View File

@@ -221,7 +221,7 @@ void ownCloudGui::slotComputeOverallSyncStatus()
_tray->setToolTip(tr("Please sign in")); _tray->setToolTip(tr("Please sign in"));
return; return;
} }
if (!a->isConnected()) { if (!a->isConnectedOrMaintenance()) {
_tray->setIcon(Theme::instance()->folderOfflineIcon(true)); _tray->setIcon(Theme::instance()->folderOfflineIcon(true));
_tray->setToolTip(tr("Disconnected from server")); _tray->setToolTip(tr("Disconnected from server"));
return; return;
@@ -432,7 +432,7 @@ void ownCloudGui::setupActions()
connect(_actionLogout, SIGNAL(triggered()), _app, SLOT(slotLogout())); connect(_actionLogout, SIGNAL(triggered()), _app, SLOT(slotLogout()));
if(_app->debugMode()) { if(_app->debugMode()) {
_actionCrash = new QAction(tr("Crash now"), this); _actionCrash = new QAction(tr("Crash now", "Only shows in debug mode to allow testing the crash handler"), this);
connect(_actionCrash, SIGNAL(triggered()), _app, SLOT(slotCrash())); connect(_actionCrash, SIGNAL(triggered()), _app, SLOT(slotCrash()));
} else { } else {
_actionCrash = 0; _actionCrash = 0;
@@ -654,7 +654,7 @@ void ownCloudGui::slotShowShareDialog(const QString &sharePath, const QString &l
ShareDialog *w = new ShareDialog(account, sharePath, localPath); ShareDialog *w = new ShareDialog(account, sharePath, localPath);
w->getShares(); w->getShares();
w->setAttribute( Qt::WA_DeleteOnClose, true ); w->setAttribute( Qt::WA_DeleteOnClose, true );
w->show(); raiseDialog(w);
} }

View File

@@ -211,9 +211,11 @@ void OwncloudSetupWizard::testOwnCloudConnect()
{ {
AccountPtr account = _ocWizard->account(); AccountPtr account = _ocWizard->account();
ValidateDavAuthJob *job = new ValidateDavAuthJob(account, this); auto *job = new PropfindJob(account, "/", this);
job->setIgnoreCredentialFailure(true); job->setIgnoreCredentialFailure(true);
connect(job, SIGNAL(authResult(QNetworkReply*)), SLOT(slotConnectionCheck(QNetworkReply*))); job->setProperties(QList<QByteArray>() << "getlastmodified");
connect(job, SIGNAL(result(QVariantMap)), _ocWizard, SLOT(successfulStep()));
connect(job, SIGNAL(networkError(QNetworkReply*)), this, SLOT(slotConnectionCheck(QNetworkReply*)));
job->start(); job->start();
} }
@@ -249,7 +251,7 @@ void OwncloudSetupWizard::slotConnectionCheck(QNetworkReply* reply)
_ocWizard->successfulStep(); _ocWizard->successfulStep();
break; break;
default: default:
if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 403) { if (!_ocWizard->account()->credentials()->stillValid(reply)) {
msg = tr("Access forbidden by server. To verify that you have proper access, " msg = tr("Access forbidden by server. To verify that you have proper access, "
"<a href=\"%1\">click here</a> to access the service with your browser.") "<a href=\"%1\">click here</a> to access the service with your browser.")
.arg(_ocWizard->account()->url().toString()); .arg(_ocWizard->account()->url().toString());
@@ -274,7 +276,7 @@ void OwncloudSetupWizard::slotCreateLocalAndRemoteFolders(const QString& localFo
// ownCloud is newly created. // ownCloud is newly created.
_ocWizard->appendToConfigurationLog( tr("Local sync folder %1 already exists, setting it up for sync.<br/><br/>").arg(localFolder)); _ocWizard->appendToConfigurationLog( tr("Local sync folder %1 already exists, setting it up for sync.<br/><br/>").arg(localFolder));
} else { } else {
QString res = tr("Creating local sync folder %1... ").arg(localFolder); QString res = tr("Creating local sync folder %1...").arg(localFolder);
if( fi.mkpath( localFolder ) ) { if( fi.mkpath( localFolder ) ) {
Utility::setupFavLink( localFolder ); Utility::setupFavLink( localFolder );
// FIXME: Create a local sync folder. // FIXME: Create a local sync folder.
@@ -534,24 +536,4 @@ bool DetermineAuthTypeJob::finished()
return true; return true;
} }
ValidateDavAuthJob::ValidateDavAuthJob(AccountPtr account, QObject *parent)
: AbstractNetworkJob(account, QString(), parent)
{
}
void ValidateDavAuthJob::start()
{
QString p = account()->davPath();
QNetworkReply *reply = getRequest(p);
setReply(reply);
setupConnections(reply);
AbstractNetworkJob::start();
}
bool ValidateDavAuthJob::finished()
{
emit authResult(reply());
return true;
}
} // namespace OCC } // namespace OCC

View File

@@ -31,17 +31,6 @@ namespace OCC {
class OwncloudWizard; class OwncloudWizard;
class ValidateDavAuthJob : public AbstractNetworkJob {
Q_OBJECT
public:
ValidateDavAuthJob(AccountPtr account, QObject *parent = 0);
void start() Q_DECL_OVERRIDE;
signals:
void authResult(QNetworkReply*);
private slots:
bool finished() Q_DECL_OVERRIDE;
};
class DetermineAuthTypeJob : public AbstractNetworkJob { class DetermineAuthTypeJob : public AbstractNetworkJob {
Q_OBJECT Q_OBJECT
public: public:

View File

@@ -161,17 +161,13 @@ QString ProtocolWidget::timeString(QDateTime dt, QLocale::FormatType format) con
{ {
QLocale loc = QLocale::system(); QLocale loc = QLocale::system();
QString timeStr; QString timeStr;
QDate today = QDate::currentDate();
if( format == QLocale::NarrowFormat ) { if( format == QLocale::NarrowFormat ) {
if( dt.date().day() == today.day() ) { timeStr = loc.toString(dt, QLocale::NarrowFormat);
timeStr = loc.toString(dt.time(), QLocale::NarrowFormat);
} else {
timeStr = loc.toString(dt, QLocale::NarrowFormat);
}
} else { } else {
timeStr = loc.toString(dt, format); timeStr = loc.toString(dt, format);
} }
return timeStr; return timeStr;
} }

View File

@@ -26,7 +26,7 @@
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="rootIsDecorated"> <property name="rootIsDecorated">
<bool>true</bool> <bool>false</bool>
</property> </property>
<property name="uniformRowHeights"> <property name="uniformRowHeights">
<bool>true</bool> <bool>true</bool>
@@ -46,12 +46,12 @@
</column> </column>
<column> <column>
<property name="text"> <property name="text">
<string>3</string> <string notr="true">3</string>
</property> </property>
</column> </column>
<column> <column>
<property name="text"> <property name="text">
<string>4</string> <string notr="true">4</string>
</property> </property>
</column> </column>
</widget> </widget>

View File

@@ -56,6 +56,7 @@ QSize SelectiveSyncTreeView::sizeHint() const
void SelectiveSyncTreeView::refreshFolders() void SelectiveSyncTreeView::refreshFolders()
{ {
LsColJob *job = new LsColJob(_account, _folderPath, this); LsColJob *job = new LsColJob(_account, _folderPath, this);
job->setProperties(QList<QByteArray>() << "resourcetype" << "quota-used-bytes");
connect(job, SIGNAL(directoryListingSubfolders(QStringList)), connect(job, SIGNAL(directoryListingSubfolders(QStringList)),
this, SLOT(slotUpdateDirectories(QStringList))); this, SLOT(slotUpdateDirectories(QStringList)));
connect(job, SIGNAL(finishedWithError(QNetworkReply*)), connect(job, SIGNAL(finishedWithError(QNetworkReply*)),

View File

@@ -69,7 +69,7 @@ SettingsDialog::SettingsDialog(ownCloudGui *gui, QWidget *parent) :
setWindowTitle(Theme::instance()->appNameGUI()); setWindowTitle(Theme::instance()->appNameGUI());
QIcon accountIcon(QLatin1String(":/client/resources/accounts.png")); QIcon accountIcon(QLatin1String(":/client/resources/account.png"));
QAction *accountAction = toolBar->addAction(accountIcon, tr("Account")); QAction *accountAction = toolBar->addAction(accountIcon, tr("Account"));
accountAction->setCheckable(true); accountAction->setCheckable(true);
_ui->stack->addWidget(_accountSettings); _ui->stack->addWidget(_accountSettings);

View File

@@ -1,3 +1,17 @@
/*
* Copyright (C) 2015 by Roeland Douma
* Copyright (C) 2015 by Klaas Freitag <freitag@owncloud.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 "sharedialog.h" #include "sharedialog.h"
#include "ui_sharedialog.h" #include "ui_sharedialog.h"
#include "networkjobs.h" #include "networkjobs.h"
@@ -25,6 +39,7 @@ ShareDialog::ShareDialog(AccountPtr account, const QString &sharePath, const QSt
_account(account), _account(account),
_sharePath(sharePath), _sharePath(sharePath),
_localPath(localPath), _localPath(localPath),
_passwordJobRunning(false),
_public_share_id(0) _public_share_id(0)
{ {
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
@@ -33,6 +48,11 @@ ShareDialog::ShareDialog(AccountPtr account, const QString &sharePath, const QSt
_ui->pushButton_copy->setText(tr("Copy Link")); _ui->pushButton_copy->setText(tr("Copy Link"));
connect(_ui->pushButton_copy, SIGNAL(clicked(bool)), SLOT(slotPushButtonCopyLinkPressed())); connect(_ui->pushButton_copy, SIGNAL(clicked(bool)), SLOT(slotPushButtonCopyLinkPressed()));
QPushButton *closeButton = _ui->buttonBox->button(QDialogButtonBox::Close);
if( closeButton ) {
connect( closeButton, SIGNAL(clicked()), this, SLOT(close()) );
}
// the following progress indicator widgets are added to layouts which makes them // the following progress indicator widgets are added to layouts which makes them
// automatically deleted once the dialog dies. // automatically deleted once the dialog dies.
_pi_link = new QProgressIndicator(); _pi_link = new QProgressIndicator();
@@ -51,6 +71,7 @@ ShareDialog::ShareDialog(AccountPtr account, const QString &sharePath, const QSt
_ui->widget_shareLink->hide(); _ui->widget_shareLink->hide();
_ui->lineEdit_password->hide(); _ui->lineEdit_password->hide();
_ui->pushButton_setPassword->hide();
_ui->calendar->hide(); _ui->calendar->hide();
QFileInfo f_info(_localPath); QFileInfo f_info(_localPath);
@@ -60,11 +81,18 @@ ShareDialog::ShareDialog(AccountPtr account, const QString &sharePath, const QSt
QString name; QString name;
if( f_info.isDir() ) { if( f_info.isDir() ) {
name = tr("Share directory %2").arg(_localPath); name = tr("Share Directory");
} else { } else {
name = tr("Share file %1").arg(_localPath); name = tr("Share File");
} }
_ui->label_name->setText(name); _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)); _ui->label_sharePath->setText(tr("%1 path: %2").arg(Theme::instance()->appNameGUI()).arg(_sharePath));
this->setWindowTitle(tr("%1 Sharing").arg(Theme::instance()->appNameGUI())); this->setWindowTitle(tr("%1 Sharing").arg(Theme::instance()->appNameGUI()));
@@ -150,6 +178,10 @@ void ShareDialog::slotPasswordReturnPressed()
void ShareDialog::setPassword(const QString &password) void ShareDialog::setPassword(const QString &password)
{ {
if( _passwordJobRunning ) {
// This happens because the entry field and the button both trigger this slot.
return;
}
_pi_password->startAnimation(); _pi_password->startAnimation();
QUrl url; QUrl url;
QList<QPair<QString, QString> > requestParams; QList<QPair<QString, QString> > requestParams;
@@ -177,6 +209,7 @@ void ShareDialog::setPassword(const QString &password)
job->setPostParams(requestParams); job->setPostParams(requestParams);
connect(job, SIGNAL(jobFinished(QString)), this, SLOT(slotPasswordSet(QString))); connect(job, SIGNAL(jobFinished(QString)), this, SLOT(slotPasswordSet(QString)));
job->start(); job->start();
_passwordJobRunning = true;
} }
void ShareDialog::slotPasswordSet(const QString &reply) void ShareDialog::slotPasswordSet(const QString &reply)
@@ -188,15 +221,15 @@ void ShareDialog::slotPasswordSet(const QString &reply)
if (code != 100) { if (code != 100) {
displayError(code); displayError(code);
} else { }
/* /*
* When setting/deleting a password from a share the old share is * When setting/deleting a password from a share the old share is
* deleted and a new one is created. So we need to refetch the shares * deleted and a new one is created. So we need to refetch the shares
* at this point. * at this point.
*/ */
getShares(); getShares();
}
_passwordJobRunning = false;
_pi_password->stopAnimation(); _pi_password->stopAnimation();
} }
@@ -224,44 +257,53 @@ void ShareDialog::slotSharesFetched(const QString &reply)
bool success = false; bool success = false;
QVariantMap json = QtJson::parse(reply, success).toMap(); QVariantMap json = QtJson::parse(reply, success).toMap();
ShareDialog::_shares = json.value("ocs").toMap().value("data").toList(); ShareDialog::_shares = json.value("ocs").toMap().value("data").toList();
Q_FOREACH(auto share, ShareDialog::_shares) const QString versionString = AccountManager::instance()->account()->serverVersion();
{
Q_FOREACH(auto share, ShareDialog::_shares) {
QVariantMap data = share.toMap(); QVariantMap data = share.toMap();
if (data.value("share_type").toInt() == SHARETYPE_PUBLIC) if (data.value("share_type").toInt() == SHARETYPE_PUBLIC) {
{
_public_share_id = data.value("id").toULongLong(); _public_share_id = data.value("id").toULongLong();
_ui->widget_shareLink->show(); _ui->widget_shareLink->show();
_ui->checkBox_shareLink->setChecked(true); _ui->checkBox_shareLink->setChecked(true);
if (data.value("share_with").isValid()) if (data.value("share_with").isValid()) {
{
_ui->checkBox_password->setChecked(true); _ui->checkBox_password->setChecked(true);
_ui->lineEdit_password->setPlaceholderText("********"); _ui->lineEdit_password->setPlaceholderText("********");
_ui->lineEdit_password->show(); _ui->lineEdit_password->show();
_ui->pushButton_setPassword->show();
} else {
_ui->checkBox_password->setChecked(false);
// _ui->lineEdit_password->setPlaceholderText("********");
_ui->lineEdit_password->hide();
_ui->pushButton_setPassword->hide();
} }
if (data.value("expiration").isValid()) if (data.value("expiration").isValid()) {
{
_ui->calendar->setSelectedDate(QDate::fromString(data.value("expiration").toString(), "yyyy-MM-dd 00:00:00")); _ui->calendar->setSelectedDate(QDate::fromString(data.value("expiration").toString(), "yyyy-MM-dd 00:00:00"));
_ui->calendar->setMinimumDate(QDate::currentDate().addDays(1)); _ui->calendar->setMinimumDate(QDate::currentDate().addDays(1));
_ui->calendar->show(); _ui->calendar->show();
_ui->checkBox_expire->setChecked(true); _ui->checkBox_expire->setChecked(true);
} else {
_ui->calendar->hide();
_ui->checkBox_expire->setChecked(false);
} }
const QString versionString = AccountManager::instance()->account()->serverVersion();
QString url; QString url;
// From ownCloud server version 8 on, a different share link scheme is used. // From ownCloud server version 8 on, a different share link scheme is used.
if (versionString.contains('.') && versionString.split('.')[0].toInt() >= 8) { if (versionString.contains('.') && versionString.split('.')[0].toInt() >= 8) {
url = Account::concatUrlPath(_account->url(), QString("index.php/s/%1").arg(data.value("token").toString())).toString(); url = Account::concatUrlPath(_account->url(), QString("index.php/s/%1").arg(data.value("token").toString())).toString();
} else { } else {
url = Account::concatUrlPath(_account->url(), QString("public.php?service=files&t=%1").arg(data.value("token").toString())).toString(); QList<QPair<QString, QString>> queryArgs;
queryArgs.append(qMakePair(QString("service"), QString("files")));
queryArgs.append(qMakePair(QString("t"), data.value("token").toString()));
url = Account::concatUrlPath(_account->url(), QLatin1String("public.php"), queryArgs).toString();
} }
_ui->lineEdit_shareLink->setText(url); _ui->lineEdit_shareLink->setText(url);
} }
} }
setShareCheckBoxTitle(_shares.count() > 0);
} }
void ShareDialog::slotDeleteShareFetched(const QString &reply) void ShareDialog::slotDeleteShareFetched(const QString &reply)
@@ -280,14 +322,17 @@ void ShareDialog::slotDeleteShareFetched(const QString &reply)
_ui->lineEdit_shareLink->clear(); _ui->lineEdit_shareLink->clear();
_ui->widget_shareLink->hide(); _ui->widget_shareLink->hide();
_ui->lineEdit_password->hide(); _ui->lineEdit_password->hide();
_ui->pushButton_setPassword->hide();
_ui->checkBox_expire->setChecked(false); _ui->checkBox_expire->setChecked(false);
_ui->calendar->hide(); _ui->calendar->hide();
setShareCheckBoxTitle(false);
} }
void ShareDialog::slotCheckBoxShareLinkClicked() void ShareDialog::slotCheckBoxShareLinkClicked()
{ {
if (_ui->checkBox_shareLink->checkState() == Qt::Checked) if (_ui->checkBox_shareLink->checkState() == Qt::Checked) {
{
_pi_link->startAnimation(); _pi_link->startAnimation();
QUrl url = Account::concatUrlPath(_account->url(), QLatin1String("ocs/v1.php/apps/files_sharing/api/v1/shares")); QUrl url = Account::concatUrlPath(_account->url(), QLatin1String("ocs/v1.php/apps/files_sharing/api/v1/shares"));
QList<QPair<QString, QString> > postParams; QList<QPair<QString, QString> > postParams;
@@ -297,9 +342,7 @@ void ShareDialog::slotCheckBoxShareLinkClicked()
job->setPostParams(postParams); job->setPostParams(postParams);
connect(job, SIGNAL(jobFinished(QString)), this, SLOT(slotCreateShareFetched(QString))); connect(job, SIGNAL(jobFinished(QString)), this, SLOT(slotCreateShareFetched(QString)));
job->start(); job->start();
} } else {
else
{
_pi_link->startAnimation(); _pi_link->startAnimation();
QUrl url = Account::concatUrlPath(_account->url(), QString("ocs/v1.php/apps/files_sharing/api/v1/shares/%1").arg(_public_share_id)); QUrl url = Account::concatUrlPath(_account->url(), QString("ocs/v1.php/apps/files_sharing/api/v1/shares/%1").arg(_public_share_id));
OcsShareJob *job = new OcsShareJob("DELETE", url, _account, this); OcsShareJob *job = new OcsShareJob("DELETE", url, _account, this);
@@ -334,6 +377,7 @@ void ShareDialog::slotCreateShareFetched(const QString &reply)
_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(); QString url = json.value("ocs").toMap().values("data")[0].toMap().value("url").toString();
_ui->lineEdit_shareLink->setText(url); _ui->lineEdit_shareLink->setText(url);
setShareCheckBoxTitle(true);
_ui->widget_shareLink->show(); _ui->widget_shareLink->show();
} }
@@ -343,6 +387,7 @@ void ShareDialog::slotCheckBoxPasswordClicked()
if (_ui->checkBox_password->checkState() == Qt::Checked) if (_ui->checkBox_password->checkState() == Qt::Checked)
{ {
_ui->lineEdit_password->show(); _ui->lineEdit_password->show();
_ui->pushButton_setPassword->show();
_ui->lineEdit_password->setPlaceholderText(tr("Choose a password for the public link")); _ui->lineEdit_password->setPlaceholderText(tr("Choose a password for the public link"));
} }
else else
@@ -351,6 +396,7 @@ void ShareDialog::slotCheckBoxPasswordClicked()
_ui->lineEdit_password->setPlaceholderText(QString()); _ui->lineEdit_password->setPlaceholderText(QString());
_pi_password->startAnimation(); _pi_password->startAnimation();
_ui->lineEdit_password->hide(); _ui->lineEdit_password->hide();
_ui->pushButton_setPassword->hide();
} }
} }
@@ -393,6 +439,19 @@ int ShareDialog::checkJsonReturnCode(const QString &reply, QString &message)
return code; return code;
} }
void ShareDialog::setShareCheckBoxTitle(bool haveShares)
{
const QString noSharesTitle(tr("Check to share by public link"));
const QString haveSharesTitle(tr("Shared by public link (uncheck to delete share)"));
if( haveShares ) {
_ui->checkBox_shareLink->setText( haveSharesTitle );
} else {
_ui->checkBox_shareLink->setText( noSharesTitle );
}
}
void ShareDialog::displayError(int code) void ShareDialog::displayError(int code)
{ {
const QString errMsg = tr("OCS API error code: %1").arg(code); const QString errMsg = tr("OCS API error code: %1").arg(code);
@@ -430,7 +489,7 @@ bool ShareDialog::uploadExternalFile()
FolderMan::instance()->folder(folderName); FolderMan::instance()->folder(folderName);
if( ! folder ) { if( ! folder ) {
qDebug() << "Folder not defined: " << folderName; qDebug() << "Folder not defined: " << folderName;
displayInfo(tr("Can not find a folder to upload to.")); displayInfo(tr("Cannot find an folder to upload to."));
return false; return false;
} }
@@ -453,7 +512,7 @@ bool ShareDialog::uploadExternalFile()
QFileInfo target(_expectedSyncFile); QFileInfo target(_expectedSyncFile);
if( target.exists() ) { if( target.exists() ) {
_ui->label_sharePath->setText(tr("A sync file with the same name exists. " _ui->label_sharePath->setText(tr("A sync file with the same name exists. "
"The file can not be registered to sync.")); "The file cannot be registered to sync."));
// TODO: Add a file comparison here. If the existing file is still the same // TODO: Add a file comparison here. If the existing file is still the same
// then the file-to-copy we can share it. // then the file-to-copy we can share it.
_sharePath.clear(); _sharePath.clear();
@@ -497,7 +556,7 @@ void ShareDialog::slotNextSyncFinished( const SyncResult& result )
_uploadFails ++; _uploadFails ++;
if( _uploadFails > 2 ) { if( _uploadFails > 2 ) {
// stop the upload job // stop the upload job
displayInfo(tr("The file can not be synced.")); displayInfo(tr("The file cannot be synced."));
} }
} else { } else {
// it's there and the sync was successful. // it's there and the sync was successful.
@@ -544,13 +603,19 @@ void OcsShareJob::start()
QNetworkRequest req; QNetworkRequest req;
req.setRawHeader("OCS-APIREQUEST", "true"); req.setRawHeader("OCS-APIREQUEST", "true");
req.setRawHeader("Content-Type", "application/x-www-form-urlencoded"); req.setRawHeader("Content-Type", "application/x-www-form-urlencoded");
QBuffer *buffer = new QBuffer;
QStringList tmp; // Url encode the _postParams and put them in a buffer.
QByteArray postData;
Q_FOREACH(auto tmp2, _postParams) { Q_FOREACH(auto tmp2, _postParams) {
tmp.append(tmp2.first + "=" + tmp2.second); if (! postData.isEmpty()) {
postData.append("&");
}
postData.append(QUrl::toPercentEncoding(tmp2.first));
postData.append("=");
postData.append(QUrl::toPercentEncoding(tmp2.second));
} }
buffer->setData(tmp.join("&").toAscii()); QBuffer *buffer = new QBuffer;
buffer->setData(postData);
auto queryItems = _url.queryItems(); auto queryItems = _url.queryItems();
queryItems.append(qMakePair(QString::fromLatin1("format"), QString::fromLatin1("json"))); queryItems.append(qMakePair(QString::fromLatin1("format"), QString::fromLatin1("json")));

View File

@@ -1,5 +1,6 @@
/* /*
* Copyright (C) by * Copyright (C) 2015 by Roeland Douma
* Copyright (C) 2015 by Klaas Freitag <freitag@owncloud.com>
* *
* 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
@@ -74,6 +75,7 @@ private slots:
void slotPushButtonCopyLinkPressed(); void slotPushButtonCopyLinkPressed();
void slotThumbnailFetched(const int &statusCode, const QByteArray &reply); void slotThumbnailFetched(const int &statusCode, const QByteArray &reply);
private: private:
void setShareCheckBoxTitle(bool haveShares);
void displayError(int code); void displayError(int code);
void displayInfo( const QString& msg ); void displayInfo( const QString& msg );
@@ -85,6 +87,7 @@ private:
int _uploadFails; int _uploadFails;
QString _expectedSyncFile; QString _expectedSyncFile;
bool _passwordJobRunning;
QList<QVariant> _shares; QList<QVariant> _shares;
qulonglong _public_share_id; qulonglong _public_share_id;
void setPassword(const QString &password); void setPassword(const QString &password);
@@ -94,6 +97,7 @@ private:
QProgressIndicator *_pi_link; QProgressIndicator *_pi_link;
QProgressIndicator *_pi_password; QProgressIndicator *_pi_password;
QProgressIndicator *_pi_date; QProgressIndicator *_pi_date;
}; };
} }

View File

@@ -72,7 +72,7 @@
</font> </font>
</property> </property>
<property name="text"> <property name="text">
<string>OwnCloud Path:</string> <string>ownCloud Path:</string>
</property> </property>
</widget> </widget>
</item> </item>
@@ -113,7 +113,7 @@
<item> <item>
<widget class="QCheckBox" name="checkBox_expire"> <widget class="QCheckBox" name="checkBox_expire">
<property name="text"> <property name="text">
<string>Set expiry date</string> <string>Set expiration date</string>
</property> </property>
</widget> </widget>
</item> </item>
@@ -164,6 +164,19 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="3" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0"> <item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_shareLink"> <layout class="QHBoxLayout" name="horizontalLayout_shareLink">
<item> <item>
@@ -182,18 +195,12 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0"> <item row="5" column="0">
<spacer name="verticalSpacer"> <widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation"> <property name="standardButtons">
<enum>Qt::Vertical</enum> <set>QDialogButtonBox::Close</set>
</property> </property>
<property name="sizeHint" stdset="0"> </widget>
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item> </item>
</layout> </layout>
</widget> </widget>

View File

@@ -55,7 +55,8 @@ enum csync_exclude_type_e {
CSYNC_FILE_SILENTLY_EXCLUDED, CSYNC_FILE_SILENTLY_EXCLUDED,
CSYNC_FILE_EXCLUDE_AND_REMOVE, CSYNC_FILE_EXCLUDE_AND_REMOVE,
CSYNC_FILE_EXCLUDE_LIST, CSYNC_FILE_EXCLUDE_LIST,
CSYNC_FILE_EXCLUDE_INVALID_CHAR CSYNC_FILE_EXCLUDE_INVALID_CHAR,
CSYNC_FILE_EXCLUDE_LONG_FILENAME
}; };
typedef enum csync_exclude_type_e CSYNC_EXCLUDE_TYPE; typedef enum csync_exclude_type_e CSYNC_EXCLUDE_TYPE;
@@ -313,7 +314,14 @@ void SocketApi::slotSyncItemDiscovered(const QString &folder, const SyncFileItem
return; return;
} }
const QString path = f->path() + item.destination(); QString path = f->path() + item.destination();
// the trailing slash for directories must be appended as the filenames coming in
// from the plugins have that too. Otherwise the according entry item is not found
// in the plugin.
if( item._type == SyncFileItem::Type::Directory ) {
path += QLatin1Char('/');
}
const QString command = QLatin1String("SYNC"); const QString command = QLatin1String("SYNC");
broadcastMessage(QLatin1String("STATUS"), path, command); broadcastMessage(QLatin1String("STATUS"), path, command);
@@ -386,8 +394,6 @@ void SocketApi::command_RETRIEVE_FILE_STATUS(const QString& argument, SocketType
DEBUG << "folder offline or not watched:" << argument; DEBUG << "folder offline or not watched:" << argument;
statusString = QLatin1String("NOP"); statusString = QLatin1String("NOP");
} else { } else {
const QString file = QDir::cleanPath(argument).mid(QDir::cleanPath(syncFolder->path()).length()+1); const QString file = QDir::cleanPath(argument).mid(QDir::cleanPath(syncFolder->path()).length()+1);
SyncFileStatus fileStatus = this->fileStatus(syncFolder, file, _excludes); SyncFileStatus fileStatus = this->fileStatus(syncFolder, file, _excludes);
@@ -528,15 +534,20 @@ SyncFileStatus SocketApi::fileStatus(Folder *folder, const QString& systemFileNa
fileNameSlash += QLatin1Char('/'); fileNameSlash += QLatin1Char('/');
} }
QFileInfo fi(file); if( !FileSystem::fileExists(file) ) {
if( !fi.exists() ) {
qDebug() << "OO File " << file << " is not existing"; qDebug() << "OO File " << file << " is not existing";
return SyncFileStatus(SyncFileStatus::STATUS_STAT_ERROR); return SyncFileStatus(SyncFileStatus::STATUS_STAT_ERROR);
} }
// file is ignored? // file is ignored?
if( fi.isSymLink() ) { // Qt considers .lnk files symlinks on Windows so we need to work
// around that here.
const QFileInfo fi(file);
if( fi.isSymLink()
#ifdef Q_OS_WIN
&& fi.suffix() != "lnk"
#endif
) {
return SyncFileStatus(SyncFileStatus::STATUS_IGNORE); return SyncFileStatus(SyncFileStatus::STATUS_IGNORE);
} }

View File

@@ -70,7 +70,6 @@ private slots:
private: private:
SyncFileStatus fileStatus(Folder *folder, const QString& systemFileName, c_strlist_t *excludes ); SyncFileStatus fileStatus(Folder *folder, const QString& systemFileName, c_strlist_t *excludes );
SyncJournalFileRecord dbFileRecord_capi( Folder *folder, QString fileName ); SyncJournalFileRecord dbFileRecord_capi( Folder *folder, QString fileName );
SyncFileStatus recursiveFolderStatus(Folder *folder, const QString& fileName, c_strlist_t *excludes );
SqlQuery *getSqlQuery( Folder *folder ); SqlQuery *getSqlQuery( Folder *folder );
void sendMessage(SocketType* socket, const QString& message, bool doWait = false); void sendMessage(SocketType* socket, const QString& message, bool doWait = false);

View File

@@ -15,6 +15,7 @@
#include "account.h" #include "account.h"
#include "accountstate.h" #include "accountstate.h"
#include "utility.h" #include "utility.h"
#include "theme.h"
#include <QMenu> #include <QMenu>
#include <QUrl> #include <QUrl>
@@ -184,7 +185,7 @@ void SslButton::updateAccountState(AccountState *accountState)
oldMenu->deleteLater(); // setMenu do not delete the previous menu. oldMenu->deleteLater(); // setMenu do not delete the previous menu.
} }
if (account->url().scheme() == QLatin1String("https")) { if (account->url().scheme() == QLatin1String("https")) {
setIcon(QIcon(QPixmap(Utility::hidpiFileName(":/client/resources/lock-https.png")))); setIcon(QIcon(QPixmap(Theme::hidpiFileName(":/client/resources/lock-https.png"))));
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); QMenu *menu = new QMenu(this);
@@ -217,7 +218,7 @@ void SslButton::updateAccountState(AccountState *accountState)
} }
setMenu(menu); setMenu(menu);
} else { } else {
setIcon(QIcon(QPixmap(Utility::hidpiFileName(":/client/resources/lock-http.png")))); setIcon(QIcon(QPixmap(Theme::hidpiFileName(":/client/resources/lock-http.png"))));
setToolTip(tr("This connection is NOT secure as it is not encrypted.\n")); setToolTip(tr("This connection is NOT secure as it is not encrypted.\n"));
} }
} }

View File

@@ -67,7 +67,7 @@ OwncloudAdvancedSetupPage::OwncloudAdvancedSetupPage()
_ui.lServerIcon->setText(QString()); _ui.lServerIcon->setText(QString());
_ui.lServerIcon->setPixmap(appIcon.pixmap(48)); _ui.lServerIcon->setPixmap(appIcon.pixmap(48));
_ui.lLocalIcon->setText(QString()); _ui.lLocalIcon->setText(QString());
_ui.lLocalIcon->setPixmap(QPixmap(Utility::hidpiFileName(":/client/resources/folder-sync.png"))); _ui.lLocalIcon->setPixmap(QPixmap(Theme::hidpiFileName(":/client/resources/folder-sync.png")));
} }
void OwncloudAdvancedSetupPage::setupCustomization() void OwncloudAdvancedSetupPage::setupCustomization()

View File

@@ -1,3 +1,17 @@
/*
* Copyright (C) 2015 by Jeroen Hoek
* Copyright (C) 2015 by Olivier Goffart <ogoffart@owncloud.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 "wizard/owncloudconnectionmethoddialog.h" #include "wizard/owncloudconnectionmethoddialog.h"
#include "utility.h" #include "utility.h"
#include <QUrl> #include <QUrl>

View File

@@ -1,3 +1,17 @@
/*
* Copyright (C) 2015 by Jeroen Hoek
* Copyright (C) 2015 by Olivier Goffart <ogoffart@owncloud.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 OWNCLOUDCONNECTIONMETHODDIALOG_H #ifndef OWNCLOUDCONNECTIONMETHODDIALOG_H
#define OWNCLOUDCONNECTIONMETHODDIALOG_H #define OWNCLOUDCONNECTIONMETHODDIALOG_H

View File

@@ -116,11 +116,11 @@ void OwncloudSetupPage::slotUrlChanged(const QString& url)
} }
if (url.startsWith(QLatin1String("http://"))) { if (url.startsWith(QLatin1String("http://"))) {
_ui.urlLabel->setPixmap(QPixmap(Utility::hidpiFileName(":/client/resources/lock-http.png"))); _ui.urlLabel->setPixmap(QPixmap(Theme::hidpiFileName(":/client/resources/lock-http.png")));
_ui.urlLabel->setToolTip(tr("This url is NOT secure as it is not encrypted.\n" _ui.urlLabel->setToolTip(tr("This url is NOT secure as it is not encrypted.\n"
"It is not advisable to use it.")); "It is not advisable to use it."));
} else { } else {
_ui.urlLabel->setPixmap(QPixmap(Utility::hidpiFileName(":/client/resources/lock-https.png"))); _ui.urlLabel->setPixmap(QPixmap(Theme::hidpiFileName(":/client/resources/lock-https.png")));
_ui.urlLabel->setToolTip(tr("This url is secure. You can use it.")); _ui.urlLabel->setToolTip(tr("This url is secure. You can use it."));
} }
} }

View File

@@ -58,7 +58,6 @@ public:
void setMultipleFoldersExist( bool ); void setMultipleFoldersExist( bool );
void setConfigExists( bool ); void setConfigExists( bool );
bool configExists(); bool configExists();
void successfulStep();
AbstractCredentials* getCredentials() const; AbstractCredentials* getCredentials() const;
void raiseCertificatePopup(); void raiseCertificatePopup();
@@ -72,6 +71,7 @@ public slots:
void setRemoteFolder( const QString& ); void setRemoteFolder( const QString& );
void appendToConfigurationLog( const QString& msg, LogType type = LogParagraph ); void appendToConfigurationLog( const QString& msg, LogType type = LogParagraph );
void slotCurrentPageChanged( int ); void slotCurrentPageChanged( int );
void successfulStep();
signals: signals:
void clearPendingRequests(); void clearPendingRequests();

View File

@@ -21,7 +21,6 @@
#include "wizard/owncloudwizardresultpage.h" #include "wizard/owncloudwizardresultpage.h"
#include "wizard/owncloudwizardcommon.h" #include "wizard/owncloudwizardcommon.h"
#include "theme.h" #include "theme.h"
#include "utility.h"
namespace OCC namespace OCC
{ {
@@ -41,7 +40,7 @@ OwncloudWizardResultPage::OwncloudWizardResultPage()
setSubTitle( QLatin1String(" ") ); setSubTitle( QLatin1String(" ") );
_ui.pbOpenLocal->setText(tr("Open Local Folder")); _ui.pbOpenLocal->setText(tr("Open Local Folder"));
_ui.pbOpenLocal->setIcon(QIcon(Utility::hidpiFileName(":/client/resources/folder-sync.png"))); _ui.pbOpenLocal->setIcon(QIcon(Theme::hidpiFileName(":/client/resources/folder-sync.png")));
_ui.pbOpenLocal->setIconSize(QSize(48, 48)); _ui.pbOpenLocal->setIconSize(QSize(48, 48));
_ui.pbOpenLocal->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); _ui.pbOpenLocal->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
connect(_ui.pbOpenLocal, SIGNAL(clicked()), SLOT(slotOpenLocal())); connect(_ui.pbOpenLocal, SIGNAL(clicked()), SLOT(slotOpenLocal()));

View File

@@ -90,6 +90,7 @@ if(USE_NEON)
list(APPEND libsync_SRCS list(APPEND libsync_SRCS
propagator_legacy.cpp propagator_legacy.cpp
) )
add_definitions(-DUSE_NEON)
endif(USE_NEON) endif(USE_NEON)
# These headers are installed for libowncloudsync to be used by 3rd party apps # These headers are installed for libowncloudsync to be used by 3rd party apps
@@ -151,9 +152,9 @@ GENERATE_EXPORT_HEADER( ${synclib_NAME}
if(TOKEN_AUTH_ONLY) if(TOKEN_AUTH_ONLY)
qt5_use_modules(${synclib_NAME} Network Xml Sql) qt5_use_modules(${synclib_NAME} Network)
else() else()
qt5_use_modules(${synclib_NAME} Widgets Network Xml WebKitWidgets Sql) qt5_use_modules(${synclib_NAME} Widgets Network WebKitWidgets)
endif() endif()
set_target_properties( ${synclib_NAME} PROPERTIES set_target_properties( ${synclib_NAME} PROPERTIES

View File

@@ -380,43 +380,22 @@ void Account::setUrl(const QUrl &url)
_url = url; _url = url;
} }
QUrl Account::concatUrlPath(const QUrl &url, const QString &concatPath) QUrl Account::concatUrlPath(const QUrl &url, const QString &concatPath,
const QList< QPair<QString, QString> > &queryItems)
{ {
QUrl tmpUrl = url; QString path = url.path();
QString path = tmpUrl.path(); if (! concatPath.isEmpty()) {
// avoid '//' // avoid '//'
if (path.endsWith('/') && concatPath.startsWith('/')) { if (path.endsWith('/') && concatPath.startsWith('/')) {
path.chop(1); path.chop(1);
} // avoid missing '/' } // avoid missing '/'
else if (!path.endsWith('/') && !concatPath.startsWith('/')) { else if (!path.endsWith('/') && !concatPath.startsWith('/')) {
path += QLatin1Char('/'); path += QLatin1Char('/');
}
path += concatPath; // put togehter the complete path
QList< QPair<QString, QString> > queryItems;
// Check if there are query items within the path and if so, add them properly to the url.
if( path.contains(QLatin1Char('?')) ) {
// get the position of the delimiter between path and query items.
// remember: myphpscript.php?queryItem1=foo&queryItem2=bar
int cutPos = path.indexOf(QLatin1Char('?'));
if( cutPos > -1 ) {
QString itemStr = path.right(path.length() - cutPos-1);
// remote the query item part from the path.
if( cutPos < path.length() ) {
path.truncate(cutPos);
}
// parse the query items into the list of QPairs of Strings.
QStringList items = itemStr.split(QLatin1Char('&'));
Q_FOREACH( QString item, items ) {
QStringList pair = item.split(QLatin1Char('='));
if( pair.size() > 1 ) {
queryItems.append( QPair<QString, QString>(pair.at(0), pair.at(1)) );
}
}
} }
path += concatPath; // put the complete path together
} }
QUrl tmpUrl = url;
tmpUrl.setPath(path); tmpUrl.setPath(path);
if( queryItems.size() > 0 ) { if( queryItems.size() > 0 ) {
tmpUrl.setQueryItems(queryItems); tmpUrl.setQueryItems(queryItems);

View File

@@ -136,7 +136,8 @@ public:
void setSslErrorHandler(AbstractSslErrorHandler *handler); void setSslErrorHandler(AbstractSslErrorHandler *handler);
// static helper function // static helper function
static QUrl concatUrlPath(const QUrl &url, const QString &concatPath); static QUrl concatUrlPath(const QUrl &url, const QString &concatPath,
const QList< QPair<QString, QString> > &queryItems = (QList<QPair<QString, QString>>()));
/** Returns a new settings pre-set in a specific group. The Settings will be created /** Returns a new settings pre-set in a specific group. The Settings will be created
with the given parent. If no parents is specified, the caller must destroy the settings */ with the given parent. If no parents is specified, the caller must destroy the settings */

View File

@@ -46,6 +46,8 @@ QString ConnectionValidator::statusString( Status stat )
return QLatin1String("Status not found"); return QLatin1String("Status not found");
case UserCanceledCredentials: case UserCanceledCredentials:
return QLatin1String("User canceled credentials"); return QLatin1String("User canceled credentials");
case ServerMaintenance:
return QLatin1String("Server in maintenance mode");
case Timeout: case Timeout:
return QLatin1String("Timeout"); return QLatin1String("Timeout");
} }
@@ -138,7 +140,7 @@ void ConnectionValidator::slotAuthFailed(QNetworkReply *reply)
Status stat = Timeout; Status stat = Timeout;
if( reply->error() == QNetworkReply::AuthenticationRequiredError || if( reply->error() == QNetworkReply::AuthenticationRequiredError ||
reply->error() == QNetworkReply::OperationCanceledError ) { // returned if the user/pwd is wrong. !_account->credentials()->stillValid(reply)) {
qDebug() << reply->error() << reply->errorString(); qDebug() << reply->error() << reply->errorString();
qDebug() << "******** Password is wrong!"; qDebug() << "******** Password is wrong!";
_errors << tr("The provided credentials are not correct"); _errors << tr("The provided credentials are not correct");
@@ -146,6 +148,18 @@ void ConnectionValidator::slotAuthFailed(QNetworkReply *reply)
} else if( reply->error() != QNetworkReply::NoError ) { } else if( reply->error() != QNetworkReply::NoError ) {
_errors << reply->errorString(); _errors << reply->errorString();
const int httpStatus =
reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if ( httpStatus == 503 ) {
// Is this a maintenance mode reply from the server
// or a regular 503 from somewhere else?
QByteArray body = reply->readAll();
if ( body.contains("Sabre\\DAV\\Exception\\ServiceUnavailable") ) {
_errors.clear();
stat = ServerMaintenance;
}
}
} }
reportResult( stat ); reportResult( stat );

View File

@@ -75,6 +75,7 @@ public:
CredentialsWrong, CredentialsWrong,
StatusNotFound, StatusNotFound,
UserCanceledCredentials, UserCanceledCredentials,
ServerMaintenance,
// actually also used for other errors on the authed request // actually also used for other errors on the authed request
Timeout Timeout
}; };

View File

@@ -19,6 +19,7 @@
#include <QWebPage> #include <QWebPage>
#include <QMessageBox> #include <QMessageBox>
#include <QNetworkReply> #include <QNetworkReply>
#include <QSettings>
#include "creds/shibboleth/shibbolethwebview.h" #include "creds/shibboleth/shibbolethwebview.h"
#include "creds/shibbolethcredentials.h" #include "creds/shibbolethcredentials.h"
@@ -26,6 +27,11 @@
#include "logger.h" #include "logger.h"
#include "accessmanager.h" #include "accessmanager.h"
#include "theme.h" #include "theme.h"
#include "configfile.h"
namespace {
const char ShibbolethWebViewGeometryC[] = "ShibbolethWebView/Geometry";
}
namespace OCC namespace OCC
{ {
@@ -39,6 +45,7 @@ ShibbolethWebView::ShibbolethWebView(AccountPtr account, QWidget* parent)
// no minimize // no minimize
setWindowFlags(Qt::Dialog); setWindowFlags(Qt::Dialog);
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
QWebPage* page = new QWebPage(this); QWebPage* page = new QWebPage(this);
page->setNetworkAccessManager(account->networkAccessManager()); page->setNetworkAccessManager(account->networkAccessManager());
connect(page, SIGNAL(loadStarted()), connect(page, SIGNAL(loadStarted()),
@@ -60,10 +67,18 @@ ShibbolethWebView::ShibbolethWebView(AccountPtr account, QWidget* parent)
if (shibCookie != QNetworkCookie()) { if (shibCookie != QNetworkCookie()) {
Logger::instance()->postOptionalGuiLog(tr("Reauthentication required"), tr("Your session has expired. You need to re-login to continue to use the client.")); Logger::instance()->postOptionalGuiLog(tr("Reauthentication required"), tr("Your session has expired. You need to re-login to continue to use the client."));
} }
ConfigFile config;
QSettings settings(config.configFile());
resize(900, 700); // only effective the first time, later overridden by restoreGeometry
restoreGeometry(settings.value(ShibbolethWebViewGeometryC).toByteArray());
} }
ShibbolethWebView::~ShibbolethWebView() ShibbolethWebView::~ShibbolethWebView()
{ {
ConfigFile config;
QSettings settings(config.configFile());
settings.setValue(ShibbolethWebViewGeometryC, saveGeometry());
} }
void ShibbolethWebView::onNewCookiesForUrl (const QList<QNetworkCookie>& cookieList, const QUrl& url) void ShibbolethWebView::onNewCookiesForUrl (const QList<QNetworkCookie>& cookieList, const QUrl& url)
@@ -105,7 +120,7 @@ void ShibbolethWebView::slotLoadFinished(bool success)
} }
if (!title().isNull()) { if (!title().isNull()) {
setWindowTitle(tr("%1 - %2").arg(Theme::instance()->appNameGUI(), title())); setWindowTitle(QString::fromLatin1("%1 - %2 (%3)").arg(Theme::instance()->appNameGUI(), title(), url().host()));
} }
if (!success) { if (!success) {

View File

@@ -68,7 +68,6 @@ int getauth(const char *prompt,
return re; return re;
} }
const char userC[] = "user";
const char authenticationFailedC[] = "owncloud-authentication-failed"; const char authenticationFailedC[] = "owncloud-authentication-failed";
} // ns } // ns
@@ -80,8 +79,8 @@ public:
: AccessManager(parent), _cred(cred) {} : AccessManager(parent), _cred(cred) {}
protected: protected:
QNetworkReply *createRequest(Operation op, const QNetworkRequest &request, QIODevice *outgoingData) { QNetworkReply *createRequest(Operation op, const QNetworkRequest &request, QIODevice *outgoingData) {
if (_cred->user().isEmpty() || _cred->password().isEmpty() || _cred->_token.isEmpty()) { if (_cred->user().isEmpty() || _cred->password().isEmpty()) {
qWarning() << Q_FUNC_INFO << "Empty user/password/token provided!"; qWarning() << Q_FUNC_INFO << "Empty user/password provided!";
} }
QNetworkRequest req(request); QNetworkRequest req(request);
@@ -91,7 +90,9 @@ protected:
// A pre-authenticated cookie // A pre-authenticated cookie
QByteArray token = _cred->_token.toUtf8(); QByteArray token = _cred->_token.toUtf8();
setRawCookie(token, request.url()); if (token.length() > 0) {
setRawCookie(token, request.url());
}
return AccessManager::createRequest(op, req, outgoingData); return AccessManager::createRequest(op, req, outgoingData);
} }

View File

@@ -66,21 +66,25 @@ void DiscoveryJob::update_job_update_callback (bool local,
DiscoveryJob *updateJob = static_cast<DiscoveryJob*>(userdata); DiscoveryJob *updateJob = static_cast<DiscoveryJob*>(userdata);
if (updateJob) { if (updateJob) {
// Don't wanna overload the UI // Don't wanna overload the UI
if (!updateJob->lastUpdateProgressCallbackCall.isValid()) { if (!updateJob->_lastUpdateProgressCallbackCall.isValid()) {
updateJob->lastUpdateProgressCallbackCall.restart(); // first call updateJob->_lastUpdateProgressCallbackCall.restart(); // first call
} else if (updateJob->lastUpdateProgressCallbackCall.elapsed() < 200) { } else if (updateJob->_lastUpdateProgressCallbackCall.elapsed() < 200) {
return; return;
} else { } else {
updateJob->lastUpdateProgressCallbackCall.restart(); updateJob->_lastUpdateProgressCallbackCall.restart();
} }
QString path(QUrl::fromPercentEncoding(QByteArray(dirUrl)).section('/', -1)); QByteArray pPath(dirUrl);
emit updateJob->folderDiscovered(local, path); int indx = pPath.lastIndexOf('/');
if(indx>-1) {
const QString path = QUrl::fromPercentEncoding( pPath.mid(indx+1));
emit updateJob->folderDiscovered(local, path);
}
} }
} }
int get_errno_from_http_errcode( int err ) { int get_errno_from_http_errcode( int err, const QString & reason ) {
int new_errno = 0; int new_errno = 0;
switch(err) { switch(err) {
@@ -143,8 +147,11 @@ int get_errno_from_http_errcode( int err ) {
new_errno = EIO; new_errno = EIO;
break; break;
case 503: /* Service Unavailable */ case 503: /* Service Unavailable */
new_errno = ERRNO_SERVICE_UNAVAILABLE; if (reason == "Storage not available") {
// FIXME Distinguish between service unavailable and storage unavilable new_errno = ERRNO_STORAGE_UNAVAILABLE;
} else {
new_errno = ERRNO_SERVICE_UNAVAILABLE;
}
break; break;
case 413: /* Request Entity too Large */ case 413: /* Request Entity too Large */
new_errno = EFBIG; new_errno = EFBIG;
@@ -166,6 +173,11 @@ void DiscoverySingleDirectoryJob::start()
{ {
// Start the actual HTTP job // Start the actual HTTP job
LsColJob *lsColJob = new LsColJob(_account, _subPath, this); LsColJob *lsColJob = new LsColJob(_account, _subPath, this);
lsColJob->setProperties(QList<QByteArray>() << "resourcetype" << "getlastmodified"
<< "getcontentlength" << "getetag" << "http://owncloud.org/ns:id"
<< "http://owncloud.org/ns:downloadURL" << "http://owncloud.org/ns:dDC"
<< "http://owncloud.org/ns:permissions");
QObject::connect(lsColJob, SIGNAL(directoryListingIterated(QString,QMap<QString,QString>)), QObject::connect(lsColJob, SIGNAL(directoryListingIterated(QString,QMap<QString,QString>)),
this, SLOT(directoryListingIteratedSlot(QString,QMap<QString,QString>))); this, SLOT(directoryListingIteratedSlot(QString,QMap<QString,QString>)));
QObject::connect(lsColJob, SIGNAL(finishedWithError(QNetworkReply*)), this, SLOT(lsJobFinishedWithErrorSlot(QNetworkReply*))); QObject::connect(lsColJob, SIGNAL(finishedWithError(QNetworkReply*)), this, SLOT(lsJobFinishedWithErrorSlot(QNetworkReply*)));
@@ -276,13 +288,14 @@ void DiscoverySingleDirectoryJob::lsJobFinishedWithErrorSlot(QNetworkReply *r)
{ {
QString contentType = r->header(QNetworkRequest::ContentTypeHeader).toString(); QString contentType = r->header(QNetworkRequest::ContentTypeHeader).toString();
int httpCode = r->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); int httpCode = r->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QString httpReason = r->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
QString msg = r->errorString(); QString msg = r->errorString();
int errnoCode = 0; int errnoCode = 0;
qDebug() << Q_FUNC_INFO << r->errorString() << httpCode << r->error(); qDebug() << Q_FUNC_INFO << r->errorString() << httpCode << r->error();
if (r->error() != QNetworkReply::NoError) { if (httpCode != 0 && httpCode != 207) {
errnoCode = get_errno_from_http_errcode(httpCode, httpReason);
} else if (r->error() != QNetworkReply::NoError) {
errnoCode = EIO; errnoCode = EIO;
} else if (httpCode != 207) {
errnoCode = get_errno_from_http_errcode(httpCode);
} 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;
@@ -300,6 +313,15 @@ 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
@@ -314,8 +336,9 @@ void DiscoveryMainThread::doOpendirSlot(QString subPath, DiscoveryDirectoryResul
while (fullPath.endsWith('/')) { while (fullPath.endsWith('/')) {
fullPath.chop(1); fullPath.chop(1);
} }
qDebug() << Q_FUNC_INFO << _pathPrefix << subPath << fullPath;
// emit _discoveryJob->folderDiscovered(false, subPath);
_discoveryJob->update_job_update_callback (false, subPath.toUtf8(), _discoveryJob);
// Result gets written in there // Result gets written in there
_currentDiscoveryDirectoryResult = r; _currentDiscoveryDirectoryResult = r;
@@ -410,7 +433,7 @@ csync_vio_handle_t* DiscoveryJob::remote_vio_opendir_hook (const char *url,
directoryResult->code = EIO; directoryResult->code = EIO;
discoveryJob->_vioMutex.lock(); discoveryJob->_vioMutex.lock();
QString qurl = QString::fromUtf8(url); const QString qurl = QString::fromUtf8(url);
emit discoveryJob->doOpendirSignal(qurl, directoryResult); emit discoveryJob->doOpendirSignal(qurl, directoryResult);
discoveryJob->_vioWaitCondition.wait(&discoveryJob->_vioMutex, ULONG_MAX); // FIXME timeout? discoveryJob->_vioWaitCondition.wait(&discoveryJob->_vioMutex, ULONG_MAX); // FIXME timeout?
discoveryJob->_vioMutex.unlock(); discoveryJob->_vioMutex.unlock();
@@ -421,6 +444,8 @@ csync_vio_handle_t* DiscoveryJob::remote_vio_opendir_hook (const char *url,
if (directoryResult->code != 0) { if (directoryResult->code != 0) {
qDebug() << Q_FUNC_INFO << directoryResult->code << "when opening" << url; qDebug() << Q_FUNC_INFO << directoryResult->code << "when opening" << url;
errno = directoryResult->code; errno = directoryResult->code;
// save the error string to the context
discoveryJob->_csync_ctx->error_string = qstrdup( directoryResult->msg.toUtf8().constData() );
return NULL; return NULL;
} }
@@ -450,9 +475,11 @@ void DiscoveryJob::remote_vio_closedir_hook (csync_vio_handle_t *dhandle, void
{ {
DiscoveryJob *discoveryJob = static_cast<DiscoveryJob*>(userdata); DiscoveryJob *discoveryJob = static_cast<DiscoveryJob*>(userdata);
if (discoveryJob) { if (discoveryJob) {
qDebug() << Q_FUNC_INFO << discoveryJob;
DiscoveryDirectoryResult *directoryResult = static_cast<DiscoveryDirectoryResult*> (dhandle); DiscoveryDirectoryResult *directoryResult = static_cast<DiscoveryDirectoryResult*> (dhandle);
QString path = directoryResult->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);
} }
} }
@@ -472,7 +499,7 @@ void DiscoveryJob::start() {
csync_set_log_callback(_log_callback); csync_set_log_callback(_log_callback);
csync_set_log_level(_log_level); csync_set_log_level(_log_level);
csync_set_log_userdata(_log_userdata); csync_set_log_userdata(_log_userdata);
lastUpdateProgressCallbackCall.invalidate(); _lastUpdateProgressCallbackCall.invalidate();
int ret = csync_update(_csync_ctx); int ret = csync_update(_csync_ctx);
_csync_ctx->checkSelectiveSyncBlackListHook = 0; _csync_ctx->checkSelectiveSyncBlackListHook = 0;

View File

@@ -87,7 +87,16 @@ 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() { ~DiscoveryMainThread() {
// Delete the _contents_ of the list-map explicitly:
foreach (const QLinkedList<csync_vio_file_stat_t*> & list, _directoryContents) { foreach (const QLinkedList<csync_vio_file_stat_t*> & list, _directoryContents) {
foreach (csync_vio_file_stat_t* stat, list) { foreach (csync_vio_file_stat_t* stat, list) {
csync_vio_file_stat_destroy(stat); csync_vio_file_stat_destroy(stat);
@@ -100,6 +109,7 @@ 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(QLinkedList<csync_vio_file_stat_t*>);
@@ -117,11 +127,11 @@ public:
class DiscoveryJob : public QObject { class DiscoveryJob : public QObject {
Q_OBJECT Q_OBJECT
friend class DiscoveryMainThread; friend class DiscoveryMainThread;
CSYNC *_csync_ctx; CSYNC *_csync_ctx;
csync_log_callback _log_callback; csync_log_callback _log_callback;
int _log_level; int _log_level;
void* _log_userdata; void* _log_userdata;
QElapsedTimer lastUpdateProgressCallbackCall; QElapsedTimer _lastUpdateProgressCallbackCall;
/** /**
* return true if the given path should be synced, * return true if the given path should be synced,
@@ -164,6 +174,8 @@ 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

@@ -120,7 +120,7 @@ bool FileSystem::renameReplace(const QString& originFileName, const QString& des
// Qt 5.1 has QSaveFile::renameOverwrite we cold use. // Qt 5.1 has QSaveFile::renameOverwrite we cold use.
// ### FIXME // ### FIXME
success = true; success = true;
bool destExists = QFileInfo::exists(destinationFileName); bool destExists = fileExists(destinationFileName);
if( destExists && !QFile::remove(destinationFileName) ) { if( destExists && !QFile::remove(destinationFileName) ) {
*errorString = orig.errorString(); *errorString = orig.errorString();
qDebug() << Q_FUNC_INFO << "Target file could not be removed."; qDebug() << Q_FUNC_INFO << "Target file could not be removed.";
@@ -214,26 +214,69 @@ bool FileSystem::openFileSharedRead(QFile* file, QString* error)
return ok; return ok;
} }
#ifdef Q_OS_WIN
static bool isLnkFile(const QString& filename)
{
return filename.endsWith(".lnk");
}
static bool isLnkFile(const QFileInfo& fi)
{
return fi.suffix() == "lnk";
}
static qint64 getSizeWithCsync(const QString& filename)
{
qint64 result = 0;
csync_vio_file_stat_t* stat = csync_vio_file_stat_new();
if (csync_vio_local_stat(filename.toUtf8().data(), stat) != -1
&& (stat->fields & CSYNC_VIO_FILE_STAT_FIELDS_SIZE)) {
result = stat->size;
} else {
qDebug() << "Could not get size time for" << filename << "with csync";
}
csync_vio_file_stat_destroy(stat);
return result;
}
#endif
qint64 FileSystem::getSize(const QString& filename) qint64 FileSystem::getSize(const QString& filename)
{ {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
if (filename.endsWith(".lnk")) { if (isLnkFile(filename)) {
// Use csync to get the file size. Qt seems unable to get at it. // Use csync to get the file size. Qt seems unable to get at it.
qint64 result = 0; return getSizeWithCsync(filename);
csync_vio_file_stat_t* stat = csync_vio_file_stat_new();
if (csync_vio_local_stat(filename.toUtf8().data(), stat) != -1
&& (stat->fields & CSYNC_VIO_FILE_STAT_FIELDS_SIZE)) {
result = stat->size;
} else {
qDebug() << "Could not get size time for" << filename << "with csync";
}
csync_vio_file_stat_destroy(stat);
return result;
} }
#endif #endif
return QFileInfo(filename).size(); return QFileInfo(filename).size();
} }
#ifdef Q_OS_WIN
static bool fileExistsWin(const QString& filename)
{
WIN32_FIND_DATA FindFileData;
HANDLE hFind;
hFind = FindFirstFileW( (wchar_t*)filename.utf16(), &FindFileData);
if (hFind == INVALID_HANDLE_VALUE) {
return false;
}
FindClose(hFind);
return true;
}
#endif
bool FileSystem::fileExists(const QString& filename)
{
#ifdef Q_OS_WIN
if (isLnkFile(filename)) {
// Use a native check.
return fileExistsWin(filename);
}
#endif
QFileInfo file(filename);
return file.exists();
}
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
QString FileSystem::fileSystemForPath(const QString & path) QString FileSystem::fileSystemForPath(const QString & path)
{ {

View File

@@ -14,11 +14,13 @@
#pragma once #pragma once
#include <QString> #include <QString>
#include <QFile>
#include <ctime> #include <ctime>
#include <owncloudlib.h> #include <owncloudlib.h>
class QFile;
class QFileInfo;
namespace OCC { namespace OCC {
/** /**
@@ -39,7 +41,7 @@ void OWNCLOUDSYNC_EXPORT setFileHidden(const QString& filename, bool hidden);
* Use this over QFileInfo::lastModified() to avoid timezone related bugs. See * Use this over QFileInfo::lastModified() to avoid timezone related bugs. See
* owncloud/core#9781 for details. * owncloud/core#9781 for details.
*/ */
time_t OWNCLOUDSYNC_EXPORT getModTime(const QString &filename); time_t OWNCLOUDSYNC_EXPORT getModTime(const QString& filename);
bool setModTime(const QString &filename, time_t modTime); bool setModTime(const QString &filename, time_t modTime);
@@ -50,6 +52,13 @@ bool setModTime(const QString &filename, time_t modTime);
*/ */
qint64 OWNCLOUDSYNC_EXPORT getSize(const QString& filename); qint64 OWNCLOUDSYNC_EXPORT getSize(const QString& filename);
/** Checks whether a file exists.
*
* Use this over QFileInfo::exists() and QFile::exists() to avoid bugs with lnk
* files, see above.
*/
bool OWNCLOUDSYNC_EXPORT fileExists(const QString& filename);
/** /**
* Rename the file \a originFileName to \a destinationFileName, and overwrite the destination if it * Rename the file \a originFileName to \a destinationFileName, and overwrite the destination if it
* already exists * already exists

View File

@@ -31,15 +31,17 @@ static void mirallLogCatcher(QtMsgType type, const char *msg)
static void qInstallMessageHandler(QtMsgHandler h) { static void qInstallMessageHandler(QtMsgHandler h) {
qInstallMsgHandler(h); qInstallMsgHandler(h);
} }
#else #elif QT_VERSION < QT_VERSION_CHECK(5, 4, 0)
static void mirallLogCatcher(QtMsgType, const QMessageLogContext &ctx, const QString &message) { static void mirallLogCatcher(QtMsgType, const QMessageLogContext &ctx, const QString &message) {
Q_UNUSED(ctx);
QByteArray file = ctx.file; QByteArray file = ctx.file;
file = file.mid(file.lastIndexOf('/') + 1); file = file.mid(file.lastIndexOf('/') + 1);
Logger::instance()->mirallLog( QString::fromLocal8Bit(file) + QLatin1Char(':') + QString::number(ctx.line) Logger::instance()->mirallLog( QString::fromLocal8Bit(file) + QLatin1Char(':') + QString::number(ctx.line)
+ QLatin1Char(' ') + message) ; + QLatin1Char(' ') + message) ;
} }
#else
static void mirallLogCatcher(QtMsgType type, const QMessageLogContext &ctx, const QString &message) {
Logger::instance()->doLog( qFormatLogMessage(type, ctx, message) ) ;
}
#endif #endif
Logger *Logger::instance() Logger *Logger::instance()
@@ -51,11 +53,20 @@ Logger *Logger::instance()
Logger::Logger( QObject* parent) : QObject(parent), Logger::Logger( QObject* parent) : QObject(parent),
_showTime(true), _doLogging(false), _doFileFlush(false), _logExpire(0) _showTime(true), _doLogging(false), _doFileFlush(false), _logExpire(0)
{ {
#ifndef NO_MSG_HANDLER
#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
qSetMessagePattern("%{time MM-dd hh:mm:ss:zzz} %{threadid} %{function}: %{message}");
#endif
qInstallMessageHandler(mirallLogCatcher); qInstallMessageHandler(mirallLogCatcher);
#else
Q_UNUSED(mirallLogCatcher)
#endif
} }
Logger::~Logger() { Logger::~Logger() {
#ifndef NO_MSG_HANDLER
qInstallMessageHandler(0); qInstallMessageHandler(0);
#endif
} }
@@ -91,6 +102,11 @@ void Logger::log(Log log)
// _logs.append(log); // _logs.append(log);
// std::cout << qPrintable(log.message) << std::endl; // std::cout << qPrintable(log.message) << std::endl;
doLog(msg);
}
void Logger::doLog(const QString& msg)
{
{ {
QMutexLocker lock(&_mutex); QMutexLocker lock(&_mutex);
if( _logstream ) { if( _logstream ) {
@@ -98,7 +114,6 @@ void Logger::log(Log log)
if( _doFileFlush ) _logstream->flush(); if( _doFileFlush ) _logstream->flush();
} }
} }
emit newLog(msg); emit newLog(msg);
} }

View File

@@ -43,6 +43,7 @@ class OWNCLOUDSYNC_EXPORT Logger : public QObject
public: public:
void log(Log log); void log(Log log);
void doLog(const QString &log);
static void csyncLog( const QString& message ); static void csyncLog( const QString& message );
static void mirallLog( const QString& message ); static void mirallLog( const QString& message );

View File

@@ -329,24 +329,44 @@ LsColJob::LsColJob(AccountPtr account, const QString &path, QObject *parent)
{ {
} }
void LsColJob::setProperties(QList<QByteArray> properties)
{
_properties = properties;
}
QList<QByteArray> LsColJob::properties() const
{
return _properties;
}
void LsColJob::start() void LsColJob::start()
{ {
QList<QByteArray> properties = _properties;
if (properties.isEmpty()) {
qWarning() << "Propfind with no properties!";
}
QByteArray propStr;
foreach (const QByteArray &prop, properties) {
if (prop.contains(':')) {
int colIdx = prop.lastIndexOf(":");
auto ns = prop.left(colIdx);
if (ns == "http://owncloud.org/ns") {
propStr += " <oc:" + prop.mid(colIdx+1) + " />\n";
} else {
propStr += " <" + prop.mid(colIdx+1) + " xmlns=\"" + ns + "\" />\n";
}
} else {
propStr += " <d:" + prop + " />\n";
}
}
QNetworkRequest req; QNetworkRequest req;
req.setRawHeader("Depth", "1"); req.setRawHeader("Depth", "1");
// FIXME The results are delivered without namespace, if this is ever a problem we need to check it..
QByteArray xml("<?xml version=\"1.0\" ?>\n" QByteArray xml("<?xml version=\"1.0\" ?>\n"
"<d:propfind xmlns:d=\"DAV:\" xmlns:oc=\"http://owncloud.org/ns\">\n" "<d:propfind xmlns:d=\"DAV:\" xmlns:oc=\"http://owncloud.org/ns\">\n"
" <d:prop>\n" " <d:prop>\n"
" <d:resourcetype/>\n" + propStr +
" <d:quota-used-bytes/>\n"
" <d:getlastmodified/>\n"
" <d:getcontentlength/>\n"
" <d:resourcetype/>\n"
" <d:getetag/>\n"
" <oc:id/>\n"
" <oc:downloadURL/>\n"
" <oc:dDC/>\n"
" <oc:permissions/>\n"
" </d:prop>\n" " </d:prop>\n"
"</d:propfind>\n"); "</d:propfind>\n");
QBuffer *buf = new QBuffer(this); QBuffer *buf = new QBuffer(this);
@@ -575,7 +595,7 @@ void PropfindJob::start()
QList<QByteArray> properties = _properties; QList<QByteArray> properties = _properties;
if (properties.isEmpty()) { if (properties.isEmpty()) {
properties << "allprop"; qWarning() << "Propfind with no properties!";
} }
QNetworkRequest req; QNetworkRequest req;
req.setRawHeader("Depth", "0"); req.setRawHeader("Depth", "0");

View File

@@ -136,24 +136,52 @@ public:
void start() Q_DECL_OVERRIDE; void start() Q_DECL_OVERRIDE;
QHash<QString, qint64> _sizes; QHash<QString, qint64> _sizes;
/**
* Used to specify which properties shall be retrieved.
*
* The properties can
* - contain no colon: they refer to a property in the DAV: namespace
* - contain a colon: and thus specify an explicit namespace,
* e.g. "ns:with:colons:bar", which is "bar" in the "ns:with:colons" namespace
*/
void setProperties(QList<QByteArray> properties);
QList<QByteArray> properties() const;
signals: signals:
void directoryListingSubfolders(const QStringList &items); void directoryListingSubfolders(const QStringList &items);
void directoryListingIterated(const QString name, QMap<QString,QString> properties); void directoryListingIterated(const QString &name, const QMap<QString,QString> &properties);
void finishedWithError(QNetworkReply *reply); void finishedWithError(QNetworkReply *reply);
void finishedWithoutError(); void finishedWithoutError();
private slots: private slots:
virtual bool finished() Q_DECL_OVERRIDE; virtual bool finished() Q_DECL_OVERRIDE;
private:
QList<QByteArray> _properties;
}; };
/** /**
* @brief The PropfindJob class * @brief The PropfindJob class
*
* Setting the desired properties with setProperties() is mandatory.
*
* Note that this job is only for querying one item.
* There is also the LsColJob which can be used to list collections
*/ */
class PropfindJob : public AbstractNetworkJob { class OWNCLOUDSYNC_EXPORT PropfindJob : public AbstractNetworkJob {
Q_OBJECT Q_OBJECT
public: public:
explicit PropfindJob(AccountPtr account, const QString &path, QObject *parent = 0); explicit PropfindJob(AccountPtr account, const QString &path, QObject *parent = 0);
void start() Q_DECL_OVERRIDE; void start() Q_DECL_OVERRIDE;
/**
* Used to specify which properties shall be retrieved.
*
* The properties can
* - contain no colon: they refer to a property in the DAV: namespace
* - contain a colon: and thus specify an explicit namespace,
* e.g. "ns:with:colons:bar", which is "bar" in the "ns:with:colons" namespace
*/
void setProperties(QList<QByteArray> properties); void setProperties(QList<QByteArray> properties);
QList<QByteArray> properties() const; QList<QByteArray> properties() const;

View File

@@ -78,7 +78,7 @@ void PropagateItemJob::done(SyncFileItem::Status status, const QString &errorStr
if( status == SyncFileItem::Success || status == SyncFileItem::Conflict) { if( status == SyncFileItem::Success || status == SyncFileItem::Conflict) {
status = SyncFileItem::Restoration; status = SyncFileItem::Restoration;
} else { } else {
_item._errorString += tr("; Restoration Failed: ") + errorString; _item._errorString += tr("; Restoration Failed: %1").arg(errorString);
} }
} else { } else {
if( _item._errorString.isEmpty() ) { if( _item._errorString.isEmpty() ) {
@@ -101,7 +101,7 @@ void PropagateItemJob::done(SyncFileItem::Status status, const QString &errorStr
if (blacklist(_propagator->_journal, _item) && _item._hasBlacklistEntry) { if (blacklist(_propagator->_journal, _item) && _item._hasBlacklistEntry) {
// do not error if the item was, and continues to be, blacklisted // do not error if the item was, and continues to be, blacklisted
status = SyncFileItem::FileIgnored; status = SyncFileItem::FileIgnored;
_item._errorString.prepend(tr("Continue blacklisting: ")); _item._errorString.prepend(tr("Continue blacklisting:") + " ");
} }
break; break;
case SyncFileItem::Success: case SyncFileItem::Success:

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