[Pkg-owncloud-commits] [owncloud-client] 97/332: sync engine: try to respect permission
Sandro Knauß
hefee-guest at moszumanska.debian.org
Thu Aug 14 21:06:44 UTC 2014
This is an automated email from the git hooks/post-receive script.
hefee-guest pushed a commit to branch master
in repository owncloud-client.
commit b83f6c0b3ae01ebf991ecfc8c15ee2271cdf78dd
Author: Olivier Goffart <ogoffart at woboq.com>
Date: Sat Jun 7 11:49:46 2014 +0200
sync engine: try to respect permission
This is still Work in progress
---
src/mirall/owncloudpropagator.cpp | 10 ++-
src/mirall/owncloudpropagator.h | 10 ++-
src/mirall/syncengine.cpp | 185 ++++++++++++++++++++++++++++++++++++++
src/mirall/syncengine.h | 7 ++
src/mirall/syncfileitem.h | 3 +-
5 files changed, 210 insertions(+), 5 deletions(-)
diff --git a/src/mirall/owncloudpropagator.cpp b/src/mirall/owncloudpropagator.cpp
index 0003b0e..8644d6f 100644
--- a/src/mirall/owncloudpropagator.cpp
+++ b/src/mirall/owncloudpropagator.cpp
@@ -43,7 +43,15 @@ static int maximumActiveJob() {
void PropagateItemJob::done(SyncFileItem::Status status, const QString &errorString)
{
- _item._errorString = errorString;
+ if (_item._isRestoration) {
+ if( status == SyncFileItem::Success || status == SyncFileItem::Conflict) {
+ status = SyncFileItem::SoftError;
+ } else {
+ _item._errorString += tr("; Restoration Failed: ") + errorString;
+ }
+ } else {
+ _item._errorString = errorString;
+ }
_item._status = status;
// Blacklisting
diff --git a/src/mirall/owncloudpropagator.h b/src/mirall/owncloudpropagator.h
index 33146aa..ab99ef2 100644
--- a/src/mirall/owncloudpropagator.h
+++ b/src/mirall/owncloudpropagator.h
@@ -139,11 +139,15 @@ protected:
* set a custom restore job message that is used if the restore job succeeded.
* It is displayed in the activity view.
*/
- QString restoreJobMsg() const { return _restoreJobMsg; }
- void setRestoreJobMsg( const QString& msg = QString() ) { _restoreJobMsg = msg; }
+ QString restoreJobMsg() const {
+ return _item._isRestoration ? _item._errorString : QString();
+ }
+ void setRestoreJobMsg( const QString& msg = QString() ) {
+ _item._isRestoration = true;
+ _item._errorString = msg;
+ }
SyncFileItem _item;
- QString _restoreJobMsg;
protected slots:
void slotRestoreJobCompleted(const SyncFileItem& );
diff --git a/src/mirall/syncengine.cpp b/src/mirall/syncengine.cpp
index 65267d1..3d391aa 100644
--- a/src/mirall/syncengine.cpp
+++ b/src/mirall/syncengine.cpp
@@ -526,6 +526,7 @@ void SyncEngine::slotUpdateFinished(int updateResult)
handleSyncError(_csync_ctx, "csync_reconcile");
return;
}
+
_stopWatch.addLapTime(QLatin1String("Reconcile Finished"));
_progressInfo = Progress::Info();
@@ -548,6 +549,9 @@ void SyncEngine::slotUpdateFinished(int updateResult)
it->_file = adjustRenamedPath(it->_file);
}
+ // make sure everything is allowed
+ checkForPermission();
+
// Sanity check
if (!_journal->isConnected()) {
qDebug() << "Bailing out, DB failure";
@@ -698,6 +702,187 @@ QString SyncEngine::adjustRenamedPath(const QString& original)
return original;
}
+void SyncEngine::checkForPermission()
+{
+ for (SyncFileItemVector::iterator it = _syncedItems.begin(); it != _syncedItems.end(); ++it) {
+
+ if (it->_direction != SyncFileItem::Up) {
+ // Currently we only check server-side permissions
+ continue;
+ }
+
+ switch(it->_instruction) {
+ case CSYNC_INSTRUCTION_NEW: {
+ int slashPos = it->_file.lastIndexOf('/');
+ QString parentDir = slashPos <= 0 ? "" : it->_file.mid(0, slashPos);
+ const QByteArray perms = getPermissions(parentDir);
+ if (perms.isNull()) {
+ // No permissions set
+ break;
+ } else if (it->_isDirectory && !perms.contains("K")) {
+ qDebug() << "checkForPermission: ERROR" << it->_file;
+ it->_instruction = CSYNC_INSTRUCTION_ERROR;
+ it->_status = SyncFileItem::NormalError;
+ it->_errorString = tr("Not allowed because you don't have permission to add sub-directories in that directory");
+
+ const QString path = it->_file + QLatin1Char('/');
+ for (SyncFileItemVector::iterator it_next = it + 1; it_next != _syncedItems.end() && it_next->_file.startsWith(path); ++it_next) {
+ it = it_next;
+ it->_instruction = CSYNC_INSTRUCTION_ERROR;
+ it->_status = SyncFileItem::NormalError;
+ it->_errorString = tr("Not allowed because you don't have permission to add parent directory");
+ }
+
+ } else if (!it->_isDirectory && !perms.contains("C")) {
+ qDebug() << "checkForPermission: ERROR" << it->_file;
+ it->_instruction = CSYNC_INSTRUCTION_ERROR;
+ it->_status = SyncFileItem::NormalError;
+ it->_errorString = tr("Not allowed because you don't have permission to add files in that directory");
+ }
+ break;
+ }
+ case CSYNC_INSTRUCTION_SYNC: {
+ const QByteArray perms = getPermissions(it->_file);
+ if (perms.isNull()) {
+ // No permissions set
+ break;
+ } if (!it->_isDirectory && !perms.contains("W")) {
+ qDebug() << "checkForPermission: RESTORING" << it->_file;
+ it->_instruction = CSYNC_INSTRUCTION_CONFLICT;
+ it->_direction = SyncFileItem::Down;
+ it->_isRestoration = true;
+ it->_errorString = tr("Not allowed to upload this file because it is read-only on the server, restoring");
+ continue;
+ }
+ break;
+ }
+ case CSYNC_INSTRUCTION_REMOVE: {
+ const QByteArray perms = getPermissions(it->_file);
+ if (perms.isNull()) {
+ // No permissions set
+ break;
+ } if (!perms.contains("D")) {
+ qDebug() << "checkForPermission: RESTORING" << it->_file;
+ it->_instruction = CSYNC_INSTRUCTION_NEW;
+ it->_direction = SyncFileItem::Down;
+ it->_isRestoration = true;
+ it->_errorString = tr("Not allowed to remove, restoring");
+
+ if (it->_isDirectory) {
+ // restore all sub items
+ const QString path = it->_file + QLatin1Char('/');
+ for (SyncFileItemVector::iterator it_next = it + 1;
+ it_next != _syncedItems.end() && it_next->_file.startsWith(path); ++it_next) {
+ it = it_next;
+
+ if (it->_instruction != CSYNC_INSTRUCTION_REMOVE) {
+ qWarning() << "non-removed job within a removed directory"
+ << it->_file << it->_instruction;
+ continue;
+ }
+
+ qDebug() << "checkForPermission: RESTORING" << it->_file;
+
+ it->_instruction = CSYNC_INSTRUCTION_NEW;
+ it->_direction = SyncFileItem::Down;
+ it->_isRestoration = true;
+ it->_errorString = tr("Not allowed to remove, restoring");
+ }
+ }
+ }
+ break;
+ }
+
+ case CSYNC_INSTRUCTION_RENAME: {
+
+ int slashPos = it->_renameTarget.lastIndexOf('/');
+ const QString parentDir = slashPos <= 0 ? "" : it->_renameTarget.mid(0, slashPos-1);
+ const QByteArray destPerms = getPermissions(parentDir);
+ const QByteArray filePerms = getPermissions(it->_file);
+
+ //true when it is just a rename in the same directory. (not a move)
+ bool isRename = it->_file.startsWith(parentDir) && it->_file.lastIndexOf('/') == slashPos;
+
+
+ // Check if we are allowed to move to the destination.
+ bool destinationOK = true;
+ if (isRename || destPerms.isNull()) {
+ // no need to check for the destination dir permission
+ destinationOK = true;
+ } else if (it->_isDirectory && !destPerms.contains("K")) {
+ destinationOK = false;
+ } else if (!it->_isDirectory && !destPerms.contains("C")) {
+ destinationOK = false;
+ }
+
+ // check if we are allowed to move from the source
+ bool sourceOK = true;
+ if (!filePerms.isNull()
+ && ((isRename && !filePerms.contains("N"))
+ || (!isRename && !filePerms.contains("M")))) {
+
+ // We are not allowed to move or rename this file
+ sourceOK = false;
+
+ if (filePerms.contains("D") && destinationOK) {
+ // but we are allowed to delete it
+ // TODO! simulate delete & upload
+ }
+ }
+
+ if (!sourceOK && !destinationOK) {
+ // Both the source and the destination won't allow move. Move back to the original
+ std::swap(it->_file, it->_renameTarget);
+ it->_direction = SyncFileItem::Down;
+ it->_errorString = tr("Move not allowed, item restored");
+ it->_isRestoration = true;
+ qDebug() << "checkForPermission: MOVING BACK" << it->_file;
+ } else if (!sourceOK || !destinationOK) {
+ // One of them is not possible, just throw an error
+ it->_instruction = CSYNC_INSTRUCTION_ERROR;
+ it->_status = SyncFileItem::NormalError;
+ const QString errorString = tr("Move not allowed because %1 is read-only").arg(
+ sourceOK ? tr("the destination") : tr("the source"));
+ it->_errorString = errorString;
+
+ qDebug() << "checkForPermission: ERROR MOVING" << it->_file << errorString;
+
+ if (it->_isDirectory) {
+ const QString path = it->_file + QLatin1Char('/');
+ for (SyncFileItemVector::iterator it_next = it + 1;
+ it_next != _syncedItems.end() && it_next->_file.startsWith(path); ++it_next) {
+ it = it_next;
+ it->_instruction = CSYNC_INSTRUCTION_ERROR;
+ it->_status = SyncFileItem::NormalError;
+ it->_errorString = errorString;
+ qDebug() << "checkForPermission: ERROR MOVING" << it->_file;
+ }
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
+
+QByteArray SyncEngine::getPermissions(const QString& file)
+{
+ //FIXME;
+ static bool isTest = qgetenv("OWNCLOUD_TEST_PERMISSIONS").toInt();
+ if (isTest) {
+ QRegExp rx("_PERM_([^_]*)_[^/]*$");
+ if (rx.indexIn(file) != -1) {
+ qDebug() << Q_FUNC_INFO << file << rx.cap(1);
+ return rx.cap(1).toLatin1();
+ }
+ }
+ qDebug() << Q_FUNC_INFO << file << "*" << isTest;
+ return QByteArray();
+}
+
+
void SyncEngine::abort()
{
csync_request_abort(_csync_ctx);
diff --git a/src/mirall/syncengine.h b/src/mirall/syncengine.h
index 6aeb384..cb45f32 100644
--- a/src/mirall/syncengine.h
+++ b/src/mirall/syncengine.h
@@ -126,6 +126,13 @@ private:
QHash<QString, QString> _renamedFolders;
QString adjustRenamedPath(const QString &original);
+ /**
+ * check if we are allowed to propagate everything, and if we are not, adjust the instructions
+ * to recover
+ */
+ void checkForPermission();
+ QByteArray getPermissions(const QString& file);
+
bool _hasFiles; // true if there is at least one file that is not ignored or removed
int _uploadLimit;
diff --git a/src/mirall/syncfileitem.h b/src/mirall/syncfileitem.h
index b869a3d..2dc882a 100644
--- a/src/mirall/syncfileitem.h
+++ b/src/mirall/syncfileitem.h
@@ -51,7 +51,7 @@ public:
SyncFileItem() : _type(UnknownType), _direction(None), _instruction(CSYNC_INSTRUCTION_NONE),
_size(0), _should_update_etag(false), _blacklistedInDb(false),
- _status(NoStatus), _httpErrorCode(0), _requestDuration(0) {}
+ _status(NoStatus), _httpErrorCode(0), _requestDuration(0), _isRestoration(false) {}
friend bool operator==(const SyncFileItem& item1, const SyncFileItem& item2) {
return item1._file == item2._file;
@@ -97,6 +97,7 @@ public:
int _httpErrorCode;
QString _responseTimeStamp;
quint64 _requestDuration;
+ bool _isRestoration; // The original operation was forbidden, and this is a restoration
struct {
quint64 _size;
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/owncloud-client.git
More information about the Pkg-owncloud-commits
mailing list