packages can now generate a hash of their contents; inc unit test
svn path=/trunk/KDE/kdelibs/; revision=1026489
This commit is contained in:
parent
72c4534396
commit
19f55f804b
@ -1,2 +1,3 @@
|
||||
#cmakedefine ENABLE_REMOTE_WIDGETS
|
||||
#cmakedefine QCA2_FOUND
|
||||
|
||||
|
84
package.cpp
84
package.cpp
@ -19,11 +19,16 @@
|
||||
*******************************************************************************/
|
||||
|
||||
#include "package.h"
|
||||
#include "config-plasma.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QRegExp>
|
||||
|
||||
#ifdef QCA2_FOUND
|
||||
#include <QtCrypto>
|
||||
#endif
|
||||
|
||||
#include <karchive.h>
|
||||
#include <kcomponentdata.h>
|
||||
#include <kdesktopfile.h>
|
||||
@ -165,6 +170,85 @@ const PackageStructure::Ptr Package::structure() const
|
||||
return d->structure;
|
||||
}
|
||||
|
||||
#ifdef QCA2_FOUND
|
||||
void PackagePrivate::updateHash(const QString &basePath, const QString &subPath, const QDir &dir, QCA::Hash &hash)
|
||||
{
|
||||
// hash is calculated as a function of:
|
||||
// * files ordered alphabetically by name, with each file's:
|
||||
// * path relative to the content root
|
||||
// * file data
|
||||
// * directories ordered alphabetically by name, with each dir's:
|
||||
// * path relative to the content root
|
||||
// * file listing (recursing)
|
||||
// symlinks (in both the file and dir case) are handled by adding
|
||||
// the name of the symlink itself and the abs path of what it points to
|
||||
|
||||
const QDir::SortFlags sorting = QDir::Name | QDir::IgnoreCase;
|
||||
const QDir::Filters filters = QDir::Hidden | QDir::System | QDir::NoDotAndDotDot;
|
||||
foreach (const QString &file, dir.entryList(QDir::Files | filters, sorting)) {
|
||||
if (!subPath.isEmpty()) {
|
||||
hash.update(subPath.toUtf8());
|
||||
}
|
||||
|
||||
hash.update(file.toUtf8());
|
||||
|
||||
QFileInfo info(dir.path() + '/' + file);
|
||||
if (info.isSymLink()) {
|
||||
hash.update(info.symLinkTarget().toUtf8());
|
||||
} else {
|
||||
QFile f(info.filePath());
|
||||
if (f.open(QIODevice::ReadOnly)) {
|
||||
while (!f.atEnd()) {
|
||||
hash.update(f.read(1024));
|
||||
}
|
||||
} else {
|
||||
kWarning() << "permissions fail?" << info.permissions() << info.isFile();
|
||||
kWarning() << "could not add" << f.fileName() << "to the hash; file could not be opened for reading";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (const QString &subDirPath, dir.entryList(QDir::Dirs | filters, sorting)) {
|
||||
const QString relativePath = subPath + subDirPath + '/';
|
||||
hash.update(relativePath.toUtf8());
|
||||
|
||||
QDir subDir(dir.path());
|
||||
subDir.cd(subDirPath);
|
||||
|
||||
if (subDir.path() != subDir.canonicalPath()) {
|
||||
hash.update(subDir.canonicalPath().toUtf8());
|
||||
} else {
|
||||
updateHash(basePath, relativePath, subDir, hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
QString Package::hash() const
|
||||
{
|
||||
#ifdef QCA2_FOUND
|
||||
if (!QCA::isSupported("sha1")) {
|
||||
kWarning() << "can not create hash for" << path() << "due to no SHA1 support in QCA2";
|
||||
return QString();
|
||||
}
|
||||
|
||||
const QString basePath = d->structure->path() + d->structure->contentsPrefix();
|
||||
QDir dir(basePath);
|
||||
|
||||
if (!dir.exists()) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
QCA::Hash hash("sha1");
|
||||
d->updateHash(basePath, QString(), dir, hash);
|
||||
return QCA::arrayToHex(hash.final().toByteArray());
|
||||
#else
|
||||
// no QCA2!
|
||||
kWarning() << "can not create hash for" << path() << "due to no cryptographic support (QCA2)";
|
||||
return QString();
|
||||
#endif
|
||||
}
|
||||
|
||||
//TODO: provide a version of this that allows one to ask for certain types of packages, etc?
|
||||
// should we be using KService here instead/as well?
|
||||
QStringList Package::listInstalled(const QString &packageRoot) // static
|
||||
|
@ -135,6 +135,11 @@ class PLASMA_EXPORT Package
|
||||
*/
|
||||
const PackageStructure::Ptr structure() const;
|
||||
|
||||
/**
|
||||
* @return a SHA1 hash digest of the contents of the package in hexadecimal form
|
||||
*/
|
||||
QString hash() const;
|
||||
|
||||
/**
|
||||
* Returns a list of all installed packages by name
|
||||
*
|
||||
|
@ -35,6 +35,10 @@ public:
|
||||
void unpublish();
|
||||
bool isPublished() const;
|
||||
|
||||
#ifdef QCA2_FOUND
|
||||
void updateHash(const QString &basePath, const QString &subPath, const QDir &dir, QCA::Hash &hash);
|
||||
#endif
|
||||
|
||||
PackageStructure::Ptr structure;
|
||||
Service *service;
|
||||
bool valid;
|
||||
|
@ -18,6 +18,7 @@
|
||||
*******************************************************************************/
|
||||
|
||||
#include "plasmoidpackagetest.h"
|
||||
#include "../config-plasma.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
@ -26,8 +27,15 @@
|
||||
#include "plasma/applet.h"
|
||||
#include "plasma/packagemetadata.h"
|
||||
|
||||
#ifdef QCA2_FOUND
|
||||
#include <QtCrypto>
|
||||
#endif
|
||||
|
||||
void PlasmoidPackageTest::init()
|
||||
{
|
||||
#ifdef QCA2_FOUND
|
||||
QCA::Initializer *cryptoInit = new QCA::Initializer;
|
||||
#endif
|
||||
mPackage = QString("Package");
|
||||
mPackageRoot = QDir::homePath() + "/.kde-unit-test/packageRoot";
|
||||
ps = Plasma::Applet::packageStructure();
|
||||
@ -42,7 +50,7 @@ void PlasmoidPackageTest::cleanup()
|
||||
|
||||
// Clean things up.
|
||||
QDir local = QDir::homePath() + QLatin1String("/.kde-unit-test/packageRoot");
|
||||
foreach(const QString &dir, local.entryList(QDir::Dirs)) {
|
||||
foreach (const QString &dir, local.entryList(QDir::Dirs)) {
|
||||
removeDir(QLatin1String("packageRoot/" + dir.toLatin1() + "/contents/code"));
|
||||
removeDir(QLatin1String("packageRoot/" + dir.toLatin1() + "/contents/images"));
|
||||
removeDir(QLatin1String("packageRoot/" + dir.toLatin1() + "/contents"));
|
||||
@ -70,8 +78,7 @@ void PlasmoidPackageTest::createTestPackage(const QString &packageName)
|
||||
{
|
||||
QDir pRoot(mPackageRoot);
|
||||
// Create the root and package dir.
|
||||
if(!pRoot.exists())
|
||||
{
|
||||
if (!pRoot.exists()) {
|
||||
QVERIFY(QDir().mkpath(mPackageRoot));
|
||||
}
|
||||
|
||||
@ -166,14 +173,18 @@ void PlasmoidPackageTest::isValid()
|
||||
QVERIFY(file.open(QIODevice::WriteOnly | QIODevice::Text));
|
||||
|
||||
out.setDevice(&file);
|
||||
out << "THIS IS A PLASMOID SCRIPT.....";
|
||||
out << "THIS IS A PLASMOID SCRIPT.....\n";
|
||||
file.flush();
|
||||
file.close();
|
||||
|
||||
file.setPermissions(QFile::ReadUser | QFile::WriteUser);
|
||||
// Main file exists so should be valid now.
|
||||
delete p;
|
||||
p = new Plasma::Package(mPackageRoot, mPackage, ps);
|
||||
QVERIFY(p->isValid());
|
||||
#ifdef QCA2_FOUND
|
||||
QCOMPARE(QString("0b8c7de4bee1ac6f373276ac2b5776c9194b2c56"), p->hash());
|
||||
#endif
|
||||
}
|
||||
|
||||
void PlasmoidPackageTest::filePath()
|
||||
|
Loading…
Reference in New Issue
Block a user