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