SVN commit 1356916 by narvaez: Merging work from GSoC 2011 on Metalink HTTP Headers as planned feature for KDE SC 4.11 CCEMAIL: dahalaishraj@gmail.com M +1 -1 core/transferhandler.h M +2 -1 main.cpp M +4 -2 transfer-plugins/metalink/CMakeLists.txt A transfer-plugins/metalink/abstractmetalink.cpp [License: GPL (v2+)] A transfer-plugins/metalink/abstractmetalink.h [License: GPL (v2+)] M +1 -1 transfer-plugins/metalink/kget_metalinkfactory.desktop D transfer-plugins/metalink/metalink.cpp D transfer-plugins/metalink/metalink.h M +17 -9 transfer-plugins/metalink/metalinkfactory.cpp M +15 -4 transfer-plugins/metalink/metalinkfactory.h A transfer-plugins/metalink/metalinkhttp.cpp [License: GPL (v2+)] A transfer-plugins/metalink/metalinkhttp.h [License: GPL (v2+)] A transfer-plugins/metalink/metalinkxml.cpp [License: GPL (v2+)] A transfer-plugins/metalink/metalinkxml.h [License: GPL (v2+)] M +165 -0 ui/metalinkcreator/metalinker.cpp M +87 -1 ui/metalinkcreator/metalinker.h --- trunk/KDE/kdenetwork/kget/core/transferhandler.h #1356915:1356916 @@ -28,7 +28,7 @@ * Class TransferHandler: * * --- Overview --- - * This class is the rapresentation of a Transfer object from the views' + * This class is the representation of a Transfer object from the views' * perspective (proxy pattern). In fact the views never handle directly the * Transfer objects themselves (because this would break the model/view policy). * As a general rule, all the code strictly related to the views should placed --- trunk/KDE/kdenetwork/kget/main.cpp #1356915:1356916 @@ -105,7 +105,7 @@ QByteArray("2." + QByteArray::number(KDE_VERSION_MINOR) + '.' + QByteArray::number(KDE_VERSION_RELEASE)), ki18n("An advanced download manager for KDE"), KAboutData::License_GPL, - ki18n("(C) 2005 - 2011, The KGet developers\n" + ki18n("(C) 2005 - 2012, The KGet developers\n" "(C) 2001 - 2002, Patrick Charbonnier\n" "(C) 2002, Carsten Pfeiffer\n" "(C) 1998 - 2000, Matej Koss"), @@ -117,6 +117,7 @@ aboutData.addAuthor(ki18n("Manolo Valdes"), ki18n("Core Developer, Multithreaded Plugin Author"), "nolis71cu@gmail.com"); aboutData.addAuthor(ki18n("Matthias Fuchs"), ki18n("Core Developer"), "mat69@gmx.net"); aboutData.addAuthor(ki18n("Javier Goday"), ki18n("Developer"), "jgoday@gmail.com"); + aboutData.addAuthor(ki18n("Aish Raj Dahal"), ki18n("Google Summer of Code Student")); aboutData.addAuthor(ki18n("Ernesto Rodriguez Ortiz"), ki18n("Mms Plugin Author"), "eortiz@uci.cu"); aboutData.addAuthor(ki18n("Patrick Charbonnier"), ki18n("Former Developer"), "pch@freeshell.org"); aboutData.addAuthor(ki18n("Carsten Pfeiffer"), ki18n("Former Developer"), "pfeiffer@kde.org"); --- trunk/KDE/kdenetwork/kget/transfer-plugins/metalink/CMakeLists.txt #1356915:1356916 @@ -7,7 +7,9 @@ set(kget_metalinkfactory_PART_SRCS metalinkfactory.cpp - metalink.cpp + abstractmetalink.cpp + metalinkxml.cpp + metalinkhttp.cpp fileselectiondlg.cpp ../../ui/metalinkcreator/metalinker.cpp ) @@ -43,4 +45,4 @@ target_link_libraries(kcm_kget_metalinkfactory ${KDE4_KDEUI_LIBS} ${KDE4_KIO_LIBS}) install(TARGETS kcm_kget_metalinkfactory DESTINATION ${PLUGIN_INSTALL_DIR}) -install(FILES kget_metalinkfactory_config.desktop DESTINATION ${SERVICES_INSTALL_DIR}) \ No newline at end of file +install(FILES kget_metalinkfactory_config.desktop DESTINATION ${SERVICES_INSTALL_DIR}) --- trunk/KDE/kdenetwork/kget/transfer-plugins/metalink/kget_metalinkfactory.desktop #1356915:1356916 @@ -115,7 +115,7 @@ # options for library loader X-KDE-Library=kget_metalinkfactory X-KDE-KGet-plugintype=TransferFactory -X-KDE-KGet-rank=90 +X-KDE-KGet-rank=110 X-KDE-KGet-framework-version=1 X-KDE-PluginInfo-Author=Manolo Valdes --- trunk/KDE/kdenetwork/kget/transfer-plugins/metalink/metalinkfactory.cpp #1356915:1356916 @@ -2,6 +2,7 @@ Copyright (C) 2004 Dario Massarin Copyright (C) 2007 Manolo Valdes + Copyright (C) 2012 Aish Raj Dahal This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public @@ -13,36 +14,43 @@ #include "core/scheduler.h" #include "core/transfergroup.h" -#include "metalink.h" +#include "metalinkhttp.h" +#include "metalinkxml.h" #include -KGET_EXPORT_PLUGIN( metalinkFactory ) +KGET_EXPORT_PLUGIN( MetalinkFactory ) -metalinkFactory::metalinkFactory(QObject *parent, const QVariantList &args) +MetalinkFactory::MetalinkFactory(QObject *parent, const QVariantList &args) : TransferFactory(parent, args) { } -metalinkFactory::~metalinkFactory() +MetalinkFactory::~MetalinkFactory() { } -Transfer * metalinkFactory::createTransfer( const KUrl &srcUrl, const KUrl &destUrl, +Transfer * MetalinkFactory::createTransfer( const KUrl &srcUrl, const KUrl &destUrl, TransferGroup * parent, Scheduler * scheduler, const QDomElement * e ) { kDebug(5001) << "metalinkFactory::createTransfer"; - if (isSupported(srcUrl)) - { - return new Metalink(parent, this, scheduler, srcUrl, destUrl, e); + m_metalinkHttpChecker = new KGetMetalink::MetalinkHttpParser(srcUrl); + + if (m_metalinkHttpChecker->isMetalinkHttp()) { + //kDebug(5001) << "createtransfer:: This is metalinkhttp"; + return new MetalinkHttp(parent,this,scheduler,srcUrl,destUrl,m_metalinkHttpChecker,e); } + else if (isSupported(srcUrl)) { + //kDebug(5001) << "createtransfer:: This is metalink / xml"; + return new MetalinkXml(parent, this, scheduler, srcUrl, destUrl, e); + } return 0; } -bool metalinkFactory::isSupported(const KUrl &url) const +bool MetalinkFactory::isSupported(const KUrl &url) const { return (url.fileName().endsWith(QLatin1String(".metalink")) || url.fileName().endsWith(QLatin1String(".meta4"))); } --- trunk/KDE/kdenetwork/kget/transfer-plugins/metalink/metalinkfactory.h #1356915:1356916 @@ -1,6 +1,7 @@ /* This file is part of the KDE project Copyright (C) 2004 Dario Massarin + Copyright (C) 2012 Aish Raj Dahal This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public @@ -12,25 +13,35 @@ #define METALINK_FACTORY_H #include "core/plugin/transferfactory.h" +#include "ui/metalinkcreator/metalinker.h" class Transfer; class TransferGroup; class Scheduler; -class metalinkFactory : public TransferFactory + +class MetalinkFactory : public TransferFactory { Q_OBJECT public: - metalinkFactory(QObject *parent, const QVariantList &args); - ~metalinkFactory(); + MetalinkFactory(QObject *parent, const QVariantList &args); + ~MetalinkFactory(); Transfer * createTransfer( const KUrl &srcUrl, const KUrl &destUrl, TransferGroup * parent, Scheduler * scheduler, const QDomElement * e = 0 ); QString displayName(){return "MetaLink";} + /** + * Checks if a URL is supported by this plugin. + * + * @param The Url to be tested + * @return True if the URL is a metalink (xml or http). + */ + bool isSupported(const KUrl &url) const; - bool isSupported(const KUrl &url) const; + private: + KGetMetalink::MetalinkHttpParser *m_metalinkHttpChecker; }; #endif --- trunk/KDE/kdenetwork/kget/ui/metalinkcreator/metalinker.cpp #1356915:1356916 @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (C) 2009 Matthias Fuchs * +* Copyright (C) 2012 Aish Raj Dahal * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -1334,3 +1335,167 @@ } } #endif //HAVE_NEPOMUK + + +KGetMetalink::MetalinkHttpParser::~MetalinkHttpParser() +{ + +} + +QString* KGetMetalink::MetalinkHttpParser::getEtag() +{ + return &m_EtagValue; +} + +void KGetMetalink::MetalinkHttpParser::checkMetalinkHttp() +{ + if (!m_Url.isValid()) { + kDebug() << "Url not valid"; + return; + } + + KIO::TransferJob *job; + job = KIO::get(m_Url); + job->addMetaData("PropagateHttpHeader", "true"); + job->setRedirectionHandlingEnabled(false); + connect(job, SIGNAL(result(KJob*)), this, SLOT(slotHeaderResult(KJob*))); // Finished + connect(job, SIGNAL(redirection(KIO::Job*,KUrl)), this, SLOT(slotRedirection(KIO::Job*,KUrl))); // Redirection + connect(job,SIGNAL(mimetype(KIO::Job*,QString)),this,SLOT(detectMime(KIO::Job*,QString))); // Mime detection. + kDebug() << " Verifying Metalink/HTTP Status" ; + m_loop.exec(); +} + +void KGetMetalink::MetalinkHttpParser::detectMime(KIO::Job *job, const QString &type) +{ + kDebug() << "Mime Type: " << type ; + job->kill(); + m_loop.exit(); +} + +void KGetMetalink::MetalinkHttpParser::slotHeaderResult(KJob* kjob) +{ + KIO::Job* job = qobject_cast(kjob); + const QString httpHeaders = job ? job->queryMetaData("HTTP-Headers") : QString(); + parseHeaders(httpHeaders); + setMetalinkHSatus(); + + // Handle the redirection... (Comment out if not desired) + if (m_redirectionUrl.isValid()) { + m_Url = m_redirectionUrl; + m_redirectionUrl = KUrl(); + checkMetalinkHttp(); + } + +} + +void KGetMetalink::MetalinkHttpParser::slotRedirection(KIO::Job *job, const KUrl & url) +{ + Q_UNUSED(job) + m_redirectionUrl = url; +} + +bool KGetMetalink::MetalinkHttpParser::isMetalinkHttp() +{ + if (m_MetalinkHSatus) { + kDebug() << "Metalink Http detected" ; + } + else { + kDebug() << "No Metalink HTTP response found" ; + } + return m_MetalinkHSatus; +} + +void KGetMetalink::MetalinkHttpParser::parseHeaders(const QString &httpHeader) +{ + QString trimedHeader = httpHeader.mid(httpHeader.indexOf('\n') + 1).trimmed(); + + foreach(QString line, trimedHeader.split('\n')) { + int colon = line.indexOf(':'); + QString headerName = line.left(colon).trimmed(); + QString headerValue = line.mid(colon + 1).trimmed(); + m_headerInfo.insertMulti(headerName, headerValue); + } + + m_EtagValue = m_headerInfo.value("ETag"); +} + +void KGetMetalink::MetalinkHttpParser::setMetalinkHSatus() +{ + bool linkStatus, digestStatus; + linkStatus = digestStatus = false; + if (m_headerInfo.contains("link")) { + QList linkValues = m_headerInfo.values("link"); + + foreach(QString linkVal, linkValues) { + if (linkVal.contains("rel=duplicate")) { + linkStatus = true; + break; + } + } + } + + if (m_headerInfo.contains("digest")) { + QList digestValues = m_headerInfo.values("digest"); + + foreach(QString digestVal, digestValues) { + if (digestVal.contains("sha-256", Qt::CaseInsensitive)) { + digestStatus = true; + break; + } + } + } + + if ((linkStatus) && (digestStatus)) { + m_MetalinkHSatus = true; + } + +} + +KUrl KGetMetalink::MetalinkHttpParser::getUrl() +{ + return m_Url; +} + +QMultiMap* KGetMetalink::MetalinkHttpParser::getHeaderInfo() +{ + return & m_headerInfo; +} + +bool KGetMetalink::httpLinkHeader::operator<(const httpLinkHeader &other) const +{ + return m_depth < other.m_depth; +} + +void KGetMetalink::httpLinkHeader::headerBuilder(const QString &line) +{ + url = line.mid(line.indexOf("<") + 1,line.indexOf(">") -1).trimmed(); + QList attribList = line.split(";"); + foreach ( QString str, attribList) { + QString attribId = str.mid(0,str.indexOf("=")).trimmed(); + QString attribValue = str.mid(str.indexOf("=")+1).trimmed(); + if (attribId == "rel") { + m_reltype = attribValue; + } + if (attribId == "depth") { + m_depth = attribValue.toInt(); + } + if (attribId == "geo") { + m_geo = attribValue; + } + if (attribId == "pref") { + m_pref = true; + } + if (attribId == "pri") { + priority = attribValue.toUInt(); + } + if (attribId == "type") { + type = attribValue; + } + + if (attribId == "name") { + name = attribValue; + } + } +} + +#include "metalinker.moc" --- trunk/KDE/kdenetwork/kget/ui/metalinkcreator/metalinker.h #1356915:1356916 @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (C) 2009 Matthias Fuchs * +* Copyright (C) 2012 Aish Raj Dahal * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -25,6 +26,9 @@ #include #include #include +#include +#include +#include #ifdef HAVE_NEPOMUK namespace Nepomuk @@ -248,7 +252,7 @@ bool isValid() const; /** - * Controlls if the name attribute is valid, i.e. it is not empty and + * Controls if the name attribute is valid, i.e. it is not empty and * does not contain any directory traversal directives or information, * as described in the Metalink 4.0 specification 4.1.2.1. */ @@ -412,6 +416,88 @@ #endif //HAVE_NEPOMUK }; +class MetalinkHttpParser : public QObject +{ + Q_OBJECT + public: + MetalinkHttpParser(const KUrl& Url) + : m_Url(Url), m_MetalinkHSatus(false) , m_EtagValue(QString("")) + { + checkMetalinkHttp(); } + ~MetalinkHttpParser(); + + /** + * @return true if m_Url is a metalink/http supported URL. + */ + + bool isMetalinkHttp(); + + /** + * @return the Url m_Url which is being tested for metalink + */ + + KUrl getUrl(); + QMultiMap* getHeaderInfo(); + + /** + * @return Returns the ETag if present in the HTTP headers + */ + + QString* getEtag(); + + private slots: + void slotHeaderResult(KJob* kjob); + void checkMetalinkHttp(); + void detectMime(KIO::Job * job, const QString & type); + void slotRedirection(KIO::Job*, const KUrl&); + + + private: + KUrl m_Url; + KUrl m_redirectionUrl; + bool m_MetalinkHSatus; + QEventLoop m_loop; + QMultiMap m_headerInfo; + QString m_EtagValue ; + + /** + * Parsees the Metalink values from QString to the Map + * @param Value of the QString ie raw HTTP headers + */ + void parseHeaders(const QString&); + + /** + * Sets the status of m_MetalinkHStatus to true if the URL is a Metalink + */ + void setMetalinkHSatus(); + +}; + +class httpLinkHeader : public Metaurl +{ + public: + httpLinkHeader() + : m_pref(false) + { + } + + QString m_reltype; + bool m_pref; + int m_depth; + QString m_geo; + + /** + * Loads information from a header value into metalink header structure. + * @param Value of the "link" HTTP header response. + */ + void headerBuilder(const QString &); + + bool operator<(const httpLinkHeader &) const; + +}; + +} + #endif // Metalinker_H