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"