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
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.