1
0
mirror of https://github.com/chylex/Nextcloud-Desktop.git synced 2026-04-07 09:46:48 +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)
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
option(BUILD_LIBRARIES_ONLY "BUILD_LIBRARIES_ONLY" OFF)

View File

@@ -1,11 +1,38 @@
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)
* Documentation fixes and updates
* Nautilus Python plugin fixed for Python 3
* GUI wording fixes plus improved log messages
* 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
* Avoid initial ETag fetch job at startup, which is not needed.
* 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)
* Introduce a general timeout of 300s for network operations
* 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)
* Significantly reduced CPU load when checking for local and remote changes
* Speed up file stat code on Windows
@@ -148,7 +175,7 @@ version 1.6.0 (release 2014-05-30 )
Qt 5.2 or later
* Forward server exception messages to client error messages
* 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
* Shibboleth: Warn if authenticating with a different user
* 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: Do not pop up IdP login immediately when modifying account
* 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 )
* 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
* 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.
* Wait up to 30 secs before complaining about missing systray
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
* [Fixes] NSIS installer fixes
* [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] Silently ignore "installed = true" status.php
* 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
* [Fixes] Clarify string in folder wizard
* [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] Skip folders with no absolute path
* [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 )
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" )

View File

@@ -4,7 +4,7 @@ set( MIRALL_VERSION_PATCH 0 )
set( MIRALL_SOVERSION 0 )
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 )
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_KILLING_PROCESSES_TEXT "Matando os procesos ${APPLICATION_EXECUTABLE}."
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_3 "Non desinstalar"
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_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_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_DetailPrint "Creando os accesos directos no escritorio"
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 $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "选择需要执行的维护选项。"
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_DetailPrint "添加 ${APPLICATION_NAME} 快捷方式到开始菜单。"
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "桌面快捷方式"
@@ -42,5 +44,3 @@ StrCpy $INIT_INSTALLER_RUNNING "安装程序已经运行。"
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "卸载程序需要管理员权限,请重试"
StrCpy $INIT_UNINSTALLER_RUNNING "卸载程序已经运行。"
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 $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 $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_DetailPrint "Poteka dodajanje bližnjice programa ${APPLICATION_NAME} v programski meni."
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 $INIT_UNINSTALLER_RUNNING "Program za odstranjevanje namestitve je že zagnan."
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_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_DetailPrint "Creando Accesos Directos de Escritorio"
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Acceso Directo al Lanzador Rápido"
StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Creando accesos directos de escritorio"
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_APPLICATION_Desc "${APPLICATION_NAME} esencial."
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 $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 $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 $UAC_ERROR_ELEVATE "No se ha podido elevar, error:"
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-https.png</file>
<file>resources/lock-https@2x.png</file>
<file>resources/accounts.png</file>
<file>resources/account.png</file>
</qresource>
</RCC>

View File

@@ -40,7 +40,7 @@ set(__get_git_revision_description YES)
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
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")
while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories
set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}")
@@ -53,6 +53,13 @@ function(get_git_head_revision _refspecvar _hashvar)
endif()
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
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")
if(NOT EXISTS "${GIT_DATA}")
file(MAKE_DIRECTORY "${GIT_DATA}")

View File

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

View File

@@ -2,25 +2,21 @@
# Redistribution and use is allowed according to the terms of the BSD license.
# 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)
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
OUTPUT_VARIABLE GCC_VERSION)
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)
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)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
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 (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER MATCHES "clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
endif (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER MATCHES "clang")
# TODO: handle msvc compilers warnings?
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
endif(DEFINED MIRALL_FATAL_WARNINGS)

View File

@@ -573,15 +573,6 @@ int csync_commit(CSYNC *ctx) {
}
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);
ctx->remote.read_from_db = 0;

View File

