summaryrefslogtreecommitdiff
path: root/plugins/cordova-plugin-file/src/ubuntu/file.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/cordova-plugin-file/src/ubuntu/file.cpp')
-rw-r--r--plugins/cordova-plugin-file/src/ubuntu/file.cpp912
1 files changed, 912 insertions, 0 deletions
diff --git a/plugins/cordova-plugin-file/src/ubuntu/file.cpp b/plugins/cordova-plugin-file/src/ubuntu/file.cpp
new file mode 100644
index 00000000..395ab2dd
--- /dev/null
+++ b/plugins/cordova-plugin-file/src/ubuntu/file.cpp
@@ -0,0 +1,912 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "file.h"
+
+#include <QApplication>
+
+namespace {
+ class FileError {
+ public:
+ static const QString kEncodingErr;
+ static const QString kTypeMismatchErr;
+ static const QString kNotFoundErr;
+ static const QString kSecurityErr;
+ static const QString kAbortErr;
+ static const QString kNotReadableErr;
+ static const QString kNoModificationAllowedErr;
+ static const QString kInvalidStateErr;
+ static const QString kSyntaxErr;
+ static const QString kInvalidModificationErr;
+ static const QString kQuotaExceededErr;
+ static const QString kPathExistsErr;
+ };
+
+ bool checkFileName(const QString &name) {
+ if (name.contains(":")){
+ return false;
+ }
+ return true;
+ }
+};
+
+const QString FileError::kEncodingErr("FileError.ENCODING_ERR");
+const QString FileError::kTypeMismatchErr("FileError.TYPE_MISMATCH_ERR");
+const QString FileError::kNotFoundErr("FileError.NOT_FOUND_ERR");
+const QString FileError::kSecurityErr("FileError.SECURITY_ERR");
+const QString FileError::kAbortErr("FileError.ABORT_ERR");
+const QString FileError::kNotReadableErr("FileError.NOT_READABLE_ERR");
+const QString FileError::kNoModificationAllowedErr("FileError.NO_MODIFICATION_ALLOWED_ERR");
+const QString FileError::kInvalidStateErr("FileError.INVALID_STATE_ERR");
+const QString FileError::kSyntaxErr("FileError.SYNTAX_ERR");
+const QString FileError::kInvalidModificationErr("FileError.INVALID_MODIFICATION_ERR");
+const QString FileError::kQuotaExceededErr("FileError.QUOTA_EXCEEDED_ERR");
+const QString FileError::kPathExistsErr("FileError.PATH_EXISTS_ERR");
+
+File::File(Cordova *cordova) :
+ CPlugin(cordova),
+ _persistentDir(QString("%1/.local/share/%2/persistent").arg(QDir::homePath()).arg(QCoreApplication::applicationName())) {
+ QDir::root().mkpath(_persistentDir.absolutePath());
+}
+
+QVariantMap File::file2map(const QFileInfo &fileInfo) {
+ QVariantMap res;
+
+ res.insert("name", fileInfo.fileName());
+ QPair<QString, QString> r = GetRelativePath(fileInfo);
+ res.insert("fullPath", QString("/") + r.second);
+ res.insert("filesystemName", r.first);
+
+ res.insert("nativeURL", QString("file://localhost") + fileInfo.absoluteFilePath());
+ res.insert("isDirectory", (int)fileInfo.isDir());
+ res.insert("isFile", (int)fileInfo.isFile());
+
+ return res;
+}
+
+QVariantMap File::dir2map(const QDir &dir) {
+ return file2map(QFileInfo(dir.absolutePath()));
+}
+
+QPair<QString, QString> File::GetRelativePath(const QFileInfo &fileInfo) {
+ QString fullPath = fileInfo.isDir() ? QDir::cleanPath(fileInfo.absoluteFilePath()) : fileInfo.absoluteFilePath();
+
+ QString relativePath1 = _persistentDir.relativeFilePath(fullPath);
+ QString relativePath2 = QDir::temp().relativeFilePath(fullPath);
+
+ if (!(relativePath1[0] != '.' || relativePath2[0] != '.')) {
+ if (relativePath1.size() > relativePath2.size()) {
+ return QPair<QString, QString>("temporary", relativePath2);
+ } else {
+ return QPair<QString, QString>("persistent", relativePath1);
+ }
+ }
+
+ if (relativePath1[0] != '.')
+ return QPair<QString, QString>("persistent", relativePath1);
+ return QPair<QString, QString>("temporary", relativePath2);
+}
+
+void File::requestFileSystem(int scId, int ecId, unsigned short type, unsigned long long size) {
+ QDir dir;
+
+ if (size >= 1000485760){
+ this->callback(ecId, FileError::kQuotaExceededErr);
+ return;
+ }
+
+ if (type == 0)
+ dir = QDir::temp();
+ else
+ dir = _persistentDir;
+
+ if (type > 1) {
+ this->callback(ecId, FileError::kSyntaxErr);
+ return;
+ } else {
+ QVariantMap res;
+ res.insert("root", dir2map(dir));
+ if (type == 0)
+ res.insert("name", "temporary");
+ else
+ res.insert("name", "persistent");
+
+ this->cb(scId, res);
+ }
+}
+
+QPair<bool, QFileInfo> File::resolveURI(int ecId, const QString &uri) {
+ QPair<bool, QFileInfo> result;
+
+ result.first = false;
+
+ QUrl url = QUrl::fromUserInput(uri);
+
+ if (url.scheme() == "file" && url.isValid()) {
+ result.first = true;
+ result.second = QFileInfo(url.path());
+ return result;
+ }
+
+ if (url.scheme() != "cdvfile") {
+ if (ecId)
+ this->callback(ecId, FileError::kTypeMismatchErr);
+ return result;
+ }
+
+ QString path = url.path().replace("//", "/");
+ //NOTE: colon is not safe in url, it is not a valid path in Win and Mac, simple disable it here.
+ if (path.contains(":") || !url.isValid()){
+ if (ecId)
+ this->callback(ecId, FileError::kEncodingErr);
+ return result;
+ }
+ if (!path.startsWith("/persistent/") && !path.startsWith("/temporary/")) {
+ if (ecId)
+ this->callback(ecId, FileError::kEncodingErr);
+ return result;
+ }
+
+ result.first = true;
+ if (path.startsWith("/persistent/")) {
+ QString relativePath = path.mid(QString("/persistent/").size());
+ result.second = QFileInfo(_persistentDir.filePath(relativePath));
+ } else {
+ QString relativePath = path.mid(QString("/temporary/").size());
+ result.second = QFileInfo(QDir::temp().filePath(relativePath));
+ }
+ return result;
+}
+
+QPair<bool, QFileInfo> File::resolveURI(const QString &uri) {
+ return resolveURI(0, uri);
+}
+
+
+void File::_getLocalFilesystemPath(int scId, int ecId, const QString& uri) {
+ QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
+
+ if (!f1.first)
+ return;
+
+ this->cb(scId, f1.second.absoluteFilePath());
+}
+
+void File::resolveLocalFileSystemURI(int scId, int ecId, const QString &uri) {
+ if (uri[0] == '/' || uri[0] == '.') {
+ this->callback(ecId, FileError::kEncodingErr);
+ return;
+ }
+
+ QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
+
+ if (!f1.first)
+ return;
+
+ QFileInfo fileInfo = f1.second;
+ if (!fileInfo.exists()) {
+ this->callback(ecId, FileError::kNotFoundErr);
+ return;
+ }
+
+ this->cb(scId, file2map(fileInfo));
+}
+
+void File::getFile(int scId, int ecId, const QString &parentPath, const QString &rpath, const QVariantMap &options) {
+ QPair<bool, QFileInfo> f1 = resolveURI(ecId, parentPath + "/" + rpath);
+ if (!f1.first)
+ return;
+
+ bool create = options.value("create").toBool();
+ bool exclusive = options.value("exclusive").toBool();
+ QFile file(f1.second.absoluteFilePath());
+
+ // if create is false and the path represents a directory, return error
+ QFileInfo fileInfo = f1.second;
+ if ((!create) && fileInfo.isDir()) {
+ this->callback(ecId, FileError::kTypeMismatchErr);
+ return;
+ }
+
+ // if file does exist, and create is true and exclusive is true, return error
+ if (file.exists()) {
+ if (create && exclusive) {
+ this->callback(ecId, FileError::kPathExistsErr);
+ return;
+ }
+ }
+ else {
+ // if file does not exist and create is false, return error
+ if (!create) {
+ this->callback(ecId, FileError::kNotFoundErr);
+ return;
+ }
+
+ file.open(QIODevice::WriteOnly);
+ file.close();
+
+ // Check if creation was successfull
+ if (!file.exists()) {
+ this->callback(ecId, FileError::kNoModificationAllowedErr);
+ return;
+ }
+ }
+
+ this->cb(scId, file2map(QFileInfo(file)));
+}
+
+void File::getDirectory(int scId, int ecId, const QString &parentPath, const QString &rpath, const QVariantMap &options) {
+ QPair<bool, QFileInfo> f1 = resolveURI(ecId, parentPath + "/" + rpath);
+ if (!f1.first)
+ return;
+
+ bool create = options.value("create").toBool();
+ bool exclusive = options.value("exclusive").toBool();
+ QDir dir(f1.second.absoluteFilePath());
+
+ QFileInfo &fileInfo = f1.second;
+ if ((!create) && fileInfo.isFile()) {
+ this->callback(ecId, FileError::kTypeMismatchErr);
+ return;
+ }
+
+ if (dir.exists()) {
+ if (create && exclusive) {
+ this->callback(ecId, FileError::kPathExistsErr);
+ return;
+ }
+ }
+ else {
+ if (!create) {
+ this->callback(ecId, FileError::kNotFoundErr);
+ return;
+ }
+
+ QString folderName = dir.dirName();
+ dir.cdUp();
+ dir.mkdir(folderName);
+ dir.cd(folderName);
+
+ if (!dir.exists()) {
+ this->callback(ecId, FileError::kNoModificationAllowedErr);
+ return;
+ }
+ }
+
+ this->cb(scId, dir2map(dir));
+}
+
+void File::removeRecursively(int scId, int ecId, const QString &uri) {
+ QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
+
+ if (!f1.first)
+ return;
+
+ QDir dir(f1.second.absoluteFilePath());
+ if (File::rmDir(dir))
+ this->cb(scId);
+ else
+ this->callback(ecId, FileError::kNoModificationAllowedErr);
+}
+
+void File::write(int scId, int ecId, const QString &uri, const QString &_data, unsigned long long position, bool binary) {
+ QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
+
+ if (!f1.first)
+ return;
+
+ QFile file(f1.second.absoluteFilePath());
+
+ file.open(QIODevice::WriteOnly);
+ file.close();
+
+ if (!file.exists()) {
+ this->callback(ecId, FileError::kNotFoundErr);
+ return;
+ }
+
+ QFileInfo fileInfo(file);
+ if (!file.open(QIODevice::ReadWrite)) {
+ this->callback(ecId, FileError::kNoModificationAllowedErr);
+ return;
+ }
+
+ if (!binary) {
+ QTextStream textStream(&file);
+ textStream.setCodec("UTF-8");
+ textStream.setAutoDetectUnicode(true);
+
+ if (!textStream.seek(position)) {
+ file.close();
+ fileInfo.refresh();
+
+ this->callback(ecId, FileError::kInvalidModificationErr);
+ return;
+ }
+
+ textStream << _data;
+ textStream.flush();
+ } else {
+ QByteArray data(_data.toUtf8());
+ if (!file.seek(position)) {
+ file.close();
+ fileInfo.refresh();
+
+ this->callback(ecId, FileError::kInvalidModificationErr);
+ return;
+ }
+
+ file.write(data.data(), data.length());
+ }
+
+ file.flush();
+ file.close();
+ fileInfo.refresh();
+
+ this->cb(scId, fileInfo.size() - position);
+}
+
+void File::truncate(int scId, int ecId, const QString &uri, unsigned long long size) {
+ QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
+
+ if (!f1.first)
+ return;
+
+ QFile file(f1.second.absoluteFilePath());
+
+ if (!file.exists()) {
+ this->callback(ecId, FileError::kNotFoundErr);
+ return;
+ }
+
+ if (!file.resize(size)) {
+ this->callback(ecId, FileError::kNoModificationAllowedErr);
+ return;
+ }
+
+ this->cb(scId, size);
+}
+
+void File::getParent(int scId, int ecId, const QString &uri) {
+ QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
+
+ if (!f1.first)
+ return;
+ QDir dir(f1.second.absoluteFilePath());
+
+ //can't cdup more than app's root
+ // Try to change into upper directory
+ if (dir != _persistentDir && dir != QDir::temp()){
+ if (!dir.cdUp()) {
+ this->callback(ecId, FileError::kNotFoundErr);
+ return;
+ }
+
+ }
+ this->cb(scId, dir2map(dir));
+}
+
+void File::remove(int scId, int ecId, const QString &uri) {
+ QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
+ if (!f1.first)
+ return;
+
+ QFileInfo &fileInfo = f1.second;
+ //TODO: fix
+ if (!fileInfo.exists() || (fileInfo.absoluteFilePath() == _persistentDir.absolutePath()) || (QDir::temp() == fileInfo.absoluteFilePath())) {
+ this->callback(ecId, FileError::kNoModificationAllowedErr);
+ return;
+ }
+
+ if (fileInfo.isDir()) {
+ QDir dir(fileInfo.absoluteFilePath());
+ if (dir.rmdir(dir.absolutePath())) {
+ this->cb(scId);
+ return;
+ }
+ } else {
+ QFile file(fileInfo.absoluteFilePath());
+ if (file.remove()) {
+ this->cb(scId);
+ return;
+ }
+ }
+
+ this->callback(ecId, FileError::kInvalidModificationErr);
+}
+
+void File::getFileMetadata(int scId, int ecId, const QString &uri) {
+ QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
+
+ if (!f1.first)
+ return;
+ QFileInfo &fileInfo = f1.second;
+
+ if (!fileInfo.exists()) {
+ this->callback(ecId, FileError::kNotFoundErr);
+ } else {
+ QMimeType mime = _db.mimeTypeForFile(fileInfo.fileName());
+
+ QString args = QString("{name: %1, fullPath: %2, type: %3, lastModifiedDate: new Date(%4), size: %5}")
+ .arg(CordovaInternal::format(fileInfo.fileName())).arg(CordovaInternal::format(fileInfo.absoluteFilePath()))
+ .arg(CordovaInternal::format(mime.name())).arg(fileInfo.lastModified().toMSecsSinceEpoch())
+ .arg(fileInfo.size());
+
+ this->callback(scId, args);
+ }
+}
+
+void File::getMetadata(int scId, int ecId, const QString &uri) {
+ QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
+
+ if (!f1.first)
+ return;
+ QFileInfo &fileInfo = f1.second;
+
+ if (!fileInfo.exists())
+ this->callback(ecId, FileError::kNotFoundErr);
+ else {
+ QVariantMap obj;
+ obj.insert("modificationTime", fileInfo.lastModified().toMSecsSinceEpoch());
+ obj.insert("size", fileInfo.isDir() ? 0 : fileInfo.size());
+ this->cb(scId, obj);
+ }
+}
+
+void File::readEntries(int scId, int ecId, const QString &uri) {
+ QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
+
+ if (!f1.first)
+ return;
+ QDir dir(f1.second.absoluteFilePath());
+ QString entriesList;
+
+ if (!dir.exists()) {
+ this->callback(ecId, FileError::kNotFoundErr);
+ return;
+ }
+
+ for (const QFileInfo &fileInfo: dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) {
+ entriesList += CordovaInternal::format(file2map(fileInfo)) + ",";
+ }
+ // Remove trailing comma
+ if (entriesList.size() > 0)
+ entriesList.remove(entriesList.size() - 1, 1);
+
+ entriesList = "new Array(" + entriesList + ")";
+
+ this->callback(scId, entriesList);
+}
+
+void File::readAsText(int scId, int ecId, const QString &uri, const QString &/*encoding*/, int sliceStart, int sliceEnd) {
+ QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
+
+ if (!f1.first)
+ return;
+
+ QFile file(f1.second.absoluteFilePath());
+
+ if (!file.exists()) {
+ this->callback(ecId, FileError::kNotFoundErr);
+ return;
+ }
+
+ if (!file.open(QIODevice::ReadOnly)) {
+ this->callback(ecId, FileError::kNotReadableErr);
+ return;
+ }
+
+ QByteArray content = file.readAll();
+
+ if (sliceEnd == -1)
+ sliceEnd = content.size();
+ if (sliceEnd < 0) {
+ sliceEnd++;
+ sliceEnd = std::max(0, content.size() + sliceEnd);
+ }
+ if (sliceEnd > content.size())
+ sliceEnd = content.size();
+
+ if (sliceStart < 0)
+ sliceStart = std::max(0, content.size() + sliceStart);
+ if (sliceStart > content.size())
+ sliceStart = content.size();
+
+ if (sliceStart > sliceEnd)
+ sliceEnd = sliceStart;
+
+ //FIXME: encoding
+ content = content.mid(sliceStart, sliceEnd - sliceStart);
+
+ this->cb(scId, content);
+}
+
+void File::readAsArrayBuffer(int scId, int ecId, const QString &uri, int sliceStart, int sliceEnd) {
+ const QString str2array("\
+ (function strToArray(str) { \
+ var res = new Uint8Array(str.length); \
+ for (var i = 0; i < str.length; i++) { \
+ res[i] = str.charCodeAt(i); \
+ } \
+ return res; \
+ })(\"%1\")");
+
+ QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
+
+ if (!f1.first)
+ return;
+
+ QFile file(f1.second.absoluteFilePath());
+
+ if (!file.exists()) {
+ this->callback(ecId, FileError::kNotFoundErr);
+ return;
+ }
+
+ if (!file.open(QIODevice::ReadOnly)) {
+ this->callback(ecId, FileError::kNotReadableErr);
+ return;
+ }
+ QString res;
+ QByteArray content = file.readAll();
+
+ if (sliceEnd == -1)
+ sliceEnd = content.size();
+ if (sliceEnd < 0) {
+ sliceEnd++;
+ sliceEnd = std::max(0, content.size() + sliceEnd);
+ }
+ if (sliceEnd > content.size())
+ sliceEnd = content.size();
+
+ if (sliceStart < 0)
+ sliceStart = std::max(0, content.size() + sliceStart);
+ if (sliceStart > content.size())
+ sliceStart = content.size();
+
+ if (sliceStart > sliceEnd)
+ sliceEnd = sliceStart;
+
+ content = content.mid(sliceStart, sliceEnd - sliceStart);
+
+ res.reserve(content.length() * 6);
+ for (uchar c: content) {
+ res += "\\x";
+ res += QString::number(c, 16).rightJustified(2, '0').toUpper();
+ }
+
+ this->callback(scId, str2array.arg(res));
+}
+
+void File::readAsBinaryString(int scId, int ecId, const QString &uri, int sliceStart, int sliceEnd) {
+ QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
+
+ if (!f1.first)
+ return;
+
+ QFile file(f1.second.absoluteFilePath());
+
+ if (!file.exists()) {
+ this->callback(ecId, FileError::kNotFoundErr);
+ return;
+ }
+
+ if (!file.open(QIODevice::ReadOnly)) {
+ this->callback(ecId, FileError::kNotReadableErr);
+ return;
+ }
+ QString res;
+ QByteArray content = file.readAll();
+
+ if (sliceEnd == -1)
+ sliceEnd = content.size();
+ if (sliceEnd < 0) {
+ sliceEnd++;
+ sliceEnd = std::max(0, content.size() + sliceEnd);
+ }
+ if (sliceEnd > content.size())
+ sliceEnd = content.size();
+
+ if (sliceStart < 0)
+ sliceStart = std::max(0, content.size() + sliceStart);
+ if (sliceStart > content.size())
+ sliceStart = content.size();
+
+ if (sliceStart > sliceEnd)
+ sliceEnd = sliceStart;
+
+ content = content.mid(sliceStart, sliceEnd - sliceStart);
+
+ res.reserve(content.length() * 6);
+ for (uchar c: content) {
+ res += "\\x";
+ res += QString::number(c, 16).rightJustified(2, '0').toUpper();
+ }
+ this->callback(scId, "\"" + res + "\"");
+}
+
+void File::readAsDataURL(int scId, int ecId, const QString &uri, int sliceStart, int sliceEnd) {
+ QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
+
+ if (!f1.first)
+ return;
+
+ QFile file(f1.second.absoluteFilePath());
+ QFileInfo &fileInfo = f1.second;
+
+ if (!file.exists()) {
+ this->callback(ecId, FileError::kNotReadableErr);
+ return;
+ }
+
+ if (!file.open(QIODevice::ReadOnly)) {
+ this->callback(ecId, FileError::kNotReadableErr);
+ return;
+ }
+
+ QByteArray content = file.readAll();
+ QString contentType(_db.mimeTypeForFile(fileInfo.fileName()).name());
+
+ if (sliceEnd == -1)
+ sliceEnd = content.size();
+ if (sliceEnd < 0) {
+ sliceEnd++;
+ sliceEnd = std::max(0, content.size() + sliceEnd);
+ }
+ if (sliceEnd > content.size())
+ sliceEnd = content.size();
+
+ if (sliceStart < 0)
+ sliceStart = std::max(0, content.size() + sliceStart);
+ if (sliceStart > content.size())
+ sliceStart = content.size();
+
+ if (sliceStart > sliceEnd)
+ sliceEnd = sliceStart;
+
+ content = content.mid(sliceStart, sliceEnd - sliceStart);
+
+ this->cb(scId, QString("data:%1;base64,").arg(contentType) + content.toBase64());
+}
+
+bool File::rmDir(const QDir &dir) {
+ if (dir == _persistentDir || dir == QDir::temp()) {//can't remove root dir
+ return false;
+ }
+ bool result = true;
+ if (dir.exists()) {
+ // Iterate over entries and remove them
+ Q_FOREACH(const QFileInfo &fileInfo, dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) {
+ if (fileInfo.isDir()) {
+ result = rmDir(fileInfo.absoluteFilePath());
+ }
+ else {
+ result = QFile::remove(fileInfo.absoluteFilePath());
+ }
+
+ if (!result) {
+ return result;
+ }
+ }
+
+ // Finally remove the current dir
+ return dir.rmdir(dir.absolutePath());
+ }
+ return result;
+}
+
+bool File::copyFile(int scId, int ecId,const QString& sourceUri, const QString& destinationUri, const QString& newName) {
+ QPair<bool, QFileInfo> destDir = resolveURI(ecId, destinationUri);
+ QPair<bool, QFileInfo> sourceFile = resolveURI(ecId, sourceUri);
+
+ if (!destDir.first || !sourceFile.first)
+ return false;
+
+ if (!checkFileName(newName)) {
+ this->callback(ecId, FileError::kEncodingErr);
+ return false;
+ }
+
+ if (destDir.second.isFile()) {
+ this->callback(ecId, FileError::kInvalidModificationErr);
+ return false;
+ }
+
+ if (!destDir.second.isDir()) {
+ this->callback(ecId, FileError::kNotFoundErr);
+ return false;
+ }
+
+ QFileInfo &fileInfo = sourceFile.second;
+ QString fileName((newName.isEmpty()) ? fileInfo.fileName() : newName);
+ QString destinationFile(QDir(destDir.second.absoluteFilePath()).filePath(fileName));
+ if (QFile::copy(fileInfo.absoluteFilePath(), destinationFile)){
+ this->cb(scId, file2map(QFileInfo(destinationFile)));
+ return true;
+ }
+ this->callback(ecId, FileError::kInvalidModificationErr);
+ return false;
+}
+
+void File::copyDir(int scId, int ecId,const QString& sourceUri, const QString& destinationUri, const QString& newName) {
+ QPair<bool, QFileInfo> destDir = resolveURI(ecId, destinationUri);
+ QPair<bool, QFileInfo> sourceDir = resolveURI(ecId, sourceUri);
+
+ if (!destDir.first || !sourceDir.first)
+ return;
+ if (!checkFileName(newName)) {
+ this->callback(ecId, FileError::kEncodingErr);
+ return;
+ }
+
+ QString targetName = ((newName.isEmpty()) ? sourceDir.second.fileName() : newName);
+ QString target(QDir(destDir.second.absoluteFilePath()).filePath(targetName));
+
+ if (QFileInfo(target).isFile()){
+ this->callback(ecId, FileError::kInvalidModificationErr);
+ return;
+ }
+
+ // check: copy directory into itself
+ if (QDir(sourceDir.second.absoluteFilePath()).relativeFilePath(target)[0] != '.'){
+ this->callback(ecId, FileError::kInvalidModificationErr);
+ return;
+ }
+
+ if (!QDir(target).exists()){
+ QDir(destDir.second.absoluteFilePath()).mkdir(target);;
+ } else{
+ this->callback(ecId, FileError::kInvalidModificationErr);
+ return;
+ }
+
+ if (copyFolder(sourceDir.second.absoluteFilePath(), target)){
+ this->cb(scId, dir2map(QDir(target)));
+ return;
+ }
+ this->callback(ecId, FileError::kInvalidModificationErr);
+ return;
+}
+
+void File::copyTo(int scId, int ecId, const QString& source, const QString& destinationDir, const QString& newName) {
+ QPair<bool, QFileInfo> f1 = resolveURI(ecId, source);
+
+ if (!f1.first)
+ return;
+
+ if (f1.second.isDir())
+ copyDir(scId, ecId, source, destinationDir, newName);
+ else
+ copyFile(scId, ecId, source, destinationDir, newName);
+}
+
+void File::moveFile(int scId, int ecId,const QString& sourceUri, const QString& destinationUri, const QString& newName) {
+ QPair<bool, QFileInfo> sourceFile = resolveURI(ecId, sourceUri);
+ QPair<bool, QFileInfo> destDir = resolveURI(ecId, destinationUri);
+
+ if (!destDir.first || !sourceFile.first)
+ return;
+ if (!checkFileName(newName)) {
+ this->callback(ecId, FileError::kEncodingErr);
+ return;
+ }
+
+ QString fileName = ((newName.isEmpty()) ? sourceFile.second.fileName() : newName);
+ QString target = QDir(destDir.second.absoluteFilePath()).filePath(fileName);
+
+ if (sourceFile.second == QFileInfo(target)) {
+ this->callback(ecId, FileError::kInvalidModificationErr);
+ return;
+ }
+
+ if (!destDir.second.exists()) {
+ this->callback(ecId, FileError::kNotFoundErr);
+ return;
+ }
+ if (!destDir.second.isDir()){
+ this->callback(ecId, FileError::kInvalidModificationErr);
+ return;
+ }
+
+ if (QFileInfo(target).exists()) {
+ if (!QFile::remove(target)) {
+ this->callback(ecId, FileError::kInvalidModificationErr);
+ return;
+ }
+ }
+
+ QFile::rename(sourceFile.second.absoluteFilePath(), target);
+ this->cb(scId, file2map(QFileInfo(target)));
+}
+
+void File::moveDir(int scId, int ecId,const QString& sourceUri, const QString& destinationUri, const QString& newName){
+ QPair<bool, QFileInfo> sourceDir = resolveURI(ecId, sourceUri);
+ QPair<bool, QFileInfo> destDir = resolveURI(ecId, destinationUri);
+
+ if (!destDir.first || !sourceDir.first)
+ return;
+ if (!checkFileName(newName)) {
+ this->callback(ecId, FileError::kEncodingErr);
+ return;
+ }
+
+ QString fileName = ((newName.isEmpty()) ? sourceDir.second.fileName() : newName);
+ QString target = QDir(destDir.second.absoluteFilePath()).filePath(fileName);
+
+ if (!destDir.second.exists()){
+ this->callback(ecId, FileError::kNotFoundErr);
+ return;
+ }
+
+ if (destDir.second.isFile()){
+ this->callback(ecId, FileError::kInvalidModificationErr);
+ return;
+ }
+
+ // check: copy directory into itself
+ if (QDir(sourceDir.second.absoluteFilePath()).relativeFilePath(target)[0] != '.'){
+ this->callback(ecId, FileError::kInvalidModificationErr);
+ return;
+ }
+
+ if (QFileInfo(target).exists() && !QDir(destDir.second.absoluteFilePath()).rmdir(fileName)) {
+ this->callback(ecId, FileError::kInvalidModificationErr);
+ return;
+ }
+
+ if (copyFolder(sourceDir.second.absoluteFilePath(), target)) {
+ rmDir(sourceDir.second.absoluteFilePath());
+ this->cb(scId, file2map(QFileInfo(target)));
+ } else {
+ this->callback(ecId, FileError::kNoModificationAllowedErr);
+ }
+}
+
+void File::moveTo(int scId, int ecId, const QString& source, const QString& destinationDir, const QString& newName) {
+ QPair<bool, QFileInfo> f1 = resolveURI(ecId, source);
+
+ if (!f1.first)
+ return;
+
+ if (f1.second.isDir())
+ moveDir(scId, ecId, source, destinationDir, newName);
+ else
+ moveFile(scId, ecId, source, destinationDir, newName);
+}
+
+bool File::copyFolder(const QString& sourceFolder, const QString& destFolder) {
+ QDir sourceDir(sourceFolder);
+ if (!sourceDir.exists())
+ return false;
+ QDir destDir(destFolder);
+ if (!destDir.exists()){
+ destDir.mkdir(destFolder);
+ }
+ QStringList files = sourceDir.entryList(QDir::Files);
+ for (int i = 0; i< files.count(); i++)
+ {
+ QString srcName = sourceFolder + "/" + files[i];
+ QString destName = destFolder + "/" + files[i];
+ QFile::copy(srcName, destName);
+ }
+ files.clear();
+ files = sourceDir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
+ for (int i = 0; i< files.count(); i++)
+ {
+ QString srcName = sourceFolder + "/" + files[i];
+ QString destName = destFolder + "/" + files[i];
+ copyFolder(srcName, destName);
+ }
+ return true;
+}