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

Plasma

  • plasma
package.cpp
Go to the documentation of this file.
1 /******************************************************************************
2 * Copyright 2007 by Aaron Seigo <aseigo@kde.org> *
3 * Copyright 2007 by Riccardo Iaconelli <riccardo@kde.org> *
4 * *
5 * This library is free software; you can redistribute it and/or *
6 * modify it under the terms of the GNU Library General Public *
7 * License as published by the Free Software Foundation; either *
8 * version 2 of the License, or (at your option) any later version. *
9 * *
10 * This library is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
13 * Library General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU Library General Public License *
16 * along with this library; see the file COPYING.LIB. If not, write to *
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
18 * Boston, MA 02110-1301, USA. *
19 *******************************************************************************/
20 
21 #include "package.h"
22 #include "config-plasma.h"
23 
24 #include <QDir>
25 #include <QFile>
26 #include <QRegExp>
27 #include <QtNetwork/QHostInfo>
28 
29 #ifdef QCA2_FOUND
30 #include <QtCrypto>
31 #endif
32 
33 #include <karchive.h>
34 #include <kcomponentdata.h>
35 #include <kdesktopfile.h>
36 #include <kmimetype.h>
37 #include <kplugininfo.h>
38 #include <kstandarddirs.h>
39 #include <ktar.h>
40 #include <ktempdir.h>
41 #include <ktemporaryfile.h>
42 #include <kzip.h>
43 #include <kdebug.h>
44 
45 #include "authorizationmanager.h"
46 #include "dataenginemanager.h"
47 #include "packagemetadata.h"
48 #include "scripting/scriptengine.h"
49 #include "private/authorizationmanager_p.h"
50 #include "private/componentinstaller_p.h"
51 #include "private/package_p.h"
52 #include "private/plasmoidservice_p.h"
53 #include "private/service_p.h"
54 
55 namespace Plasma
56 {
57 
58 bool copyFolder(QString sourcePath, QString targetPath)
59 {
60  QDir source(sourcePath);
61  if(!source.exists())
62  return false;
63 
64  QDir target(targetPath);
65  if(!target.exists()) {
66  QString targetName = target.dirName();
67  target.cdUp();
68  target.mkdir(targetName);
69  target = QDir(targetPath);
70  }
71 
72  foreach (const QString &fileName, source.entryList(QDir::Files)) {
73  QString sourceFilePath = sourcePath + QDir::separator() + fileName;
74  QString targetFilePath = targetPath + QDir::separator() + fileName;
75 
76  if (!QFile::copy(sourceFilePath, targetFilePath)) {
77  return false;
78  }
79  }
80 
81  foreach (const QString &subFolderName, source.entryList(QDir::AllDirs | QDir::NoDotAndDotDot)) {
82  QString sourceSubFolderPath = sourcePath + QDir::separator() + subFolderName;
83  QString targetSubFolderPath = targetPath + QDir::separator() + subFolderName;
84 
85  if (!copyFolder(sourceSubFolderPath, targetSubFolderPath)) {
86  return false;
87  }
88  }
89 
90  return true;
91 }
92 
93 bool removeFolder(QString folderPath)
94 {
95  QDir folder(folderPath);
96  if(!folder.exists())
97  return false;
98 
99  foreach (const QString &fileName, folder.entryList(QDir::Files)) {
100  if (!QFile::remove(folderPath + QDir::separator() + fileName)) {
101  return false;
102  }
103  }
104 
105  foreach (const QString &subFolderName, folder.entryList(QDir::AllDirs | QDir::NoDotAndDotDot)) {
106  if (!removeFolder(folderPath + QDir::separator() + subFolderName)) {
107  return false;
108  }
109  }
110 
111  QString folderName = folder.dirName();
112  folder.cdUp();
113  return folder.rmdir(folderName);
114 }
115 
116 Package::Package()
117  : d(new PackagePrivate(PackageStructure::Ptr(0), QString()))
118 {
119 }
120 
121 Package::Package(const QString &packageRoot, const QString &package,
122  PackageStructure::Ptr structure)
123  : d(new PackagePrivate(structure, packageRoot, package))
124 {
125 }
126 
127 Package::Package(const QString &packagePath, PackageStructure::Ptr structure)
128  : d(new PackagePrivate(structure, packagePath))
129 {
130 }
131 
132 Package::Package(const Package &other)
133  : d(new PackagePrivate(*other.d))
134 {
135 }
136 
137 Package::~Package()
138 {
139  delete d;
140 }
141 
142 Package &Package::operator=(const Package &rhs)
143 {
144  if (&rhs != this) {
145  *d = *rhs.d;
146  }
147 
148  return *this;
149 }
150 
151 bool Package::isValid() const
152 {
153  return d->isValid();
154 }
155 
156 bool PackagePrivate::isValid()
157 {
158  if (!valid || !structure) {
159  return false;
160  }
161 
162  //search for the file in all prefixes and in all possible paths for each prefix
163  //even if it's a big nested loop, usually there is one prefix and one location
164  //so shouldn't cause too much disk access
165  QStringList prefixes = structure->contentsPrefixPaths();
166  if (prefixes.isEmpty()) {
167  prefixes << QString();
168  }
169 
170  foreach (const char *dir, structure->requiredDirectories()) {
171  bool failed = true;
172  foreach (const QString &path, structure->searchPath(dir)) {
173  foreach (const QString &prefix, prefixes) {
174  if (QFile::exists(structure->path() + prefix + path)) {
175  failed = false;
176  break;
177  }
178  }
179  if (!failed) {
180  break;
181  }
182  }
183 
184  if (failed) {
185  kWarning() << "Could not find required directory" << dir;
186  valid = false;
187  return false;
188  }
189  }
190 
191  foreach (const char *file, structure->requiredFiles()) {
192  bool failed = true;
193  foreach (const QString &path, structure->searchPath(file)) {
194  foreach (const QString &prefix, prefixes) {
195  if (QFile::exists(structure->path() + prefix + path)) {
196  failed = false;
197  break;
198  }
199  }
200  if (!failed) {
201  break;
202  }
203  }
204 
205  if (failed) {
206  kWarning() << "Could not find required file" << file;
207  valid = false;
208  return false;
209  }
210  }
211 
212  valid = true;
213  return true;
214 }
215 
216 QString Package::filePath(const char *fileType, const QString &filename) const
217 {
218  if (!d->valid) {
219  //kDebug() << "package is not valid";
220  return QString();
221  }
222 
223  QStringList paths;
224 
225  if (qstrlen(fileType) != 0) {
226  paths = d->structure->searchPath(fileType);
227 
228  if (paths.isEmpty()) {
229  //kDebug() << "no matching path came of it, while looking for" << fileType << filename;
230  return QString();
231  }
232  } else {
233  //when filetype is empty paths is always empty, so try with an empty string
234  paths << QString();
235  }
236 
237  //Nested loop, but in the medium case resolves to just one iteration
238  QStringList prefixes = d->structure->contentsPrefixPaths();
239  if (prefixes.isEmpty()) {
240  prefixes << QString();
241  }
242 
243  //kDebug() << "prefixes:" << prefixes.count() << prefixes;
244  foreach (const QString &contentsPrefix, prefixes) {
245  const QString prefix(d->structure->path() + contentsPrefix);
246 
247  foreach (const QString &path, paths) {
248  QString file = prefix + path;
249 
250  if (!filename.isEmpty()) {
251  file.append("/").append(filename);
252  }
253 
254  //kDebug() << "testing" << file << QFile::exists("/bin/ls") << QFile::exists(file);
255  if (QFile::exists(file)) {
256  if (d->structure->allowExternalPaths()) {
257  //kDebug() << "found" << file;
258  return file;
259  }
260 
261  // ensure that we don't return files outside of our base path
262  // due to symlink or ../ games
263  QDir dir(file);
264  QString canonicalized = dir.canonicalPath() + QDir::separator();
265 
266  //kDebug() << "testing that" << canonicalized << "is in" << d->structure->path();
267  if (canonicalized.startsWith(d->structure->path())) {
268  //kDebug() << "found" << file;
269  return file;
270  }
271  }
272  }
273  }
274 
275  //kDebug() << fileType << filename << "does not exist in" << prefixes << "at root" << d->structure->path();
276  return QString();
277 }
278 
279 QString Package::filePath(const char *fileType) const
280 {
281  return filePath(fileType, QString());
282 }
283 
284 QStringList Package::entryList(const char *fileType) const
285 {
286  if (!d->valid) {
287  return QStringList();
288  }
289 
290  return d->structure->entryList(fileType);
291 }
292 
293 PackageMetadata Package::metadata() const
294 {
295  if (d->structure) {
296  return d->structure->metadata();
297  }
298 
299  return PackageMetadata();
300 }
301 
302 void Package::setPath(const QString &path)
303 {
304  d->setPathFromStructure(path);
305 }
306 
307 const QString Package::path() const
308 {
309  return d->structure ? d->structure->path() : QString();
310 }
311 
312 const PackageStructure::Ptr Package::structure() const
313 {
314  return d->structure;
315 }
316 
317 #ifdef QCA2_FOUND
318 void PackagePrivate::updateHash(const QString &basePath, const QString &subPath, const QDir &dir, QCA::Hash &hash)
319 {
320  // hash is calculated as a function of:
321  // * files ordered alphabetically by name, with each file's:
322  // * path relative to the content root
323  // * file data
324  // * directories ordered alphabetically by name, with each dir's:
325  // * path relative to the content root
326  // * file listing (recursing)
327  // symlinks (in both the file and dir case) are handled by adding
328  // the name of the symlink itself and the abs path of what it points to
329 
330  const QDir::SortFlags sorting = QDir::Name | QDir::IgnoreCase;
331  const QDir::Filters filters = QDir::Hidden | QDir::System | QDir::NoDotAndDotDot;
332  foreach (const QString &file, dir.entryList(QDir::Files | filters, sorting)) {
333  if (!subPath.isEmpty()) {
334  hash.update(subPath.toUtf8());
335  }
336 
337  hash.update(file.toUtf8());
338 
339  QFileInfo info(dir.path() + '/' + file);
340  if (info.isSymLink()) {
341  hash.update(info.symLinkTarget().toUtf8());
342  } else {
343  QFile f(info.filePath());
344  if (f.open(QIODevice::ReadOnly)) {
345  while (!f.atEnd()) {
346  hash.update(f.read(1024));
347  }
348  } else {
349  kWarning() << "could not add" << f.fileName() << "to the hash; file could not be opened for reading. "
350  << "permissions fail?" << info.permissions() << info.isFile();
351  }
352  }
353  }
354 
355  foreach (const QString &subDirPath, dir.entryList(QDir::Dirs | filters, sorting)) {
356  const QString relativePath = subPath + subDirPath + '/';
357  hash.update(relativePath.toUtf8());
358 
359  QDir subDir(dir.path());
360  subDir.cd(subDirPath);
361 
362  if (subDir.path() != subDir.canonicalPath()) {
363  hash.update(subDir.canonicalPath().toUtf8());
364  } else {
365  updateHash(basePath, relativePath, subDir, hash);
366  }
367  }
368 }
369 #endif
370 
371 QString Package::contentsHash() const
372 {
373 #ifdef QCA2_FOUND
374  if (!d->valid) {
375  kWarning() << "can not create hash due to Package being invalid";
376  return QString();
377  }
378 
379  //FIXME: the initializer should go somewhere global to be shared between all plasma uses?
380  QCA::Initializer init;
381  if (!QCA::isSupported("sha1")) {
382  kWarning() << "can not create hash for" << path() << "due to no SHA1 support in QCA2";
383  return QString();
384  }
385 
386  QCA::Hash hash("sha1");
387  QString metadataPath = d->structure->path() + "metadata.desktop";
388  if (QFile::exists(metadataPath)) {
389  QFile f(metadataPath);
390  if (f.open(QIODevice::ReadOnly)) {
391  while (!f.atEnd()) {
392  hash.update(f.read(1024));
393  }
394  } else {
395  kWarning() << "could not add" << f.fileName() << "to the hash; file could not be opened for reading.";
396  }
397  } else {
398  kWarning() << "no metadata at" << metadataPath;
399  }
400 
401  QStringList prefixes = d->structure->contentsPrefixPaths();
402  if (prefixes.isEmpty()) {
403  prefixes << QString();
404  }
405 
406  foreach (QString prefix, prefixes) {
407  const QString basePath = d->structure->path() + prefix;
408  QDir dir(basePath);
409 
410  if (!dir.exists()) {
411  return QString();
412  }
413 
414  d->updateHash(basePath, QString(), dir, hash);
415  }
416  return QCA::arrayToHex(hash.final().toByteArray());
417 #else
418  // no QCA2!
419  kWarning() << "can not create hash for" << path() << "due to no cryptographic support (QCA2)";
420  return QString();
421 #endif
422 }
423 
424 //TODO: provide a version of this that allows one to ask for certain types of packages, etc?
425 // should we be using KService here instead/as well?
426 QStringList Package::listInstalled(const QString &packageRoot) // static
427 {
428  QDir dir(packageRoot);
429 
430  if (!dir.exists()) {
431  return QStringList();
432  }
433 
434  QStringList packages;
435 
436  foreach (const QString &sdir, dir.entryList(QDir::AllDirs | QDir::Readable)) {
437  QString metadata = packageRoot + '/' + sdir + "/metadata.desktop";
438  if (QFile::exists(metadata)) {
439  PackageMetadata m(metadata);
440  packages << m.pluginName();
441  }
442  }
443 
444  return packages;
445 }
446 
447 QStringList Package::listInstalledPaths(const QString &packageRoot) // static
448 {
449  QDir dir(packageRoot);
450 
451  if (!dir.exists()) {
452  return QStringList();
453  }
454 
455  QStringList packages;
456 
457  foreach (const QString &sdir, dir.entryList(QDir::AllDirs | QDir::Readable)) {
458  QString metadata = packageRoot + '/' + sdir + "/metadata.desktop";
459  if (QFile::exists(metadata)) {
460  packages << sdir;
461  }
462  }
463 
464  return packages;
465 }
466 
467 bool Package::installPackage(const QString &package,
468  const QString &packageRoot,
469  const QString &servicePrefix) // static
470 {
471  //TODO: report *what* failed if something does fail
472  QDir root(packageRoot);
473 
474  if (!root.exists()) {
475  KStandardDirs::makeDir(packageRoot);
476  if (!root.exists()) {
477  kWarning() << "Could not create package root directory:" << packageRoot;
478  return false;
479  }
480  }
481 
482  QFileInfo fileInfo(package);
483  if (!fileInfo.exists()) {
484  kWarning() << "No such file:" << package;
485  return false;
486  }
487 
488  QString path;
489  KTempDir tempdir;
490  bool archivedPackage = false;
491 
492  if (fileInfo.isDir()) {
493  // we have a directory, so let's just install what is in there
494  path = package;
495 
496  // make sure we end in a slash!
497  if (path[path.size() - 1] != '/') {
498  path.append('/');
499  }
500  } else {
501  KArchive *archive = 0;
502  KMimeType::Ptr mimetype = KMimeType::findByPath(package);
503 
504  if (mimetype->is("application/zip")) {
505  archive = new KZip(package);
506  } else if (mimetype->is("application/x-compressed-tar") ||
507  mimetype->is("application/x-tar")|| mimetype->is("application/x-bzip-compressed-tar") ||
508  mimetype->is("application/x-xz") || mimetype->is("application/x-lzma")) {
509  archive = new KTar(package);
510  } else {
511  kWarning() << "Could not open package file, unsupported archive format:" << package << mimetype->name();
512  return false;
513  }
514 
515  if (!archive->open(QIODevice::ReadOnly)) {
516  kWarning() << "Could not open package file:" << package;
517  delete archive;
518  return false;
519  }
520 
521  archivedPackage = true;
522  path = tempdir.name();
523 
524  const KArchiveDirectory *source = archive->directory();
525  source->copyTo(path);
526 
527  QStringList entries = source->entries();
528  if (entries.count() == 1) {
529  const KArchiveEntry *entry = source->entry(entries[0]);
530  if (entry->isDirectory()) {
531  path.append(entry->name()).append("/");
532  }
533  }
534  delete archive;
535  }
536 
537  QString metadataPath = path + "metadata.desktop";
538  if (!QFile::exists(metadataPath)) {
539  kWarning() << "No metadata file in package" << package << metadataPath;
540  return false;
541  }
542 
543  PackageMetadata meta(metadataPath);
544  QString targetName = meta.pluginName();
545 
546  if (targetName.isEmpty()) {
547  kWarning() << "Package plugin name not specified";
548  return false;
549  }
550 
551  // Ensure that package names are safe so package uninstall can't inject
552  // bad characters into the paths used for removal.
553  QRegExp validatePluginName("^[\\w-\\.]+$"); // Only allow letters, numbers, underscore and period.
554  if (!validatePluginName.exactMatch(targetName)) {
555  kWarning() << "Package plugin name " << targetName << "contains invalid characters";
556  return false;
557  }
558 
559  targetName = packageRoot + '/' + targetName;
560  if (QFile::exists(targetName)) {
561  kWarning() << targetName << "already exists";
562  return false;
563  }
564 
565  if (archivedPackage) {
566  // it's in a temp dir, so just move it over.
567  const bool ok = copyFolder(path, targetName);
568  removeFolder(path);
569  if (!ok) {
570  kWarning() << "Could not move package to destination:" << targetName;
571  return false;
572  }
573  } else {
574  kDebug() << "************************** 12";
575  // it's a directory containing the stuff, so copy the contents rather
576  // than move them
577  const bool ok = copyFolder(path, targetName);
578  kDebug() << "************************** 13";
579  if (!ok) {
580  kWarning() << "Could not copy package to destination:" << targetName;
581  return false;
582  }
583  }
584 
585  if (archivedPackage) {
586  // no need to remove the temp dir (which has been successfully moved if it's an archive)
587  tempdir.setAutoRemove(false);
588  }
589  // check for missing dependencies
590  QString requiredScriptEngine = meta.implementationApi();
591  if (!requiredScriptEngine.isEmpty()) {
592  // figure out the component type to query for
593  ComponentTypes componentTypes = static_cast<ComponentTypes>(0);
594  QStringList serviceTypes = meta.serviceType().split(',');
595  if (serviceTypes.contains("Plasma/Applet")) {
596  componentTypes |= AppletComponent;
597  }
598  if (serviceTypes.contains("Plasma/DataEngine")) {
599  componentTypes |= DataEngineComponent;
600  }
601  if (serviceTypes.contains("Plasma/Runner")) {
602  componentTypes |= RunnerComponent;
603  }
604  if (serviceTypes.contains("Plasma/Wallpaper")) {
605  componentTypes |= WallpaperComponent;
606  }
607  if (!knownLanguages(componentTypes).contains(requiredScriptEngine)) {
608  // install the missing script engine
609  // force prompting because the user has just explicitly installed a widget
610  ComponentInstaller::self()->installMissingComponent("scriptengine", requiredScriptEngine, 0, true);
611  }
612  }
613  QStringList requiredDataEngines = meta.requiredDataEngines();
614  if (requiredDataEngines.isEmpty()) {
615  // check whether this was explicitly specified as empty
616  QString metaPath = targetName + "/metadata.desktop";
617  KDesktopFile df(metaPath);
618  KConfigGroup cg = df.desktopGroup();
619  if (!cg.hasKey("X-Plasma-RequiredDataEngines")) {
620  // not specified at all, try running the dependency extraction
621  requiredDataEngines = ComponentInstaller::self()->extractDataEngineDependencies(targetName,
622  requiredScriptEngine);
623  }
624  }
625  if (!requiredDataEngines.isEmpty()) {
626  QStringList knownDataEngines = DataEngineManager::self()->listAllEngines(meta.application());
627  foreach (const QString &requiredDataEngine, requiredDataEngines) {
628  if (!knownDataEngines.contains(requiredDataEngine)) {
629  // install the missing data engine
630  // force prompting because the user has just explicitly installed a widget
631  ComponentInstaller::self()->installMissingComponent("dataengine", requiredDataEngine, 0, true);
632  }
633  }
634  }
635 
636  if (!servicePrefix.isEmpty()) {
637  // and now we register it as a service =)
638  kDebug() << "************************** 1";
639  QString metaPath = targetName + "/metadata.desktop";
640  kDebug() << "************************** 2";
641  KDesktopFile df(metaPath);
642  KConfigGroup cg = df.desktopGroup();
643  kDebug() << "************************** 3";
644 
645  // Q: should not installing it as a service disqualify it?
646  // Q: i don't think so since KServiceTypeTrader may not be
647  // used by the installing app in any case, and the
648  // package is properly installed - aseigo
649 
650  //TODO: reduce code duplication with registerPackage below
651 
652  QString serviceName = servicePrefix + meta.pluginName();
653 
654  QString service = KStandardDirs::locateLocal("services", serviceName + ".desktop");
655  kDebug() << "************************** 4";
656  const bool ok = QFile::copy(metaPath, service);
657  kDebug() << "************************** 5";
658  if (ok) {
659  // the icon in the installed file needs to point to the icon in the
660  // installation dir!
661  QString iconPath = targetName + '/' + cg.readEntry("Icon");
662  QFile icon(iconPath);
663  if (icon.exists()) {
664  KDesktopFile df(service);
665  KConfigGroup cg = df.desktopGroup();
666  cg.writeEntry("Icon", iconPath);
667  }
668  } else {
669  kWarning() << "Could not register package as service (this is not necessarily fatal):" << serviceName;
670  }
671  kDebug() << "************************** 7";
672  }
673 
674  return true;
675 }
676 
677 bool Package::uninstallPackage(const QString &pluginName,
678  const QString &packageRoot,
679  const QString &servicePrefix) // static
680 {
681  // We need to remove the package directory and its metadata file.
682  QString targetName = pluginName;
683  targetName = packageRoot + '/' + targetName;
684 
685  if (!QFile::exists(targetName)) {
686  kWarning() << targetName << "does not exist";
687  return false;
688  }
689 
690  QString serviceName = servicePrefix + pluginName;
691 
692  QString service = KStandardDirs::locateLocal("services", serviceName + ".desktop");
693  kDebug() << "Removing service file " << service;
694  bool ok = QFile::remove(service);
695 
696  if (!ok) {
697  kWarning() << "Unable to remove " << service;
698  }
699 
700  ok = removeFolder(targetName);
701  const QString errorString("unknown");
702  if (!ok) {
703  kWarning() << "Could not delete package from:" << targetName << " : " << errorString;
704  return false;
705  }
706 
707  return true;
708 }
709 
710 bool Package::registerPackage(const PackageMetadata &data, const QString &iconPath)
711 {
712  QString serviceName("plasma-applet-" + data.pluginName());
713  QString service = KStandardDirs::locateLocal("services", serviceName + ".desktop");
714 
715  if (data.pluginName().isEmpty()) {
716  return false;
717  }
718 
719  data.write(service);
720 
721  KDesktopFile config(service);
722  KConfigGroup cg = config.desktopGroup();
723  const QString type = data.type().isEmpty() ? "Service" : data.type();
724  cg.writeEntry("Type", type);
725  const QString serviceTypes = data.serviceType().isNull() ? "Plasma/Applet,Plasma/Containment" : data.serviceType();
726  cg.writeEntry("X-KDE-ServiceTypes", serviceTypes);
727  cg.writeEntry("X-KDE-PluginInfo-EnabledByDefault", true);
728 
729  QFile icon(iconPath);
730  if (icon.exists()) {
731  //FIXME: the '/' search will break on non-UNIX. do we care?
732  QString installedIcon("plasma_applet_" + data.pluginName() +
733  iconPath.right(iconPath.length() - iconPath.lastIndexOf("/")));
734  cg.writeEntry("Icon", installedIcon);
735  installedIcon = KStandardDirs::locateLocal("icon", installedIcon);
736  QFile::copy(iconPath, installedIcon);
737  }
738 
739  return true;
740 }
741 
742 bool Package::createPackage(const PackageMetadata &metadata,
743  const QString &source,
744  const QString &destination,
745  const QString &icon) // static
746 {
747  Q_UNUSED(icon)
748  if (!metadata.isValid()) {
749  kWarning() << "Metadata file is not complete";
750  return false;
751  }
752 
753  // write metadata in a temporary file
754  KTemporaryFile metadataFile;
755  if (!metadataFile.open()) {
756  return false;
757  }
758  metadata.write(metadataFile.fileName());
759 
760  // put everything into a zip archive
761  KZip creation(destination);
762  creation.setCompression(KZip::NoCompression);
763  if (!creation.open(QIODevice::WriteOnly)) {
764  return false;
765  }
766 
767  creation.addLocalFile(metadataFile.fileName(), "metadata.desktop");
768  creation.addLocalDirectory(source, "contents");
769  creation.close();
770  return true;
771 }
772 
773 PackagePrivate::PackagePrivate(const PackageStructure::Ptr st, const QString &p)
774  : structure(st),
775  service(0)
776 {
777  setPathFromStructure(p);
778 }
779 
780 PackagePrivate::PackagePrivate(const PackageStructure::Ptr st, const QString &packageRoot, const QString &path)
781  : structure(st),
782  service(0)
783 {
784  setPathFromStructure(packageRoot.isEmpty() ? path : packageRoot % "/" % path);
785 }
786 
787 PackagePrivate::PackagePrivate(const PackagePrivate &other)
788  : structure(other.structure),
789  service(other.service),
790  valid(other.valid)
791 {
792 }
793 
794 PackagePrivate::~PackagePrivate()
795 {
796 }
797 
798 PackagePrivate &PackagePrivate::operator=(const PackagePrivate &rhs)
799 {
800  structure = rhs.structure;
801  service = rhs.service;
802  valid = rhs.valid;
803  return *this;
804 }
805 
806 void PackagePrivate::setPathFromStructure(const QString &path)
807 {
808  if (!structure) {
809  valid = false;
810  return;
811  }
812 
813  QStringList paths;
814  if (path.isEmpty()) {
815  paths << structure->defaultPackageRoot();
816  } else if (QDir::isRelativePath(path)) {
817  QString p = structure->defaultPackageRoot() % "/" % path % "/";
818 
819  if (QDir::isRelativePath(p)) {
820  paths = KGlobal::dirs()->findDirs("data", p);
821  } else {
822  paths << p;
823  }
824  } else {
825  paths << path;
826  }
827 
828  foreach (const QString &p, paths) {
829  structure->setPath(p);
830  // reset valid, otherwise isValid() short-circuits
831  valid = true;
832  if (isValid()) {
833  return;
834  }
835  }
836 
837  valid = false;
838  structure->setPath(QString());
839 }
840 
841 void PackagePrivate::publish(AnnouncementMethods methods)
842 {
843  if (!structure) {
844  return;
845  }
846 
847  if (!service) {
848  service = new PlasmoidService(structure->path());
849  }
850 
851  QString resourceName =
852  i18nc("%1 is the name of a plasmoid, %2 the name of the machine that plasmoid is published on",
853  "%1 on %2", structure->metadata().name(), QHostInfo::localHostName());
854  kDebug() << "publishing package under name " << resourceName;
855  service->d->publish(methods, resourceName, structure->metadata());
856 }
857 
858 void PackagePrivate::unpublish()
859 {
860  if (service) {
861  service->d->unpublish();
862  }
863 }
864 
865 bool PackagePrivate::isPublished() const
866 {
867  if (service) {
868  return service->d->isPublished();
869  } else {
870  return false;
871  }
872 }
873 
874 } // Namespace
packagemetadata.h
Plasma::WallpaperComponent
Plasma::Wallpaper based plugins.
Definition: plasma.h:231
Plasma::PackageMetadata::serviceType
QString serviceType() const
Definition: packagemetadata.cpp:172
authorizationmanager.h
Plasma::PackageMetadata::pluginName
QString pluginName() const
Definition: packagemetadata.cpp:262
Plasma::PackageMetadata::application
QString application() const
Definition: packagemetadata.cpp:212
Plasma::Package::listInstalled
static QStringList listInstalled(const QString &packageRoot)
Returns a list of all installed packages by name.
Definition: package.cpp:426
Plasma::Package::listInstalledPaths
static QStringList listInstalledPaths(const QString &packageRoot)
Returns a list of all paths of installed packages in the given root.
Definition: package.cpp:447
Plasma::PackageMetadata::write
void write(const QString &filename) const
Writes out the metadata to filename, which should be a .desktop file.
Definition: packagemetadata.cpp:88
Plasma::Package::structure
const PackageStructure::Ptr structure() const
Definition: package.cpp:312
Plasma::PackageMetadata::isValid
bool isValid() const
Definition: packagemetadata.cpp:80
Plasma::Package::registerPackage
static bool registerPackage(const PackageMetadata &data, const QString &iconPath)
Registers a package described by the given desktop file.
Definition: package.cpp:710
Plasma::Package::uninstallPackage
static bool uninstallPackage(const QString &package, const QString &packageRoot, const QString &servicePrefix)
Uninstalls a package.
Definition: package.cpp:677
Plasma::Package::installPackage
static bool installPackage(const QString &package, const QString &packageRoot, const QString &servicePrefix)
Installs a package.
Definition: package.cpp:467
Plasma::Package::path
const QString path() const
Definition: package.cpp:307
Plasma::PackageMetadata::requiredDataEngines
QStringList requiredDataEngines() const
Definition: packagemetadata.cpp:252
Plasma::copyFolder
bool copyFolder(QString sourcePath, QString targetPath)
Definition: package.cpp:58
Plasma::PackageMetadata::type
QString type() const
Definition: packagemetadata.cpp:242
Plasma::Package::operator=
Package & operator=(const Package &rhs)
Assignment operator.
Definition: package.cpp:142
Plasma::PackageStructure::Ptr
KSharedPtr< PackageStructure > Ptr
Definition: packagestructure.h:77
Plasma::Package::isValid
bool isValid() const
Definition: package.cpp:151
Plasma::Package
object representing an installed Plasmagik package
Definition: package.h:42
Plasma::DataEngineManager::self
static DataEngineManager * self()
Singleton pattern accessor.
Definition: dataenginemanager.cpp:90
dataenginemanager.h
Plasma::removeFolder
bool removeFolder(QString folderPath)
Definition: package.cpp:93
Plasma::RunnerComponent
Plasma::AbstractRunner based plugsin.
Definition: plasma.h:228
Plasma::DataEngineManager::listAllEngines
static QStringList listAllEngines(const QString &parentApp=QString())
Definition: dataenginemanager.cpp:160
Plasma::Package::entryList
QStringList entryList(const char *fileType) const
Get the list of files of a given type.
Definition: package.cpp:284
Plasma::Package::metadata
PackageMetadata metadata() const
Definition: package.cpp:293
Plasma::Package::~Package
~Package()
Definition: package.cpp:137
Plasma::Package::contentsHash
QString contentsHash() const
Definition: package.cpp:371
Plasma::AppletComponent
Plasma::Applet based plugins.
Definition: plasma.h:226
Plasma::PackageMetadata::implementationApi
QString implementationApi() const
Definition: packagemetadata.cpp:247
Plasma::type
static QScriptValue type(QScriptContext *ctx, QScriptEngine *eng)
Definition: easingcurve.cpp:63
Plasma::DataEngineComponent
Plasma::DataEngine based plugins.
Definition: plasma.h:227
package.h
Plasma::Package::Package
Package()
Default constructor that creates an invalid Package.
Definition: package.cpp:116
Plasma::knownLanguages
QStringList knownLanguages(ComponentTypes types)
Definition: scriptengine.cpp:67
scriptengine.h
Plasma::PackageMetadata
Provides metadata for a Package.
Definition: packagemetadata.h:40
Plasma::Package::setPath
void setPath(const QString &path)
Sets the path to the root of this package.
Definition: package.cpp:302
Plasma::PackageStructure
A description of the expected file structure of a given package type.
Definition: packagestructure.h:72
Plasma::Package::filePath
QString filePath(const char *fileType, const QString &filename) const
Get the path to a given file.
Definition: package.cpp:216
Plasma::Package::createPackage
static bool createPackage(const PackageMetadata &metadata, const QString &source, const QString &destination, const QString &icon=QString())
Creates a package based on the metadata from the files contained in the source directory.
Definition: package.cpp:742
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue May 6 2014 16:54:12 by doxygen 1.8.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.10.5 API Reference

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