File indexing completed on 2024-05-12 04:57:44
0001 /* 0002 This file is part of Choqok, the KDE micro-blogging client 0003 0004 SPDX-FileCopyrightText: 2010-2012 Andrey Esin <gmlastik@gmail.com> 0005 0006 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0007 */ 0008 0009 #include "flickr.h" 0010 0011 #include <QCryptographicHash> 0012 #include <QDebug> 0013 #include <QDomDocument> 0014 #include <QDomElement> 0015 0016 #include <KIO/StoredTransferJob> 0017 #include <KPluginFactory> 0018 0019 #include "mediamanager.h" 0020 #include "passwordmanager.h" 0021 0022 #include "flickrsettings.h" 0023 0024 const static QString apiKey = QLatin1String("13f602e6e705834d8cdd5dd2ccb19651"); 0025 const static QString apiSecret = QLatin1String("98c89dbe39ae3bea"); 0026 const static QString apiKeSec = apiSecret + QLatin1String("api_key") + apiKey; 0027 0028 K_PLUGIN_CLASS_WITH_JSON(Flickr, "choqok_flickr.json") 0029 0030 Flickr::Flickr(QObject *parent, const QList<QVariant> &) 0031 : Choqok::Uploader(QLatin1String("choqok_flickr"), parent) 0032 { 0033 } 0034 0035 Flickr::~Flickr() 0036 { 0037 } 0038 0039 void Flickr::upload(const QUrl &localUrl, const QByteArray &medium, const QByteArray &mediumType) 0040 { 0041 QUrl url(QLatin1String("https://api.flickr.com/services/upload/")); 0042 FlickrSettings::self()->load(); 0043 QString token = Choqok::PasswordManager::self()->readPassword(QStringLiteral("flickr_%1") 0044 .arg(FlickrSettings::username())); 0045 QMap<QString, QByteArray> formdata; 0046 formdata[QLatin1String("api_key")] = apiKey.toUtf8(); 0047 formdata[QLatin1String("auth_token")] = token.toUtf8(); 0048 0049 QString preSign; 0050 if (FlickrSettings::hidefromsearch()) { 0051 formdata[QLatin1String("hidden")] = QByteArray("2"); 0052 preSign.append(QLatin1String("hidden2")); 0053 } else { 0054 formdata[QLatin1String("hidden")] = QByteArray("1"); 0055 preSign.append(QLatin1String("hidden1")); 0056 } 0057 0058 if (FlickrSettings::forprivate()) { 0059 0060 if (FlickrSettings::forfamily()) { 0061 formdata[QLatin1String("is_family")] = QByteArray("1"); 0062 preSign.append(QLatin1String("is_family1")); 0063 } 0064 0065 if (FlickrSettings::forfriends()) { 0066 formdata[QLatin1String("is_friend")] = QByteArray("1"); 0067 preSign.append(QLatin1String("is_friend1")); 0068 } 0069 formdata[QLatin1String("is_public")] = QByteArray("0"); 0070 preSign.append(QLatin1String("is_public0")); 0071 } else if (FlickrSettings::forpublic()) { 0072 formdata[QLatin1String("is_public")] = QByteArray("1"); 0073 preSign.append(QLatin1String("is_public1")); 0074 } 0075 0076 if (FlickrSettings::safe()) { 0077 formdata[QLatin1String("safety_level")] = QByteArray("1"); 0078 preSign.append(QLatin1String("safety_level1")); 0079 } 0080 if (FlickrSettings::moderate()) { 0081 formdata[QLatin1String("safety_level")] = QByteArray("2"); 0082 preSign.append(QLatin1String("safety_level2")); 0083 } 0084 if (FlickrSettings::restricted()) { 0085 formdata[QLatin1String("safety_level")] = QByteArray("3"); 0086 preSign.append(QLatin1String("safety_level3")); 0087 } 0088 0089 formdata[QLatin1String("api_sig")] = createSign("auth_token" + token.toUtf8() + preSign.toUtf8()); 0090 0091 QMap<QString, QByteArray> mediafile; 0092 mediafile[QLatin1String("name")] = "photo"; 0093 mediafile[QLatin1String("filename")] = localUrl.fileName().toUtf8(); 0094 mediafile[QLatin1String("mediumType")] = mediumType; 0095 mediafile[QLatin1String("medium")] = medium; 0096 QList< QMap<QString, QByteArray> > listMediafiles; 0097 listMediafiles.append(mediafile); 0098 0099 QByteArray data = Choqok::MediaManager::createMultipartFormData(formdata, listMediafiles); 0100 0101 KIO::StoredTransferJob *job = KIO::storedHttpPost(data, url, KIO::HideProgressInfo) ; 0102 if (!job) { 0103 qCritical() << "Cannot create a http POST request!"; 0104 return; 0105 } 0106 job->addMetaData(QLatin1String("content-type"), QLatin1String("Content-Type: multipart/form-data; boundary=AaB03x")); 0107 mUrlMap[job] = localUrl; 0108 connect(job, &KIO::StoredTransferJob::result, this, &Flickr::slotUpload); 0109 job->start(); 0110 } 0111 0112 void Flickr::slotUpload(KJob *job) 0113 { 0114 QUrl localUrl = mUrlMap.take(job); 0115 if (job->error()) { 0116 qCritical() << "Job Error:" << job->errorString(); 0117 Q_EMIT uploadingFailed(localUrl, job->errorString()); 0118 return; 0119 } else { 0120 QDomDocument rep; 0121 QByteArray buffer = qobject_cast<KIO::StoredTransferJob *>(job)->data(); 0122 //qDebug() << buffer; 0123 rep.setContent(buffer); 0124 QString photoId; 0125 QDomElement element = rep.documentElement(); 0126 if (element.tagName() == QLatin1String("rsp")) { 0127 QString res; 0128 res = element.attribute(QLatin1String("stat") , QLatin1String("fail")); 0129 QDomNode node = element.firstChild(); 0130 while (!node.isNull()) { 0131 QDomElement elem = node.toElement(); 0132 if (res == QLatin1String("ok")) { 0133 0134 if (elem.tagName() == QLatin1String("photoid")) { 0135 photoId = elem.text(); 0136 } 0137 0138 QString remUrl; 0139 if (FlickrSettings::shorturl()) { 0140 remUrl = QLatin1String("https://flic.kr/p/") + base58encode(photoId.toULongLong()); 0141 } else { 0142 remUrl = QLatin1String("https://flickr.com/photos/") + FlickrSettings::nsid() + QLatin1Char('/') + photoId; 0143 } 0144 0145 Q_EMIT mediumUploaded(localUrl, remUrl); 0146 return; 0147 0148 } else if (res == QLatin1String("fail")) { 0149 QString errMsg; 0150 if (elem.tagName() == QLatin1String("err")) { 0151 errMsg = elem.text(); 0152 int errCode = elem.attribute(QLatin1String("code") , QLatin1String("0")).toInt(); 0153 switch (errCode) { 0154 case 2: 0155 errMsg = i18n("The photo required argument was missing"); 0156 break; 0157 case 3: 0158 errMsg = i18n("The file was not correctly uploaded"); 0159 break; 0160 case 4: 0161 errMsg = i18n("The file was zero bytes in length"); 0162 break; 0163 case 5: 0164 errMsg = i18n("Filetype was not recognised"); 0165 break; 0166 case 6: 0167 errMsg = i18n("The calling user has reached their monthly bandwidth limit"); 0168 break; 0169 case 96: 0170 case 97: 0171 errMsg = i18n("Signature problem. Please try again later"); 0172 break; 0173 case 98: 0174 case 99: 0175 /*TODO: 0176 Show auth dialog 0177 */ 0178 errMsg = i18n("Login failed. Please re-authenticate Choqok"); 0179 break; 0180 case 105: 0181 errMsg = i18n("The requested service is temporarily unavailable. Try again later"); 0182 break; 0183 default: 0184 errMsg = i18n("Unknown Error:%1. Please try again later", errCode); 0185 break; 0186 } 0187 Q_EMIT uploadingFailed(localUrl, errMsg); 0188 return; 0189 } 0190 } else { 0191 Q_EMIT uploadingFailed(localUrl, i18n("Malformed response")); 0192 return; 0193 } 0194 node = node.nextSibling(); 0195 } 0196 } else { 0197 Q_EMIT uploadingFailed(localUrl, i18n("Malformed response")); 0198 return; 0199 } 0200 } 0201 } 0202 0203 QString Flickr::base58encode(quint64 num) 0204 { 0205 QString alphabet = QLatin1String("123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"); 0206 uint baseCount = alphabet.count(); 0207 QString encoded; 0208 while (num >= baseCount) { 0209 encoded.prepend(alphabet.at(int(num % baseCount))); 0210 num /= baseCount; 0211 } 0212 if (num) { 0213 encoded.prepend(alphabet.at(int(num))); 0214 } 0215 return encoded; 0216 } 0217 0218 QByteArray Flickr::createSign(QByteArray req) 0219 { 0220 return QCryptographicHash::hash(apiKeSec.toUtf8().append(req), QCryptographicHash::Md5).toHex(); 0221 } 0222 0223 #include "flickr.moc" 0224 #include "moc_flickr.cpp"