1 /*************************************************************************** 2 * Copyright (C) 2009 Matthias Fuchs <mat69@gmx.net> * 3 * Copyright (C) 2012 Aish Raj Dahal <dahalaishraj@gmail.com> * 4 * * 5 * This program is free software; you can redistribute it and/or modify * 6 * it under the terms of the GNU General Public License as published by * 7 * the Free Software Foundation; either version 2 of the License, or * 8 * (at your option) any later version. * 9 * * 10 * This program is distributed in the hope that it will be useful, * 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 * GNU General Public License for more details. * 14 * * 15 * You should have received a copy of the GNU General Public License * 16 * along with this program; if not, write to the * 17 * Free Software Foundation, Inc., * 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * 19 ***************************************************************************/ 20 21 #ifndef Metalinker_H 22 #define Metalinker_H 23 24 #include <KIO/Job> 25 #include <QUrl> 26 #include <QDate> 27 #include <QDomElement> 28 #include <QEventLoop> 29 #include <QString> 30 #include <QObject> 31 32 /** 33 * The following classes try to resemble the structure of a Metalink-document, they partially support 34 * the Metalink specification version 3.0 2nd ed and Draft 09 35 * It is possible to load and save metalinks and to edit them inbetween, you could also create a metalink 36 * from scratch 37 */ 38 39 namespace KGetMetalink 40 { 41 42 class DateConstruct 43 { 44 public: DateConstruct()45 DateConstruct() 46 : negativeOffset(false) 47 { 48 } 49 50 void setData(const QDateTime &dateTime, const QTime &timeZoneOffset = QTime(), bool negativeOffset = false); 51 void setData(const QString &dateConstruct); 52 53 void clear(); 54 55 bool isNull() const; 56 bool isValid() const; 57 58 QString toString() const; 59 60 QDateTime dateTime; 61 QTime timeZoneOffset; 62 bool negativeOffset; 63 }; 64 65 /** 66 * This class contains a url and the name, it can be used to e.g. describe a publisher 67 */ 68 class UrlText 69 { 70 public: UrlText()71 UrlText() {} 72 isEmpty()73 bool isEmpty() const {return name.isEmpty() && url.isEmpty();} 74 75 void clear(); 76 77 QString name; 78 QUrl url; 79 }; 80 81 /** 82 * Files, File and Metadata contain this 83 * Metadata not as member and only for compatibility 84 */ 85 class CommonData 86 { 87 public: CommonData()88 CommonData() {} 89 90 void load(const QDomElement &e); 91 void save(QDomElement &e) const; 92 93 void clear(); 94 95 QString identity; 96 QString version; 97 QString description; 98 QStringList oses; 99 QUrl logo; 100 QStringList languages; 101 UrlText publisher; 102 QString copyright; 103 }; 104 105 class Metaurl 106 { 107 public: Metaurl()108 Metaurl() 109 : priority(0) 110 { 111 } 112 113 /** 114 * "smaller" urls are less important than larger, larger urls should be preferred 115 */ 116 bool operator<(const Metaurl &other) const; 117 118 void load(const QDomElement &e); 119 void save(QDomElement &e) const; 120 121 bool isValid(); 122 123 void clear(); 124 125 QString type; 126 127 /** 128 * the priority of the urls, 1 is highest priority, 999999 lowest 129 * default is 0 as in not set and thus is ranked even behind 999999 130 */ 131 uint priority; 132 133 /** 134 * Optional the name of a file that should be get of that metaurl 135 */ 136 QString name; 137 138 QUrl url; 139 }; 140 141 class Url 142 { 143 public: Url()144 Url() 145 : priority(0) 146 { 147 } 148 149 /** 150 * "smaller" urls are less important than larger, larger urls should be preferred 151 */ 152 bool operator<(const Url &other) const; 153 154 void load(const QDomElement &e); 155 void save(QDomElement &e) const; 156 157 bool isValid(); 158 159 void clear(); 160 161 /** 162 * the priority of the urls, 1 is highest priority, 999999 lowest 163 * default is 0 as in not set and thus is ranked even behind 999999 164 */ 165 uint priority; 166 167 /** 168 * the location of the server eg. "uk" 169 */ 170 QString location; 171 172 QUrl url; 173 }; 174 175 class Resources 176 { 177 public: Resources()178 Resources() {} 179 isValid()180 bool isValid() const {return !urls.isEmpty() || !metaurls.isEmpty();} 181 182 void load(const QDomElement &e); 183 void save(QDomElement &e) const; 184 185 void clear(); 186 187 QList<Url> urls; 188 QList<Metaurl> metaurls; 189 }; 190 191 class Pieces 192 { 193 public: Pieces()194 Pieces() 195 : length(0) 196 { 197 } 198 199 void load(const QDomElement &e); 200 void save(QDomElement &e) const; 201 202 void clear(); 203 204 QString type; 205 KIO::filesize_t length; 206 QStringList hashes; 207 }; 208 209 class Verification 210 { 211 public: Verification()212 Verification() {} 213 214 void load(const QDomElement &e); 215 void save(QDomElement &e) const; 216 217 void clear(); 218 219 QHash<QString, QString> hashes; 220 QList<Pieces> pieces; 221 QHash<QString, QString> signatures; 222 }; 223 224 class File 225 { 226 public: File()227 File() 228 : size(0) 229 { 230 } 231 232 void load(const QDomElement &e); 233 void save(QDomElement &e) const; 234 235 void clear(); 236 237 bool isValid() const; 238 239 /** 240 * Controls if the name attribute is valid, i.e. it is not empty and 241 * does not contain any directory traversal directives or information, 242 * as described in the Metalink 4.0 specification 4.1.2.1. 243 */ 244 bool isValidNameAttribute() const; 245 246 QString name; 247 Verification verification; 248 KIO::filesize_t size; 249 CommonData data; 250 Resources resources; 251 }; 252 253 class Files 254 { 255 public: Files()256 Files() {} 257 258 bool isValid() const; 259 260 void load(const QDomElement &e); 261 void save(QDomElement &e) const; 262 263 void clear(); 264 265 QList<File> files; 266 }; 267 268 class Metalink 269 { 270 public: Metalink()271 Metalink() 272 : dynamic(false) 273 { 274 } 275 276 /** 277 * checks if the minimum requirements of a metalink are met 278 * @return true if the minimum requirements are met 279 */ 280 bool isValid() const; 281 282 void load(const QDomElement &e); 283 284 /** 285 * Save the metalink 286 * @return the QDomDocument containing the metalink 287 */ 288 QDomDocument save() const; 289 290 void clear(); 291 292 bool dynamic; 293 QString xmlns; //the xmlns value is ignored when saving, instead the data format described in the specification is always used 294 DateConstruct published; //when the metalink was published 295 QUrl origin; 296 QString generator; 297 DateConstruct updated; //when the metalink was updated 298 Files files; 299 300 static const QString KGET_DESCRIPTION; 301 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 302 }; 303 304 /** 305 * @class Metalink_v3 306 * Metalink version 3.0 2nd ed 307 * Used only for loading and saving, uses itself Metalink internally 308 */ 309 class Metalink_v3 310 { 311 public: 312 Metalink_v3(); 313 314 Metalink metalink(); 315 void setMetalink(const Metalink &metalink); 316 317 void load(const QDomElement &e); 318 319 /** 320 * Save the metalink 321 * @return the QDomDocument containing the metalink 322 */ 323 QDomDocument save() const; 324 325 private: 326 void parseFiles(const QDomElement &e); 327 Resources parseResources(const QDomElement &e); 328 DateConstruct parseDateConstruct(const QString &data); 329 CommonData parseCommonData(const QDomElement &e); 330 331 /** 332 * Inherits CommonData, the inheritor inherits every settings 333 * from the ancestor it has not set itself 334 */ 335 void inheritCommonData(const CommonData &ancestor, CommonData *inheritor); 336 337 void saveFiles(QDomElement &e) const; 338 void saveResources(const Resources &resources, QDomElement &e) const; 339 void saveVerification(const Verification &verification, QDomElement &e) const; 340 void saveCommonData(const CommonData &data, QDomElement &e) const; 341 QString dateConstructToString(const DateConstruct &date) const; 342 343 private: 344 Metalink m_metalink; 345 static const uint MAX_PREFERENCE; 346 }; 347 348 /** 349 * This class can handle the loading and saving of metalinks on the filesystem 350 */ 351 class HandleMetalink 352 { 353 public: 354 /** 355 * Loads destination into metalink 356 * @param destination the place of the metalink in the filesystem 357 * @param metalink the instance of Metalink where the metalink will be stored 358 * @return return true if it worked 359 */ 360 static bool load(const QUrl &destination, Metalink *metalink); 361 362 /** 363 * Loads data into metalink 364 * @param data the contents of a metalink 365 * @param metalink the instance of Metalink where the metalink will be stored 366 * @return return true if it worked 367 */ 368 static bool load(const QByteArray &data, Metalink *metalink); 369 370 /** 371 * Saves metalink to destination 372 * @param destination the place where the metlink will be saved, the ending defines 373 * what version should be used: *.meta4 --> Metalink 4.0; *.metalink --> Metalink 3.0 374 * @param metalink the instance of metalink that will be written to the filesystem 375 * @return return true if it worked 376 */ 377 static bool save(const QUrl &destination, Metalink *metalink); 378 379 }; 380 381 class MetalinkHttpParser : public QObject 382 { 383 Q_OBJECT 384 public: MetalinkHttpParser(const QUrl & Url)385 MetalinkHttpParser(const QUrl& Url) 386 : m_Url(Url), m_MetalinkHSatus(false) , m_EtagValue(QString("")) 387 { 388 checkMetalinkHttp(); 389 } 390 391 ~MetalinkHttpParser() override; 392 393 /** 394 * @return true if m_Url is a metalink/http supported URL. 395 */ 396 397 bool isMetalinkHttp(); 398 399 /** 400 * @return the Url m_Url which is being tested for metalink 401 */ 402 403 QUrl getUrl(); 404 QMultiMap<QString, QString>* getHeaderInfo(); 405 406 /** 407 * @return Returns the ETag if present in the HTTP headers 408 */ 409 410 QString* getEtag(); 411 412 private Q_SLOTS: 413 void slotHeaderResult(KJob* kjob); 414 void checkMetalinkHttp(); 415 void detectMime(KIO::Job * job, const QString & type); 416 void slotRedirection(KIO::Job*, const QUrl&); 417 418 419 private: 420 QUrl m_Url; 421 QUrl m_redirectionUrl; 422 bool m_MetalinkHSatus; 423 QEventLoop m_loop; 424 QMultiMap<QString, QString> m_headerInfo; 425 QString m_EtagValue ; 426 427 /** 428 * Parsees the Metalink values from QString to the Map 429 * @param Value of the QString ie raw HTTP headers 430 */ 431 void parseHeaders(const QString&); 432 433 /** 434 * Sets the status of m_MetalinkHStatus to true if the URL is a Metalink 435 */ 436 void setMetalinkHSatus(); 437 438 }; 439 440 class HttpLinkHeader : public Metaurl 441 { 442 public: 443 HttpLinkHeader(const QString &headerLine); 444 445 QString reltype; 446 bool pref; 447 int depth; 448 QString geo; 449 450 /** 451 * Loads information from a header value into metalink header structure. 452 * @param line Value of the "link" HTTP header response. 453 */ 454 void parseHeaderLine(const QString &); 455 456 bool operator<(const HttpLinkHeader &) const; 457 }; 458 459 } 460 461 #endif // Metalinker_H 462