[app] Moved hashing utilities to BooksUtil
This commit is contained in:
parent
26510f1d9e
commit
ed219c1af1
3 changed files with 104 additions and 66 deletions
|
@ -35,20 +35,10 @@
|
|||
#include "BooksStorage.h"
|
||||
#include "BooksTask.h"
|
||||
#include "BooksUtil.h"
|
||||
#include "BooksDefs.h"
|
||||
|
||||
#include "HarbourDebug.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QCryptographicHash>
|
||||
|
||||
#include <sys/xattr.h>
|
||||
#include <linux/xattr.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define DIGEST_XATTR XATTR_USER_PREFIX BOOKS_APP_NAME ".md5-hash"
|
||||
#define DIGEST_TYPE (QCryptographicHash::Md5)
|
||||
#define DIGEST_SIZE (16)
|
||||
|
||||
enum BooksImportRole {
|
||||
BooksImportRoleTitle = Qt::UserRole,
|
||||
|
@ -103,7 +93,6 @@ public:
|
|||
void performTask();
|
||||
void scanDir(QDir aDir);
|
||||
bool isDuplicate(QString aPath, QFileInfoList aFileList);
|
||||
QByteArray calculateFileHash(QString aPath);
|
||||
QByteArray getFileHash(QString aPath);
|
||||
|
||||
Q_SIGNALS:
|
||||
|
@ -134,60 +123,16 @@ BooksImportModel::Task::~Task()
|
|||
delete [] iBuf;
|
||||
}
|
||||
|
||||
QByteArray BooksImportModel::Task::calculateFileHash(QString aPath)
|
||||
{
|
||||
QByteArray result;
|
||||
QFile file(aPath);
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
const qint64 size = file.size();
|
||||
uchar* map = file.map(0, size);
|
||||
if (map) {
|
||||
const char* ptr = (char*)map;
|
||||
qint64 bytesLeft = size;
|
||||
QCryptographicHash hash(DIGEST_TYPE);
|
||||
hash.reset();
|
||||
while (!isCanceled() && bytesLeft > DIGEST_SIZE) {
|
||||
hash.addData(ptr, DIGEST_SIZE);
|
||||
bytesLeft -= DIGEST_SIZE;
|
||||
ptr += DIGEST_SIZE;
|
||||
}
|
||||
if (!isCanceled()) {
|
||||
if (bytesLeft) {
|
||||
hash.addData(ptr, bytesLeft);
|
||||
}
|
||||
result = hash.result();
|
||||
HASSERT(result.size() == DIGEST_SIZE);
|
||||
HDEBUG(qPrintable(aPath) << QString(result.toHex()));
|
||||
}
|
||||
file.unmap(map);
|
||||
} else {
|
||||
HWARN("error mapping" << qPrintable(aPath));
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QByteArray BooksImportModel::Task::getFileHash(QString aPath)
|
||||
{
|
||||
if (iFileHash.contains(aPath)) {
|
||||
return iFileHash.value(aPath);
|
||||
} else {
|
||||
QByteArray hash;
|
||||
char attr[DIGEST_SIZE];
|
||||
QByteArray fname = aPath.toLocal8Bit();
|
||||
if (getxattr(fname, DIGEST_XATTR, attr, sizeof(attr)) == DIGEST_SIZE) {
|
||||
hash = QByteArray(attr, sizeof(attr));
|
||||
HDEBUG(qPrintable(aPath) << QString(hash.toHex()));
|
||||
} else {
|
||||
hash = calculateFileHash(aPath);
|
||||
if (hash.size() == DIGEST_SIZE &&
|
||||
setxattr(fname, DIGEST_XATTR, hash, hash.size(), 0)) {
|
||||
HDEBUG("Failed to set " DIGEST_XATTR " xattr on" <<
|
||||
fname.constData() << ":" << strerror(errno));
|
||||
}
|
||||
QByteArray hash(BooksUtil::fileHashAttr(aPath));
|
||||
if (hash.isEmpty()) {
|
||||
hash = BooksUtil::computeFileHashAndSetAttr(aPath, this);
|
||||
}
|
||||
if (hash.size() == DIGEST_SIZE) {
|
||||
if (!hash.isEmpty()) {
|
||||
iFileHash.insert(aPath, hash);
|
||||
iHashFile.insert(hash, aPath);
|
||||
}
|
||||
|
@ -249,7 +194,6 @@ void BooksImportModel::Task::scanDir(QDir aDir)
|
|||
if (!isDuplicate(filePath, iDestFiles) &&
|
||||
!isDuplicate(filePath, iSrcFiles)) {
|
||||
BooksBook* newBook = new BooksBook(dummy, QString(), book);
|
||||
newBook->moveToThread(thread());
|
||||
iBooks.append(newBook);
|
||||
iSrcFiles.append(fileInfo);
|
||||
HDEBUG("found" << path.c_str() << newBook->title());
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2015-2018 Jolla Ltd.
|
||||
* Copyright (C) 2015-2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of the BSD license as follows:
|
||||
*
|
||||
|
@ -14,7 +14,7 @@
|
|||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Nemo Mobile nor the names of its contributors
|
||||
* * Neither the name of Jolla Ltd nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
|
@ -32,6 +32,8 @@
|
|||
*/
|
||||
|
||||
#include "BooksUtil.h"
|
||||
#include "BooksDefs.h"
|
||||
#include "BooksTask.h"
|
||||
#include "HarbourDebug.h"
|
||||
|
||||
#include "ZLDir.h"
|
||||
|
@ -39,6 +41,16 @@
|
|||
|
||||
#include <queue>
|
||||
|
||||
#include <QCryptographicHash>
|
||||
|
||||
#include <sys/xattr.h>
|
||||
#include <linux/xattr.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define DIGEST_XATTR XATTR_USER_PREFIX BOOKS_APP_NAME ".md5-hash"
|
||||
#define DIGEST_TYPE (QCryptographicHash::Md5)
|
||||
#define DIGEST_SIZE (16)
|
||||
|
||||
shared_ptr<Book> BooksUtil::bookFromFile(std::string aPath)
|
||||
{
|
||||
shared_ptr<Book> book;
|
||||
|
@ -78,6 +90,82 @@ shared_ptr<Book> BooksUtil::bookFromFile(std::string aPath)
|
|||
return book;
|
||||
}
|
||||
|
||||
QByteArray BooksUtil::computeFileHash(QString aPath, BooksTask* aTask)
|
||||
{
|
||||
QByteArray result;
|
||||
QFile file(aPath);
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
const qint64 size = file.size();
|
||||
uchar* map = file.map(0, size);
|
||||
if (map) {
|
||||
const char* ptr = (char*)map;
|
||||
qint64 bytesLeft = size;
|
||||
QCryptographicHash hash(DIGEST_TYPE);
|
||||
hash.reset();
|
||||
if (aTask) {
|
||||
while (!aTask->isCanceled() && bytesLeft > DIGEST_SIZE) {
|
||||
hash.addData(ptr, DIGEST_SIZE);
|
||||
bytesLeft -= DIGEST_SIZE;
|
||||
ptr += DIGEST_SIZE;
|
||||
}
|
||||
} else {
|
||||
while (bytesLeft > DIGEST_SIZE) {
|
||||
hash.addData(ptr, DIGEST_SIZE);
|
||||
bytesLeft -= DIGEST_SIZE;
|
||||
ptr += DIGEST_SIZE;
|
||||
}
|
||||
}
|
||||
if (!aTask || !aTask->isCanceled()) {
|
||||
if (bytesLeft) {
|
||||
hash.addData(ptr, bytesLeft);
|
||||
}
|
||||
result = hash.result();
|
||||
HASSERT(result.size() == DIGEST_SIZE);
|
||||
HDEBUG(qPrintable(aPath) << QString(result.toHex()));
|
||||
}
|
||||
file.unmap(map);
|
||||
} else {
|
||||
HWARN("error mapping" << qPrintable(aPath));
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QByteArray BooksUtil::fileHashAttr(QString aPath)
|
||||
{
|
||||
QByteArray hash;
|
||||
QByteArray fname(aPath.toLocal8Bit());
|
||||
char attr[DIGEST_SIZE];
|
||||
if (getxattr(fname, DIGEST_XATTR, attr, sizeof(attr)) == DIGEST_SIZE) {
|
||||
hash = QByteArray(attr, sizeof(attr));
|
||||
HDEBUG(qPrintable(aPath) << QString(hash.toHex()));
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
bool BooksUtil::setFileHashAttr(QString aPath, QByteArray aHash)
|
||||
{
|
||||
if (aHash.size() == DIGEST_SIZE) {
|
||||
QByteArray fname(aPath.toLocal8Bit());
|
||||
if (setxattr(fname, DIGEST_XATTR, aHash, aHash.size(), 0) == 0) {
|
||||
return true;
|
||||
}
|
||||
HDEBUG("Failed to set " DIGEST_XATTR " xattr on" <<
|
||||
fname.constData() << ":" << strerror(errno));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray BooksUtil::computeFileHashAndSetAttr(QString aPath, BooksTask* aTask)
|
||||
{
|
||||
QByteArray hash = computeFileHash(aPath, aTask);
|
||||
if (!hash.isEmpty()) {
|
||||
BooksUtil::setFileHashAttr(aPath, hash);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
bool BooksUtil::isValidFileName(QString aName)
|
||||
{
|
||||
return !aName.isEmpty() &&
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2015-2018 Jolla Ltd.
|
||||
* Copyright (C) 2015-2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of the BSD license as follows:
|
||||
*
|
||||
|
@ -14,7 +14,7 @@
|
|||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Nemo Mobile nor the names of its contributors
|
||||
* * Neither the name of Jolla Ltd nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
|
@ -40,10 +40,16 @@
|
|||
|
||||
#include <QString>
|
||||
|
||||
class BooksTask;
|
||||
|
||||
namespace BooksUtil {
|
||||
shared_ptr<Book> bookFromFile(std::string aPath);
|
||||
shared_ptr<Book> bookFromFile(QString aPath);
|
||||
bool isValidFileName(QString aName);
|
||||
QByteArray fileHashAttr(QString aPath);
|
||||
bool setFileHashAttr(QString aPath, QByteArray aHash);
|
||||
QByteArray computeFileHash(QString aPath, BooksTask* aTask = NULL);
|
||||
QByteArray computeFileHashAndSetAttr(QString aPath, BooksTask* aTask = NULL);
|
||||
}
|
||||
|
||||
inline shared_ptr<Book> BooksUtil::bookFromFile(QString aPath)
|
||||
|
|
Loading…
Reference in a new issue