• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.8.3 API Reference
  • KDE Home
  • Contact Us
 

Plasma

package.cpp
Go to the documentation of this file.
00001 /******************************************************************************
00002 *   Copyright 2007 by Aaron Seigo <aseigo@kde.org>                            *
00003 *   Copyright 2007 by Riccardo Iaconelli <riccardo@kde.org>                   *
00004 *                                                                             *
00005 *   This library is free software; you can redistribute it and/or             *
00006 *   modify it under the terms of the GNU Library General Public               *
00007 *   License as published by the Free Software Foundation; either              *
00008 *   version 2 of the License, or (at your option) any later version.          *
00009 *                                                                             *
00010 *   This library is distributed in the hope that it will be useful,           *
00011 *   but WITHOUT ANY WARRANTY; without even the implied warranty of            *
00012 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU          *
00013 *   Library General Public License for more details.                          *
00014 *                                                                             *
00015 *   You should have received a copy of the GNU Library General Public License *
00016 *   along with this library; see the file COPYING.LIB.  If not, write to      *
00017 *   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,      *
00018 *   Boston, MA 02110-1301, USA.                                               *
00019 *******************************************************************************/
00020 
00021 #include "package.h"
00022 #include "config-plasma.h"
00023 
00024 #include <QDir>
00025 #include <QFile>
00026 #include <QRegExp>
00027 #include <QtNetwork/QHostInfo>
00028 
00029 #ifdef QCA2_FOUND
00030 #include <QtCrypto>
00031 #endif
00032 
00033 #include <karchive.h>
00034 #include <kcomponentdata.h>
00035 #include <kdesktopfile.h>
00036 #ifndef PLASMA_NO_KIO
00037 #include <kio/copyjob.h>
00038 #include <kio/deletejob.h>
00039 #include <kio/jobclasses.h>
00040 #include <kio/job.h>
00041 #endif
00042 #include <kmimetype.h>
00043 #include <kplugininfo.h>
00044 #include <kstandarddirs.h>
00045 #include <ktar.h>
00046 #include <ktempdir.h>
00047 #include <ktemporaryfile.h>
00048 #include <kzip.h>
00049 #include <kdebug.h>
00050 
00051 #include "authorizationmanager.h"
00052 #include "packagemetadata.h"
00053 #include "private/authorizationmanager_p.h"
00054 #include "private/package_p.h"
00055 #include "private/plasmoidservice_p.h"
00056 #include "private/service_p.h"
00057 
00058 namespace Plasma
00059 {
00060 
00061 #ifdef PLASMA_NO_KIO // Provide some convenience for dealing with folders
00062 
00063 bool copyFolder(QString sourcePath, QString targetPath)
00064 {
00065     QDir source(sourcePath);
00066     if(!source.exists())
00067         return false;
00068 
00069     QDir target(targetPath);
00070     if(!target.exists()) {
00071         QString targetName = target.dirName();
00072         target.cdUp();
00073         target.mkdir(targetName);
00074         target = QDir(targetPath);
00075     }
00076 
00077     foreach (const QString &fileName, source.entryList(QDir::Files)) {
00078         QString sourceFilePath = sourcePath + QDir::separator() + fileName;
00079         QString targetFilePath = targetPath + QDir::separator() + fileName;
00080 
00081         if (!QFile::copy(sourceFilePath, targetFilePath)) {
00082             return false;
00083         }
00084     }
00085 
00086     foreach (const QString &subFolderName, source.entryList(QDir::AllDirs | QDir::NoDotAndDotDot)) {
00087         QString sourceSubFolderPath = sourcePath + QDir::separator() + subFolderName;
00088         QString targetSubFolderPath = targetPath + QDir::separator() + subFolderName;
00089 
00090         if (!copyFolder(sourceSubFolderPath, targetSubFolderPath)) {
00091             return false;
00092         }
00093     }
00094 
00095     return true;
00096 }
00097 
00098 bool removeFolder(QString folderPath)
00099 {
00100     QDir folder(folderPath);
00101     if(!folder.exists())
00102         return false;
00103 
00104     foreach (const QString &fileName, folder.entryList(QDir::Files)) {
00105         if (!QFile::remove(folderPath + QDir::separator() + fileName)) {
00106             return false;
00107         }
00108     }
00109 
00110     foreach (const QString &subFolderName, folder.entryList(QDir::AllDirs | QDir::NoDotAndDotDot)) {
00111         if (!removeFolder(folderPath + QDir::separator() + subFolderName)) {
00112             return false;
00113         }
00114     }
00115 
00116     QString folderName = folder.dirName();
00117     folder.cdUp();
00118     return folder.rmdir(folderName);
00119 }
00120 
00121 #endif // PLASMA_NO_KIO
00122 
00123 
00124 Package::Package()
00125     : d(new PackagePrivate(PackageStructure::Ptr(0), QString()))
00126 {
00127 }
00128 
00129 Package::Package(const QString &packageRoot, const QString &package,
00130                  PackageStructure::Ptr structure)
00131     : d(new PackagePrivate(structure, packageRoot, package))
00132 {
00133 }
00134 
00135 Package::Package(const QString &packagePath, PackageStructure::Ptr structure)
00136     : d(new PackagePrivate(structure, packagePath))
00137 {
00138 }
00139 
00140 Package::Package(const Package &other)
00141     : d(new PackagePrivate(*other.d))
00142 {
00143 }
00144 
00145 Package::~Package()
00146 {
00147     delete d;
00148 }
00149 
00150 Package &Package::operator=(const Package &rhs)
00151 {
00152     if (&rhs != this) {
00153         *d = *rhs.d;
00154     }
00155 
00156     return *this;
00157 }
00158 
00159 bool Package::isValid() const
00160 {
00161     if (!d->valid) {
00162         return false;
00163     }
00164 
00165     //search for the file in all prefixes and in all possible paths for each prefix
00166     //even if it's a big nested loop, usually there is one prefix and one location
00167     //so shouldn't cause too much disk access
00168     QStringList prefixes = d->structure->contentsPrefixPaths();
00169     if (prefixes.isEmpty()) {
00170         prefixes << QString();
00171     }
00172 
00173     foreach (const char *dir, d->structure->requiredDirectories()) {
00174         bool failed = true;
00175         foreach (const QString &path, d->structure->searchPath(dir)) {
00176             foreach (const QString &prefix, prefixes) {
00177                 if (QFile::exists(d->structure->path() + prefix + path)) {
00178                     failed = false;
00179                     break;
00180                 }
00181             }
00182             if (!failed) {
00183                 break;
00184             }
00185         }
00186 
00187         if (failed) {
00188             kWarning() << "Could not find required directory" << dir;
00189             d->valid = false;
00190             return false;
00191         }
00192     }
00193 
00194     foreach (const char *file, d->structure->requiredFiles()) {
00195         bool failed = true;
00196         foreach (const QString &path, d->structure->searchPath(file)) {
00197             foreach (const QString &prefix, prefixes) {
00198                 if (QFile::exists(d->structure->path() + prefix + path)) {
00199                     failed = false;
00200                     break;
00201                 }
00202             }
00203             if (!failed) {
00204                 break;
00205             }
00206         }
00207 
00208         if (failed) {
00209             kWarning() << "Could not find required file" << file;
00210             d->valid = false;
00211             return false;
00212         }
00213     }
00214 
00215     return true;
00216 }
00217 
00218 QString Package::filePath(const char *fileType, const QString &filename) const
00219 {
00220     if (!d->valid) {
00221         //kDebug() << "package is not valid";
00222         return QString();
00223     }
00224 
00225     QStringList paths;
00226 
00227     if (qstrlen(fileType) != 0) {
00228         paths = d->structure->searchPath(fileType);
00229 
00230         if (paths.isEmpty()) {
00231             //kDebug() << "no matching path came of it, while looking for" << fileType << filename;
00232             return QString();
00233         }
00234     } else {
00235         //when filetype is empty paths is always empty, so try with an empty string
00236         paths << QString();
00237     }
00238 
00239     //Nested loop, but in the medium case resolves to just one iteration
00240     QStringList prefixes = d->structure->contentsPrefixPaths();
00241     if (prefixes.isEmpty()) {
00242         prefixes << QString();
00243     }
00244 
00245     //kDebug() << "prefixes:" << prefixes.count() << prefixes;
00246     foreach (const QString &contentsPrefix, prefixes) {
00247         const QString prefix(d->structure->path() + contentsPrefix);
00248 
00249         foreach (const QString &path, paths) {
00250             QString file = prefix + path;
00251 
00252             if (!filename.isEmpty()) {
00253                 file.append("/").append(filename);
00254             }
00255 
00256             //kDebug() << "testing" << file << QFile::exists("/bin/ls") << QFile::exists(file);
00257             if (QFile::exists(file)) {
00258                 if (d->structure->allowExternalPaths()) {
00259                     //kDebug() << "found" << file;
00260                     return file;
00261                 }
00262 
00263                 // ensure that we don't return files outside of our base path
00264                 // due to symlink or ../ games
00265                 QDir dir(file);
00266                 QString canonicalized = dir.canonicalPath() + QDir::separator();
00267 
00268                 //kDebug() << "testing that" << canonicalized << "is in" << d->structure->path();
00269                 if (canonicalized.startsWith(d->structure->path())) {
00270                     //kDebug() << "found" << file;
00271                     return file;
00272                 }
00273             }
00274         }
00275     }
00276 
00277     //kDebug() << fileType << filename << "does not exist in" << prefixes << "at root" << d->structure->path();
00278     return QString();
00279 }
00280 
00281 QString Package::filePath(const char *fileType) const
00282 {
00283     return filePath(fileType, QString());
00284 }
00285 
00286 QStringList Package::entryList(const char *fileType) const
00287 {
00288     if (!d->valid) {
00289         return QStringList();
00290     }
00291 
00292     return d->structure->entryList(fileType);
00293 }
00294 
00295 PackageMetadata Package::metadata() const
00296 {
00297     if (d->structure) {
00298         return d->structure->metadata();
00299     }
00300 
00301     return PackageMetadata();
00302 }
00303 
00304 void Package::setPath(const QString &path)
00305 {
00306     if (d->structure) {
00307         d->structure->setPath(path);
00308         d->valid = !d->structure->path().isEmpty();
00309     }
00310 }
00311 
00312 const QString Package::path() const
00313 {
00314     return d->structure ? d->structure->path() : QString();
00315 }
00316 
00317 const PackageStructure::Ptr Package::structure() const
00318 {
00319     return d->structure;
00320 }
00321 
00322 #ifdef QCA2_FOUND
00323 void PackagePrivate::updateHash(const QString &basePath, const QString &subPath, const QDir &dir, QCA::Hash &hash)
00324 {
00325     // hash is calculated as a function of:
00326     // * files ordered alphabetically by name, with each file's:
00327     //      * path relative to the content root
00328     //      * file data
00329     // * directories ordered alphabetically by name, with each dir's:
00330     //      * path relative to the content root
00331     //      * file listing (recursing)
00332     // symlinks (in both the file and dir case) are handled by adding
00333     // the name of the symlink itself and the abs path of what it points to
00334 
00335     const QDir::SortFlags sorting = QDir::Name | QDir::IgnoreCase;
00336     const QDir::Filters filters = QDir::Hidden | QDir::System | QDir::NoDotAndDotDot;
00337     foreach (const QString &file, dir.entryList(QDir::Files | filters, sorting)) {
00338         if (!subPath.isEmpty()) {
00339             hash.update(subPath.toUtf8());
00340         }
00341 
00342         hash.update(file.toUtf8());
00343 
00344         QFileInfo info(dir.path() + '/' + file);
00345         if (info.isSymLink()) {
00346             hash.update(info.symLinkTarget().toUtf8());
00347         } else {
00348             QFile f(info.filePath());
00349             if (f.open(QIODevice::ReadOnly)) {
00350                 while (!f.atEnd()) {
00351                     hash.update(f.read(1024));
00352                 }
00353             } else {
00354                 kWarning() << "could not add" << f.fileName() << "to the hash; file could not be opened for reading. "
00355                            << "permissions fail?" << info.permissions() << info.isFile();
00356             }
00357         }
00358     }
00359 
00360     foreach (const QString &subDirPath, dir.entryList(QDir::Dirs | filters, sorting)) {
00361         const QString relativePath = subPath + subDirPath + '/';
00362         hash.update(relativePath.toUtf8());
00363 
00364         QDir subDir(dir.path());
00365         subDir.cd(subDirPath);
00366 
00367         if (subDir.path() != subDir.canonicalPath()) {
00368             hash.update(subDir.canonicalPath().toUtf8());
00369         } else {
00370             updateHash(basePath, relativePath, subDir, hash);
00371         }
00372     }
00373 }
00374 #endif
00375 
00376 QString Package::contentsHash() const
00377 {
00378 #ifdef QCA2_FOUND
00379     if (!d->valid) {
00380         kWarning() << "can not create hash due to Package being invalid";
00381         return QString();
00382     }
00383 
00384     //FIXME: the initializer should go somewhere global to be shared between all plasma uses?
00385     QCA::Initializer init;
00386     if (!QCA::isSupported("sha1")) {
00387         kWarning() << "can not create hash for" << path() << "due to no SHA1 support in QCA2";
00388         return QString();
00389     }
00390 
00391     QCA::Hash hash("sha1");
00392     QString metadataPath = d->structure->path() + "metadata.desktop";
00393     if (QFile::exists(metadataPath)) {
00394         QFile f(metadataPath);
00395         if (f.open(QIODevice::ReadOnly)) {
00396             while (!f.atEnd()) {
00397                 hash.update(f.read(1024));
00398             }
00399         } else {
00400             kWarning() << "could not add" << f.fileName() << "to the hash; file could not be opened for reading.";
00401         }
00402     } else {
00403         kWarning() << "no metadata at" << metadataPath;
00404     }
00405 
00406     QStringList prefixes = d->structure->contentsPrefixPaths();
00407     if (prefixes.isEmpty()) {
00408         prefixes << QString();
00409     }
00410 
00411     foreach (QString prefix, prefixes) {
00412         const QString basePath = d->structure->path() + prefix;
00413         QDir dir(basePath);
00414 
00415         if (!dir.exists()) {
00416             return QString();
00417         }
00418 
00419         d->updateHash(basePath, QString(), dir, hash);
00420     }
00421     return QCA::arrayToHex(hash.final().toByteArray());
00422 #else
00423     // no QCA2!
00424     kWarning() << "can not create hash for" << path() << "due to no cryptographic support (QCA2)";
00425     return QString();
00426 #endif
00427 }
00428 
00429 //TODO: provide a version of this that allows one to ask for certain types of packages, etc?
00430 //      should we be using KService here instead/as well?
00431 QStringList Package::listInstalled(const QString &packageRoot) // static
00432 {
00433     QDir dir(packageRoot);
00434 
00435     if (!dir.exists()) {
00436         return QStringList();
00437     }
00438 
00439     QStringList packages;
00440 
00441     foreach (const QString &sdir, dir.entryList(QDir::AllDirs | QDir::Readable)) {
00442         QString metadata = packageRoot + '/' + sdir + "/metadata.desktop";
00443         if (QFile::exists(metadata)) {
00444             PackageMetadata m(metadata);
00445             packages << m.pluginName();
00446         }
00447     }
00448 
00449     return packages;
00450 }
00451 
00452 QStringList Package::listInstalledPaths(const QString &packageRoot) // static
00453 {
00454     QDir dir(packageRoot);
00455 
00456     if (!dir.exists()) {
00457         return QStringList();
00458     }
00459 
00460     QStringList packages;
00461 
00462     foreach (const QString &sdir, dir.entryList(QDir::AllDirs | QDir::Readable)) {
00463         QString metadata = packageRoot + '/' + sdir + "/metadata.desktop";
00464         if (QFile::exists(metadata)) {
00465             packages << sdir;
00466         }
00467     }
00468 
00469     return packages;
00470 }
00471 
00472 bool Package::installPackage(const QString &package,
00473                              const QString &packageRoot,
00474                              const QString &servicePrefix) // static
00475 {
00476     //TODO: report *what* failed if something does fail
00477     QDir root(packageRoot);
00478 
00479     if (!root.exists()) {
00480         KStandardDirs::makeDir(packageRoot);
00481         if (!root.exists()) {
00482             kWarning() << "Could not create package root directory:" << packageRoot;
00483             return false;
00484         }
00485     }
00486 
00487     QFileInfo fileInfo(package);
00488     if (!fileInfo.exists()) {
00489         kWarning() << "No such file:" << package;
00490         return false;
00491     }
00492 
00493     QString path;
00494     KTempDir tempdir;
00495     bool archivedPackage = false;
00496 
00497     if (fileInfo.isDir()) {
00498         // we have a directory, so let's just install what is in there
00499         path = package;
00500 
00501         // make sure we end in a slash!
00502         if (path[path.size() - 1] != '/') {
00503             path.append('/');
00504         }
00505     } else {
00506         KArchive *archive = 0;
00507         KMimeType::Ptr mimetype = KMimeType::findByPath(package);
00508 
00509         if (mimetype->is("application/zip")) {
00510             archive = new KZip(package);
00511         } else if (mimetype->is("application/x-compressed-tar") ||
00512                    mimetype->is("application/x-tar")|| mimetype->is("application/x-bzip-compressed-tar") ||
00513                    mimetype->is("application/x-xz") || mimetype->is("application/x-lzma")) {
00514             archive = new KTar(package);
00515         } else {
00516             kWarning() << "Could not open package file, unsupported archive format:" << package << mimetype->name();
00517             return false;
00518         }
00519 
00520         if (!archive->open(QIODevice::ReadOnly)) {
00521             kWarning() << "Could not open package file:" << package;
00522         delete archive;
00523             return false;
00524         }
00525 
00526         archivedPackage = true;
00527         path = tempdir.name();
00528 
00529         const KArchiveDirectory *source = archive->directory();
00530         source->copyTo(path);
00531 
00532         QStringList entries = source->entries();
00533         if (entries.count() == 1) {
00534             const KArchiveEntry *entry = source->entry(entries[0]);
00535             if (entry->isDirectory()) {
00536                 path.append(entry->name()).append("/");
00537             }
00538         }
00539     delete archive;
00540     }
00541 
00542     QString metadataPath = path + "metadata.desktop";
00543     if (!QFile::exists(metadataPath)) {
00544         kWarning() << "No metadata file in package" << package << metadataPath;
00545         return false;
00546     }
00547 
00548     PackageMetadata meta(metadataPath);
00549     QString targetName = meta.pluginName();
00550 
00551     if (targetName.isEmpty()) {
00552         kWarning() << "Package plugin name not specified";
00553         return false;
00554     }
00555 
00556     // Ensure that package names are safe so package uninstall can't inject
00557     // bad characters into the paths used for removal.
00558     QRegExp validatePluginName("^[\\w-\\.]+$"); // Only allow letters, numbers, underscore and period.
00559     if (!validatePluginName.exactMatch(targetName)) {
00560         kWarning() << "Package plugin name " << targetName << "contains invalid characters";
00561         return false;
00562     }
00563 
00564     targetName = packageRoot + '/' + targetName;
00565     if (QFile::exists(targetName)) {
00566         kWarning() << targetName << "already exists";
00567         return false;
00568     }
00569 
00570     if (archivedPackage) {
00571         // it's in a temp dir, so just move it over.
00572 #ifndef PLASMA_NO_KIO
00573         KIO::CopyJob *job = KIO::move(KUrl(path), KUrl(targetName), KIO::HideProgressInfo);
00574         const bool ok = job->exec();
00575         const QString errorString = job->errorString();
00576 #else
00577         const bool ok = copyFolder(path, targetName);
00578         removeFolder(path);
00579         const QString errorString("unknown");
00580 #endif
00581         if (!ok) {
00582             kWarning() << "Could not move package to destination:" << targetName << " : " << errorString;
00583             return false;
00584         }
00585     } else {
00586         // it's a directory containing the stuff, so copy the contents rather
00587         // than move them
00588 #ifndef PLASMA_NO_KIO
00589         KIO::CopyJob *job = KIO::copy(KUrl(path), KUrl(targetName), KIO::HideProgressInfo);
00590         const bool ok = job->exec();
00591         const QString errorString = job->errorString();
00592 #else
00593         const bool ok = copyFolder(path, targetName);
00594         const QString errorString("unknown");
00595 #endif
00596         if (!ok) {
00597             kWarning() << "Could not copy package to destination:" << targetName << " : " << errorString;
00598             return false;
00599         }
00600     }
00601 
00602     if (archivedPackage) {
00603         // no need to remove the temp dir (which has been successfully moved if it's an archive)
00604         tempdir.setAutoRemove(false);
00605     }
00606 
00607     if (!servicePrefix.isEmpty()) {
00608         // and now we register it as a service =)
00609         QString metaPath = targetName + "/metadata.desktop";
00610         KDesktopFile df(metaPath);
00611         KConfigGroup cg = df.desktopGroup();
00612 
00613         // Q: should not installing it as a service disqualify it?
00614         // Q: i don't think so since KServiceTypeTrader may not be
00615         // used by the installing app in any case, and the
00616         // package is properly installed - aseigo
00617 
00618         //TODO: reduce code duplication with registerPackage below
00619 
00620         QString serviceName = servicePrefix + meta.pluginName();
00621 
00622         QString service = KStandardDirs::locateLocal("services", serviceName + ".desktop");
00623 #ifndef PLASMA_NO_KIO
00624         KIO::FileCopyJob *job = KIO::file_copy(metaPath, service, -1, KIO::HideProgressInfo);
00625         const bool ok = job->exec();
00626         const QString errorString = job->errorString();
00627 #else
00628         const bool ok = QFile::copy(metaPath, service);
00629         const QString errorString("unknown");
00630 #endif
00631         if (ok) {
00632             // the icon in the installed file needs to point to the icon in the
00633             // installation dir!
00634             QString iconPath = targetName + '/' + cg.readEntry("Icon");
00635             QFile icon(iconPath);
00636             if (icon.exists()) {
00637                 KDesktopFile df(service);
00638                 KConfigGroup cg = df.desktopGroup();
00639                 cg.writeEntry("Icon", iconPath);
00640             }
00641         } else {
00642             kWarning() << "Could not register package as service (this is not necessarily fatal):" << serviceName << " : " << errorString;
00643         }
00644     }
00645 
00646     return true;
00647 }
00648 
00649 bool Package::uninstallPackage(const QString &pluginName,
00650                                const QString &packageRoot,
00651                                const QString &servicePrefix) // static
00652 {
00653     // We need to remove the package directory and its metadata file.
00654     QString targetName = pluginName;
00655     targetName = packageRoot + '/' + targetName;
00656 
00657     if (!QFile::exists(targetName)) {
00658         kWarning() << targetName << "does not exist";
00659         return false;
00660     }
00661 
00662     QString serviceName = servicePrefix + pluginName;
00663 
00664     QString service = KStandardDirs::locateLocal("services", serviceName + ".desktop");
00665     kDebug() << "Removing service file " << service;
00666     bool ok = QFile::remove(service);
00667 
00668     if (!ok) {
00669         kWarning() << "Unable to remove " << service;
00670     }
00671 
00672 #ifndef PLASMA_NO_KIO
00673     KIO::DeleteJob *job = KIO::del(KUrl(targetName));
00674     ok = job->exec();
00675     const QString errorString = job->errorString();
00676 #else
00677     ok = removeFolder(targetName);
00678     const QString errorString("unknown");
00679 #endif
00680     if (!ok) {
00681         kWarning() << "Could not delete package from:" << targetName << " : " << errorString;
00682         return false;
00683     }
00684 
00685     return true;
00686 }
00687 
00688 bool Package::registerPackage(const PackageMetadata &data, const QString &iconPath)
00689 {
00690     QString serviceName("plasma-applet-" + data.pluginName());
00691     QString service = KStandardDirs::locateLocal("services", serviceName + ".desktop");
00692 
00693     if (data.pluginName().isEmpty()) {
00694         return false;
00695     }
00696 
00697     data.write(service);
00698 
00699     KDesktopFile config(service);
00700     KConfigGroup cg = config.desktopGroup();
00701     const QString type = data.type().isEmpty() ? "Service" : data.type();
00702     cg.writeEntry("Type", type);
00703     const QString serviceTypes = data.serviceType().isNull() ? "Plasma/Applet,Plasma/Containment" : data.serviceType();
00704     cg.writeEntry("X-KDE-ServiceTypes", serviceTypes);
00705     cg.writeEntry("X-KDE-PluginInfo-EnabledByDefault", true);
00706 
00707     QFile icon(iconPath);
00708     if (icon.exists()) {
00709         //FIXME: the '/' search will break on non-UNIX. do we care?
00710         QString installedIcon("plasma_applet_" + data.pluginName() +
00711                               iconPath.right(iconPath.length() - iconPath.lastIndexOf("/")));
00712         cg.writeEntry("Icon", installedIcon);
00713         installedIcon = KStandardDirs::locateLocal("icon", installedIcon);
00714 #ifndef PLASMA_NO_KIO
00715         KIO::FileCopyJob *job = KIO::file_copy(iconPath, installedIcon, -1, KIO::HideProgressInfo);
00716         job->exec();
00717 #else
00718         QFile::copy(iconPath, installedIcon);
00719 #endif
00720     }
00721 
00722     return true;
00723 }
00724 
00725 bool Package::createPackage(const PackageMetadata &metadata,
00726                             const QString &source,
00727                             const QString &destination,
00728                             const QString &icon) // static
00729 {
00730     Q_UNUSED(icon)
00731     if (!metadata.isValid()) {
00732         kWarning() << "Metadata file is not complete";
00733         return false;
00734     }
00735 
00736     // write metadata in a temporary file
00737     KTemporaryFile metadataFile;
00738     if (!metadataFile.open()) {
00739         return false;
00740     }
00741     metadata.write(metadataFile.fileName());
00742 
00743     // put everything into a zip archive
00744     KZip creation(destination);
00745     creation.setCompression(KZip::NoCompression);
00746     if (!creation.open(QIODevice::WriteOnly)) {
00747         return false;
00748     }
00749 
00750     creation.addLocalFile(metadataFile.fileName(), "metadata.desktop");
00751     creation.addLocalDirectory(source, "contents");
00752     creation.close();
00753     return true;
00754 }
00755 
00756 PackagePrivate::PackagePrivate(const PackageStructure::Ptr st, const QString &p)
00757         : structure(st),
00758           service(0)
00759 {
00760     if (structure) {
00761         if (p.isEmpty()) {
00762             structure->setPath(structure->defaultPackageRoot());
00763         } else {
00764             structure->setPath(p);
00765         }
00766     }
00767 
00768     valid = structure && !structure->path().isEmpty();
00769 }
00770 
00771 PackagePrivate::PackagePrivate(const PackageStructure::Ptr st, const QString &packageRoot, const QString &path)
00772         : structure(st),
00773           service(0)
00774 {
00775     if (structure) {
00776         if (packageRoot.isEmpty()) {
00777             structure->setPath(structure->defaultPackageRoot()%"/"%path);
00778         } else {
00779             structure->setPath(packageRoot%"/"%path);
00780         }
00781     }
00782 
00783     valid = structure && !structure->path().isEmpty();
00784 }
00785 
00786 PackagePrivate::PackagePrivate(const PackagePrivate &other)
00787         : structure(other.structure),
00788           service(other.service),
00789           valid(other.valid)
00790 {
00791 }
00792 
00793 PackagePrivate::~PackagePrivate()
00794 {
00795 }
00796 
00797 PackagePrivate &PackagePrivate::operator=(const PackagePrivate &rhs)
00798 {
00799     structure = rhs.structure;
00800     service = rhs.service;
00801     valid = rhs.valid;
00802     return *this;
00803 }
00804 
00805 void PackagePrivate::publish(AnnouncementMethods methods)
00806 {
00807     if (!structure) {
00808         return;
00809     }
00810 
00811     if (!service) {
00812         service = new PlasmoidService(structure->path());
00813     }
00814 
00815     QString resourceName =
00816     i18nc("%1 is the name of a plasmoid, %2 the name of the machine that plasmoid is published on",
00817           "%1 on %2", structure->metadata().name(), QHostInfo::localHostName());
00818     kDebug() << "publishing package under name " << resourceName;
00819     service->d->publish(methods, resourceName, structure->metadata());
00820 }
00821 
00822 void PackagePrivate::unpublish()
00823 {
00824     if (service) {
00825         service->d->unpublish();
00826     }
00827 }
00828 
00829 bool PackagePrivate::isPublished() const
00830 {
00831     if (service) {
00832         return service->d->isPublished();
00833     } else {
00834         return false;
00835     }
00836 }
00837 
00838 } // Namespace
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Sun May 13 2012 21:36:54 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Plasma

Skip menu "Plasma"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs-4.8.3 API Reference

Skip menu "kdelibs-4.8.3 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal