Merge branch '1.8'

This commit is contained in:
Olivier Goffart 2015-04-16 12:49:31 +02:00
commit 5dffd11755
27 changed files with 3536 additions and 216 deletions

View file

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

2
binary

@ -1 +1 @@
Subproject commit 01d73965dc8b862d1b2310d3ef801c297b697ec7
Subproject commit 1fb9ddfa9a9a1b4dbc447eee10dbed89172d968a

View file

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

View file

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

View file

@ -445,7 +445,9 @@ restart_sync:
if (!f.open(QFile::ReadOnly)) {
qCritical() << "Could not open file containing the list of unsynced folders: " << options.unsyncedfolders;
} else {
selectiveSyncList = QString::fromUtf8(f.readAll()).split('\n');
// filter out empty lines and comments
selectiveSyncList = QString::fromUtf8(f.readAll()).split('\n').filter(QRegExp("\\S+")).filter(QRegExp("^[^#]"));
for (int i = 0; i < selectiveSyncList.count(); ++i) {
if (!selectiveSyncList.at(i).endsWith(QLatin1Char('/'))) {
selectiveSyncList[i].append(QLatin1Char('/'));

View file

@ -218,10 +218,52 @@ void OwncloudSetupWizard::testOwnCloudConnect()
job->setIgnoreCredentialFailure(true);
job->setProperties(QList<QByteArray>() << "getlastmodified");
connect(job, SIGNAL(result(QVariantMap)), _ocWizard, SLOT(successfulStep()));
connect(job, SIGNAL(networkError(QNetworkReply*)), this, SLOT(slotConnectionCheck(QNetworkReply*)));
connect(job, SIGNAL(finishedWithError()), this, SLOT(slotAuthError()));
connect(job, SIGNAL(networkError(QNetworkReply*)), this, SLOT(slotAuthNetworkError(QNetworkReply*)));
job->start();
}
void OwncloudSetupWizard::slotAuthError()
{
QString errorMsg;
PropfindJob* job = qobject_cast<PropfindJob*>(sender());
if (!job) {
qWarning() << "Can't check for authed redirects. This slot should be invoked from PropfindJob!";
return;
}
// If there were redirects on the *authed* requests, also store
// the updated server URL, similar to redirects on status.php.
QUrl redirectUrl = job->reply()->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
if (!redirectUrl.isEmpty()) {
qDebug() << "authed request was redirected to" << redirectUrl.toString();
// strip the expected path
QString path = redirectUrl.path();
static QString expectedPath = "/" + _ocWizard->account()->davPath();
if (path.endsWith(expectedPath)) {
path.chop(expectedPath.size());
redirectUrl.setPath(path);
qDebug() << "setting account url to" << redirectUrl.toString();
_ocWizard->account()->setUrl(redirectUrl);
testOwnCloudConnect();
return;
} else {
errorMsg = tr("The authenticated request to the server was redirected to "
"'%1'. The URL is bad, the server is misconfigured.")
.arg(redirectUrl.toString());
}
}
if (errorMsg.isEmpty()) {
errorMsg = tr("There was an invalid response to an authenticated webdav request");
}
_ocWizard->displayError(errorMsg, false);
_ocWizard->show();
}
bool OwncloudSetupWizard::checkDowngradeAdvised(QNetworkReply* reply)
{
if(reply->url().scheme() != QLatin1String("https")) {
@ -245,7 +287,7 @@ bool OwncloudSetupWizard::checkDowngradeAdvised(QNetworkReply* reply)
return true;
}
void OwncloudSetupWizard::slotConnectionCheck(QNetworkReply* reply)
void OwncloudSetupWizard::slotAuthNetworkError(QNetworkReply* reply)
{
QString msg = reply->errorString();
switch (reply->error()) {
@ -294,7 +336,7 @@ void OwncloudSetupWizard::slotCreateLocalAndRemoteFolders(const QString& localFo
}
if (nextStep) {
EntityExistsJob *job = new EntityExistsJob(_ocWizard->account(), _ocWizard->account()->davPath() + remoteFolder, this);
connect(job, SIGNAL(exists(QNetworkReply*)), SLOT(slotAuthCheckReply(QNetworkReply*)));
connect(job, SIGNAL(exists(QNetworkReply*)), SLOT(slotRemoteFolderExists(QNetworkReply*)));
job->start();
} else {
finalizeSetup( false );
@ -302,7 +344,7 @@ void OwncloudSetupWizard::slotCreateLocalAndRemoteFolders(const QString& localFo
}
// ### TODO move into EntityExistsJob once we decide if/how to return gui strings from jobs
void OwncloudSetupWizard::slotAuthCheckReply(QNetworkReply *reply)
void OwncloudSetupWizard::slotRemoteFolderExists(QNetworkReply *reply)
{
bool ok = true;
QString error;
@ -522,8 +564,10 @@ bool DetermineAuthTypeJob::finished()
} else if (redirection.toString().endsWith(account()->davPath())) {
// do a new run
_redirects++;
resetTimeout();
setReply(getRequest(redirection));
setupConnections(reply());
return false; // don't discard
} else {
QRegExp shibbolethyWords("SAML|wayf");

View file

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

View file

@ -169,8 +169,8 @@ QString ProtocolWidget::timeString(QDateTime dt, QLocale::FormatType format) con
{
const QLocale loc = QLocale::system();
QString dtFormat = loc.dateTimeFormat(format);
static const QRegExp re("HH:mm(?!:ss)");
dtFormat.replace(re, "HH:mm:ss");
static const QRegExp re("(HH|H|hh|h):mm(?!:s)");
dtFormat.replace(re, "\\1:mm:ss");
return loc.toString(dt, dtFormat);
}

View file

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

View file

@ -40,7 +40,7 @@
namespace OCC {
static const char caCertsKeyC[] = "CaCertificates";
//static const char caCertsKeyC[] = "CaCertificates"; only used from account.cpp
static const char remotePollIntervalC[] = "remotePollInterval";
static const char forceSyncIntervalC[] = "forceSyncInterval";
static const char monoIconsC[] = "monoIcons";
@ -317,20 +317,6 @@ bool ConfigFile::dataExists(const QString& group, const QString& key) const
return settings.contains(key);
}
QByteArray ConfigFile::caCerts( )
{
QSettings settings(configFile(), QSettings::IniFormat);
return settings.value( QLatin1String(caCertsKeyC) ).toByteArray();
}
void ConfigFile::setCaCerts( const QByteArray & certs )
{
QSettings settings(configFile(), QSettings::IniFormat);
settings.setValue( QLatin1String(caCertsKeyC), certs );
settings.sync();
}
int ConfigFile::remotePollInterval( const QString& connection ) const
{
QString con( connection );

View file

@ -285,6 +285,13 @@ void DiscoverySingleDirectoryJob::directoryListingIteratedSlot(QString file,QMap
void DiscoverySingleDirectoryJob::lsJobFinishedWithoutErrorSlot()
{
if (!_ignoredFirst) {
// This is a sanity check, if we haven't _ignoredFirst then it means we never received any directoryListingIteratedSlot
// which means somehow the server XML was bogus
emit finishedWithError(ERRNO_WRONG_CONTENT, QLatin1String("Server error: PROPFIND reply is not XML formatted!"));
deleteLater();
return;
}
emit etagConcatenation(_etagConcatenation);
emit finishedWithResult(_results);
deleteLater();
@ -296,7 +303,7 @@ void DiscoverySingleDirectoryJob::lsJobFinishedWithErrorSlot(QNetworkReply *r)
int httpCode = r->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QString httpReason = r->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
QString msg = r->errorString();
int errnoCode = 0;
int errnoCode = EIO; // Something went wrong
qDebug() << Q_FUNC_INFO << r->errorString() << httpCode << r->error();
if (httpCode != 0 && httpCode != 207) {
errnoCode = get_errno_from_http_errcode(httpCode, httpReason);
@ -305,6 +312,8 @@ void DiscoverySingleDirectoryJob::lsJobFinishedWithErrorSlot(QNetworkReply *r)
} else if (!contentType.contains("application/xml; charset=utf-8")) {
msg = QLatin1String("Server error: PROPFIND reply is not XML formatted!");
errnoCode = ERRNO_WRONG_CONTENT;
} else {
// Default keep at EIO, see above
}
emit finishedWithError(errnoCode, msg);

View file

@ -63,7 +63,7 @@ struct DiscoveryDirectoryResult {
int code;
QList<FileStatPointer> list;
int listIndex;
DiscoveryDirectoryResult() : code(0), listIndex(0) { }
DiscoveryDirectoryResult() : code(EIO), listIndex(0) { }
};
// Run in the main thread, reporting to the DiscoveryJobMainThread object

View file

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

View file

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

View file

@ -519,10 +519,14 @@ void PropagateDownloadFileQNAM::downloadFinished()
_tmpFile.setPermissions(existingFile.permissions());
}
FileSystem::setFileHidden(_tmpFile.fileName(), false);
FileSystem::setModTime(_tmpFile.fileName(), _item._modtime);
// We need to fetch the time again because some file system such as FAT have a less than a second
// Accuracy, and we really need the time from the file system. (#3103)
_item._modtime = FileSystem::getModTime(_tmpFile.fileName());
QString error;
_propagator->addTouchedFile(fn);
FileSystem::setFileHidden(_tmpFile.fileName(), false);
if (!FileSystem::renameReplace(_tmpFile.fileName(), fn, &error)) {
qDebug() << Q_FUNC_INFO << QString("Rename failed: %1 => %2").arg(_tmpFile.fileName()).arg(fn);
// If we moved away the original file due to a conflict but can't
@ -543,7 +547,6 @@ void PropagateDownloadFileQNAM::downloadFinished()
// Maybe we downloaded a newer version of the file than we thought we would...
// Get up to date information for the journal.
FileSystem::setModTime(fn, _item._modtime);
_item._size = FileSystem::getSize(fn);
_propagator->_journal->setFileRecord(SyncJournalFileRecord(_item, fn));

View file

@ -695,7 +695,8 @@ void PropagateDownloadFileLegacy::start()
&& !FileSystem::fileEquals(fn, tmpFile.fileName()); // compare the files to see if there was an actual conflict.
//In case of conflict, make a backup of the old file
if (isConflict) {
QString conflictFileName = makeConflictFileName(fn, Utility::qDateTimeFromTime_t(_item._modtime));
auto conflictDate = FileSystem::fileExists(fn) ? FileSystem::getModTime(fn) : _item._modtime;
QString conflictFileName = makeConflictFileName(fn, Utility::qDateTimeFromTime_t(conflictDate));
QString renameError;
if (!FileSystem::rename(fn, conflictFileName, &renameError)) {
//If the rename fails, don't replace it.

View file

@ -999,8 +999,8 @@ void SyncEngine::checkForPermission()
it->_direction = SyncFileItem::Down;
it->_isRestoration = true;
// take the things to write to the db from the "other" node (i.e: info from server)
// ^^ FIXME This might not be needed anymore since we merge the info in treewalkFile
it->_modtime = it->log._other_modtime;
it->_size = it->log._other_size;
it->_fileId = it->log._other_fileId;
it->_etag = it->log._other_etag;
it->_errorString = tr("Not allowed to upload this file because it is read-only on the server, restoring");

View file

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

245
test/testxmlparse.h Normal file
View file

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

View file

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

View file

@ -1362,7 +1362,7 @@ It is not advisable to use it.</source>
<message>
<location filename="../src/libsync/propagateupload.cpp" line="121"/>
<source>Invalid JSON reply from the poll URL</source>
<translation type="unfinished"/>
<translation>Λανθασμένη απάντηση JSON από την ιστοσελίδα poll</translation>
</message>
</context>
<context>
@ -1552,7 +1552,7 @@ It is not advisable to use it.</source>
<message>
<location filename="../src/libsync/propagateupload.cpp" line="468"/>
<source>Poll URL missing</source>
<translation type="unfinished"/>
<translation>Η διεύθυνση poll URL λείπει</translation>
</message>
<message>
<location filename="../src/libsync/propagateupload.cpp" line="493"/>

View file

@ -809,22 +809,22 @@ Les motifs cochés seront également supprimés s&apos;ils empêchent la suppres
<message>
<location filename="../src/gui/ignorelisteditor.cpp" line="106"/>
<source>Add a new ignore pattern:</source>
<translation>Ajouter un nouveau modèle à ignorer :</translation>
<translation>Ajoutez un nouveau motif à ignorer :</translation>
</message>
<message>
<location filename="../src/gui/ignorelisteditor.cpp" line="128"/>
<source>Edit Ignore Pattern</source>
<translation>Éditer le modèle</translation>
<translation>Modifier le motif</translation>
</message>
<message>
<location filename="../src/gui/ignorelisteditor.cpp" line="129"/>
<source>Edit ignore pattern:</source>
<translation>Éditer le modèle :</translation>
<translation>Éditer le motif :</translation>
</message>
<message>
<location filename="../src/gui/ignorelisteditor.cpp" line="140"/>
<source>This entry is provided by the system at &apos;%1&apos; and cannot be modified in this view.</source>
<translation>Cette entrée est fournie par le système à &apos;%1&apos; et ne peut être modifiée dans cette vue.</translation>
<translation>Cette entrée est fournie par le système dans &apos;%1&apos; et ne peut être modifiée dans cette vue.</translation>
</message>
</context>
<context>
@ -2123,7 +2123,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message>
<location filename="../src/libsync/syncengine.cpp" line="95"/>
<source>CSync failed to load or create the journal file. Make sure you have read and write permissions in the local sync directory.</source>
<translation>CSync na pu charger ou créer le fichier de journalisation. Veuillez vérifier que vous possédez les droits en lecture/écriture dans le répertoire de synchronisation local.</translation>
<translation>CSync na pu charger ou créer le fichier de journalisation. Veuillez vérifier que vous possédez les droits en lecture et écriture dans le répertoire de synchronisation local.</translation>
</message>
<message>
<location filename="../src/libsync/syncengine.cpp" line="99"/>
@ -2158,17 +2158,17 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message>
<location filename="../src/libsync/syncengine.cpp" line="117"/>
<source>CSync processing step reconcile failed.</source>
<translation>Erreur CSync lors de l&apos;opération d&apos;harmonisation</translation>
<translation>Erreur CSync lors de l&apos;opération de réconciliation</translation>
</message>
<message>
<location filename="../src/libsync/syncengine.cpp" line="120"/>
<source>CSync could not authenticate at the proxy.</source>
<translation>CSync ne peut s&apos;authentifier auprès du proxy.</translation>
<translation>CSync n&apos;a pu s&apos;authentifier auprès du proxy.</translation>
</message>
<message>
<location filename="../src/libsync/syncengine.cpp" line="123"/>
<source>CSync failed to lookup proxy or server.</source>
<translation>CSync n&apos;a pu trouver un proxy ou serveur auquel se connecter.</translation>
<translation>CSync n&apos;a pu trouver le proxy ou serveur auquel se connecter.</translation>
</message>
<message>
<location filename="../src/libsync/syncengine.cpp" line="126"/>
@ -2183,7 +2183,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message>
<location filename="../src/libsync/syncengine.cpp" line="132"/>
<source>A network connection timeout happened.</source>
<translation>Le délai d&apos;attente pour la connexion réseau a é dépassé.</translation>
<translation>Le délai d&apos;attente de la connexion réseau a é dépassé.</translation>
</message>
<message>
<location filename="../src/libsync/syncengine.cpp" line="135"/>
@ -2198,7 +2198,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message>
<location filename="../src/libsync/syncengine.cpp" line="141"/>
<source>CSync failed to access </source>
<translation>Echec de CSync pour accéder</translation>
<translation>CSync n&apos;a pu accéder à</translation>
</message>
<message>
<location filename="../src/libsync/syncengine.cpp" line="144"/>
@ -2279,7 +2279,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<location filename="../src/libsync/syncengine.cpp" line="895"/>
<location filename="../src/libsync/syncengine.cpp" line="902"/>
<source>Ignored because of the &quot;choose what to sync&quot; blacklist</source>
<translation>Ignoré à cause de la liste noire du contenu à synchroniser.</translation>
<translation>Ignoré à cause de la liste noire &quot;Choisir le contenu à synchroniser&quot;.</translation>
</message>
<message>
<location filename="../src/libsync/syncengine.cpp" line="920"/>
@ -2404,7 +2404,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message>
<location filename="../src/gui/owncloudgui.cpp" line="326"/>
<source>Managed Folders:</source>
<translation>Répertoires suivis :</translation>
<translation>Répertoires configurés :</translation>
</message>
<message>
<location filename="../src/gui/owncloudgui.cpp" line="335"/>
@ -2464,7 +2464,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message>
<location filename="../src/gui/owncloudgui.cpp" line="446"/>
<source>Quota n/a</source>
<translation>Quota n/a</translation>
<translation>Quota non disponible ou non applicable</translation>
</message>
<message>
<location filename="../src/gui/owncloudgui.cpp" line="453"/>
@ -2474,7 +2474,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message>
<location filename="../src/gui/owncloudgui.cpp" line="465"/>
<source>No items synced recently</source>
<translation>Aucun item synchronisé récemment</translation>
<translation>Aucun élément synchronisé récemment</translation>
</message>
<message>
<location filename="../src/gui/owncloudgui.cpp" line="477"/>
@ -2484,12 +2484,12 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message>
<location filename="../src/gui/owncloudgui.cpp" line="482"/>
<source>Syncing %1 of %2 (%3 left)</source>
<translation>Synchronisation %1 de %2 (%3 restant)</translation>
<translation>Synchronisation de %1 sur %2 (%3 restant)</translation>
</message>
<message>
<location filename="../src/gui/owncloudgui.cpp" line="487"/>
<source>Syncing %1 (%2 left)</source>
<translation>Synchronisation %1 (%2 restant)</translation>
<translation>Synchronisation de %1 (%2 restant)</translation>
</message>
<message>
<location filename="../src/gui/owncloudgui.cpp" line="507"/>
@ -2566,7 +2566,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message>
<location filename="../src/gui/wizard/owncloudadvancedsetuppage.ui" line="224"/>
<source>S&amp;ync everything from server</source>
<translation>Synchroniser tout le contenu depuis le serveur</translation>
<translation>S&amp;ynchroniser tout le contenu depuis le serveur</translation>
</message>
<message>
<location filename="../src/gui/wizard/owncloudadvancedsetuppage.ui" line="306"/>
@ -2584,17 +2584,17 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message>
<location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="43"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Failed to connect to the secure server address specified. How do you wish to proceed?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Impossible de se connecter au serveur via l&apos;adresse sécurisée indiquée. Comment voulez-vous procéder ?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Impossible de se connecter au serveur via l&apos;adresse sécurisée indiquée. Que souhaitez-vous faire ?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="55"/>
<source>Select a different URL</source>
<translation>Sélectionner un URL différent</translation>
<translation>Sélectionner une URL différente</translation>
</message>
<message>
<location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="62"/>
<source>Retry unencrypted over HTTP (insecure)</source>
<translation>Réessayer en clair sur HTTP (non sécurisé)</translation>
<translation>Essayer en clair sur HTTP (non sécurisé)</translation>
</message>
<message>
<location filename="../src/gui/wizard/owncloudconnectionmethoddialog.ui" line="69"/>
@ -2604,7 +2604,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message>
<location filename="../src/gui/wizard/owncloudconnectionmethoddialog.cpp" line="18"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Failed to connect to the secure server address &lt;em&gt;%1&lt;/em&gt;. How do you wish to proceed?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Impossible de se connecter à l&apos;adresse sécurisée du serveur &lt;em&gt;%1&lt;/em&gt;. Comment voulez-vous procéder ?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Impossible de se connecter à l&apos;adresse sécurisée &lt;em&gt;%1&lt;/em&gt;. Que souhaitez-vous faire ?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
</context>
<context>
@ -2696,7 +2696,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message>
<location filename="../src/gui/owncloudsetuppage.ui" line="120"/>
<source>&amp;Do not store password on local machine</source>
<translation>&amp;Ne pas mémoriser le mot de passe sur la machine locale</translation>
<translation>Ne &amp;pas mémoriser le mot de passe sur la machine locale</translation>
</message>
<message>
<location filename="../src/gui/owncloudsetuppage.ui" line="140"/>
@ -2786,7 +2786,7 @@ Il est déconseillé de l&apos;utiliser.</translation>
<message>
<location filename="../src/gui/main.cpp" line="46"/>
<source>%1 requires on a working system tray. If you are running XFCE, please follow &lt;a href=&quot;http://docs.xfce.org/xfce/xfce4-panel/systray&quot;&gt;these instructions&lt;/a&gt;. Otherwise, please install a system tray application such as &apos;trayer&apos; and try again.</source>
<translation>%1 nécessite la présence d&apos;une zone de notification système (system tray). Si vous utilisez XFCE, veuillez suivre &lt;a href=&quot;http://docs.xfce.org/xfce/xfce4-panel/systray&quot;&gt;ces instructions&lt;/a&gt;. Sinon, installez une application mettant en place une zone de notification, telle que &apos;trayer&apos;, et essayez à nouveau.</translation>
<translation>%1 nécessite la présence d&apos;une zone de notification système. Si vous utilisez XFCE, veuillez suivre &lt;a href=&quot;http://docs.xfce.org/xfce/xfce4-panel/systray&quot;&gt;ces instructions&lt;/a&gt;. Sinon, installez une application mettant en place une zone de notification, telle que &apos;trayer&apos;, et essayez à nouveau.</translation>
</message>
</context>
<context>

View file

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

View file

@ -166,7 +166,7 @@
<message>
<location filename="../src/gui/accountsettings.cpp" line="610"/>
<source>Discovering &apos;%1&apos;</source>
<translation type="unfinished"/>
<translation>Rozpoznaję &apos;%1&apos;</translation>
</message>
<message>
<location filename="../src/gui/accountsettings.cpp" line="650"/>
@ -1446,12 +1446,12 @@ Niezalecane jest jego użycie.</translation>
<message>
<location filename="../src/libsync/propagatorjobs.cpp" line="57"/>
<source>Error removing &apos;%1&apos;: %2; </source>
<translation type="unfinished"/>
<translation>Błąd usuwania &apos;%1&apos;: %2; </translation>
</message>
<message>
<location filename="../src/libsync/propagatorjobs.cpp" line="68"/>
<source>Could not remove directory &apos;%1&apos;; </source>
<translation type="unfinished"/>
<translation>Nie mogę usunąć katalogu &apos;%1&apos;;</translation>
</message>
<message>
<location filename="../src/libsync/propagatorjobs.cpp" line="83"/>
@ -1535,7 +1535,7 @@ Niezalecane jest jego użycie.</translation>
<message>
<location filename="../src/libsync/propagateupload.cpp" line="156"/>
<source>File Removed</source>
<translation type="unfinished"/>
<translation>Usunięto plik</translation>
</message>
<message>
<location filename="../src/libsync/propagateupload.cpp" line="171"/>
@ -2473,7 +2473,7 @@ Niezalecane jest jego użycie.</translation>
<message>
<location filename="../src/gui/owncloudgui.cpp" line="477"/>
<source>Discovering &apos;%1&apos;</source>
<translation type="unfinished"/>
<translation>Rozpoznaję &apos;%1&apos;</translation>
</message>
<message>
<location filename="../src/gui/owncloudgui.cpp" line="482"/>
@ -2748,22 +2748,22 @@ Kliknij</translation>
<message>
<location filename="../src/libsync/utility.cpp" line="113"/>
<source>%L1 TiB</source>
<translation type="unfinished"/>
<translation>%L1 TiB</translation>
</message>
<message>
<location filename="../src/libsync/utility.cpp" line="116"/>
<source>%L1 GiB</source>
<translation type="unfinished"/>
<translation>%L1 GiB</translation>
</message>
<message>
<location filename="../src/libsync/utility.cpp" line="119"/>
<source>%L1 MiB</source>
<translation type="unfinished"/>
<translation>%L1 MiB</translation>
</message>
<message>
<location filename="../src/libsync/utility.cpp" line="122"/>
<source>%L1 KiB</source>
<translation type="unfinished"/>
<translation>%L1 KiB</translation>
</message>
<message>
<location filename="../src/libsync/utility.cpp" line="125"/>

2928
translations/client_sr.ts Normal file

File diff suppressed because it is too large Load diff

View file

@ -668,7 +668,7 @@ Detta kan bero på att konfigurationen för mappen ändrats, eller att alla file
<message>
<location filename="../src/gui/folderwizard.cpp" line="444"/>
<source>Choose What to Sync: You can optionally deselect remote subfolders you do not wish to synchronize.</source>
<translation type="unfinished"/>
<translation>Välj Vad du vill Synka: Du har även möjlighet att avmarkera mappar servern som du ej vill synkronisera.</translation>
</message>
</context>
<context>
@ -733,7 +733,7 @@ Detta kan bero på att konfigurationen för mappen ändrats, eller att alla file
<message>
<location filename="../src/gui/generalsettings.ui" line="47"/>
<source>Show crash reporter</source>
<translation type="unfinished"/>
<translation>Visa kraschrapporteringsverktyg</translation>
</message>
<message>
<location filename="../src/gui/generalsettings.ui" line="57"/>
@ -1420,7 +1420,7 @@ Det är inte lämpligt använda den.</translation>
<message>
<location filename="../src/libsync/owncloudpropagator.cpp" line="104"/>
<source>Continue blacklisting: </source>
<translation type="unfinished"/>
<translation>Fortsätt svartlista:</translation>
</message>
<message>
<location filename="../src/libsync/owncloudpropagator.cpp" line="200"/>
@ -1477,7 +1477,7 @@ Det är inte lämpligt använda den.</translation>
<message>
<location filename="../src/libsync/propagateremotedelete.cpp" line="103"/>
<source>Wrong HTTP code returned by server. Expected 204, but recieved &quot;%1 %2&quot;.</source>
<translation type="unfinished"/>
<translation>Fel HTTP-kod returnerades av servern. Förväntade 204, men tog emot &quot;%1 %2&quot;.</translation>
</message>
</context>
<context>

View file

@ -341,7 +341,7 @@ Total time left %5</source>
<context>
<name>OCC::DiscoveryMainThread</name>
<message>
<location filename="../src/libsync/discoveryphase.cpp" line="411"/>
<location filename="../src/libsync/discoveryphase.cpp" line="420"/>
<source>Aborted by the user</source>
<translation type="unfinished"></translation>
</message>
@ -1232,109 +1232,119 @@ It is not advisable to use it.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="258"/>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="254"/>
<source>The authenticated request to the server was redirected to &apos;%1&apos;. The URL is bad, the server is misconfigured.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="261"/>
<source>There was an invalid response to an authenticated webdav request</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="300"/>
<source>Access forbidden by server. To verify that you have proper access, &lt;a href=&quot;%1&quot;&gt;click here&lt;/a&gt; to access the service with your browser.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="280"/>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="322"/>
<source>Local sync folder %1 already exists, setting it up for sync.&lt;br/&gt;&lt;br/&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="282"/>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="324"/>
<source>Creating local sync folder %1...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="286"/>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="328"/>
<source>ok</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="288"/>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="330"/>
<source>failed.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="290"/>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="332"/>
<source>Could not create local folder %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="315"/>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="357"/>
<source>No remote folder specified!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="321"/>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="363"/>
<source>Error: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="334"/>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="376"/>
<source>creating folder on ownCloud: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="350"/>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="392"/>
<source>Remote folder %1 created successfully.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="352"/>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="394"/>
<source>The remote folder %1 already exists. Connecting it for syncing.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="354"/>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="356"/>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="396"/>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="398"/>
<source>The folder creation resulted in HTTP error code %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="358"/>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="400"/>
<source>The remote folder creation failed because the provided credentials are wrong!&lt;br/&gt;Please go back and check your credentials.&lt;/p&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="361"/>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="403"/>
<source>&lt;p&gt;&lt;font color=&quot;red&quot;&gt;Remote folder creation failed probably because the provided credentials are wrong.&lt;/font&gt;&lt;br/&gt;Please go back and check your credentials.&lt;/p&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="366"/>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="367"/>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="408"/>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="409"/>
<source>Remote folder %1 creation failed with error &lt;tt&gt;%2&lt;/tt&gt;.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="383"/>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="425"/>
<source>A sync connection from %1 to remote directory %2 was set up.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="388"/>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="430"/>
<source>Successfully connected to %1!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="395"/>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="437"/>
<source>Connection to %1 could not be established. Please check again.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="408"/>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="450"/>
<source>Folder rename failed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="409"/>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="451"/>
<source>Can&apos;t remove and back up the folder because the folder or a file in it is open in another program. Please close the folder or file and hit retry or cancel the setup.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="455"/>
<location filename="../src/gui/owncloudsetupwizard.cpp" line="497"/>
<source>&lt;font color=&quot;green&quot;&gt;&lt;b&gt;Local sync folder %1 successfully created!&lt;/b&gt;&lt;/font&gt;</source>
<translation type="unfinished"></translation>
</message>
@ -1680,22 +1690,22 @@ It is not advisable to use it.</source>
<context>
<name>OCC::SelectiveSyncDialog</name>
<message>
<location filename="../src/gui/selectivesyncdialog.cpp" line="337"/>
<location filename="../src/gui/selectivesyncdialog.cpp" line="360"/>
<source>Unchecked folders will be &lt;b&gt;removed&lt;/b&gt; from your local file system and will not be synchronized to this computer anymore</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/selectivesyncdialog.cpp" line="350"/>
<location filename="../src/gui/selectivesyncdialog.cpp" line="373"/>
<source>Choose What to Sync: Select remote subfolders you wish to synchronize.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/selectivesyncdialog.cpp" line="351"/>
<location filename="../src/gui/selectivesyncdialog.cpp" line="374"/>
<source>Choose What to Sync: Deselect remote subfolders you do not wish to synchronize.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/selectivesyncdialog.cpp" line="357"/>
<location filename="../src/gui/selectivesyncdialog.cpp" line="380"/>
<source>Choose What to Sync</source>
<translation type="unfinished"></translation>
</message>
@ -1703,28 +1713,28 @@ It is not advisable to use it.</source>
<context>
<name>OCC::SelectiveSyncTreeView</name>
<message>
<location filename="../src/gui/selectivesyncdialog.cpp" line="36"/>
<location filename="../src/gui/selectivesyncdialog.cpp" line="59"/>
<source>Loading ...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/selectivesyncdialog.cpp" line="47"/>
<location filename="../src/gui/selectivesyncdialog.cpp" line="70"/>
<source>Name</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/selectivesyncdialog.cpp" line="48"/>
<location filename="../src/gui/selectivesyncdialog.cpp" line="71"/>
<source>Size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/selectivesyncdialog.cpp" line="144"/>
<location filename="../src/gui/selectivesyncdialog.cpp" line="191"/>
<location filename="../src/gui/selectivesyncdialog.cpp" line="167"/>
<location filename="../src/gui/selectivesyncdialog.cpp" line="214"/>
<source>No subfolders currently on the server.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui/selectivesyncdialog.cpp" line="193"/>
<location filename="../src/gui/selectivesyncdialog.cpp" line="216"/>
<source>An error occured while loading the list of sub folders.</source>
<translation type="unfinished"></translation>
</message>