/* * Copyright (C) by Roeland Jago Douma * * 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 "sharemanager.h" #include "ocssharejob.h" #include "account.h" #include namespace { struct CreateShare { QString path; OCC::Share::ShareType shareType; QString shareWith; OCC::Share::Permissions permissions; }; } // anonymous namespace Q_DECLARE_METATYPE(CreateShare) namespace OCC { Share::Share(AccountPtr account, const QString& id, const QString& path, const ShareType shareType, const Permissions permissions, const QSharedPointer shareWith) : _account(account), _id(id), _path(path), _shareType(shareType), _permissions(permissions), _shareWith(shareWith) { } AccountPtr Share::account() const { return _account; } QString Share::getId() const { return _id; } Share::ShareType Share::getShareType() const { return _shareType; } QSharedPointer Share::getShareWith() const { return _shareWith; } void Share::setPermissions(Permissions permissions) { OcsShareJob *job = new OcsShareJob(_account); connect(job, SIGNAL(shareJobFinished(QVariantMap, QVariant)), SLOT(slotPermissionsSet(QVariantMap, QVariant))); connect(job, SIGNAL(ocsError(int, QString)), SLOT(slotOcsError(int, QString))); job->setPermissions(getId(), permissions); } void Share::slotPermissionsSet(const QVariantMap &, const QVariant &value) { _permissions = (Permissions)value.toInt(); emit permissionsSet(); } Share::Permissions Share::getPermissions() const { return _permissions; } void Share::deleteShare() { OcsShareJob *job = new OcsShareJob(_account); connect(job, SIGNAL(shareJobFinished(QVariantMap, QVariant)), SLOT(slotDeleted())); connect(job, SIGNAL(ocsError(int, const QString &)), SLOT(slotOcsError(int, const QString &))); job->deleteShare(getId()); } void Share::slotDeleted() { emit shareDeleted(); } void Share::slotOcsError(int statusCode, const QString &message) { emit serverError(statusCode, message); } QUrl LinkShare::getLink() const { return _url; } QDate LinkShare::getExpireDate() const { return _expireDate; } bool LinkShare::isPasswordSet() const { return _passwordSet; } LinkShare::LinkShare(AccountPtr account, const QString& id, const QString& path, Permissions permissions, bool passwordSet, const QUrl& url, const QDate& expireDate) : Share(account, id, path, Share::TypeLink, permissions), _passwordSet(passwordSet), _expireDate(expireDate), _url(url) { } bool LinkShare::getPublicUpload() { return ((_permissions & SharePermissionUpdate) && (_permissions & SharePermissionCreate)); } void LinkShare::setPublicUpload(bool publicUpload) { OcsShareJob *job = new OcsShareJob(_account); connect(job, SIGNAL(shareJobFinished(QVariantMap, QVariant)), SLOT(slotPublicUploadSet(QVariantMap, QVariant))); connect(job, SIGNAL(ocsError(int, QString)), SLOT(slotOcsError(int, QString))); job->setPublicUpload(getId(), publicUpload); } void LinkShare::slotPublicUploadSet(const QVariantMap&, const QVariant &value) { if (value.toBool()) { _permissions = SharePermissionRead | SharePermissionUpdate | SharePermissionCreate; } else { _permissions = SharePermissionRead; } emit publicUploadSet(); } void LinkShare::setPassword(const QString &password) { OcsShareJob *job = new OcsShareJob(_account); connect(job, SIGNAL(shareJobFinished(QVariantMap, QVariant)), SLOT(slotPasswordSet(QVariantMap, QVariant))); connect(job, SIGNAL(ocsError(int, QString)), SLOT(slotSetPasswordError(int,QString))); job->setPassword(getId(), password); } void LinkShare::slotPasswordSet(const QVariantMap&, const QVariant &value) { _passwordSet = value.toString() == ""; emit passwordSet(); } void LinkShare::setExpireDate(const QDate &date) { OcsShareJob *job = new OcsShareJob(_account); connect(job, SIGNAL(shareJobFinished(QVariantMap, QVariant)), SLOT(slotExpireDateSet(QVariantMap, QVariant))); connect(job, SIGNAL(ocsError(int, QString)), SLOT(slotOcsError(int, QString))); job->setExpireDate(getId(), date); } void LinkShare::slotExpireDateSet(const QVariantMap& reply, const QVariant &value) { auto data = reply.value("ocs").toMap().value("data").toMap(); /* * If the reply provides a data back (more REST style) * they use this date. */ if (data.value("expiration").isValid()) { _expireDate = QDate::fromString(data.value("expiration").toString(), "yyyy-MM-dd 00:00:00"); } else { _expireDate = value.toDate(); } emit expireDateSet(); } void LinkShare::slotSetPasswordError(int statusCode, const QString &message) { emit passwordSetError(statusCode, message); } ShareManager::ShareManager(AccountPtr account, QObject *parent) : QObject(parent), _account(account) { } void ShareManager::createLinkShare(const QString &path, const QString &password) { OcsShareJob *job = new OcsShareJob(_account); connect(job, SIGNAL(shareJobFinished(QVariantMap, QVariant)), SLOT(slotLinkShareCreated(QVariantMap))); connect(job, SIGNAL(ocsError(int, QString)), SLOT(slotOcsError(int, QString))); job->createLinkShare(path, password); } void ShareManager::slotLinkShareCreated(const QVariantMap &reply) { QString message; int code = OcsShareJob::getJsonReturnCode(reply, message); /* * Before we had decent sharing capabilities on the server a 403 "generally" * meant that a share was password protected */ if (code == 403) { emit linkShareRequiresPassword(message); return; } //Parse share auto data = reply.value("ocs").toMap().value("data").toMap(); QSharedPointer share(parseLinkShare(data)); emit linkShareCreated(share); } void ShareManager::createShare(const QString& path, const Share::ShareType shareType, const QString shareWith, const Share::Permissions permissions) { auto job = new OcsShareJob(_account); // Store values that we need for creating this share later. CreateShare continuation; continuation.path = path; continuation.shareType = shareType; continuation.shareWith = shareWith; continuation.permissions = permissions; _jobContinuation[job] = QVariant::fromValue(continuation); connect(job, SIGNAL(shareJobFinished(QVariantMap,QVariant)), SLOT(slotCreateShare(QVariantMap))); connect(job, SIGNAL(ocsError(int,QString)), SLOT(slotOcsError(int,QString))); job->getSharedWithMe(); } void ShareManager::slotCreateShare(const QVariantMap &reply) { if (!_jobContinuation.contains(sender())) return; CreateShare cont = _jobContinuation[sender()].value(); if (cont.path.isEmpty()) return; _jobContinuation.remove(sender()); // Find existing share permissions (if this was shared with us) Share::Permissions existingPermissions = SharePermissionDefault; foreach (const QVariant & element, reply["ocs"].toMap()["data"].toList()) { QVariantMap map = element.toMap(); if (map["file_target"] == cont.path) existingPermissions = Share::Permissions(map["permissions"].toInt()); } // Limit the permissions we request for a share to the ones the item // was shared with initially. if (cont.permissions == SharePermissionDefault) { cont.permissions = existingPermissions; } else if (existingPermissions != SharePermissionDefault) { cont.permissions &= existingPermissions; } OcsShareJob *job = new OcsShareJob(_account); connect(job, SIGNAL(shareJobFinished(QVariantMap, QVariant)), SLOT(slotShareCreated(QVariantMap))); connect(job, SIGNAL(ocsError(int, QString)), SLOT(slotOcsError(int, QString))); job->createShare(cont.path, cont.shareType, cont.shareWith, cont.permissions); } void ShareManager::slotShareCreated(const QVariantMap &reply) { //Parse share auto data = reply.value("ocs").toMap().value("data").toMap(); QSharedPointer share(parseShare(data)); emit shareCreated(share); } void ShareManager::fetchShares(const QString &path) { OcsShareJob *job = new OcsShareJob(_account); connect(job, SIGNAL(shareJobFinished(QVariantMap, QVariant)), SLOT(slotSharesFetched(QVariantMap))); connect(job, SIGNAL(ocsError(int, QString)), SLOT(slotOcsError(int, QString))); job->getShares(path); } void ShareManager::slotSharesFetched(const QVariantMap &reply) { auto tmpShares = reply.value("ocs").toMap().value("data").toList(); const QString versionString = _account->serverVersion(); qDebug() << Q_FUNC_INFO << versionString << "Fetched" << tmpShares.count() << "shares"; QList> shares; foreach(const auto &share, tmpShares) { auto data = share.toMap(); auto shareType = data.value("share_type").toInt(); QSharedPointer newShare; if (shareType == Share::TypeLink) { newShare = parseLinkShare(data); } else { newShare = parseShare(data); } shares.append(QSharedPointer(newShare)); } qDebug() << Q_FUNC_INFO << "Sending " << shares.count() << "shares"; emit sharesFetched(shares); } QSharedPointer ShareManager::parseLinkShare(const QVariantMap &data) { QUrl url; // From ownCloud server 8.2 the url field is always set for public shares if (data.contains("url")) { url = QUrl(data.value("url").toString()); } else if (_account->serverVersionInt() >= (8 << 16)) { // From ownCloud server version 8 on, a different share link scheme is used. url = QUrl(Account::concatUrlPath(_account->url(), QString("index.php/s/%1").arg(data.value("token").toString())).toString()); } else { QList> queryArgs; queryArgs.append(qMakePair(QString("service"), QString("files"))); queryArgs.append(qMakePair(QString("t"), data.value("token").toString())); url = QUrl(Account::concatUrlPath(_account->url(), QLatin1String("public.php"), queryArgs).toString()); } QDate expireDate; if (data.value("expiration").isValid()) { expireDate = QDate::fromString(data.value("expiration").toString(), "yyyy-MM-dd 00:00:00"); } return QSharedPointer(new LinkShare(_account, data.value("id").toString(), data.value("path").toString(), (Share::Permissions)data.value("permissions").toInt(), data.value("share_with").isValid(), url, expireDate)); } QSharedPointer ShareManager::parseShare(const QVariantMap &data) { QSharedPointer sharee(new Sharee(data.value("share_with").toString(), data.value("share_with_displayname").toString(), (Sharee::Type)data.value("share_type").toInt())); return QSharedPointer(new Share(_account, data.value("id").toString(), data.value("path").toString(), (Share::ShareType)data.value("share_type").toInt(), (Share::Permissions)data.value("permissions").toInt(), sharee)); } void ShareManager::slotOcsError(int statusCode, const QString &message) { emit serverError(statusCode, message); } }