File indexing completed on 2024-04-21 15:32:08

0001 /** ===========================================================
0002  * @file
0003  *
0004  * This file is a part of KDE project
0005  * <a href="https://commits.kde.org/libmediawiki">libmediawiki</a>
0006  *
0007  * @date   2011-03-22
0008  * @brief  a MediaWiki C++ interface for KDE
0009  *
0010  * @author Copyright (C) 2011-2012 by Gilles Caulier
0011  *         <a href="mailto:caulier dot gilles at gmail dot com">caulier dot gilles at gmail dot com</a>
0012  * @author Copyright (C) 2010 by Alexandre Mendes
0013  *         <a href="mailto:alex dot mendes1988 at gmail dot com">alex dot mendes1988 at gmail dot com</a>
0014  *
0015  * This program is free software; you can redistribute it
0016  * and/or modify it under the terms of the GNU General
0017  * Public License as published by the Free Software Foundation;
0018  * either version 2, or (at your option)
0019  * any later version.
0020  *
0021  * This program is distributed in the hope that it will be useful,
0022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0024  * GNU General Public License for more details.
0025  *
0026  * ============================================================ */
0027 
0028 #include "queryinfo.h"
0029 
0030 
0031 // Qt includes
0032 
0033 #include <QDateTime>
0034 #include <QTimer>
0035 #include <QUrl>
0036 #include <QUrlQuery>
0037 #include <QXmlStreamReader>
0038 #include <QRegExp>
0039 
0040 #include <QNetworkAccessManager>
0041 #include <QNetworkCookie>
0042 #include <QNetworkReply>
0043 #include <QNetworkRequest>
0044 
0045 // Local includes
0046 
0047 #include "mediawiki.h"
0048 #include "job_p.h"
0049 
0050 namespace mediawiki
0051 {
0052 
0053 class QueryInfoPrivate : public JobPrivate
0054 {
0055 
0056 public:
0057 
0058     QueryInfoPrivate(MediaWiki& mediawiki)
0059         : JobPrivate(mediawiki)
0060     {}
0061 
0062     QVector<Protection>    protections;
0063     QMap<QString, QString> requestParameter;
0064     Page                   page;
0065 };
0066 
0067 QueryInfo::QueryInfo(MediaWiki& mediawiki, QObject* const parent)
0068     : Job(*new QueryInfoPrivate(mediawiki), parent)
0069 {
0070 }
0071 
0072 QueryInfo::~QueryInfo()
0073 {
0074 }
0075 
0076 void QueryInfo::setPageName(const QString& title)
0077 {
0078     Q_D(QueryInfo);
0079     d->requestParameter[QStringLiteral("titles")] = title;
0080 }
0081 
0082 void QueryInfo::setToken(const QString& token)
0083 {
0084     Q_D(QueryInfo);
0085     d->requestParameter[QStringLiteral("intoken")] = token;
0086 }
0087 
0088 void QueryInfo::setPageId(unsigned int id)
0089 {
0090     Q_D(QueryInfo);
0091     d->requestParameter[QStringLiteral("pageids")] = QString::number(id);
0092 }
0093 
0094 void QueryInfo::setRevisionId(unsigned int id)
0095 {
0096     Q_D(QueryInfo);
0097     d->requestParameter[QStringLiteral("revids")] = QString::number(id);
0098 }
0099 
0100 void QueryInfo::start()
0101 {
0102     QTimer::singleShot(0, this, SLOT(doWorkSendRequest()));
0103 }
0104 
0105 void QueryInfo::doWorkSendRequest()
0106 {
0107     Q_D(QueryInfo);
0108 
0109     // Set the url
0110     QUrl url = d->mediawiki.url();
0111     QUrlQuery query;
0112     query.addQueryItem(QStringLiteral("format"), QStringLiteral("xml"));
0113     query.addQueryItem(QStringLiteral("action"), QStringLiteral("query"));
0114     query.addQueryItem(QStringLiteral("prop"),   QStringLiteral("info"));
0115     query.addQueryItem(QStringLiteral("inprop"), QStringLiteral("protection|talkid|watched|subjectid|url|readable|preload"));
0116 
0117     QMapIterator<QString, QString> i(d->requestParameter);
0118     while (i.hasNext())
0119     {
0120         i.next();
0121         query.addQueryItem(i.key(), i.value());
0122     }
0123     url.setQuery(query);
0124 
0125     // Set the request
0126     QNetworkRequest request(url);
0127     request.setRawHeader("User-Agent", d->mediawiki.userAgent().toUtf8());
0128     QByteArray cookie = "";
0129     QList<QNetworkCookie> mediawikiCookies = d->manager->cookieJar()->cookiesForUrl(d->mediawiki.url());
0130 
0131     for(int i = 0 ; i < mediawikiCookies.size(); ++i)
0132     {
0133         cookie += mediawikiCookies.at(i).toRawForm(QNetworkCookie::NameAndValueOnly);
0134         cookie += ';';
0135     }
0136     request.setRawHeader( "Cookie", cookie );
0137 
0138     // Send the request
0139     d->reply = d->manager->get(request);
0140     connectReply();
0141 
0142     connect(d->reply, SIGNAL(finished()),
0143             this, SLOT(doWorkProcessReply()));
0144 }
0145 
0146 void QueryInfo::doWorkProcessReply()
0147 {
0148     Q_D(QueryInfo);
0149 
0150     disconnect(d->reply, SIGNAL(finished()), 
0151                this, SLOT(doWorkProcessReply()));
0152 
0153     if (d->reply->error() == QNetworkReply::NoError)
0154     {
0155         // Replace & in &amp;
0156         QString content = QString::fromUtf8(d->reply->readAll());
0157         QRegExp regex(QStringLiteral("&(?!\\w+;)"));
0158         content.replace(regex, QStringLiteral("&amp;"));
0159         QXmlStreamReader reader(content);
0160         QVector<Protection> protect;
0161 
0162         while (!reader.atEnd() && !reader.hasError())
0163         {
0164             QXmlStreamReader::TokenType token = reader.readNext();
0165             QXmlStreamAttributes attrs = reader.attributes();
0166 
0167             if (token == QXmlStreamReader::StartElement)
0168             {
0169                 if (reader.name() == QLatin1String("page"))
0170                 {
0171                     d->page.setPageId(attrs.value(QStringLiteral("pageid")).toString().toUInt());
0172                     d->page.setTitle(attrs.value(QStringLiteral("title")).toString());
0173                     d->page.setNs(attrs.value(QStringLiteral("ns")).toString().toUInt());
0174                     d->page.setTouched(QDateTime::fromString(attrs.value(QStringLiteral("touched")).toString(), QStringLiteral("yyyy'-'MM'-'dd'T'hh':'mm':'ss'Z'")));
0175                     d->page.setLastRevId(attrs.value(QStringLiteral("lastrevid")).toString().toUInt());
0176                     d->page.setCounter(attrs.value(QStringLiteral("counter")).toString().toUInt());
0177                     d->page.setLength(attrs.value(QStringLiteral("length")).toString().toUInt());
0178                     d->page.setStarttimestamp(QDateTime::fromString(attrs.value(QStringLiteral("starttimestamp")).toString(), QStringLiteral("yyyy'-'MM'-'dd'T'hh':'mm':'ss'Z'")));
0179                     d->page.setEditToken(attrs.value(QStringLiteral("edittoken")).toString());
0180                     d->page.setTalkid(attrs.value(QStringLiteral("talkid")).toString().toUInt());
0181                     d->page.setFullurl(QUrl(attrs.value(QStringLiteral("fullurl")).toString()));
0182                     d->page.setEditurl(QUrl(attrs.value(QStringLiteral("editurl")).toString()));
0183                     d->page.setReadable(attrs.value(QStringLiteral("readable")).toString());
0184                     d->page.setPreload(attrs.value(QStringLiteral("preload")).toString());
0185                 }
0186                 else if (reader.name() == QLatin1String("protection"))
0187                 {
0188                     protect.clear();
0189                 }
0190                 else if (reader.name() == QLatin1String("pr"))
0191                 {
0192                     QString expiry(attrs.value(QStringLiteral("expiry")).toString());
0193                     QString level(attrs.value(QStringLiteral("level")).toString());
0194                     QString type(attrs.value(QStringLiteral("type")).toString());
0195                     QString source;
0196 
0197                     if(!attrs.value(QStringLiteral("source")).toString().isEmpty())
0198                     {
0199                         source = attrs.value(QStringLiteral("source")).toString();
0200                     }
0201                     else if(!attrs.value(QStringLiteral("cascade")).toString().isEmpty())
0202                     {
0203                         source = attrs.value(QStringLiteral("cascade")).toString();
0204                     }
0205 
0206                     Protection p;
0207                     p.setExpiry(expiry);
0208                     p.setLevel(level);
0209                     p.setType(type);
0210                     p.setSource(source);
0211                     protect.push_back(p);
0212                 }
0213             }
0214             else if (token == QXmlStreamReader::EndElement)
0215             {
0216                 if (reader.name() == QLatin1String("page"))
0217                 {
0218                     d->protections = protect;
0219                 }
0220             }
0221         }
0222         if (!reader.hasError())
0223         {
0224             setError(KJob::NoError);
0225             emit protection(protect);
0226             emit page(d->page);
0227         }
0228         else
0229         {
0230             setError(Job::XmlError);
0231         }
0232     }
0233     else
0234     {
0235         setError(Job::NetworkError);
0236     }
0237 
0238     emitResult();
0239 }
0240 
0241 } // namespace mediawiki