1/*
2 SPDX-FileCopyrightText: 2007-2011 Aaron Seigo <aseigo@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#ifndef KPACKAGE_PACKAGE_H
8#define KPACKAGE_PACKAGE_H
9
10#include <QCryptographicHash>
11#include <QMetaType>
12#include <QStringList>
13#include <QUrl>
14
15#include <KPluginMetaData>
16
17#include <kpackage/package_export.h>
18
19#include <KJob>
20
21/*!
22 * \namespace KPackage
23 * \inmodule KPackage
24 */
25namespace KPackage
26{
27// TODO: write documentation on USING a package
28
29class PackagePrivate;
30class PackageStructure;
31
32/*!
33 * \class KPackage::Package
34 * \inheaderfile KPackage/Package
35 * \inmodule KPackage
36 *
37 * \brief Object representing an installed package.
38 *
39 * Package defines what is in a package and provides easy access to the contents.
40 *
41 * To define a package, one might write the following code:
42 *
43 * \code
44 * Package package;
45 *
46 * package.addDirectoryDefinition("images", "pics/");
47 * package.setMimeTypes("images", QStringList{"image/svg", "image/png", "image/jpeg"});
48 *
49 * package.addDirectoryDefinition("scripts", "code/");
50 * package.setMimeTypes("scripts", QStringList{"text/\*"});
51 *
52 * package.addFileDefinition("mainscript", "code/main.js");
53 * package.setRequired("mainscript", true);
54 * \endcode
55 *
56 * One may also choose to create a subclass of PackageStructure and include the setup
57 * in the constructor.
58 *
59 * Either way, Package creates a self-documenting contract between the packager and
60 * the application without exposing package internals such as actual on-disk structure
61 * of the package or requiring that all contents be explicitly known ahead of time.
62 *
63 * Subclassing PackageStructure does have provide a number of potential const benefits:
64 * \list
65 * \li the package can be notified of path changes via the virtual pathChanged() method
66 * \li the subclass may implement mechanisms to install and remove packages using the virtual install and uninstall methods
67 * \li subclasses can be compiled as plugins for easy re-use
68 * \endlist
69 **/
70class KPACKAGE_EXPORT Package
71{
72public:
73 /*!
74 * Default constructor
75 *
76 * \a structure if a null pointer is passed in, this will creates an empty (invalid) Package;
77 * otherwise the structure is allowed to set up the Package's initial layout
78 */
79 explicit Package(PackageStructure *structure = nullptr);
80
81 Package(const Package &other);
82
83 virtual ~Package();
84
85 Package &operator=(const Package &rhs);
86
87 /*!
88 * Returns \c true if this package has a valid PackageStructure associatedw it with it.
89 *
90 * A package may not be valid, but have a valid structure. Useful when dealing with
91 * Package objects in a semi-initialized state (e.g. before calling setPath())
92 * \since 5.1
93 */
94 bool hasValidStructure() const;
95
96 /*!
97 * Return \c true if all the required components exist
98 **/
99 bool isValid() const;
100
101 /*!
102 * Sets the path to the root of this package
103 *
104 * \a path an absolute path, or a relative path to the default package root
105 */
106 void setPath(const QString &path);
107
108 /*!
109 * Returns the path to the root of this particular package
110 */
111 const QString path() const;
112
113 /*!
114 * Get the path to a given file based on the key and an optional filename.
115 * Example: finding the main script in a scripting package:
116 * filePath("mainscript")
117 *
118 * Example: finding a specific image in the images directory:
119 * filePath("images", "myimage.png")
120 *
121 * \a key the key of the file type to look for,
122 *
123 * \a filename optional name of the file to locate within the package
124 *
125 * Returns path to the file on disk. QString() if not found.
126 **/
127 QString filePath(const QByteArray &key, const QString &filename = QString()) const;
128
129 /*!
130 * Get the url to a given file based on the key and an optional filename, is the file:// or qrc:// format
131 * Example: finding the main script in a scripting package:
132 * filePath("mainscript")
133 *
134 * Example: finding a specific image in the images directory:
135 * filePath("images", "myimage.png")
136 *
137 * \a key the key of the file type to look for,
138 *
139 * \a filename optional name of the file to locate within the package
140 *
141 * Returns path to the file on disk. QUrl() if not found.
142 * \since 5.41
143 **/
144 QUrl fileUrl(const QByteArray &key, const QString &filename = QString()) const;
145
146 /*!
147 * Get the list of files of a given type.
148 *
149 * \a fileType the type of file to look for, as defined in the
150 * package structure.
151 * Returns list of files by name, suitable for passing to filePath
152 **/
153 QStringList entryList(const QByteArray &key) const;
154
155 /*!
156 * Returns true if the item at path exists and is required
157 **/
158 bool isRequired(const QByteArray &key) const;
159
160 /*!
161 * Returns the mimeTypes associated with the path, if any
162 **/
163 QStringList mimeTypes(const QByteArray &key) const;
164
165 /*!
166 * Returns the prefix paths inserted between the base path and content entries, in order of priority.
167 * When searching for a file, all paths will be tried in order.
168 */
169 QStringList contentsPrefixPaths() const;
170
171 /*!
172 * Returns preferred package root. This defaults to kpackage/generic/
173 */
174 QString defaultPackageRoot() const;
175
176 /*!
177 * Returns true if paths/symlinks outside the package itself should be followed.
178 * By default this is set to false for security reasons.
179 */
180 bool allowExternalPaths() const;
181
182 /*!
183 * Sets the metadata for the KPackage. This overwrites the current metadata.
184 * This should be used in case a kpackage gets loaded by name, based
185 * on the path a C++ plugin which has embedded metadata.
186 * \since 5.88
187 */
188 void setMetadata(const KPluginMetaData &data);
189
190 /*!
191 * Returns the package metadata object.
192 */
193 KPluginMetaData metadata() const;
194
195 /*!
196 * Returns a hash digest of the contents of the package in hexadecimal form
197 * \since 5.21
198 */
199 QByteArray cryptographicHash(QCryptographicHash::Algorithm algorithm) const;
200
201 /*!
202 * Adds a directory to the structure of the package. It is added as
203 * a not-required element with no associated mimeTypes.
204 * If an entry with the given key already exists, the path
205 * is added to it as a search alternative.
206 *
207 * \a key used as an internal label for this directory
208 *
209 * \a path the path within the package for this directory
210 */
211 void addDirectoryDefinition(const QByteArray &key, const QString &path);
212
213 /*!
214 * Adds a file to the structure of the package. It is added as
215 * a not-required element with no associated mimeTypes.
216 * If an entry with the given key already exists, the path
217 * is added to it as a search alternative.
218 *
219 * \a key used as an internal label for this file
220 *
221 * \a path the path within the package for this file
222 */
223 void addFileDefinition(const QByteArray &key, const QString &path);
224
225 /*!
226 * Removes a definition from the structure of the package.
227 *
228 * \a key the internal label of the file or directory to remove
229 */
230 void removeDefinition(const QByteArray &key);
231
232 /*!
233 * Sets whether or not a given part of the structure is required or not.
234 * The path must already have been added using addDirectoryDefinition
235 * or addFileDefinition.
236 *
237 * \a key the entry within the package
238 *
239 * \a required true if this entry is required, false if not
240 */
241 void setRequired(const QByteArray &key, bool required);
242
243 /*!
244 * Defines the default mimeTypes for any definitions that do not have
245 * associated mimeTypes. Handy for packages with only one or predominantly
246 * one file type.
247 *
248 * \a mimeTypes a list of mimeTypes
249 **/
250 void setDefaultMimeTypes(const QStringList &mimeTypes);
251
252 /*!
253 * Define mimeTypes for a given part of the structure
254 * The path must already have been added using addDirectoryDefinition
255 * or addFileDefinition.
256 *
257 * \a key the entry within the package
258 *
259 * \a mimeTypes a list of mimeTypes
260 **/
261 void setMimeTypes(const QByteArray &key, const QStringList &mimeTypes);
262
263 /*!
264 * Sets the prefixes that all the contents in this package should
265 * appear under. This defaults to "contents/" and is added automatically
266 * between the base path and the entries as defined by the package
267 * structure. Multiple entries can be added.
268 * In this case each file request will be searched in all prefixes in order,
269 * and the first found will be returned.
270 *
271 * \a prefix paths the directory prefix to use
272 */
273 void setContentsPrefixPaths(const QStringList &prefixPaths);
274
275 /*!
276 * Sets whether or not external paths/symlinks can be followed by a package
277 *
278 * \a allow true if paths/symlinks outside of the package should be followed,
279 * false if they should be rejected.
280 */
281 void setAllowExternalPaths(bool allow);
282
283 /*!
284 * Sets preferred package root.
285 */
286 void setDefaultPackageRoot(const QString &packageRoot);
287
288 /*!
289 * Sets the fallback package root path
290 * If a file won't be found in this package, it will search it in the package
291 * with the same structure identified by path
292 * It is intended to be used by the packageStructure
293 *
294 * \a path package root path
295 *
296 * \sa setPath
297 */
298 void setFallbackPackage(const KPackage::Package &package);
299
300 /*!
301 * Returns The fallback package root path
302 */
303 KPackage::Package fallbackPackage() const;
304
305 // Content structure description methods
306 /*!
307 * Returns all directories registered as part of this Package's structure
308 */
309 QList<QByteArray> directories() const;
310
311 /*!
312 * Returns all directories registered as part of this Package's required structure
313 */
314 QList<QByteArray> requiredDirectories() const;
315
316 /*!
317 * Returns all files registered as part of this Package's structure
318 */
319 QList<QByteArray> files() const;
320
321 /*!
322 * Returns all files registered as part of this Package's required structure
323 */
324 QList<QByteArray> requiredFiles() const;
325
326private:
327 QExplicitlySharedDataPointer<PackagePrivate> d;
328 friend class PackagePrivate;
329};
330
331}
332
333Q_DECLARE_METATYPE(KPackage::Package)
334#endif
335

source code of kpackage/src/kpackage/package.h