| /* |
| * 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; |
| } |