File indexing completed on 2024-04-14 03:54:16

0001 /*
0002     SPDX-FileCopyrightText: 2007-2011 Aaron Seigo <aseigo@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #ifndef KPACKAGE_PACKAGE_H
0008 #define KPACKAGE_PACKAGE_H
0009 
0010 #include <QCryptographicHash>
0011 #include <QMetaType>
0012 #include <QStringList>
0013 #include <QUrl>
0014 
0015 #include <KPluginMetaData>
0016 
0017 #include <kpackage/package_export.h>
0018 
0019 #include <KJob>
0020 
0021 namespace KPackage
0022 {
0023 /**
0024  * @class Package kpackage/package.h <KPackage/Package>
0025  *
0026  * @short object representing an installed package
0027  *
0028  * Package defines what is in a package and provides easy access to the contents.
0029  *
0030  * To define a package, one might write the following code:
0031  *
0032  @code
0033     Package package;
0034 
0035     package.addDirectoryDefinition("images", "pics/");
0036     package.setMimeTypes("images", QStringList{"image/svg", "image/png", "image/jpeg"});
0037 
0038     package.addDirectoryDefinition("scripts", "code/");
0039     package.setMimeTypes("scripts", QStringList{"text/\*"});
0040 
0041     package.addFileDefinition("mainscript", "code/main.js");
0042     package.setRequired("mainscript", true);
0043  @endcode
0044  * One may also choose to create a subclass of PackageStructure and include the setup
0045  * in the constructor.
0046  *
0047  * Either way, Package creates a self-documenting contract between the packager and
0048  * the application without exposing package internals such as actual on-disk structure
0049  * of the package or requiring that all contents be explicitly known ahead of time.
0050  *
0051  * Subclassing PackageStructure does have provide a number of potential const benefits:
0052  *    * the package can be notified of path changes via the virtual pathChanged() method
0053  *    * the subclass may implement mechanisms to install and remove packages using the
0054  *      virtual install and uninstall methods
0055  *    * subclasses can be compiled as plugins for easy re-use
0056  **/
0057 // TODO: write documentation on USING a package
0058 
0059 class PackagePrivate;
0060 class PackageStructure;
0061 
0062 class KPACKAGE_EXPORT Package
0063 {
0064 public:
0065     /**
0066      * Default constructor
0067      *
0068      * @param structure if a null pointer is passed in, this will creates an empty (invalid) Package;
0069      * otherwise the structure is allowed to set up the Package's initial layout
0070      */
0071     explicit Package(PackageStructure *structure = nullptr);
0072 
0073     /**
0074      * Copy constructor
0075      */
0076     Package(const Package &other);
0077 
0078     virtual ~Package();
0079 
0080     /**
0081      * Assignment operator
0082      */
0083     Package &operator=(const Package &rhs);
0084 
0085     /**
0086      * @return true if this package has a valid PackageStructure associatedw it with it.
0087      * A package may not be valid, but have a valid structure. Useful when dealing with
0088      * Package objects in a semi-initialized state (e.g. before calling setPath())
0089      * @since 5.1
0090      */
0091     bool hasValidStructure() const;
0092 
0093     /**
0094      * @return true if all the required components exist
0095      **/
0096     bool isValid() const;
0097 
0098     /**
0099      * Sets the path to the root of this package
0100      * @param path an absolute path, or a relative path to the default package root
0101      */
0102     void setPath(const QString &path);
0103 
0104     /**
0105      * @return the path to the root of this particular package
0106      */
0107     const QString path() const;
0108 
0109     /**
0110      * Get the path to a given file based on the key and an optional filename.
0111      * Example: finding the main script in a scripting package:
0112      *      filePath("mainscript")
0113      *
0114      * Example: finding a specific image in the images directory:
0115      *      filePath("images", "myimage.png")
0116      *
0117      * @param key the key of the file type to look for,
0118      * @param filename optional name of the file to locate within the package
0119      * @return path to the file on disk. QString() if not found.
0120      **/
0121     QString filePath(const QByteArray &key, const QString &filename = QString()) const;
0122 
0123     /**
0124      * Get the url to a given file based on the key and an optional filename, is the file:// or qrc:// format
0125      * Example: finding the main script in a scripting package:
0126      *      filePath("mainscript")
0127      *
0128      * Example: finding a specific image in the images directory:
0129      *      filePath("images", "myimage.png")
0130      *
0131      * @param key the key of the file type to look for,
0132      * @param filename optional name of the file to locate within the package
0133      * @return path to the file on disk. QUrl() if not found.
0134      * @since 5.41
0135      **/
0136     QUrl fileUrl(const QByteArray &key, const QString &filename = QString()) const;
0137 
0138     /**
0139      * Get the list of files of a given type.
0140      *
0141      * @param fileType the type of file to look for, as defined in the
0142      *               package structure.
0143      * @return list of files by name, suitable for passing to filePath
0144      **/
0145     QStringList entryList(const QByteArray &key) const;
0146 
0147     /**
0148      * @return true if the item at path exists and is required
0149      **/
0150     bool isRequired(const QByteArray &key) const;
0151 
0152     /**
0153      * @return the mimeTypes associated with the path, if any
0154      **/
0155     QStringList mimeTypes(const QByteArray &key) const;
0156 
0157     /**
0158      * @return the prefix paths inserted between the base path and content entries, in order of priority.
0159      *         When searching for a file, all paths will be tried in order.
0160      */
0161     QStringList contentsPrefixPaths() const;
0162 
0163     /**
0164      * @return preferred package root. This defaults to kpackage/generic/
0165      */
0166     QString defaultPackageRoot() const;
0167 
0168     /**
0169      * @return true if paths/symlinks outside the package itself should be followed.
0170      * By default this is set to false for security reasons.
0171      */
0172     bool allowExternalPaths() const;
0173 
0174     /**
0175      * Sets the metadata for the KPackage. This overwrites the current metadata.
0176      * This should be used in case a kpackage gets loaded by name, based
0177      * on the path a C++ plugin which has embedded metadata.
0178      * @since 5.88
0179      */
0180     void setMetadata(const KPluginMetaData &data);
0181 
0182     /**
0183      * @return the package metadata object.
0184      */
0185     KPluginMetaData metadata() const;
0186 
0187     /**
0188      * @return a hash digest of the contents of the package in hexadecimal form
0189      * @since 5.21
0190      */
0191     QByteArray cryptographicHash(QCryptographicHash::Algorithm algorithm) const;
0192 
0193     /**
0194      * Adds a directory to the structure of the package. It is added as
0195      * a not-required element with no associated mimeTypes.
0196      * If an entry with the given key already exists, the path
0197      * is added to it as a search alternative.
0198      *
0199      * @param key  used as an internal label for this directory
0200      * @param path the path within the package for this directory
0201      */
0202     void addDirectoryDefinition(const QByteArray &key, const QString &path);
0203 
0204     /**
0205      * Adds a file to the structure of the package. It is added as
0206      * a not-required element with no associated mimeTypes.
0207      * If an entry with the given key already exists, the path
0208      * is added to it as a search alternative.
0209      *
0210      * @param key  used as an internal label for this file
0211      * @param path the path within the package for this file
0212      */
0213     void addFileDefinition(const QByteArray &key, const QString &path);
0214 
0215     /**
0216      * Removes a definition from the structure of the package.
0217      * @param key the internal label of the file or directory to remove
0218      */
0219     void removeDefinition(const QByteArray &key);
0220 
0221     /**
0222      * Sets whether or not a given part of the structure is required or not.
0223      * The path must already have been added using addDirectoryDefinition
0224      * or addFileDefinition.
0225      *
0226      * @param key the entry within the package
0227      * @param required true if this entry is required, false if not
0228      */
0229     void setRequired(const QByteArray &key, bool required);
0230 
0231     /**
0232      * Defines the default mimeTypes for any definitions that do not have
0233      * associated mimeTypes. Handy for packages with only one or predominantly
0234      * one file type.
0235      *
0236      * @param mimeTypes a list of mimeTypes
0237      **/
0238     void setDefaultMimeTypes(const QStringList &mimeTypes);
0239 
0240     /**
0241      * Define mimeTypes for a given part of the structure
0242      * The path must already have been added using addDirectoryDefinition
0243      * or addFileDefinition.
0244      *
0245      * @param key the entry within the package
0246      * @param mimeTypes a list of mimeTypes
0247      **/
0248     void setMimeTypes(const QByteArray &key, const QStringList &mimeTypes);
0249 
0250     /**
0251      * Sets the prefixes that all the contents in this package should
0252      * appear under. This defaults to "contents/" and is added automatically
0253      * between the base path and the entries as defined by the package
0254      * structure. Multiple entries can be added.
0255      * In this case each file request will be searched in all prefixes in order,
0256      * and the first found will be returned.
0257      *
0258      * @param prefix paths the directory prefix to use
0259      */
0260     void setContentsPrefixPaths(const QStringList &prefixPaths);
0261 
0262     /**
0263      * Sets whether or not external paths/symlinks can be followed by a package
0264      * @param allow true if paths/symlinks outside of the package should be followed,
0265      *             false if they should be rejected.
0266      */
0267     void setAllowExternalPaths(bool allow);
0268 
0269     /**
0270      * Sets preferred package root.
0271      */
0272     void setDefaultPackageRoot(const QString &packageRoot);
0273 
0274     /**
0275      * Sets the fallback package root path
0276      * If a file won't be found in this package, it will search it in the package
0277      * with the same structure identified by path
0278      * It is intended to be used by the packageStructure
0279      * @param path package root path @see setPath
0280      */
0281     void setFallbackPackage(const KPackage::Package &package);
0282 
0283     /**
0284      * @return The fallback package root path
0285      */
0286     KPackage::Package fallbackPackage() const;
0287 
0288     // Content structure description methods
0289     /**
0290      * @return all directories registered as part of this Package's structure
0291      */
0292     QList<QByteArray> directories() const;
0293 
0294     /**
0295      * @return all directories registered as part of this Package's required structure
0296      */
0297     QList<QByteArray> requiredDirectories() const;
0298 
0299     /**
0300      * @return all files registered as part of this Package's structure
0301      */
0302     QList<QByteArray> files() const;
0303 
0304     /**
0305      * @return all files registered as part of this Package's required structure
0306      */
0307     QList<QByteArray> requiredFiles() const;
0308 
0309 private:
0310     QExplicitlySharedDataPointer<PackagePrivate> d;
0311     friend class PackagePrivate;
0312 };
0313 
0314 }
0315 
0316 Q_DECLARE_METATYPE(KPackage::Package)
0317 #endif