File indexing completed on 2025-01-05 03:53:36

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