@@ -91,6 +91,7 @@ enum csync_status_codes_e {
CSYNC_STATUS_OUT_OF_SPACE,
CSYNC_STATUS_QUOTA_EXCEEDED, /* UNUSED */
CSYNC_STATUS_SERVICE_UNAVAILABLE,
CSYNC_STATUS_STORAGE_UNAVAILABLE,
CSYNC_STATUS_FILE_SIZE_ERROR,
CSYNC_STATUS_CONTEXT_LOST,
CSYNC_STATUS_MERGE_FILETREE_ERROR,
@@ -104,6 +105,7 @@ enum csync_status_codes_e {
CSYNC_STATUS_INDIVIDUAL_IS_HARDLINK,
CSYNC_STATUS_INDIVIDUAL_IGNORE_LIST,
CSYNC_STATUS_INDIVIDUAL_IS_INVALID_CHARS,
CSYNC_STATUS_INDIVIDUAL_EXCLUDE_LONG_FILENAME,
CYSNC_STATUS_FILE_LOCKED_OR_OPEN
};
@@ -335,7 +337,7 @@ int csync_update(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.
*

View File

@@ -231,6 +231,14 @@ CSYNC_EXCLUDE_TYPE csync_excluded_no_ctx(c_strlist_t *excludes, const char *path
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
// Windows cannot sync files ending in spaces (#2176). It also cannot
// 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_EXCLUDE_AND_REMOVE,
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;

View File

@@ -45,6 +45,7 @@
#define ERRNO_ERROR_STRING CSYNC_CUSTOM_ERRNO_BASE+13
#define ERRNO_SERVICE_UNAVAILABLE CSYNC_CUSTOM_ERRNO_BASE+14
#define ERRNO_USER_ABORT CSYNC_CUSTOM_ERRNO_BASE+16
#define ERRNO_STORAGE_UNAVAILABLE CSYNC_CUSTOM_ERRNO_BASE+17
#endif /* _CSYNC_MACROS_H */
/* 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:
status = CSYNC_STATUS_SERVICE_UNAVAILABLE; /* Service temporarily down */
break;
case ERRNO_STORAGE_UNAVAILABLE:
status = CSYNC_STATUS_STORAGE_UNAVAILABLE; /* Storage temporarily unavailable */
break;
case EFBIG:
status = CSYNC_STATUS_FILE_SIZE_ERROR; /* File larger than 2MB */
break;

View File

@@ -416,6 +416,8 @@ out:
st->error_status = CSYNC_STATUS_INDIVIDUAL_IGNORE_LIST; /* File listed on ignore list. */
} else if (excluded == CSYNC_FILE_EXCLUDE_INVALID_CHAR) {
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
@@ -619,11 +621,11 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
if (asp < 0) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "asprintf failed!");
}
} else if(errno == ERRNO_SERVICE_UNAVAILABLE) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Service was not available!");
} else if(errno == ERRNO_STORAGE_UNAVAILABLE) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Storage was not available!");
if (ctx->current_fs) {
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( previous_fs ) {
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;
case LOCAL_REPLICA:
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);
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
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.
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.1/windows:mingw.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:/win32/openSUSE_13.2/windows:mingw:win32.repo
2. Install the cross-compiler packages and the cross-compiled dependencies::
zypper install cmake make mingw32-cross-binutils mingw32-cross-cpp mingw32-cross-gcc \
mingw32-cross-gcc-c++ mingw32-cross-pkg-config mingw32-filesystem \
mingw32-headers mingw32-runtime site-config mingw32-libqt4-sql \
mingw32-libqt4-sql-sqlite mingw32-sqlite mingw32-libsqlite-devel \
mingw32-dlfcn-devel mingw32-libssh2-devel kdewin-png2ico \
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
mingw32-cross-gcc-c++ mingw32-cross-pkg-config mingw32-filesystem \
mingw32-headers mingw32-runtime site-config \
mingw32-cross-libqt5-qmake mingw32-cross-libqt5-qttools mingw32-libqt5* \
mingw32-cross-nsis
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!
::
# 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-uac-0-3.1.x86_64.rpm
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
this parameter to the call to cmake, enter
``-DCMAKE_TOOLCHAIN_FILE=../client/admin/win/Toolchain-mingw32-openSUSE.cmake``.
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.
.. _`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
--------------------------
@@ -243,4 +255,5 @@ The following are known cmake parameters:
.. _Homebrew: http://mxcl.github.com/homebrew/
.. _`OpenSSL Windows Build`: http://slproweb.com/products/Win32OpenSSL.html
.. _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

View File

@@ -81,7 +81,7 @@ file manager integration works.
.. image:: images/client8.png
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
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"]];
_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
@@ -111,7 +111,7 @@ static ContentManager* sharedInstance = nil;
}else if( [result isEqualToString:@"NOP"]) {
// Nothing.
} else {
NSLog(@"Unknown status code %@", result);
NSLog(@"SyncState: Unknown status code %@", result);
}
NSString* normalizedPath = [path decomposedStringWithCanonicalMapping];
@@ -129,7 +129,7 @@ static ContentManager* sharedInstance = nil;
//NSLog(@"%@ %@", NSStringFromSelector(_cmd), path);
if (!_fileIconsEnabled)
{
NSLog(@"Icons are NOT ENABLED!");
NSLog(@"SyncState: Icons are NOT ENABLED!");
// return nil;
}
@@ -284,7 +284,7 @@ static ContentManager* sharedInstance = nil;
}
else
{
NSLog(@"OwnCloudFinder: refreshing icon badges failed");
NSLog(@"SyncState: refreshing icon badges failed");
return;
}
@@ -333,7 +333,7 @@ static ContentManager* sharedInstance = nil;
}
else
{
NSLog(@"OwnCloudFinder: refreshing icon badges failed");
NSLog(@"SyncState: refreshing icon badges failed");
return;
}

View File

@@ -44,12 +44,12 @@ static BOOL installed = NO;
{
if (installed)
{
NSLog(@"OwnCloudFinder: already installed");
// NSLog(@"SyncStateFinder: already installed");
return;
}
NSLog(@"OwnCloudFinder: installing ownCloud Shell extension");
// NSLog(@"SyncStateFinder: installing SyncState Shell extension");
[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(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)
@@ -81,19 +81,19 @@ static BOOL installed = NO;
installed = YES;
NSLog(@"OwnCloudFinder: installed");
// NSLog(@"SyncStateFinder: installed");
}
+ (void)uninstall
{
if (!installed)
{
NSLog(@"OwnCloudFinder: not installed");
// NSLog(@"SyncStateFinder: not installed");
return;
}
NSLog(@"OwnCloudFinder: uninstalling");
// NSLog(@"SyncStateFinder: uninstalling");
[[ContentManager sharedInstance] dealloc];
@@ -119,7 +119,7 @@ static BOOL installed = NO;
installed = NO;
NSLog(@"OwnCloudFinder: uninstalled");
// NSLog(@"SyncStateFinder: uninstalled");
}
@end

View File

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

View File

@@ -138,7 +138,7 @@ static RequestManager* sharedInstance = nil;
ContentManager *contentman = [ContentManager sharedInstance];
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"] ) {
NSString *path = [chunks objectAtIndex:2];
if( [chunks count] > 3 ) {
@@ -154,7 +154,7 @@ static RequestManager* sharedInstance = nil;
} else if( [[chunks objectAtIndex:0 ] isEqualToString:@"REGISTER_PATH"] ) {
NSNumber *one = [NSNumber numberWithInt:1];
NSString *path = [chunks objectAtIndex:1];
NSLog(@"Registering path: %@", path);
// NSLog(@"Registering path: %@", path);
[_registeredPathes setObject:one forKey:path];
[contentman repaintAllWindows];
@@ -168,12 +168,12 @@ static RequestManager* sharedInstance = nil;
[[ContentManager sharedInstance] loadIconResourcePath:path];
} else if( [[chunks objectAtIndex:0 ] isEqualToString:@"SHARE_MENU_TITLE"] ) {
_shareMenuTitle = [[chunks objectAtIndex:1] copy];
NSLog(@"Received shar menu title: %@", _shareMenuTitle);
// NSLog(@"Received shar menu title: %@", _shareMenuTitle);
} else {
NSLog(@"Unknown command %@", [chunks objectAtIndex:0]);
NSLog(@"SyncState: Unknown command %@", [chunks objectAtIndex:0]);
}
} else if (tag != READ_TAG) {
NSLog(@"Received unknown tag %ld <%@>", tag, answer);
NSLog(@"SyncState: Received unknown tag %ld <%@>", tag, answer);
}
// Read on and on
NSData* stop = [@"\n" dataUsingEncoding:NSUTF8StringEncoding];
@@ -188,13 +188,13 @@ static RequestManager* sharedInstance = nil;
}
-(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;
[self askOnSocket:@"" query:@"SHARE_MENU_TITLE"];
if( [_requestQueue count] > 0 ) {
NSLog( @"We have to empty the queue");
// NSLog( @"We have to empty the queue");
for( NSString *path in _requestQueue ) {
[self askOnSocket:path query:@"RETRIEVE_FILE_STATUS"];
}
@@ -211,7 +211,7 @@ static RequestManager* sharedInstance = nil;
- (void)socketDidDisconnect:(GCDAsyncSocket*)socket withError:(NSError*)err
{
NSLog(@"Socket DISconnected! %@", [err localizedDescription]);
// NSLog(@"Socket DISconnected! %@", [err localizedDescription]);
_isConnected = NO;
@@ -272,7 +272,7 @@ static RequestManager* sharedInstance = nil;
if (!pnsError && paths && [paths count] > 0) {
NSString *currentLatestPath = nil;
if (paths.count > 1) {
NSLog(@"Possible paths: %@", paths);
// NSLog(@"Possible paths: %@", paths);
}
for (int i = 0; i < paths.count; i++) {
NSString *currentPath = [syncStateHelperDir stringByAppendingPathComponent:[paths objectAtIndex:i]];
@@ -288,7 +288,7 @@ static RequestManager* sharedInstance = nil;
}
}
if (url) {
NSLog(@"Connect Socket to %@", url);
// NSLog(@"Connect Socket to %@", url);
[_socket connectToUrl:url withTimeout:1 error:&err];
}
}
@@ -296,7 +296,7 @@ static RequestManager* sharedInstance = nil;
- (void)menuItemClicked:(NSDictionary*)actionDictionary
{
NSLog(@"RequestManager menuItemClicked %@", actionDictionary);
// NSLog(@"RequestManager menuItemClicked %@", actionDictionary);
NSArray *filePaths = [actionDictionary valueForKey:@"files"];
for (int i = 0; i < filePaths.count; i++) {
[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 FINDER_MIN_TESTED_VERSION @"10.7"
#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);
@@ -78,14 +78,14 @@ static OSErr loadBundle(LNBundleType type, AppleEvent* reply, long refcon) {
minVersion = FINDER_MIN_TESTED_VERSION;
break;
default:
NSLog(@"Failed to load bundle for type %d", type);
NSLog(@"SyncStateInjector: Failed to load bundle for type %d", type);
return 8;
break;
}
if (isLoaded) {
NSLog(@"OwnCloudInjector: %@ already loaded.", bundleName);
// NSLog(@"SyncStateInjector: %@ already loaded.", bundleName);
return noErr;
}
@@ -149,7 +149,7 @@ static OSErr loadBundle(LNBundleType type, AppleEvent* reply, long refcon) {
}
id principalClassObject = NSClassFromString(NSStringFromClass(principalClass));
if ([principalClassObject respondsToSelector:@selector(install)]) {
NSLog(@"LiferayNativityInjector: Installing %@ ...", bundleName);
// NSLog(@"SyncStateInjector: Installing %@ ...", bundleName);
[principalClassObject install];
}
@@ -186,7 +186,7 @@ EXPORT OSErr HandleLoadEvent(const AppleEvent* ev, AppleEvent* reply, long refco
NSString* injectorVersion = [injectorBundle objectForInfoDictionaryKey:@"CFBundleVersion"];
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;
}
@@ -232,7 +232,7 @@ EXPORT OSErr HandleUnloadEvent(const AppleEvent* ev, AppleEvent* reply, long ref
@autoreleasepool {
@try {
if (!liferayNativityLoaded) {
NSLog(@"OwnCloudInjector: not loaded.");
// NSLog(@"SyncStateInjector: not loaded.");
return noErr;
}
@@ -253,7 +253,7 @@ EXPORT OSErr HandleUnloadEvent(const AppleEvent* ev, AppleEvent* reply, long ref
}
id principalClassObject = NSClassFromString(NSStringFromClass(principalClass));
if ([principalClassObject respondsToSelector:@selector(uninstall)]) {
NSLog(@"LiferayNativityInjector: Uninstalling %@ ...", bundleName);
// NSLog(@"SyncStateInjector: Uninstalling %@ ...", bundleName);
[principalClassObject uninstall];
}

View File

@@ -21,8 +21,10 @@ from gi.repository import GObject, Nautilus
# do not touch the following line.
appname = 'ownCloud'
def get_local_path(path):
return path.replace("file://", "")
def get_local_path(url):
if url[0:7] == 'file://':
url = url[7:]
return urllib.unquote(url)
def get_runtime_dir():
"""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':
return
filename = urllib.unquote(item.get_uri()[7:])
filename = get_local_path(item.get_uri())
if item.is_directory():
filename += '/'

View File

@@ -34,28 +34,40 @@ using namespace std;
#define PIPE_TIMEOUT 5*1000 //ms
#define SOCK_BUFFER 4096
std::vector<std::wstring> OCClientInterface::WatchedDirectories()
OCClientInterface::ContextMenuInfo OCClientInterface::FetchInfo()
{
auto pipename = std::wstring(L"\\\\.\\pipe\\");
pipename += L"ownCloud";
CommunicationSocket socket;
if (!WaitNamedPipe(pipename.data(), PIPE_TIMEOUT)) {
return std::vector<std::wstring>();
return {};
}
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;
Sleep(50);
while (socket.ReadLine(&response)) {
if (StringUtil::begins_with(response, wstring(L"REGISTER_PATH:"))) {
wstring responsePath = response.substr(14); // length of REGISTER_PATH
watchedDirectories.push_back(responsePath);
int sleptCount = 0;
while (sleptCount < 5) {
if (socket.ReadLine(&response)) {
if (StringUtil::begins_with(response, wstring(L"REGISTER_PATH:"))) {
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)

View File

@@ -43,7 +43,11 @@ class CommunicationSocket;
class OCClientInterface
{
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);
};

View File

@@ -150,8 +150,9 @@ IFACEMETHODIMP OCContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0));
}
OCClientInterface::ContextMenuInfo info = OCClientInterface::FetchInfo();
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)) {
skip = false;
break;
@@ -165,11 +166,12 @@ IFACEMETHODIMP OCContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT
InsertSeperator(hMenu, indexMenu);
indexMenu++;
assert(!info.shareMenuTitle.empty());
MENUITEMINFO mii = { sizeof(mii) };
mii.fMask = MIIM_BITMAP | MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_STATE;
mii.wID = idCmdFirst + IDM_SHARE;
mii.fType = MFT_STRING;
mii.dwTypeData = m_pszMenuText;
mii.dwTypeData = &info.shareMenuTitle[0];
mii.fState = MFS_ENABLED;
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>
<ModuleDefinitionFile>OCContextMenu.def</ModuleDefinitionFile>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>

View File

@@ -28,6 +28,7 @@
#include <algorithm>
#include <iostream>
#include <fstream>
#include <memory>
using namespace std;
@@ -38,9 +39,24 @@ extern HINSTANCE instanceHandle;
#define IDM_DISPLAY 0
#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)
: _referenceCount(1)
, _checker(nullptr)
, _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()
{
@@ -128,9 +134,8 @@ IFACEMETHODIMP OCOverlay::GetPriority(int *pPriority)
IFACEMETHODIMP OCOverlay::IsMemberOf(PCWSTR pwszPath, DWORD dwAttrib)
{
lazyInit();
assert(_checker);
auto watchedDirectories = _checker->WatchedDirectories();
RemotePathChecker* checker = getGlobalChecker();
auto watchedDirectories = checker->WatchedDirectories();
wstring wpath(pwszPath);
wpath.append(L"\\");
@@ -147,7 +152,7 @@ IFACEMETHODIMP OCOverlay::GetPriority(int *pPriority)
}
int state = 0;
if (!_checker->IsMonitoredPath(pwszPath, &state)) {
if (!checker->IsMonitoredPath(pwszPath, &state)) {
return MAKE_HRESULT(S_FALSE, 0, 0);
}
return MAKE_HRESULT(state == _state ? S_OK : S_FALSE, 0, 0);

View File

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

View File

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

View File

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

View File

@@ -67,6 +67,10 @@ public:
/// The account is successfully talking to the server.
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.
/// We assume this may resolve itself over time and will try
/// again automatically.
@@ -96,6 +100,7 @@ public:
void setSignedOut(bool signedOut);
bool isConnected() const;
bool isConnectedOrMaintenance() const;
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 "addcertificatedialog.h"
#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
#define ADDCERTIFICATEDIALOG_H

View File

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

View File

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

View File

@@ -29,6 +29,7 @@
#include "syncengine.h"
#include "syncrunfilelog.h"
#include "theme.h"
#include "filesystem.h"
#include "creds/abstractcredentials.h"
@@ -145,12 +146,12 @@ AccountState* Folder::accountState() const
void Folder::checkLocalPath()
{
QFileInfo fi(_path);
const QFileInfo fi(_path);
if( fi.isDir() && fi.isReadable() ) {
qDebug() << "Checked local path ok";
} else {
if( !fi.exists() ) {
if( !FileSystem::fileExists(_path) ) {
// try to create the local dir
QDir d(_path);
if( d.mkpath(_path) ) {
@@ -158,7 +159,7 @@ void Folder::checkLocalPath()
}
}
// Check directory again
if( !fi.exists() ) {
if( !FileSystem::fileExists(_path) ) {
_syncResult.setErrorString(tr("Local folder %1 does not exist.").arg(_path));
_syncResult.setStatus( SyncResult::SetupError );
} else if( !fi.isDir() ) {
@@ -590,7 +591,7 @@ void Folder::slotThreadTreeWalkResult(const SyncFileItemVector& 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
// (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(treeWalkResult(const SyncFileItemVector&)),
this, SLOT(slotThreadTreeWalkResult(const SyncFileItemVector&)), Qt::QueuedConnection);
connect( _engine.data(), SIGNAL(aboutToPropagate(const SyncFileItemVector&)),
this, SLOT(slotAboutToPropagate(const SyncFileItemVector&)), Qt::QueuedConnection);
connect( _engine.data(), SIGNAL(aboutToPropagate(SyncFileItemVector&)),
this, SLOT(slotAboutToPropagate(SyncFileItemVector&)));
connect(_engine.data(), SIGNAL(started()), SLOT(slotSyncStarted()), Qt::QueuedConnection);
connect(_engine.data(), SIGNAL(finished()), SLOT(slotSyncFinished()), Qt::QueuedConnection);

View File

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

View File

@@ -43,8 +43,9 @@ FolderMan* FolderMan::_instance = 0;
* The minimum time between a sync being requested and it
* being executed in milliseconds.
*
* This delay must be larger than the minFileAgeForUpload in
* the propagator.
* This delay must be large enough to ensure fileIsStillChanging()
* in the upload propagator doesn't decide to skip the file because
* the modification was too recent.
*/
static qint64 msBetweenRequestAndSync = 2000;
@@ -93,27 +94,25 @@ OCC::Folder::Map FolderMan::map()
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 )
{
Folder *f = folder(alias);
if( f ) {
if( _socketApi ) {
_socketApi->slotUnregisterPath(alias);
}
_folderChangeSignalMapper->removeMappings(f);
if( _folderWatchers.contains(alias)) {
_folderWatchers.remove(alias);
}
_folderMap.remove( alias );
delete f;
Folder* f = folder(alias);
if( !f ) {
return;
}
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;
@@ -121,7 +120,9 @@ int FolderMan::unloadAllFolders()
Folder::MapIterator i(_folderMap);
while (i.hasNext()) {
i.next();
Folder* f = i.value();
unloadFolder(i.key());
delete f;
cnt++;
}
_lastSyncFolder.clear();
@@ -187,7 +188,7 @@ int FolderMan::setupFolders()
{
qDebug() << "* Setup folders from " << _folderConfigPath;
unloadAllFolders();
unloadAndDeleteAllFolders();
ConfigFile cfg;
QDir storageDir(cfg.configPath());
@@ -760,48 +761,37 @@ void FolderMan::removeAllFolderDefinitions()
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 ) {
// terminate if the sync is currently underway.
qDebug() << "Removing " << alias;
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();
}
removeFolder(alias);
}
// remove a folder from the map. Should be sure n
void FolderMan::removeFolder( const QString& alias )
{
Folder *f = 0;
_scheduleQueue.removeAll(alias);
if( _folderMap.contains( alias )) {
qDebug() << "Removing " << alias;
f = _folderMap[alias]; // do not remove from the map, that is done in unloadFolder.
} else {
qDebug() << "!! Can not remove " << alias << ", not in folderMap.";
f->wipe();
f->setSyncPaused(true);
// remove the folder configuration
QFile file(f->configFile() );
if( file.exists() ) {
qDebug() << "Remove folder config file " << file.fileName();
file.remove();
}
if( f ) {
f->wipe();
// 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();
unloadFolder( alias );
if( !currentlyRunning ) {
delete f;
}
}

View File

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

View File

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

View File

@@ -68,7 +68,7 @@ LogBrowser::LogBrowser(QWidget *parent) :
mainLayout->addLayout( toolLayout );
// Search input field
QLabel *lab = new QLabel(tr("&Search: "));
QLabel *lab = new QLabel(tr("&Search:") + " ");
_findTermEdit = new QLineEdit;
lab->setBuddy( _findTermEdit );
toolLayout->addWidget(lab);
@@ -191,7 +191,7 @@ void LogBrowser::slotSave()
stream << _logWidget->toPlainText();
file.close();
} 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);

View File

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

View File

@@ -221,7 +221,7 @@ void ownCloudGui::slotComputeOverallSyncStatus()
_tray->setToolTip(tr("Please sign in"));
return;
}
if (!a->isConnected()) {
if (!a->isConnectedOrMaintenance()) {
_tray->setIcon(Theme::instance()->folderOfflineIcon(true));
_tray->setToolTip(tr("Disconnected from server"));
return;
@@ -432,7 +432,7 @@ void ownCloudGui::setupActions()
connect(_actionLogout, SIGNAL(triggered()), _app, SLOT(slotLogout()));
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()));
} else {
_actionCrash = 0;
@@ -654,7 +654,7 @@ void ownCloudGui::slotShowShareDialog(const QString &sharePath, const QString &l
ShareDialog *w = new ShareDialog(account, sharePath, localPath);
w->getShares();
w->setAttribute( Qt::WA_DeleteOnClose, true );
w->show();
raiseDialog(w);
}

View File

@@ -211,9 +211,11 @@ void OwncloudSetupWizard::testOwnCloudConnect()
{
AccountPtr account = _ocWizard->account();
ValidateDavAuthJob *job = new ValidateDavAuthJob(account, this);
auto *job = new PropfindJob(account, "/", this);
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();
}
@@ -249,7 +251,7 @@ void OwncloudSetupWizard::slotConnectionCheck(QNetworkReply* reply)
_ocWizard->successfulStep();
break;
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, "
"<a href=\"%1\">click here</a> to access the service with your browser.")
.arg(_ocWizard->account()->url().toString());
@@ -274,7 +276,7 @@ void OwncloudSetupWizard::slotCreateLocalAndRemoteFolders(const QString& localFo
// ownCloud is newly created.
_ocWizard->appendToConfigurationLog( tr("Local sync folder %1 already exists, setting it up for sync.<br/><br/>").arg(localFolder));
} 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 ) ) {
Utility::setupFavLink( localFolder );
// FIXME: Create a local sync folder.
@@ -534,24 +536,4 @@ bool DetermineAuthTypeJob::finished()
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

View File

@@ -31,17 +31,6 @@ namespace OCC {
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 {
Q_OBJECT
public:

View File

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

View File

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

View File

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

View File

@@ -69,7 +69,7 @@ SettingsDialog::SettingsDialog(ownCloudGui *gui, QWidget *parent) :
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"));
accountAction->setCheckable(true);
_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 "ui_sharedialog.h"
#include "networkjobs.h"
@@ -25,6 +39,7 @@ ShareDialog::ShareDialog(AccountPtr account, const QString &sharePath, const QSt
_account(account),
_sharePath(sharePath),
_localPath(localPath),
_passwordJobRunning(false),
_public_share_id(0)
{
setAttribute(Qt::WA_DeleteOnClose);
@@ -33,6 +48,11 @@ ShareDialog::ShareDialog(AccountPtr account, const QString &sharePath, const QSt
_ui->pushButton_copy->setText(tr("Copy Link"));
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
// automatically deleted once the dialog dies.
_pi_link = new QProgressIndicator();
@@ -51,6 +71,7 @@ ShareDialog::ShareDialog(AccountPtr account, const QString &sharePath, const QSt
_ui->widget_shareLink->hide();
_ui->lineEdit_password->hide();
_ui->pushButton_setPassword->hide();
_ui->calendar->hide();
QFileInfo f_info(_localPath);
@@ -60,11 +81,18 @@ ShareDialog::ShareDialog(AccountPtr account, const QString &sharePath, const QSt
QString name;
if( f_info.isDir() ) {
name = tr("Share directory %2").arg(_localPath);
name = tr("Share Directory");
} 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->setText(tr("%1 path: %2").arg(Theme::instance()->appNameGUI()).arg(_sharePath));
this->setWindowTitle(tr("%1 Sharing").arg(Theme::instance()->appNameGUI()));
@@ -150,6 +178,10 @@ void ShareDialog::slotPasswordReturnPressed()
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();
QUrl url;
QList<QPair<QString, QString> > requestParams;
@@ -177,6 +209,7 @@ void ShareDialog::setPassword(const QString &password)
job->setPostParams(requestParams);
connect(job, SIGNAL(jobFinished(QString)), this, SLOT(slotPasswordSet(QString)));
job->start();
_passwordJobRunning = true;
}
void ShareDialog::slotPasswordSet(const QString &reply)
@@ -188,15 +221,15 @@ void ShareDialog::slotPasswordSet(const QString &reply)
if (code != 100) {
displayError(code);
} else {
/*
}
/*
* 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
* at this point.
*/
getShares();
}
getShares();
_passwordJobRunning = false;
_pi_password->stopAnimation();
}
@@ -224,44 +257,53 @@ void ShareDialog::slotSharesFetched(const QString &reply)
bool success = false;
QVariantMap json = QtJson::parse(reply, success).toMap();
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();
if (data.value("share_type").toInt() == SHARETYPE_PUBLIC)
{
if (data.value("share_type").toInt() == SHARETYPE_PUBLIC) {
_public_share_id = data.value("id").toULongLong();
_ui->widget_shareLink->show();
_ui->checkBox_shareLink->setChecked(true);
if (data.value("share_with").isValid())
{
if (data.value("share_with").isValid()) {
_ui->checkBox_password->setChecked(true);
_ui->lineEdit_password->setPlaceholderText("********");
_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->setMinimumDate(QDate::currentDate().addDays(1));
_ui->calendar->show();
_ui->checkBox_expire->setChecked(true);
} else {
_ui->calendar->hide();
_ui->checkBox_expire->setChecked(false);
}
const QString versionString = AccountManager::instance()->account()->serverVersion();
QString url;
// From ownCloud server version 8 on, a different share link scheme is used.
if (versionString.contains('.') && versionString.split('.')[0].toInt() >= 8) {
url = Account::concatUrlPath(_account->url(), QString("index.php/s/%1").arg(data.value("token").toString())).toString();
} 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);
}
}
setShareCheckBoxTitle(_shares.count() > 0);
}
void ShareDialog::slotDeleteShareFetched(const QString &reply)
@@ -280,14 +322,17 @@ void ShareDialog::slotDeleteShareFetched(const QString &reply)
_ui->lineEdit_shareLink->clear();
_ui->widget_shareLink->hide();
_ui->lineEdit_password->hide();
_ui->pushButton_setPassword->hide();
_ui->checkBox_expire->setChecked(false);
_ui->calendar->hide();
setShareCheckBoxTitle(false);
}
void ShareDialog::slotCheckBoxShareLinkClicked()
{
if (_ui->checkBox_shareLink->checkState() == Qt::Checked)
{
if (_ui->checkBox_shareLink->checkState() == Qt::Checked) {
_pi_link->startAnimation();
QUrl url = Account::concatUrlPath(_account->url(), QLatin1String("ocs/v1.php/apps/files_sharing/api/v1/shares"));
QList<QPair<QString, QString> > postParams;
@@ -297,9 +342,7 @@ void ShareDialog::slotCheckBoxShareLinkClicked()
job->setPostParams(postParams);
connect(job, SIGNAL(jobFinished(QString)), this, SLOT(slotCreateShareFetched(QString)));
job->start();
}
else
{
} else {
_pi_link->startAnimation();
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);
@@ -334,6 +377,7 @@ void ShareDialog::slotCreateShareFetched(const QString &reply)
_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();
_ui->lineEdit_shareLink->setText(url);
setShareCheckBoxTitle(true);
_ui->widget_shareLink->show();
}
@@ -343,6 +387,7 @@ void ShareDialog::slotCheckBoxPasswordClicked()
if (_ui->checkBox_password->checkState() == Qt::Checked)
{
_ui->lineEdit_password->show();
_ui->pushButton_setPassword->show();
_ui->lineEdit_password->setPlaceholderText(tr("Choose a password for the public link"));
}
else
@@ -351,6 +396,7 @@ void ShareDialog::slotCheckBoxPasswordClicked()
_ui->lineEdit_password->setPlaceholderText(QString());
_pi_password->startAnimation();
_ui->lineEdit_password->hide();
_ui->pushButton_setPassword->hide();
}
}
@@ -393,6 +439,19 @@ int ShareDialog::checkJsonReturnCode(const QString &reply, QString &message)
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)
{
const QString errMsg = tr("OCS API error code: %1").arg(code);
@@ -430,7 +489,7 @@ bool ShareDialog::uploadExternalFile()
FolderMan::instance()->folder(folderName);
if( ! folder ) {
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;
}
@@ -453,7 +512,7 @@ bool ShareDialog::uploadExternalFile()
QFileInfo target(_expectedSyncFile);
if( target.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
// then the file-to-copy we can share it.
_sharePath.clear();
@@ -497,7 +556,7 @@ void ShareDialog::slotNextSyncFinished( const SyncResult& result )
_uploadFails ++;
if( _uploadFails > 2 ) {
// stop the upload job
displayInfo(tr("The file can not be synced."));
displayInfo(tr("The file cannot be synced."));
}
} else {
// it's there and the sync was successful.
@@ -544,13 +603,19 @@ void OcsShareJob::start()
QNetworkRequest req;
req.setRawHeader("OCS-APIREQUEST", "true");
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) {
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();
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
* it under the terms of the GNU General Public License as published by
@@ -74,6 +75,7 @@ private slots:
void slotPushButtonCopyLinkPressed();
void slotThumbnailFetched(const int &statusCode, const QByteArray &reply);
private:
void setShareCheckBoxTitle(bool haveShares);
void displayError(int code);
void displayInfo( const QString& msg );
@@ -85,6 +87,7 @@ private:
int _uploadFails;
QString _expectedSyncFile;
bool _passwordJobRunning;
QList<QVariant> _shares;
qulonglong _public_share_id;
void setPassword(const QString &password);
@@ -94,6 +97,7 @@ private:
QProgressIndicator *_pi_link;
QProgressIndicator *_pi_password;
QProgressIndicator *_pi_date;
};
}

View File

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

View File

@@ -55,7 +55,8 @@ enum csync_exclude_type_e {
CSYNC_FILE_SILENTLY_EXCLUDED,
CSYNC_FILE_EXCLUDE_AND_REMOVE,
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;
@@ -313,7 +314,14 @@ void SocketApi::slotSyncItemDiscovered(const QString &folder, const SyncFileItem
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");
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;
statusString = QLatin1String("NOP");
} else {
const QString file = QDir::cleanPath(argument).mid(QDir::cleanPath(syncFolder->path()).length()+1);
SyncFileStatus fileStatus = this->fileStatus(syncFolder, file, _excludes);
@@ -528,15 +534,20 @@ SyncFileStatus SocketApi::fileStatus(Folder *folder, const QString& systemFileNa
fileNameSlash += QLatin1Char('/');
}
QFileInfo fi(file);
if( !fi.exists() ) {
if( !FileSystem::fileExists(file) ) {
qDebug() << "OO File " << file << " is not existing";
return SyncFileStatus(SyncFileStatus::STATUS_STAT_ERROR);
}
// 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);
}

View File

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

View File

@@ -15,6 +15,7 @@
#include "account.h"
#include "accountstate.h"
#include "utility.h"
#include "theme.h"
#include <QMenu>
#include <QUrl>
@@ -184,7 +185,7 @@ void SslButton::updateAccountState(AccountState *accountState)
oldMenu->deleteLater(); // setMenu do not delete the previous menu.
}
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();
setToolTip(tr("This connection is encrypted using %1 bit %2.\n").arg(cipher.usedBits()).arg(cipher.name()));
QMenu *menu = new QMenu(this);
@@ -217,7 +218,7 @@ void SslButton::updateAccountState(AccountState *accountState)
}
setMenu(menu);
} 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"));
}
}

View File

@@ -67,7 +67,7 @@ OwncloudAdvancedSetupPage::OwncloudAdvancedSetupPage()
_ui.lServerIcon->setText(QString());
_ui.lServerIcon->setPixmap(appIcon.pixmap(48));
_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()

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 "utility.h"
#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
#define OWNCLOUDCONNECTIONMETHODDIALOG_H

View File

@@ -116,11 +116,11 @@ void OwncloudSetupPage::slotUrlChanged(const QString& url)
}
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"
"It is not advisable to use it."));
} 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."));
}
}

View File

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

View File

@@ -21,7 +21,6 @@
#include "wizard/owncloudwizardresultpage.h"
#include "wizard/owncloudwizardcommon.h"
#include "theme.h"
#include "utility.h"
namespace OCC
{
@@ -41,7 +40,7 @@ OwncloudWizardResultPage::OwncloudWizardResultPage()
setSubTitle( QLatin1String(" ") );
_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->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
connect(_ui.pbOpenLocal, SIGNAL(clicked()), SLOT(slotOpenLocal()));

View File

@@ -90,6 +90,7 @@ if(USE_NEON)
list(APPEND libsync_SRCS
propagator_legacy.cpp
)
add_definitions(-DUSE_NEON)
endif(USE_NEON)
# 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)
qt5_use_modules(${synclib_NAME} Network Xml Sql)
qt5_use_modules(${synclib_NAME} Network)
else()
qt5_use_modules(${synclib_NAME} Widgets Network Xml WebKitWidgets Sql)
qt5_use_modules(${synclib_NAME} Widgets Network WebKitWidgets)
endif()
set_target_properties( ${synclib_NAME} PROPERTIES

View File

@@ -380,43 +380,22 @@ void Account::setUrl(const QUrl &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 = tmpUrl.path();
// avoid '//'
if (path.endsWith('/') && concatPath.startsWith('/')) {
path.chop(1);
} // avoid missing '/'
else if (!path.endsWith('/') && !concatPath.startsWith('/')) {
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)) );
}
}
QString path = url.path();
if (! concatPath.isEmpty()) {
// avoid '//'
if (path.endsWith('/') && concatPath.startsWith('/')) {
path.chop(1);
} // avoid missing '/'
else if (!path.endsWith('/') && !concatPath.startsWith('/')) {
path += QLatin1Char('/');
}
path += concatPath; // put the complete path together
}
QUrl tmpUrl = url;
tmpUrl.setPath(path);
if( queryItems.size() > 0 ) {
tmpUrl.setQueryItems(queryItems);

View File

@@ -136,7 +136,8 @@ public:
void setSslErrorHandler(AbstractSslErrorHandler *handler);
// 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
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");
case UserCanceledCredentials:
return QLatin1String("User canceled credentials");
case ServerMaintenance:
return QLatin1String("Server in maintenance mode");
case Timeout:
return QLatin1String("Timeout");
}
@@ -138,7 +140,7 @@ void ConnectionValidator::slotAuthFailed(QNetworkReply *reply)
Status stat = Timeout;
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() << "******** Password is wrong!";
_errors << tr("The provided credentials are not correct");
@@ -146,6 +148,18 @@ void ConnectionValidator::slotAuthFailed(QNetworkReply *reply)
} else if( reply->error() != QNetworkReply::NoError ) {
_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 );

View File

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

View File

@@ -19,6 +19,7 @@
#include <QWebPage>
#include <QMessageBox>
#include <QNetworkReply>
#include <QSettings>
#include "creds/shibboleth/shibbolethwebview.h"
#include "creds/shibbolethcredentials.h"
@@ -26,6 +27,11 @@
#include "logger.h"
#include "accessmanager.h"
#include "theme.h"
#include "configfile.h"
namespace {
const char ShibbolethWebViewGeometryC[] = "ShibbolethWebView/Geometry";
}
namespace OCC
{
@@ -39,6 +45,7 @@ ShibbolethWebView::ShibbolethWebView(AccountPtr account, QWidget* parent)
// no minimize
setWindowFlags(Qt::Dialog);
setAttribute(Qt::WA_DeleteOnClose);
QWebPage* page = new QWebPage(this);
page->setNetworkAccessManager(account->networkAccessManager());
connect(page, SIGNAL(loadStarted()),
@@ -60,10 +67,18 @@ ShibbolethWebView::ShibbolethWebView(AccountPtr account, QWidget* parent)
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."));
}
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()
{
ConfigFile config;
QSettings settings(config.configFile());
settings.setValue(ShibbolethWebViewGeometryC, saveGeometry());
}
void ShibbolethWebView::onNewCookiesForUrl (const QList<QNetworkCookie>& cookieList, const QUrl& url)
@@ -105,7 +120,7 @@ void ShibbolethWebView::slotLoadFinished(bool success)
}
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) {

View File

@@ -68,7 +68,6 @@ int getauth(const char *prompt,
return re;
}
const char userC[] = "user";
const char authenticationFailedC[] = "owncloud-authentication-failed";
} // ns
@@ -80,8 +79,8 @@ public:
: AccessManager(parent), _cred(cred) {}
protected:
QNetworkReply *createRequest(Operation op, const QNetworkRequest &request, QIODevice *outgoingData) {
if (_cred->user().isEmpty() || _cred->password().isEmpty() || _cred->_token.isEmpty()) {
qWarning() << Q_FUNC_INFO << "Empty user/password/token provided!";
if (_cred->user().isEmpty() || _cred->password().isEmpty()) {
qWarning() << Q_FUNC_INFO << "Empty user/password provided!";
}
QNetworkRequest req(request);
@@ -91,7 +90,9 @@ protected:
// A pre-authenticated cookie
QByteArray token = _cred->_token.toUtf8();
setRawCookie(token, request.url());
if (token.length() > 0) {
setRawCookie(token, request.url());
}
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);
if (updateJob) {
// Don't wanna overload the UI
if (!updateJob->lastUpdateProgressCallbackCall.isValid()) {
updateJob->lastUpdateProgressCallbackCall.restart(); // first call
} else if (updateJob->lastUpdateProgressCallbackCall.elapsed() < 200) {
if (!updateJob->_lastUpdateProgressCallbackCall.isValid()) {
updateJob->_lastUpdateProgressCallbackCall.restart(); // first call
} else if (updateJob->_lastUpdateProgressCallbackCall.elapsed() < 200) {
return;
} else {
updateJob->lastUpdateProgressCallbackCall.restart();
updateJob->_lastUpdateProgressCallbackCall.restart();
}
QString path(QUrl::fromPercentEncoding(QByteArray(dirUrl)).section('/', -1));
emit updateJob->folderDiscovered(local, path);
QByteArray pPath(dirUrl);
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;
switch(err) {
@@ -143,8 +147,11 @@ int get_errno_from_http_errcode( int err ) {
new_errno = EIO;
break;
case 503: /* Service Unavailable */
new_errno = ERRNO_SERVICE_UNAVAILABLE;
// FIXME Distinguish between service unavailable and storage unavilable
if (reason == "Storage not available") {
new_errno = ERRNO_STORAGE_UNAVAILABLE;
} else {
new_errno = ERRNO_SERVICE_UNAVAILABLE;
}
break;
case 413: /* Request Entity too Large */
new_errno = EFBIG;
@@ -166,6 +173,11 @@ void DiscoverySingleDirectoryJob::start()
{
// Start the actual HTTP job
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>)),
this, SLOT(directoryListingIteratedSlot(QString,QMap<QString,QString>)));
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();
int httpCode = r->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QString httpReason = r->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
QString msg = r->errorString();
int errnoCode = 0;
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;
} else if (httpCode != 207) {
errnoCode = get_errno_from_http_errcode(httpCode);
} else if (!contentType.contains("application/xml; charset=utf-8")) {
msg = QLatin1String("Server error: PROPFIND reply is not XML formatted!");
errnoCode = ERRNO_WRONG_CONTENT;
@@ -300,6 +313,15 @@ void DiscoveryMainThread::setupHooks(DiscoveryJob *discoveryJob, const QString &
connect(discoveryJob, SIGNAL(doOpendirSignal(QString,DiscoveryDirectoryResult*)),
this, SLOT(doOpendirSlot(QString,DiscoveryDirectoryResult*)),
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
@@ -314,8 +336,9 @@ void DiscoveryMainThread::doOpendirSlot(QString subPath, DiscoveryDirectoryResul
while (fullPath.endsWith('/')) {
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
_currentDiscoveryDirectoryResult = r;
@@ -410,7 +433,7 @@ csync_vio_handle_t* DiscoveryJob::remote_vio_opendir_hook (const char *url,
directoryResult->code = EIO;
discoveryJob->_vioMutex.lock();
QString qurl = QString::fromUtf8(url);
const QString qurl = QString::fromUtf8(url);
emit discoveryJob->doOpendirSignal(qurl, directoryResult);
discoveryJob->_vioWaitCondition.wait(&discoveryJob->_vioMutex, ULONG_MAX); // FIXME timeout?
discoveryJob->_vioMutex.unlock();
@@ -421,6 +444,8 @@ csync_vio_handle_t* DiscoveryJob::remote_vio_opendir_hook (const char *url,
if (directoryResult->code != 0) {
qDebug() << Q_FUNC_INFO << directoryResult->code << "when opening" << url;
errno = directoryResult->code;
// save the error string to the context
discoveryJob->_csync_ctx->error_string = qstrdup( directoryResult->msg.toUtf8().constData() );
return NULL;
}
@@ -450,9 +475,11 @@ void DiscoveryJob::remote_vio_closedir_hook (csync_vio_handle_t *dhandle, void
{
DiscoveryJob *discoveryJob = static_cast<DiscoveryJob*>(userdata);
if (discoveryJob) {
qDebug() << Q_FUNC_INFO << discoveryJob;
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
emit discoveryJob->doClosedirSignal(path);
}
}
@@ -472,7 +499,7 @@ void DiscoveryJob::start() {
csync_set_log_callback(_log_callback);
csync_set_log_level(_log_level);
csync_set_log_userdata(_log_userdata);
lastUpdateProgressCallbackCall.invalidate();
_lastUpdateProgressCallbackCall.invalidate();
int ret = csync_update(_csync_ctx);
_csync_ctx->checkSelectiveSyncBlackListHook = 0;

View File

@@ -87,7 +87,16 @@ public:
DiscoveryMainThread(AccountPtr account) : QObject(), _account(account), _currentDiscoveryDirectoryResult(0) {
}
void deleteCacheEntry(QString path) {
//qDebug() << path << _directoryContents.value(path).count();
foreach (csync_vio_file_stat_t* stat, _directoryContents.value(path)) {
csync_vio_file_stat_destroy(stat);
}
_directoryContents.remove(path);
}
~DiscoveryMainThread() {
// Delete the _contents_ of the list-map explicitly:
foreach (const QLinkedList<csync_vio_file_stat_t*> & list, _directoryContents) {
foreach (csync_vio_file_stat_t* stat, list) {
csync_vio_file_stat_destroy(stat);
@@ -100,6 +109,7 @@ public:
public slots:
// From DiscoveryJob:
void doOpendirSlot(QString url, DiscoveryDirectoryResult* );
void doClosedirSlot(QString path);
// From Job:
void singleDirectoryJobResultSlot(QLinkedList<csync_vio_file_stat_t*>);
@@ -117,11 +127,11 @@ public:
class DiscoveryJob : public QObject {
Q_OBJECT
friend class DiscoveryMainThread;
CSYNC *_csync_ctx;
csync_log_callback _log_callback;
int _log_level;
void* _log_userdata;
QElapsedTimer lastUpdateProgressCallbackCall;
CSYNC *_csync_ctx;
csync_log_callback _log_callback;
int _log_level;
void* _log_userdata;
QElapsedTimer _lastUpdateProgressCallbackCall;
/**
* return true if the given path should be synced,
@@ -164,6 +174,8 @@ signals:
// After the discovery job has been woken up again (_vioWaitCondition)
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.
// ### FIXME
success = true;
bool destExists = QFileInfo::exists(destinationFileName);
bool destExists = fileExists(destinationFileName);
if( destExists && !QFile::remove(destinationFileName) ) {
*errorString = orig.errorString();
qDebug() << Q_FUNC_INFO << "Target file could not be removed.";
@@ -214,26 +214,69 @@ bool FileSystem::openFileSharedRead(QFile* file, QString* error)
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)
{
#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.
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;
return getSizeWithCsync(filename);
}
#endif
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
QString FileSystem::fileSystemForPath(const QString & path)
{

View File

@@ -14,11 +14,13 @@
#pragma once
#include <QString>
#include <QFile>
#include <ctime>
#include <owncloudlib.h>
class QFile;
class QFileInfo;
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
* 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);
@@ -50,6 +52,13 @@ bool setModTime(const QString &filename, time_t modTime);
*/
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
* already exists

View File

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

View File

@@ -43,6 +43,7 @@ class OWNCLOUDSYNC_EXPORT Logger : public QObject
public:
void log(Log log);
void doLog(const QString &log);
static void csyncLog( 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()
{
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;
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"
"<d:propfind xmlns:d=\"DAV:\" xmlns:oc=\"http://owncloud.org/ns\">\n"
" <d:prop>\n"
" <d:resourcetype/>\n"
" <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"
+ propStr +
" </d:prop>\n"
"</d:propfind>\n");
QBuffer *buf = new QBuffer(this);
@@ -575,7 +595,7 @@ void PropfindJob::start()
QList<QByteArray> properties = _properties;
if (properties.isEmpty()) {
properties << "allprop";
qWarning() << "Propfind with no properties!";
}
QNetworkRequest req;
req.setRawHeader("Depth", "0");

View File

@@ -136,24 +136,52 @@ public:
void start() Q_DECL_OVERRIDE;
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:
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 finishedWithoutError();
private slots:
virtual bool finished() Q_DECL_OVERRIDE;
private:
QList<QByteArray> _properties;
};
/**
* @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
public:
explicit PropfindJob(AccountPtr account, const QString &path, QObject *parent = 0);
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);
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) {
status = SyncFileItem::Restoration;
} else {
_item._errorString += tr("; Restoration Failed: ") + errorString;
_item._errorString += tr("; Restoration Failed: %1").arg(errorString);
}
} else {
if( _item._errorString.isEmpty() ) {
@@ -101,7 +101,7 @@ void PropagateItemJob::done(SyncFileItem::Status status, const QString &errorStr
if (blacklist(_propagator->_journal, _item) && _item._hasBlacklistEntry) {
// do not error if the item was, and continues to be, blacklisted
status = SyncFileItem::FileIgnored;
_item._errorString.prepend(tr("Continue blacklisting: "));
_item._errorString.prepend(tr("Continue blacklisting:") + " ");
}
break;
case SyncFileItem::Success:

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