Mon 21 Jul 22:43:21 CEST 2025
This commit is contained in:
parent
c13e427c2b
commit
2a8bbbd2c8
912
js/ui/cordova/plugins/cordova-plugin-file/src/ubuntu/file.cpp
Normal file
912
js/ui/cordova/plugins/cordova-plugin-file/src/ubuntu/file.cpp
Normal file
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user