File indexing completed on 2023-12-03 08:26:48

0001 /***************************************************************************
0002  *   Copyright (C) 2009 Matthias Fuchs <mat69@gmx.net>                     *
0003  *   Copyright (C) 2012 Aish Raj Dahal <dahalaishraj@gmail.com>            *
0004  *                                                                         *
0005  *   This program is free software; you can redistribute it and/or modify  *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  *                                                                         *
0010  *   This program is distributed in the hope that it will be useful,       *
0011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0013  *   GNU General Public License for more details.                          *
0014  *                                                                         *
0015  *   You should have received a copy of the GNU General Public License     *
0016  *   along with this program; if not, write to the                         *
0017  *   Free Software Foundation, Inc.,                                       *
0018  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .        *
0019  ***************************************************************************/
0020 
0021 #ifndef Metalinker_H
0022 #define Metalinker_H
0023 
0024 #include <KIO/Job>
0025 #include <QDate>
0026 #include <QDomElement>
0027 #include <QEventLoop>
0028 #include <QObject>
0029 #include <QString>
0030 #include <QUrl>
0031 
0032 /**
0033  * The following classes try to resemble the structure of a Metalink-document, they partially support
0034  * the Metalink specification version 3.0 2nd ed and Draft 09
0035  * It is possible to load and save metalinks and to edit them inbetween, you could also create a metalink
0036  * from scratch
0037  */
0038 
0039 namespace KGetMetalink
0040 {
0041 
0042 class DateConstruct
0043 {
0044 public:
0045     DateConstruct()
0046         : negativeOffset(false)
0047     {
0048     }
0049 
0050     void setData(const QDateTime &dateTime, const QTime &timeZoneOffset = QTime(), bool negativeOffset = false);
0051     void setData(const QString &dateConstruct);
0052 
0053     void clear();
0054 
0055     bool isNull() const;
0056     bool isValid() const;
0057 
0058     QString toString() const;
0059 
0060     QDateTime dateTime;
0061     QTime timeZoneOffset;
0062     bool negativeOffset;
0063 };
0064 
0065 /**
0066  * This class contains a url and the name, it can be used to e.g. describe a publisher
0067  */
0068 class UrlText
0069 {
0070 public:
0071     UrlText()
0072     {
0073     }
0074 
0075     bool isEmpty() const
0076     {
0077         return name.isEmpty() && url.isEmpty();
0078     }
0079 
0080     void clear();
0081 
0082     QString name;
0083     QUrl url;
0084 };
0085 
0086 /**
0087  * Files, File and Metadata contain this
0088  * Metadata not as member and only for compatibility
0089  */
0090 class CommonData
0091 {
0092 public:
0093     CommonData()
0094     {
0095     }
0096 
0097     void load(const QDomElement &e);
0098     void save(QDomElement &e) const;
0099 
0100     void clear();
0101 
0102     QString identity;
0103     QString version;
0104     QString description;
0105     QStringList oses;
0106     QUrl logo;
0107     QStringList languages;
0108     UrlText publisher;
0109     QString copyright;
0110 };
0111 
0112 class Metaurl
0113 {
0114 public:
0115     Metaurl()
0116         : priority(0)
0117     {
0118     }
0119 
0120     /**
0121      * "smaller" urls are less important than larger, larger urls should be preferred
0122      */
0123     bool operator<(const Metaurl &other) const;
0124 
0125     void load(const QDomElement &e);
0126     void save(QDomElement &e) const;
0127 
0128     bool isValid();
0129 
0130     void clear();
0131 
0132     QString type;
0133 
0134     /**
0135      * the priority of the urls, 1 is highest priority, 999999 lowest
0136      * default is 0 as in not set and thus is ranked even behind 999999
0137      */
0138     uint priority;
0139 
0140     /**
0141      * Optional the name of a file that should be get of that metaurl
0142      */
0143     QString name;
0144 
0145     QUrl url;
0146 };
0147 
0148 class Url
0149 {
0150 public:
0151     Url()
0152         : priority(0)
0153     {
0154     }
0155 
0156     /**
0157      * "smaller" urls are less important than larger, larger urls should be preferred
0158      */
0159     bool operator<(const Url &other) const;
0160 
0161     void load(const QDomElement &e);
0162     void save(QDomElement &e) const;
0163 
0164     bool isValid();
0165 
0166     void clear();
0167 
0168     /**
0169      * the priority of the urls, 1 is highest priority, 999999 lowest
0170      * default is 0 as in not set and thus is ranked even behind 999999
0171      */
0172     uint priority;
0173 
0174     /**
0175      * the location of the server eg. "uk"
0176      */
0177     QString location;
0178 
0179     QUrl url;
0180 };
0181 
0182 class Resources
0183 {
0184 public:
0185     Resources()
0186     {
0187     }
0188 
0189     bool isValid() const
0190     {
0191         return !urls.isEmpty() || !metaurls.isEmpty();
0192     }
0193 
0194     void load(const QDomElement &e);
0195     void save(QDomElement &e) const;
0196 
0197     void clear();
0198 
0199     QList<Url> urls;
0200     QList<Metaurl> metaurls;
0201 };
0202 
0203 class Pieces
0204 {
0205 public:
0206     Pieces()
0207         : length(0)
0208     {
0209     }
0210 
0211     void load(const QDomElement &e);
0212     void save(QDomElement &e) const;
0213 
0214     void clear();
0215 
0216     QString type;
0217     KIO::filesize_t length;
0218     QStringList hashes;
0219 };
0220 
0221 class Verification
0222 {
0223 public:
0224     Verification()
0225     {
0226     }
0227 
0228     void load(const QDomElement &e);
0229     void save(QDomElement &e) const;
0230 
0231     void clear();
0232 
0233     QHash<QString, QString> hashes;
0234     QList<Pieces> pieces;
0235     QHash<QString, QString> signatures;
0236 };
0237 
0238 class File
0239 {
0240 public:
0241     File()
0242         : size(0)
0243     {
0244     }
0245 
0246     void load(const QDomElement &e);
0247     void save(QDomElement &e) const;
0248 
0249     void clear();
0250 
0251     bool isValid() const;
0252 
0253     /**
0254      * Controls if the name attribute is valid, i.e. it is not empty and
0255      * does not contain any directory traversal directives or information,
0256      * as described in the Metalink 4.0 specification 4.1.2.1.
0257      */
0258     bool isValidNameAttribute() const;
0259 
0260     QString name;
0261     Verification verification;
0262     KIO::filesize_t size;
0263     CommonData data;
0264     Resources resources;
0265 };
0266 
0267 class Files
0268 {
0269 public:
0270     Files()
0271     {
0272     }
0273 
0274     bool isValid() const;
0275 
0276     void load(const QDomElement &e);
0277     void save(QDomElement &e) const;
0278 
0279     void clear();
0280 
0281     QList<File> files;
0282 };
0283 
0284 class Metalink
0285 {
0286 public:
0287     Metalink()
0288         : dynamic(false)
0289     {
0290     }
0291 
0292     /**
0293      * checks if the minimum requirements of a metalink are met
0294      * @return true if the minimum requirements are met
0295      */
0296     bool isValid() const;
0297 
0298     void load(const QDomElement &e);
0299 
0300     /**
0301      * Save the metalink
0302      * @return the QDomDocument containing the metalink
0303      */
0304     QDomDocument save() const;
0305 
0306     void clear();
0307 
0308     bool dynamic;
0309     QString xmlns; // the xmlns value is ignored when saving, instead the data format described in the specification is always used
0310     DateConstruct published; // when the metalink was published
0311     QUrl origin;
0312     QString generator;
0313     DateConstruct updated; // when the metalink was updated
0314     Files files;
0315 
0316     static const QString KGET_DESCRIPTION;
0317     static const uint MAX_URL_PRIORITY; // maximum priority a Metalink 4.0 Url or Metaurl can have, not to be mixed up with the highest priority
0318 };
0319 
0320 /**
0321  * @class Metalink_v3
0322  * Metalink version 3.0 2nd ed
0323  * Used only for loading and saving, uses itself Metalink internally
0324  */
0325 class Metalink_v3
0326 {
0327 public:
0328     Metalink_v3();
0329 
0330     Metalink metalink();
0331     void setMetalink(const Metalink &metalink);
0332 
0333     void load(const QDomElement &e);
0334 
0335     /**
0336      * Save the metalink
0337      * @return the QDomDocument containing the metalink
0338      */
0339     QDomDocument save() const;
0340 
0341 private:
0342     void parseFiles(const QDomElement &e);
0343     Resources parseResources(const QDomElement &e);
0344     DateConstruct parseDateConstruct(const QString &data);
0345     CommonData parseCommonData(const QDomElement &e);
0346 
0347     /**
0348      * Inherits CommonData, the inheritor inherits every settings
0349      * from the ancestor it has not set itself
0350      */
0351     void inheritCommonData(const CommonData &ancestor, CommonData *inheritor);
0352 
0353     void saveFiles(QDomElement &e) const;
0354     void saveResources(const Resources &resources, QDomElement &e) const;
0355     void saveVerification(const Verification &verification, QDomElement &e) const;
0356     void saveCommonData(const CommonData &data, QDomElement &e) const;
0357     QString dateConstructToString(const DateConstruct &date) const;
0358 
0359 private:
0360     Metalink m_metalink;
0361     static const uint MAX_PREFERENCE;
0362 };
0363 
0364 /**
0365  * This class can handle the loading and saving of metalinks on the filesystem
0366  */
0367 class HandleMetalink
0368 {
0369 public:
0370     /**
0371      * Loads destination into metalink
0372      * @param destination the place of the metalink in the filesystem
0373      * @param metalink the instance of Metalink where the metalink will be stored
0374      * @return return true if it worked
0375      */
0376     static bool load(const QUrl &destination, Metalink *metalink);
0377 
0378     /**
0379      * Loads data into metalink
0380      * @param data the contents of a metalink
0381      * @param metalink the instance of Metalink where the metalink will be stored
0382      * @return return true if it worked
0383      */
0384     static bool load(const QByteArray &data, Metalink *metalink);
0385 
0386     /**
0387      * Saves metalink to destination
0388      * @param destination the place where the metlink will be saved, the ending defines
0389      * what version should be used: *.meta4 --> Metalink 4.0; *.metalink --> Metalink 3.0
0390      * @param metalink the instance of metalink that will be written to the filesystem
0391      * @return return true if it worked
0392      */
0393     static bool save(const QUrl &destination, Metalink *metalink);
0394 };
0395 
0396 class MetalinkHttpParser : public QObject
0397 {
0398     Q_OBJECT
0399 public:
0400     MetalinkHttpParser(const QUrl &Url)
0401         : m_Url(Url)
0402         , m_MetalinkHSatus(false)
0403         , m_EtagValue(QString(""))
0404     {
0405         checkMetalinkHttp();
0406     }
0407 
0408     ~MetalinkHttpParser() override;
0409 
0410     /**
0411      * @return true if m_Url is a metalink/http supported URL.
0412      */
0413 
0414     bool isMetalinkHttp();
0415 
0416     /**
0417      * @return the Url m_Url which is being tested for metalink
0418      */
0419 
0420     QUrl getUrl();
0421     QMultiMap<QString, QString> *getHeaderInfo();
0422 
0423     /**
0424      * @return Returns the ETag if present in the HTTP headers
0425      */
0426 
0427     QString *getEtag();
0428 
0429 private Q_SLOTS:
0430     void slotHeaderResult(KJob *kjob);
0431     void checkMetalinkHttp();
0432     void detectMime(KIO::Job *job, const QString &type);
0433     void slotRedirection(KIO::Job *, const QUrl &);
0434 
0435 private:
0436     QUrl m_Url;
0437     QUrl m_redirectionUrl;
0438     bool m_MetalinkHSatus;
0439     QEventLoop m_loop;
0440     QMultiMap<QString, QString> m_headerInfo;
0441     QString m_EtagValue;
0442 
0443     /**
0444      * Parsees the Metalink values from QString to the Map
0445      * @param Value of the QString ie raw HTTP headers
0446      */
0447     void parseHeaders(const QString &);
0448 
0449     /**
0450      * Sets the status of m_MetalinkHStatus to true if the URL is a Metalink
0451      */
0452     void setMetalinkHSatus();
0453 };
0454 
0455 class HttpLinkHeader : public Metaurl
0456 {
0457 public:
0458     HttpLinkHeader(const QString &headerLine);
0459 
0460     QString reltype;
0461     bool pref;
0462     int depth;
0463     QString geo;
0464 
0465     /**
0466      * Loads information from a header value into metalink header structure.
0467      * @param line Value of the "link" HTTP header response.
0468      */
0469     void parseHeaderLine(const QString &);
0470 
0471     bool operator<(const HttpLinkHeader &) const;
0472 };
0473 
0474 }
0475 
0476 #endif // Metalinker_H