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

Skip menu "kdelibs-4.9.5 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