File indexing completed on 2024-03-24 16:13:25
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) 2011 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 "upload.h" 0029 0030 // Qt includes 0031 0032 #include <QFile> 0033 #include <QStringList> 0034 #include <QTimer> 0035 #include <QUrl> 0036 #include <QUrlQuery> 0037 #include <QXmlStreamReader> 0038 0039 #include <QNetworkAccessManager> 0040 #include <QNetworkCookie> 0041 #include <QNetworkReply> 0042 #include <QNetworkRequest> 0043 0044 // Local includes 0045 #include "job_p.h" 0046 #include "mediawiki.h" 0047 #include "queryinfo.h" 0048 0049 namespace mediawiki 0050 { 0051 class UploadPrivate : public JobPrivate 0052 { 0053 0054 public: 0055 0056 UploadPrivate(MediaWiki& mediawiki) 0057 : JobPrivate(mediawiki) 0058 { 0059 file = nullptr; 0060 } 0061 0062 static int error(const QString& error) 0063 { 0064 QString temp = error; 0065 int ret = 0; 0066 QStringList list; 0067 list << QStringLiteral("internalerror") 0068 << QStringLiteral("uploaddisabled") 0069 << QStringLiteral("invalidsessionkey") 0070 << QStringLiteral("badaccessgroups") 0071 << QStringLiteral("missingparam") 0072 << QStringLiteral("mustbeloggedin") 0073 << QStringLiteral("fetchfileerror") 0074 << QStringLiteral("nomodule") 0075 << QStringLiteral("emptyfile") 0076 << QStringLiteral("filetypemissing") 0077 << QStringLiteral("filenametooshort") 0078 << QStringLiteral("overwrite") 0079 << QStringLiteral("stashfailed"); 0080 ret = list.indexOf(temp.remove(QChar::fromLatin1('-'))); 0081 if(ret == -1) 0082 { 0083 ret = 0; 0084 } 0085 return ret + (int)Upload::InternalError ; 0086 } 0087 0088 QIODevice* file; 0089 QString filename; 0090 QString comment; 0091 QString text; 0092 QString token; 0093 }; 0094 0095 Upload::Upload(MediaWiki& mediawiki, QObject* const parent) 0096 : Job(*new UploadPrivate(mediawiki), parent) 0097 { 0098 } 0099 0100 Upload::~Upload() 0101 { 0102 } 0103 0104 void Upload::setFilename(const QString& param) 0105 { 0106 Q_D(Upload); 0107 d->filename = param; 0108 } 0109 0110 void Upload::setFile(QIODevice* const file) 0111 { 0112 Q_D(Upload); 0113 d->file = file; 0114 } 0115 0116 void Upload::setComment(const QString& param) 0117 { 0118 Q_D(Upload); 0119 d->comment = param; 0120 } 0121 0122 void Upload::setText(const QString& text) 0123 { 0124 Q_D(Upload); 0125 d->text = text; 0126 } 0127 0128 void Upload::start() 0129 { 0130 Q_D(Upload); 0131 0132 QueryInfo* info = new QueryInfo(d->mediawiki, this); 0133 info->setPageName(QStringLiteral("File:") + d->filename); 0134 info->setToken(QStringLiteral("edit")); 0135 0136 connect(info, SIGNAL(page(Page)), 0137 this, SLOT(doWorkSendRequest(Page))); 0138 0139 info->start(); 0140 } 0141 0142 void Upload::doWorkSendRequest(Page page) 0143 { 0144 Q_D(Upload); 0145 0146 QString token = page.pageEditToken(); 0147 d->token = token; 0148 0149 // Get the extension 0150 QStringList filename = d->filename.split(QChar::fromLatin1('.')); 0151 QString extension = filename.at(filename.size()-1); 0152 0153 if (extension == QLatin1String("jpg")) 0154 extension = QStringLiteral("jpeg"); 0155 else if (extension == QLatin1String("svg")) 0156 extension += QStringLiteral("+xml"); 0157 0158 QUrl url = d->mediawiki.url(); 0159 QUrlQuery query; 0160 query.addQueryItem(QStringLiteral("action"), QStringLiteral("upload")); 0161 query.addQueryItem(QStringLiteral("format"), QStringLiteral("xml")); 0162 url.setQuery(query); 0163 0164 // Add the cookies 0165 QByteArray cookie = ""; 0166 QList<QNetworkCookie> mediawikiCookies = d->manager->cookieJar()->cookiesForUrl(d->mediawiki.url()); 0167 for(int i = 0; i < mediawikiCookies.size(); ++i) 0168 { 0169 cookie += mediawikiCookies.at(i).toRawForm(QNetworkCookie::NameAndValueOnly); 0170 cookie += ';'; 0171 } 0172 0173 // Set the request 0174 QNetworkRequest request( url ); 0175 request.setRawHeader("User-Agent", d->mediawiki.userAgent().toUtf8()); 0176 request.setRawHeader("Accept-Charset", "utf-8"); 0177 0178 QByteArray boundary = "-----------------------------15827188141577679942014851228"; 0179 request.setRawHeader("Content-Type", "multipart/form-data; boundary=" + boundary); 0180 request.setRawHeader("Cookie", cookie ); 0181 0182 // send data 0183 boundary = "--" + boundary + "\r\n"; 0184 QByteArray out = boundary; 0185 0186 // ignore warnings 0187 out += "Content-Disposition: form-data; name=\"ignorewarnings\"\r\n\r\n"; 0188 out += "true\r\n"; 0189 out += boundary; 0190 0191 // filename 0192 out += "Content-Disposition: form-data; name=\"filename\"\r\n\r\n"; 0193 out += d->filename.toUtf8(); 0194 out += "\r\n"; 0195 out += boundary; 0196 0197 // comment 0198 if (!d->comment.isEmpty()) 0199 { 0200 out += "Content-Disposition: form-data; name=\"comment\"\r\n\r\n"; 0201 out += d->comment.toUtf8(); 0202 out += "\r\n"; 0203 out += boundary; 0204 } 0205 0206 // token 0207 out += "Content-Disposition: form-data; name=\"token\"\r\n\r\n"; 0208 out += d->token.toUtf8(); 0209 out += "\r\n"; 0210 out += boundary; 0211 0212 // the actual file 0213 out += "Content-Disposition: form-data; name=\"file\"; filename=\""; 0214 out += d->filename.toUtf8(); 0215 out += "\"\r\n"; 0216 out += "Content-Type: image/"; 0217 out += extension.toUtf8(); 0218 out += "\r\n\r\n"; 0219 out += d->file->readAll(); 0220 out += "\r\n"; 0221 out += boundary; 0222 0223 // description page 0224 out += "Content-Disposition: form-data; name=\"text\"\r\n"; 0225 out += "Content-Type: text/plain\r\n\r\n"; 0226 out += d->text.toUtf8(); 0227 out += "\r\n"; 0228 out += boundary.mid(0, boundary.length() - 2); 0229 out += "--\r\n"; 0230 0231 d->reply = d->manager->post( request, out ); 0232 connectReply(); 0233 connect( d->reply, SIGNAL(finished()), 0234 this, SLOT(doWorkProcessReply()) ); 0235 } 0236 0237 void Upload::doWorkProcessReply() 0238 { 0239 Q_D(Upload); 0240 0241 disconnect( d->reply, SIGNAL(finished()), 0242 this, SLOT(doWorkProcessReply()) ); 0243 0244 if ( d->reply->error() != QNetworkReply::NoError ) 0245 { 0246 this->setError(this->NetworkError); 0247 d->reply->close(); 0248 d->reply->deleteLater(); 0249 emitResult(); 0250 return; 0251 } 0252 0253 QXmlStreamReader reader( d->reply ); 0254 0255 while ( !reader.atEnd() && !reader.hasError() ) 0256 { 0257 QXmlStreamReader::TokenType token = reader.readNext(); 0258 0259 if ( token == QXmlStreamReader::StartElement ) 0260 { 0261 QXmlStreamAttributes attrs = reader.attributes(); 0262 0263 if ( reader.name() == QLatin1String( "upload" ) ) 0264 { 0265 if ( attrs.value(QStringLiteral("result")).toString() == QLatin1String("Success") ) 0266 { 0267 this->setError(KJob::NoError); 0268 } 0269 } 0270 else if ( reader.name() == QLatin1String( "error" ) ) 0271 { 0272 this->setErrorText(attrs.value( QStringLiteral("info")).toString()); 0273 this->setError(UploadPrivate::error(attrs.value(QStringLiteral("code")).toString())); 0274 } 0275 } 0276 else if ( token == QXmlStreamReader::Invalid && reader.error() != 0277 QXmlStreamReader::PrematureEndOfDocumentError) 0278 { 0279 this->setError(this->XmlError); 0280 } 0281 } 0282 0283 d->reply->close(); 0284 d->reply->deleteLater(); 0285 emitResult(); 0286 } 0287 0288 } // namespace mediawiki