File indexing completed on 2024-04-21 04:57:21

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