Skip to content
Commits on Source (101)
......@@ -14,7 +14,6 @@ build*
cscope.*
tags
t1.cfg
debian/files
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
......
9a1f736e306f135628e77bca5c1edeed8b1f3736
cd60c2b88ac858339637575f124c58d88b42e78c
ChangeLog
=========
version 2.4.0 (2017-12-XX)
version 2.4.1 (2018-02-xx)
* Ignore files with file names that can't be encoded for the filesystem (#6287, #5676, #5719)
* Issues: Speed up insertion and add hard upper limit (#6272)
* Notifications: Fix "Dismiss" action
* Notifications: Fix timer invocation on macOS
* Notifications: Immediately poll when account online
* Protocol: Remove entries for auto resolved conflicts (#6316)
* owncloudcmd: Set proxy before capabilities call (#6281)
* owncloudcmd: Do not do the capability call when --nonshib is passed
* Avatars: Use old location for servers <10 (#6279)
* Link shares: Change default share name (#6298)
* Sharing: Use maximum allowed permissions for new share (#6346)
* Nautilus integration: Work with python2 and python3
* Windows: Don't delete contents behind directory junctions (#6322)
* SyncJournal: Don't use LIKE with paths (#6322)
* Fix setting launch-on-startup when the first account is set up (#6347)
* HTTP2: Only allow with Qt 5.9.4 (#6285)
* Crash fixes
version 2.4.0 (2017-12-21)
* If you're using 2.4.0 alpha1, please upgrade as previous alphas/rcs had an issue with hidden files and renames!
* OAuth2 authentication support by opening external browser (#5668)
* Shibboleth: Change to use OAuth2 if supported (#6198)
......
set( MIRALL_VERSION_MAJOR 2 )
set( MIRALL_VERSION_MINOR 4 )
set( MIRALL_VERSION_PATCH 0 )
set( MIRALL_VERSION_YEAR 2017 )
set( MIRALL_VERSION_PATCH 1 )
set( MIRALL_VERSION_YEAR 2018 )
set( MIRALL_SOVERSION 0 )
if ( NOT DEFINED MIRALL_VERSION_SUFFIX )
......
owncloud-client (2.4.0+dfsg-1~bpo9+1) stretch-backports; urgency=medium
owncloud-client (2.4.1+dfsg-1~bpo9+1) stretch-backports; urgency=medium
* debian/gbp.conf: Set debian-branch to stretch-backports.
* Revert "Bump compat level to 11 ( no changes needed)."
* Rebuild for stretch-backports.
-- Alexander GQ Gerasiov <gq@debian.org> Tue, 09 Jan 2018 00:50:00 +0300
-- Alexander GQ Gerasiov <gq@debian.org> Wed, 04 Apr 2018 14:51:06 +0300
owncloud-client (2.4.1+dfsg-1) unstable; urgency=medium
* New upstream release.
* fix some typos in patches.
* update vcs links to salsa.
-- Sandro Knauß <hefee@debian.org> Thu, 29 Mar 2018 13:44:36 +0200
owncloud-client (2.4.0+dfsg-1) unstable; urgency=medium
......
......@@ -32,8 +32,8 @@ Build-Depends-Indep: texlive-fonts-recommended,
texlive-latex-recommended,
xsltproc
X-Python3-Version: >= 3.0
Vcs-Git: https://anonscm.debian.org/git/pkg-owncloud/owncloud-client.git
Vcs-Browser: https://anonscm.debian.org/cgit/pkg-owncloud/owncloud-client.git
Vcs-Git: https://salsa.debian.org/owncloud-team/owncloud-client.git
Vcs-Browser: https://salsa.debian.org/owncloud-team/owncloud-client
Standards-Version: 4.1.3
Homepage: https://owncloud.org/sync-clients/
......
owncloud-client_2.4.1+dfsg-1_source.buildinfo net optional
Description: Don't modify build flags within the package
For beeing able to have full control over the build process, we need
For being able to have full control over the build process, we need
full control over the build flags set. That's why it is recommended to disable
any modification from these flags from package side.
Author: Sandro Knauß <hefee@debian.org>
......
Description: Ignore the admin directory completly
Description: Ignore the admin directory completely
In the admin directory are only files for windows and mac.
There are files with no opensource license, so we removed the dir completly.
There are files with no opensource license, so we removed the dir completely.
Author: Sandro Knauß <hefee@debian.org>
Origin: debian
Last-Update: 2014-10-11
......
......@@ -5,7 +5,7 @@ Description: timestamps_from_cpp_macros
.
In debian we don't build owncloud from a random git hash, so we can remove
the line, of which git hash we create the software and when can be removed
completly.
completely.
Author: Sandro Knauß <hefee@debian.org>
Origin: Debian
Last-Update: 2015-08-22
......
......@@ -98,6 +98,186 @@ X-GNOME-Autostart-Delay=3
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
Comment[oc]=@APPLICATION_NAME@ sincronizacion del client
GenericName[oc]=Dorsièr de Sincronizacion
......@@ -181,6 +361,7 @@ Icon[it]=@APPLICATION_EXECUTABLE@
Comment[ko]=@APPLICATION_NAME@ 데스크톱 동기화 클라이언트
GenericName[ko]=폴더 동기화
Name[ko]=@APPLICATION_NAME@ 데스크톱 동기화 클라이언트
Icon[ko]=@APPLICATION_EXECUTABLE@
Comment[hu_HU]=@APPLICATION_NAME@ asztali szinkronizációs kliens
GenericName[hu_HU]=Könyvtár szinkronizálás
Name[hu_HU]=@APPLICATION_NAME@ asztali szinkr. kliens
......
......@@ -15,8 +15,13 @@
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
import sys
python3 = sys.version_info[0] >= 3
import os
import urllib
if python3:
import urllib.parse
import socket
import tempfile
......@@ -30,11 +35,11 @@ appname = 'ownCloud'
print("Initializing "+appname+"-client-nautilus extension")
def get_local_path(url):
if url[0:7] == 'file://':
url = url[7:]
return urllib.unquote(url)
unquote = urllib.parse.unquote if python3 else urllib.unquote
return unquote(url)
def get_runtime_dir():
"""Returns the value of $XDG_RUNTIME_DIR, a directory path.
......@@ -56,7 +61,7 @@ class SocketConnect(GObject.GObject):
self._watch_id = 0
self._sock = None
self._listeners = [self._update_registered_paths]
self._remainder = ''
self._remainder = ''.encode()
self.nautilusVFSFile_table = {} # not needed in this object actually but shared
# all over the other objects.
......@@ -74,7 +79,7 @@ class SocketConnect(GObject.GObject):
# print("Server command: " + cmd)
if self.connected:
try:
self._sock.send(cmd)
self._sock.send(cmd.encode())
except:
print("Sending failed.")
self.reconnect()
......@@ -113,17 +118,17 @@ class SocketConnect(GObject.GObject):
# Prepend the remaining data from last call
if len(self._remainder) > 0:
data = self._remainder + data
self._remainder = ''
self._remainder = ''.encode()
if len(data) > 0:
# Remember the remainder for next round
lastNL = data.rfind('\n');
lastNL = data.rfind('\n'.encode());
if lastNL > -1 and lastNL < len(data):
self._remainder = data[lastNL+1:]
data = data[:lastNL]
for l in data.split('\n'):
self._handle_server_response(l)
for l in data.split('\n'.encode()):
self._handle_server_response(l.decode())
else:
return False
......
......@@ -420,6 +420,30 @@ int main(int argc, char **argv)
folder.chop(1);
}
if (!options.proxy.isNull()) {
QString host;
int port = 0;
bool ok;
QStringList pList = options.proxy.split(':');
if (pList.count() == 3) {
// http: //192.168.178.23 : 8080
// 0 1 2
host = pList.at(1);
if (host.startsWith("//"))
host.remove(0, 2);
port = pList.at(2).toInt(&ok);
QNetworkProxyFactory::setUseSystemConfiguration(false);
QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::HttpProxy, host, port));
} else {
qFatal("Could not read httpproxy. The proxy should have the format \"http://hostname:port\".");
}
} else {
clientProxy.setupQtProxyFromConfig();
}
SimpleSslErrorHandler *sslErrorHandler = new SimpleSslErrorHandler;
HttpCredentialsText *cred = new HttpCredentialsText(user, password);
......@@ -431,9 +455,14 @@ int main(int argc, char **argv)
account->setCredentials(cred);
account->setSslErrorHandler(sslErrorHandler);
//obtain capabilities using event loop
QEventLoop loop;
// Perform a call to get the capabilities.
if (!options.nonShib) {
// Do not do it if '--nonshib' was passed. This mean we should only connect to the 'nonshib'
// dav endpoint. Since we do not get the capabilities, in that case, this has the additional
// side effect that chunking-ng will be disabled. (because otherwise it would use the new
// 'dav' endpoint instead of the nonshib one (which still use the old chunking)
QEventLoop loop;
JsonApiJob *job = new JsonApiJob(account, QLatin1String("ocs/v1.php/cloud/capabilities"));
job->setTimeout(timeoutToUseMsec);
QObject::connect(job, &JsonApiJob::jsonReceived, [&](const QJsonDocument &json) {
......@@ -450,6 +479,7 @@ int main(int argc, char **argv)
std::cout<<"Error connecting to server\n";
return EXIT_FAILURE;
}
}
// much lower age than the default since this utility is usually made to be run right after a change in the tests
SyncEngine::minimumFileAgeForUpload = 0;
......@@ -457,36 +487,8 @@ int main(int argc, char **argv)
int restartCount = 0;
restart_sync:
opts = &options;
if (!options.proxy.isNull()) {
QString host;
int port = 0;
bool ok;
QStringList pList = options.proxy.split(':');
if (pList.count() == 3) {
// http: //192.168.178.23 : 8080
// 0 1 2
host = pList.at(1);
if (host.startsWith("//"))
host.remove(0, 2);
port = pList.at(2).toInt(&ok);
QNetworkProxyFactory::setUseSystemConfiguration(false);
QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::HttpProxy, host, port));
}
} else {
clientProxy.setupQtProxyFromConfig();
QString url(options.target_url);
if (url.startsWith("owncloud")) {
url.remove(0, 8);
url = QString("http%1").arg(url);
}
}
QStringList selectiveSyncList;
if (!options.unsyncedfolders.isEmpty()) {
QFile f(options.unsyncedfolders);
......
......@@ -478,4 +478,22 @@ bool FileSystem::isLnkFile(const QString &filename)
return filename.endsWith(".lnk");
}
bool FileSystem::isJunction(const QString &filename)
{
#ifdef Q_OS_WIN
WIN32_FIND_DATA findData;
HANDLE hFind = FindFirstFileEx((const wchar_t *)filename.utf16(), FindExInfoBasic, &findData, FindExSearchNameMatch, NULL, 0);
if (hFind != INVALID_HANDLE_VALUE) {
FindClose(hFind);
return false;
}
return findData.dwFileAttributes != INVALID_FILE_ATTRIBUTES
&& findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT
&& findData.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
#else
Q_UNUSED(filename);
return false;
#endif
}
} // namespace OCC
......@@ -141,8 +141,16 @@ namespace FileSystem {
*/
bool OCSYNC_EXPORT isFileLocked(const QString &fileName);
/**
* Returns whether the file is a shortcut file (ends with .lnk)
*/
bool OCSYNC_EXPORT isLnkFile(const QString &filename);
/**
* Returns whether the file is a junction (windows only)
*/
bool OCSYNC_EXPORT isJunction(const QString &filename);
/*
* This function takes a path and converts it to a UNC representation of the
* string. That means that it prepends a \\?\ (unless already UNC) and converts
......
......@@ -32,6 +32,13 @@
#include "common/c_jhash.h"
// SQL expression to check whether path.startswith(prefix + '/')
// Note: '/' + 1 == '0'
#define IS_PREFIX_PATH_OF(prefix, path) \
"(" path " > (" prefix "||'/') AND " path " < (" prefix "||'0'))"
#define IS_PREFIX_PATH_OR_EQUAL(prefix, path) \
"(" path " == " prefix " OR " IS_PREFIX_PATH_OF(prefix, path) ")"
namespace OCC {
Q_LOGGING_CATEGORY(lcDb, "sync.database", QtInfoMsg)
......@@ -550,7 +557,7 @@ bool SyncJournalDb::checkConnect()
_getFilesBelowPathQuery.reset(new SqlQuery(_db));
if (_getFilesBelowPathQuery->prepare(
GET_FILE_RECORD_QUERY
" WHERE path > (?1||'/') AND path < (?1||'0') ORDER BY path||'/' ASC")) {
" WHERE " IS_PREFIX_PATH_OF("?1", "path") " ORDER BY path||'/' ASC")) {
return sqlFail("prepare _getFilesBelowPathQuery", *_getFilesBelowPathQuery);
}
......@@ -620,7 +627,7 @@ bool SyncJournalDb::checkConnect()
}
_deleteFileRecordRecursively.reset(new SqlQuery(_db));
if (_deleteFileRecordRecursively->prepare("DELETE FROM metadata WHERE path LIKE(?||'/%')")) {
if (_deleteFileRecordRecursively->prepare("DELETE FROM metadata WHERE " IS_PREFIX_PATH_OF("?1", "path"))) {
return sqlFail("prepare _deleteFileRecordRecursively", *_deleteFileRecordRecursively);
}
......@@ -1780,9 +1787,8 @@ void SyncJournalDb::avoidRenamesOnNextSync(const QByteArray &path)
}
SqlQuery query(_db);
query.prepare("UPDATE metadata SET fileid = '', inode = '0' WHERE path == ?1 OR path LIKE(?2||'/%')");
query.prepare("UPDATE metadata SET fileid = '', inode = '0' WHERE " IS_PREFIX_PATH_OR_EQUAL("?1", "path"));
query.bindValue(1, path);
query.bindValue(2, path);
query.exec();
// We also need to remove the ETags so the update phase refreshes the directory paths
......@@ -1792,25 +1798,28 @@ void SyncJournalDb::avoidRenamesOnNextSync(const QByteArray &path)
void SyncJournalDb::avoidReadFromDbOnNextSync(const QByteArray &fileName)
{
// Make sure that on the next sync, fileName is not read from the DB but uses the PROPFIND to
// get the info from the server
// We achieve that by clearing the etag of the parents directory recursively
QMutexLocker locker(&_mutex);
if (!checkConnect()) {
return;
}
// Remove trailing slash
auto argument = fileName;
if (argument.endsWith('/'))
argument.chop(1);
SqlQuery query(_db);
// This query will match entries for which the path is a prefix of fileName
// Note: CSYNC_FTW_TYPE_DIR == 2
query.prepare("UPDATE metadata SET md5='_invalid_' WHERE ?1 LIKE(path||'/%') AND type == 2;");
query.bindValue(1, fileName);
query.prepare("UPDATE metadata SET md5='_invalid_' WHERE " IS_PREFIX_PATH_OR_EQUAL("path", "?1") " AND type == 2;");
query.bindValue(1, argument);
query.exec();
// Prevent future overwrite of the etag for this sync
_avoidReadFromDbOnNextSyncFilter.append(fileName);
// Prevent future overwrite of the etags of this folder and all
// parent folders for this sync
argument.append('/');
_avoidReadFromDbOnNextSyncFilter.append(argument);
}
void SyncJournalDb::forceRemoteDiscoveryNextSync()
......
......@@ -158,15 +158,16 @@ public:
void setSelectiveSyncList(SelectiveSyncListType type, const QStringList &list);
/**
* Make sure that on the next sync, fileName is not read from the DB but uses the PROPFIND to
* get the info from the server
* Make sure that on the next sync fileName and its parents are discovered from the server.
*
* Specifically, this sets the md5 field of fileName and all its parents to _invalid_.
* That means its metadata and, if it's a directory, its direct contents.
*
* Specifically, etag (md5 field) of fileName and all its parents are set to _invalid_.
* That causes a metadata difference and a resulting discovery from the remote for the
* affected folders.
*
* Since folders in the selective sync list will not be rediscovered (csync_ftw,
* _csync_detect_update skip them), the _invalid_ marker will stay and it. And any
* _csync_detect_update skip them), the _invalid_ marker will stay. And any
* child items in the db will be ignored when reading a remote tree from the database.
*/
void avoidReadFromDbOnNextSync(const QString &fileName) { avoidReadFromDbOnNextSync(fileName.toUtf8()); }
......@@ -268,6 +269,8 @@ private:
/* This is the list of paths we called avoidReadFromDbOnNextSync on.
* It means that they should not be written to the DB in any case since doing
* that would write the etag and would void the purpose of avoidReadFromDbOnNextSync
*
* The contained paths have a trailing /.
*/
QList<QByteArray> _avoidReadFromDbOnNextSyncFilter;
......
......@@ -85,6 +85,8 @@ int csync_update(CSYNC *ctx) {
csync_gettime(&start);
ctx->current = LOCAL_REPLICA;
CSYNC_LOG(CSYNC_LOG_PRIORITY_INFO, "## Starting local discovery ##");
rc = csync_ftw(ctx, ctx->local.uri, csync_walker, MAX_DEPTH);
if (rc < 0) {
if(ctx->status_code == CSYNC_STATUS_OK) {
......@@ -104,6 +106,8 @@ int csync_update(CSYNC *ctx) {
csync_gettime(&start);
ctx->current = REMOTE_REPLICA;
CSYNC_LOG(CSYNC_LOG_PRIORITY_INFO, "## Starting remote discovery ##");
rc = csync_ftw(ctx, "", csync_walker, MAX_DEPTH);
if (rc < 0) {
if(ctx->status_code == CSYNC_STATUS_OK) {
......
......@@ -150,10 +150,18 @@ static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> f
}
}
if (ctx->current == REMOTE_REPLICA && QTextCodec::codecForLocale()->mibEnum() != 106) {
auto localCodec = QTextCodec::codecForLocale();
if (ctx->current == REMOTE_REPLICA && localCodec->mibEnum() != 106) {
/* If the locale codec is not UTF-8, we must check that the filename from the server can
* be encoded in the local file system. */
if (!QTextCodec::codecForLocale()->canEncode(QString::fromUtf8(fs->path))) {
* be encoded in the local file system.
*
* We cannot use QTextCodec::canEncode() since that can incorrectly return true, see
* https://bugreports.qt.io/browse/QTBUG-6925.
*/
QTextEncoder encoder(localCodec, QTextCodec::ConvertInvalidToNull);
if (encoder.fromUnicode(QString::fromUtf8(fs->path)).contains('\0')) {
qCDebug(lcUpdate, "cannot encode %s to local encoding %d",
fs->path.constData(), localCodec->mibEnum());
excluded = CSYNC_FILE_EXCLUDE_CANNOT_ENCODE;
}
}
......@@ -497,7 +505,7 @@ static bool fill_tree_from_db(CSYNC *ctx, const char *uri)
* without a full remote discovery being triggered. */
CSYNC_EXCLUDE_TYPE excluded = csync_excluded_traversal(ctx, st->path, st->type);
if (excluded != CSYNC_NOT_EXCLUDED) {
qDebug(lcUpdate, "%s excluded (%d)", st->path.constData(), excluded);
qInfo(lcUpdate, "%s excluded from db read (%d)", st->path.constData(), excluded);
if (excluded == CSYNC_FILE_EXCLUDE_AND_REMOVE
|| excluded == CSYNC_FILE_SILENTLY_EXCLUDED) {
......@@ -516,7 +524,7 @@ static bool fill_tree_from_db(CSYNC *ctx, const char *uri)
ctx->status_code = CSYNC_STATUS_STATEDB_LOAD_ERROR;
return false;
}
qDebug(lcUpdate, "%" PRId64 " entries read below path %s from db.", count, uri);
qInfo(lcUpdate, "%" PRId64 " entries read below path %s from db.", count, uri);
return true;
}
......
......@@ -338,7 +338,9 @@ void Application::slotownCloudWizardDone(int res)
shouldSetAutoStart = shouldSetAutoStart
&& QCoreApplication::applicationDirPath().startsWith("/Applications/");
#endif
Utility::setLaunchOnStartup(_theme->appName(), _theme->appNameGUI(), shouldSetAutoStart);
if (shouldSetAutoStart) {
Utility::setLaunchOnStartup(_theme->appName(), _theme->appNameGUI(), true);
}
_gui->slotShowSettings();
}
......