File indexing completed on 2022-09-27 13:43:08

0001 /* ============================================================
0002  *
0003  * This file is a part of KDE project
0004  *
0005  *
0006  * Date        : 2005-07-07
0007  * Description : a kipi plugin to export images to Flickr web service
0008  *
0009  * Copyright (C) 2005-2009 by Vardhman Jain <vardhman at gmail dot com>
0010  * Copyright (C) 2009-2018 by Gilles Caulier <caulier dot gilles at gmail dot com>
0011  * Copyright (C) 2017      by Maik Qualmann <metzpinguin at gmail dot com>
0012  *
0013  * This program is free software; you can redistribute it
0014  * and/or modify it under the terms of the GNU General
0015  * Public License as published by the Free Software Foundation;
0016  * either version 2, or (at your option) any later version.
0017  *
0018  * This program is distributed in the hope that it will be useful,
0019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0021  * GNU General Public License for more details.
0022  *
0023  * ============================================================ */
0024 
0025 #include "flickrtalker.h"
0026 
0027 // Qt includes
0028 
0029 #include <QByteArray>
0030 #include <QDomDocument>
0031 #include <QDomElement>
0032 #include <QFile>
0033 #include <QFileInfo>
0034 #include <QImage>
0035 #include <QMap>
0036 #include <QStringList>
0037 #include <QProgressDialog>
0038 #include <QStandardPaths>
0039 #include <QApplication>
0040 #include <QDesktopServices>
0041 #include <QMessageBox>
0042 
0043 // Libkipi includes
0044 
0045 #include <KIPI/PluginLoader>
0046 
0047 // Local includes
0048 
0049 #include "kputil.h"
0050 #include "kpversion.h"
0051 #include "mpform.h"
0052 #include "flickritem.h"
0053 #include "flickrwindow.h"
0054 #include "kipiplugins_debug.h"
0055 
0056 using namespace KIPIPlugins;
0057 
0058 namespace KIPIFlickrPlugin
0059 {
0060 
0061 FlickrTalker::FlickrTalker(QWidget* const parent, const QString& serviceName)
0062 {
0063     m_parent          = parent;
0064     m_netMngr         = nullptr;
0065     m_reply           = nullptr;
0066     m_settings        = nullptr;
0067     m_photoSetsList   = nullptr;
0068     m_authProgressDlg = nullptr;
0069     m_state           = FE_LOGOUT;
0070     m_serviceName     = serviceName;
0071     m_iface           = nullptr;
0072     m_o1              = nullptr;
0073     m_store           = nullptr;
0074     m_requestor       = nullptr;
0075 
0076     PluginLoader* const pl = PluginLoader::instance();
0077 
0078     if (pl)
0079     {
0080         m_iface = pl->interface();
0081     }
0082 
0083     if (serviceName == QLatin1String("23"))
0084     {
0085         m_apiUrl    = QLatin1String("http://www.23hq.com/services/rest/");
0086         m_authUrl   = QLatin1String("http://www.23hq.com/services/auth/");
0087         m_uploadUrl = QLatin1String("http://www.23hq.com/services/upload/");
0088 
0089         // bshanks: do 23 and flickr really share API keys? or does 23 not need
0090         // one?
0091         m_apikey    = QLatin1String("49d585bafa0758cb5c58ab67198bf632");
0092         m_secret    = QLatin1String("34b39925e6273ffd");
0093     }
0094     else
0095     {
0096         m_apiUrl    = QLatin1String("https://www.flickr.com/services/rest/");
0097         m_authUrl   = QLatin1String("https://www.flickr.com/services/oauth/authorize?perms=write");
0098         m_tokenUrl  = QLatin1String("https://www.flickr.com/services/oauth/request_token");
0099         m_accessUrl = QLatin1String("https://www.flickr.com/services/oauth/access_token");
0100         m_uploadUrl = QLatin1String("https://up.flickr.com/services/upload/");
0101 
0102         m_apikey    = QLatin1String("49d585bafa0758cb5c58ab67198bf632");
0103         m_secret    = QLatin1String("34b39925e6273ffd");
0104     }
0105 
0106     m_netMngr = new QNetworkAccessManager(this);
0107 
0108     connect(m_netMngr, SIGNAL(finished(QNetworkReply*)),
0109             this, SLOT(slotFinished(QNetworkReply*)));
0110 
0111     /* Initialize selected photo set as empty. */
0112     m_selectedPhotoSet = FPhotoSet();
0113     /* Initialize photo sets list. */
0114     m_photoSetsList    = new QLinkedList<FPhotoSet>();
0115 
0116     m_o1 = new O1(this);
0117 
0118     m_o1->setClientId(m_apikey);
0119     m_o1->setClientSecret(m_secret);
0120     m_o1->setAuthorizeUrl(QUrl(m_authUrl));
0121     m_o1->setAccessTokenUrl(QUrl(m_accessUrl));
0122     m_o1->setRequestTokenUrl(QUrl(m_tokenUrl));
0123 
0124     QString kipioauth = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1String("/kipioauthrc");
0125 
0126     m_settings = new QSettings(kipioauth, QSettings::IniFormat, this);
0127     m_store    = new O0SettingsStore(m_settings, QLatin1String(O2_ENCRYPTION_KEY), this);
0128     m_store->setGroupKey(m_serviceName);
0129     m_o1->setStore(m_store);
0130 
0131     connect(m_o1, SIGNAL(linkingFailed()),
0132             this, SLOT(slotLinkingFailed()));
0133 
0134     connect(m_o1, SIGNAL(linkingSucceeded()),
0135             this, SLOT(slotLinkingSucceeded()));
0136 
0137     connect(m_o1, SIGNAL(openBrowser(QUrl)),
0138             this, SLOT(slotOpenBrowser(QUrl)));
0139 
0140     m_requestor = new O1Requestor(m_netMngr, m_o1, this);
0141 }
0142 
0143 FlickrTalker::~FlickrTalker()
0144 {
0145     if (m_reply)
0146     {
0147         m_reply->abort();
0148     }
0149 
0150     delete m_photoSetsList;
0151 
0152     removeTemporaryDir(m_serviceName.toLatin1().constData());
0153 }
0154 
0155 void FlickrTalker::link(const QString& userName)
0156 {
0157     Q_EMIT signalBusy(true);
0158 
0159     if (userName.isEmpty())
0160     {
0161         m_store->setGroupKey(m_serviceName);
0162     }
0163     else
0164     {
0165         m_store->setGroupKey(m_serviceName + userName);
0166     }
0167 
0168     m_o1->link();
0169 }
0170 
0171 void FlickrTalker::unLink()
0172 {
0173     m_o1->unlink();
0174 }
0175 
0176 void FlickrTalker::removeUserName(const QString& userName)
0177 {
0178     if (userName.startsWith(m_serviceName))
0179     {
0180         m_settings->beginGroup(userName);
0181         m_settings->remove(QString());
0182         m_settings->endGroup();
0183     }
0184 }
0185 
0186 void FlickrTalker::slotLinkingFailed()
0187 {
0188     qCDebug(KIPIPLUGINS_LOG) << "LINK to Flickr fail";
0189     m_username = QString();
0190     Q_EMIT signalBusy(false);
0191 }
0192 
0193 void FlickrTalker::slotLinkingSucceeded()
0194 {
0195     if (!m_o1->linked())
0196     {
0197         qCDebug(KIPIPLUGINS_LOG) << "UNLINK to Flickr ok";
0198         m_username = QString();
0199         return;
0200     }
0201 
0202     qCDebug(KIPIPLUGINS_LOG) << "LINK to Flickr ok";
0203 
0204     m_username = m_o1->extraTokens()[QLatin1String("username")].toString();
0205     m_userId   = m_o1->extraTokens()[QLatin1String("user_nsid")].toString();
0206 
0207     if (m_store->groupKey() == m_serviceName)
0208     {
0209         m_settings->beginGroup(m_serviceName);
0210         QStringList keys = m_settings->allKeys();
0211         m_settings->endGroup();
0212 
0213         foreach(const QString& key, keys)
0214         {
0215             m_settings->beginGroup(m_serviceName);
0216             QVariant value = m_settings->value(key);
0217             m_settings->endGroup();
0218             m_settings->beginGroup(m_serviceName + m_username);
0219             m_settings->setValue(key, value);
0220             m_settings->endGroup();
0221         }
0222 
0223         m_store->setGroupKey(m_serviceName + m_username);
0224         removeUserName(m_serviceName);
0225     }
0226 
0227     Q_EMIT signalLinkingSucceeded();
0228 }
0229 
0230 void FlickrTalker::slotOpenBrowser(const QUrl& url)
0231 {
0232     qCDebug(KIPIPLUGINS_LOG) << "Open Browser...";
0233     QDesktopServices::openUrl(url);
0234 }
0235 
0236 QString FlickrTalker::getMaxAllowedFileSize()
0237 {
0238     return m_maxSize;
0239 }
0240 
0241 void FlickrTalker::maxAllowedFileSize()
0242 {
0243     if (m_reply)
0244     {
0245         m_reply->abort();
0246         m_reply = nullptr;
0247     }
0248 
0249     if (!m_o1->linked())
0250         return;
0251 
0252     QUrl url(m_apiUrl);
0253     QNetworkRequest netRequest(url);
0254     QList<O0RequestParameter> reqParams = QList<O0RequestParameter>();
0255 
0256     netRequest.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String(O2_MIME_TYPE_XFORM));
0257 
0258     reqParams << O0RequestParameter("method", "flickr.people.getLimits");
0259 
0260     QByteArray postData = O1::createQueryParameters(reqParams);
0261 
0262     m_reply = m_requestor->post(netRequest, reqParams, postData);
0263 
0264     m_state = FE_GETMAXSIZE;
0265     m_authProgressDlg->setLabelText(i18n("Getting the maximum allowed file size."));
0266     m_authProgressDlg->setMaximum(4);
0267     m_authProgressDlg->setValue(1);
0268     m_buffer.resize(0);
0269     Q_EMIT signalBusy(true);
0270 }
0271 
0272 void FlickrTalker::listPhotoSets()
0273 {
0274     if (m_reply)
0275     {
0276         m_reply->abort();
0277         m_reply = nullptr;
0278     }
0279 
0280     if (!m_o1->linked())
0281         return;
0282 
0283     qCDebug(KIPIPLUGINS_LOG) << "List photoset invoked";
0284 
0285     QUrl url(m_apiUrl);
0286     QNetworkRequest netRequest(url);
0287     QList<O0RequestParameter> reqParams = QList<O0RequestParameter>();
0288 
0289     netRequest.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String(O2_MIME_TYPE_XFORM));
0290 
0291     reqParams << O0RequestParameter("method", "flickr.photosets.getList");
0292 
0293     QByteArray postData = O1::createQueryParameters(reqParams);
0294 
0295     m_reply = m_requestor->post(netRequest, reqParams, postData);
0296 
0297     m_state = FE_LISTPHOTOSETS;
0298     m_buffer.resize(0);
0299     Q_EMIT signalBusy(true);
0300 }
0301 
0302 void FlickrTalker::getPhotoProperty(const QString& method, const QStringList& argList)
0303 {
0304     if (m_reply)
0305     {
0306         m_reply->abort();
0307         m_reply = nullptr;
0308     }
0309 
0310     if (!m_o1->linked())
0311         return;
0312 
0313     QUrl url(m_apiUrl);
0314     QNetworkRequest netRequest(url);
0315     QList<O0RequestParameter> reqParams = QList<O0RequestParameter>();
0316 
0317     netRequest.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String(O2_MIME_TYPE_XFORM));
0318 
0319     reqParams << O0RequestParameter("method", method.toLatin1());
0320 
0321     for (QStringList::const_iterator it = argList.constBegin(); it != argList.constEnd(); ++it)
0322     {
0323         QStringList str = (*it).split(QLatin1Char('='), Qt::SkipEmptyParts);
0324         reqParams << O0RequestParameter(str[0].toLatin1(), str[1].toLatin1());
0325     }
0326 
0327     QByteArray postData = O1::createQueryParameters(reqParams);
0328 
0329     m_reply = m_requestor->post(netRequest, reqParams, postData);
0330 
0331     m_state = FE_GETPHOTOPROPERTY;
0332     m_buffer.resize(0);
0333     Q_EMIT signalBusy(true);
0334 }
0335 
0336 void FlickrTalker::listPhotos(const QString& /*albumName*/)
0337 {
0338     // TODO
0339 }
0340 
0341 void FlickrTalker::createPhotoSet(const QString& /*albumName*/, const QString& albumTitle,
0342                                   const QString& albumDescription, const QString& primaryPhotoId)
0343 {
0344     if (m_reply)
0345     {
0346         m_reply->abort();
0347         m_reply = nullptr;
0348     }
0349 
0350     if (!m_o1->linked())
0351         return;
0352 
0353     qCDebug(KIPIPLUGINS_LOG) << "Create photoset invoked";
0354 
0355     QUrl url(m_apiUrl);
0356     QNetworkRequest netRequest(url);
0357     QList<O0RequestParameter> reqParams = QList<O0RequestParameter>();
0358 
0359     netRequest.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String(O2_MIME_TYPE_XFORM));
0360 
0361     reqParams << O0RequestParameter("method", "flickr.photosets.create");
0362     reqParams << O0RequestParameter("title", albumTitle.toLatin1());
0363     reqParams << O0RequestParameter("description", albumDescription.toLatin1());
0364     reqParams << O0RequestParameter("primary_photo_id", primaryPhotoId.toLatin1());
0365 
0366     QByteArray postData = O1::createQueryParameters(reqParams);
0367 
0368     m_reply = m_requestor->post(netRequest, reqParams, postData);
0369 
0370     m_state = FE_CREATEPHOTOSET;
0371     m_buffer.resize(0);
0372     Q_EMIT signalBusy(true);
0373 }
0374 
0375 void FlickrTalker::addPhotoToPhotoSet(const QString& photoId,
0376                                       const QString& photoSetId)
0377 {
0378     if (m_reply)
0379     {
0380         m_reply->abort();
0381         m_reply = nullptr;
0382     }
0383 
0384     if (!m_o1->linked())
0385         return;
0386 
0387     qCDebug(KIPIPLUGINS_LOG) << "AddPhotoToPhotoSet invoked";
0388 
0389     /* If the photoset id starts with the special string "UNDEFINED_", it means
0390      * it doesn't exist yet on Flickr and needs to be created. Note that it's
0391      * not necessary to subsequently add the photo to the photo set, as this
0392      * is done in the set creation call to Flickr. */
0393     if (photoSetId.startsWith(QLatin1String("UNDEFINED_")))
0394     {
0395         createPhotoSet(QLatin1String(""), m_selectedPhotoSet.title, m_selectedPhotoSet.description, photoId);
0396     }
0397     else
0398     {
0399         QUrl url(m_apiUrl);
0400         QNetworkRequest netRequest(url);
0401         QList<O0RequestParameter> reqParams = QList<O0RequestParameter>();
0402 
0403         netRequest.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String(O2_MIME_TYPE_XFORM));
0404 
0405         reqParams << O0RequestParameter("method", "flickr.photosets.addPhoto");
0406         reqParams << O0RequestParameter("photoset_id", photoSetId.toLatin1());
0407         reqParams << O0RequestParameter("photo_id", photoId.toLatin1());
0408 
0409         QByteArray postData = O1::createQueryParameters(reqParams);
0410 
0411         m_reply = m_requestor->post(netRequest, reqParams, postData);
0412 
0413         m_state = FE_ADDPHOTOTOPHOTOSET;
0414         m_buffer.resize(0);
0415         Q_EMIT signalBusy(true);
0416     }
0417 }
0418 
0419 bool FlickrTalker::addPhoto(const QString& photoPath, const FPhotoInfo& info,
0420                             bool original, bool rescale, int maxDim, int imageQuality)
0421 {
0422     if (m_reply)
0423     {
0424         m_reply->abort();
0425         m_reply = nullptr;
0426     }
0427 
0428     if (!m_o1->linked())
0429         return false;
0430 
0431     QUrl url(m_uploadUrl);
0432     QNetworkRequest netRequest(url);
0433     QList<O0RequestParameter> reqParams = QList<O0RequestParameter>();
0434 
0435     QString path = photoPath;
0436     MPForm  form;
0437 
0438     QString ispublic = (info.is_public == 1) ? QLatin1String("1") : QLatin1String("0");
0439     form.addPair(QLatin1String("is_public"), ispublic, QLatin1String("text/plain"));
0440     reqParams << O0RequestParameter("is_public", ispublic.toLatin1());
0441 
0442     QString isfamily = (info.is_family == 1) ? QLatin1String("1") : QLatin1String("0");
0443     form.addPair(QLatin1String("is_family"), isfamily, QLatin1String("text/plain"));
0444     reqParams << O0RequestParameter("is_family", isfamily.toLatin1());
0445 
0446     QString isfriend = (info.is_friend == 1) ? QLatin1String("1") : QLatin1String("0");
0447     form.addPair(QLatin1String("is_friend"), isfriend, QLatin1String("text/plain"));
0448     reqParams << O0RequestParameter("is_friend", isfriend.toLatin1());
0449 
0450     QString safetyLevel = QString::number(static_cast<int>(info.safety_level));
0451     form.addPair(QLatin1String("safety_level"), safetyLevel, QLatin1String("text/plain"));
0452     reqParams << O0RequestParameter("safety_level", safetyLevel.toLatin1());
0453 
0454     QString contentType = QString::number(static_cast<int>(info.content_type));
0455     form.addPair(QLatin1String("content_type"), contentType, QLatin1String("text/plain"));
0456     reqParams << O0RequestParameter("content_type", contentType.toLatin1());
0457 
0458     QString tags = QLatin1String("\"") + info.tags.join(QLatin1String("\" \"")) + QLatin1String("\"");
0459 
0460     if (tags.length() > 0)
0461     {
0462         form.addPair(QLatin1String("tags"), tags, QLatin1String("text/plain"));
0463         reqParams << O0RequestParameter("tags", tags.toUtf8());
0464     }
0465 
0466     if (!info.title.isEmpty())
0467     {
0468         form.addPair(QLatin1String("title"), info.title, QLatin1String("text/plain"));
0469         reqParams << O0RequestParameter("title", info.title.toUtf8());
0470     }
0471 
0472     if (!info.description.isEmpty())
0473     {
0474         form.addPair(QLatin1String("description"), info.description, QLatin1String("text/plain"));
0475         reqParams << O0RequestParameter("description", info.description.toUtf8());
0476     }
0477 
0478     if (!original)
0479     {
0480         QImage image;
0481 
0482         if (m_iface)
0483         {
0484             image = m_iface->preview(QUrl::fromLocalFile(photoPath));
0485         }
0486 
0487         if (image.isNull())
0488         {
0489             image.load(photoPath);
0490         }
0491 
0492         if (!image.isNull())
0493         {
0494             if (!m_lastTmpFile.isEmpty())
0495             {
0496                 QFile::remove(m_lastTmpFile);
0497             }
0498 
0499             path = makeTemporaryDir(m_serviceName.toLatin1().constData()).filePath(QFileInfo(photoPath)
0500                                                                          .baseName().trimmed() + QLatin1String(".jpg"));
0501 
0502             if (rescale)
0503             {
0504                 if (image.width() > maxDim || image.height() > maxDim)
0505                     image = image.scaled(maxDim, maxDim, Qt::KeepAspectRatio, Qt::SmoothTransformation);
0506             }
0507 
0508             image.save(path, "JPEG", imageQuality);
0509             m_lastTmpFile = path;
0510 
0511             // Restore all metadata.
0512 
0513             if (m_iface)
0514             {
0515                 QPointer<MetadataProcessor> meta = m_iface->createMetadataProcessor();
0516 
0517                 if (meta && meta->load(QUrl::fromLocalFile(photoPath)))
0518                 {
0519                     meta->setImageDimensions(image.size());
0520                     meta->setImageOrientation(MetadataProcessor::NORMAL);
0521 
0522                     // NOTE: see bug #153207: Flickr use IPTC keywords to create Tags in web interface
0523                     //       As IPTC do not support UTF-8, we need to remove it.
0524                     //       This function call remove all Application2 Tags.
0525                     meta->removeIptcTags(QStringList() << QLatin1String("Application2"));
0526                     // NOTE: see bug # 384260: Flickr use Xmp.dc.subject to create Tags
0527                     //       in web interface, we need to remove it.
0528                     //       This function call remove all Dublin Core Tags.
0529                     meta->removeXmpTags(QStringList() << QLatin1String("dc"));
0530 
0531                     meta->setImageProgramId(QLatin1String("Kipi-plugins"), kipipluginsVersion());
0532                     meta->save(QUrl::fromLocalFile(path), true);
0533                 }
0534                 else
0535                 {
0536                     qCWarning(KIPIPLUGINS_LOG) << "flickrExport::Image doesn't have metadata";
0537                 }
0538             }
0539 
0540             qCDebug(KIPIPLUGINS_LOG) << "Resizing and saving to temp file: " << path;
0541         }
0542     }
0543 
0544     QFileInfo tempFileInfo(path);
0545 
0546     qCDebug(KIPIPLUGINS_LOG) << "QUrl path is " << QUrl::fromLocalFile(path) << "Image size (in bytes) is "<< tempFileInfo.size();
0547 
0548     if (tempFileInfo.size() > (getMaxAllowedFileSize().toLongLong()))
0549     {
0550         Q_EMIT signalAddPhotoFailed(i18n("File Size exceeds maximum allowed file size."));
0551         return false;
0552     }
0553 
0554     if (!form.addFile(QLatin1String("photo"), path))
0555     {
0556         return false;
0557     }
0558 
0559     form.finish();
0560 
0561     netRequest.setHeader(QNetworkRequest::ContentTypeHeader, form.contentType());
0562 
0563     m_reply = m_requestor->post(netRequest, reqParams, form.formData());
0564 
0565     m_state = FE_ADDPHOTO;
0566     m_buffer.resize(0);
0567     Q_EMIT signalBusy(true);
0568     return true;
0569 }
0570 
0571 QString FlickrTalker::getUserName() const
0572 {
0573     return m_username;
0574 }
0575 
0576 QString FlickrTalker::getUserId() const
0577 {
0578     return m_userId;
0579 }
0580 
0581 void FlickrTalker::cancel()
0582 {
0583     if (m_reply)
0584     {
0585         m_reply->abort();
0586         m_reply = nullptr;
0587     }
0588 
0589     if (m_authProgressDlg && !m_authProgressDlg->isHidden())
0590     {
0591         m_authProgressDlg->hide();
0592     }
0593 }
0594 
0595 void FlickrTalker::slotError(const QString& error)
0596 {
0597     QString transError;
0598     int errorNo = error.toInt();
0599 
0600     switch (errorNo)
0601     {
0602         case 2:
0603             transError = i18n("No photo specified");
0604             break;
0605 
0606         case 3:
0607             transError = i18n("General upload failure");
0608             break;
0609 
0610         case 4:
0611             transError = i18n("Filesize was zero");
0612             break;
0613 
0614         case 5:
0615             transError = i18n("Filetype was not recognized");
0616             break;
0617 
0618         case 6:
0619             transError = i18n("User exceeded upload limit");
0620             break;
0621 
0622         case 96:
0623             transError = i18n("Invalid signature");
0624             break;
0625 
0626         case 97:
0627             transError = i18n("Missing signature");
0628             break;
0629 
0630         case 98:
0631             transError = i18n("Login Failed / Invalid auth token");
0632             break;
0633 
0634         case 100:
0635             transError = i18n("Invalid API Key");
0636             break;
0637 
0638         case 105:
0639             transError = i18n("Service currently unavailable");
0640             break;
0641 
0642         case 108:
0643             transError = i18n("Invalid Frob");
0644             break;
0645 
0646         case 111:
0647             transError = i18n("Format \"xxx\" not found");
0648             break;
0649 
0650         case 112:
0651             transError = i18n("Method \"xxx\" not found");
0652             break;
0653 
0654         case 114:
0655             transError = i18n("Invalid SOAP envelope");
0656             break;
0657 
0658         case 115:
0659             transError = i18n("Invalid XML-RPC Method Call");
0660             break;
0661 
0662         case 116:
0663             transError = i18n("The POST method is now required for all setters");
0664             break;
0665 
0666         default:
0667             transError = i18n("Unknown error");
0668             break;
0669     };
0670 
0671     QMessageBox::critical(QApplication::activeWindow(),
0672                           i18n("Error"),
0673                           i18n("Error Occurred: %1\nCannot proceed any further.", transError));
0674 }
0675 
0676 void FlickrTalker::slotFinished(QNetworkReply* reply)
0677 {
0678     Q_EMIT signalBusy(false);
0679 
0680     if (reply != m_reply)
0681     {
0682         return;
0683     }
0684 
0685     m_reply = nullptr;
0686 
0687     if (reply->error() != QNetworkReply::NoError)
0688     {
0689         if (m_state == FE_ADDPHOTO)
0690         {
0691             Q_EMIT signalAddPhotoFailed(reply->errorString());
0692         }
0693         else
0694         {
0695             QMessageBox::critical(QApplication::activeWindow(),
0696                                   i18n("Error"), reply->errorString());
0697         }
0698 
0699         reply->deleteLater();
0700         return;
0701     }
0702 
0703     m_buffer.append(reply->readAll());
0704 
0705     switch (m_state)
0706     {
0707         case (FE_LOGIN):
0708             //parseResponseLogin(m_buffer);
0709             break;
0710 
0711         case (FE_LISTPHOTOSETS):
0712             parseResponseListPhotoSets(m_buffer);
0713             break;
0714 
0715         case (FE_LISTPHOTOS):
0716             parseResponseListPhotos(m_buffer);
0717             break;
0718 
0719         case (FE_GETPHOTOPROPERTY):
0720             parseResponsePhotoProperty(m_buffer);
0721             break;
0722 
0723         case (FE_ADDPHOTO):
0724             parseResponseAddPhoto(m_buffer);
0725             break;
0726 
0727         case (FE_ADDPHOTOTOPHOTOSET):
0728             parseResponseAddPhotoToPhotoSet(m_buffer);
0729             break;
0730 
0731         case (FE_CREATEPHOTOSET):
0732             parseResponseCreatePhotoSet(m_buffer);
0733             break;
0734 
0735         case (FE_GETMAXSIZE):
0736             parseResponseMaxSize(m_buffer);
0737             break;
0738 
0739         default:  // FR_LOGOUT
0740             break;
0741     }
0742 
0743     reply->deleteLater();
0744 }
0745 
0746 void FlickrTalker::parseResponseMaxSize(const QByteArray& data)
0747 {
0748     QString errorString;
0749     QDomDocument doc(QLatin1String("mydocument"));
0750 
0751     if (!doc.setContent(data))
0752     {
0753         return;
0754     }
0755 
0756     QDomElement docElem = doc.documentElement();
0757     QDomNode node       = docElem.firstChild();
0758 
0759     QDomElement e;
0760 
0761     while (!node.isNull())
0762     {
0763         if (node.isElement() && node.nodeName() == QLatin1String("person"))
0764         {
0765             e                = node.toElement();
0766             QDomNode details = e.firstChild();
0767 
0768             while (!details.isNull())
0769             {
0770                 if (details.isElement())
0771                 {
0772                     e = details.toElement();
0773 
0774                     if (details.nodeName() == QLatin1String("photos"))
0775                     {
0776                         QDomAttr a = e.attributeNode(QLatin1String("maxupload"));
0777                         m_maxSize = a.value();
0778                         qCDebug(KIPIPLUGINS_LOG) << "Max upload size is"<<m_maxSize;
0779                     }
0780                 }
0781 
0782                 details = details.nextSibling();
0783             }
0784         }
0785 
0786         if (node.isElement() && node.nodeName() == QLatin1String("err"))
0787         {
0788             qCDebug(KIPIPLUGINS_LOG) << "Checking Error in response";
0789             errorString = node.toElement().attribute(QLatin1String("code"));
0790             qCDebug(KIPIPLUGINS_LOG) << "Error code=" << errorString;
0791             qCDebug(KIPIPLUGINS_LOG) << "Msg=" << node.toElement().attribute(QLatin1String("msg"));
0792         }
0793 
0794         node = node.nextSibling();
0795     }
0796 
0797     m_authProgressDlg->hide();
0798 }
0799 
0800 void FlickrTalker::parseResponseCreatePhotoSet(const QByteArray& data)
0801 {
0802     qCDebug(KIPIPLUGINS_LOG) << "Parse response create photoset received " << data;
0803 
0804     //bool success = false;
0805 
0806     QDomDocument doc(QLatin1String("getListPhotoSets"));
0807 
0808     if (!doc.setContent(data))
0809     {
0810         return;
0811     }
0812 
0813     QDomElement docElem = doc.documentElement();
0814     QDomNode    node    = docElem.firstChild();
0815     QDomElement e;
0816 
0817     while (!node.isNull())
0818     {
0819         if (node.isElement() && node.nodeName() == QLatin1String("photoset"))
0820         {
0821             // Parse the id from the response.
0822             QString new_id = node.toElement().attribute(QLatin1String("id"));
0823 
0824             // Set the new id in the photo sets list.
0825             QLinkedList<FPhotoSet>::iterator it = m_photoSetsList->begin();
0826 
0827             while (it != m_photoSetsList->end())
0828             {
0829                 if (it->id == m_selectedPhotoSet.id)
0830                 {
0831                     it->id = new_id;
0832                     break;
0833                 }
0834 
0835                 ++it;
0836             }
0837 
0838             // Set the new id in the selected photo set.
0839             m_selectedPhotoSet.id = new_id;
0840 
0841             qCDebug(KIPIPLUGINS_LOG) << "PhotoSet created successfully with id" << new_id;
0842             Q_EMIT signalAddPhotoSetSucceeded();
0843         }
0844 
0845         if (node.isElement() && node.nodeName() == QLatin1String("err"))
0846         {
0847             qCDebug(KIPIPLUGINS_LOG) << "Checking Error in response";
0848             QString code = node.toElement().attribute(QLatin1String("code"));
0849             qCDebug(KIPIPLUGINS_LOG) << "Error code=" << code;
0850             QString msg = node.toElement().attribute(QLatin1String("msg"));
0851             qCDebug(KIPIPLUGINS_LOG) << "Msg=" << msg;
0852             QMessageBox::critical(QApplication::activeWindow(), i18n("Error"), i18n("PhotoSet creation failed: ") + msg);
0853         }
0854 
0855         node = node.nextSibling();
0856     }
0857 }
0858 
0859 void FlickrTalker::parseResponseListPhotoSets(const QByteArray& data)
0860 {
0861     qCDebug(KIPIPLUGINS_LOG) << "parseResponseListPhotosets" << data;
0862     bool success = false;
0863     QDomDocument doc(QLatin1String("getListPhotoSets"));
0864 
0865     if (!doc.setContent(data))
0866     {
0867         return;
0868     }
0869 
0870     QDomElement docElem = doc.documentElement();
0871     QDomNode    node    = docElem.firstChild();
0872     QDomElement e;
0873 
0874     QString photoSet_id, photoSet_title, photoSet_description;
0875     m_photoSetsList->clear();
0876 
0877     while (!node.isNull())
0878     {
0879         if (node.isElement() && node.nodeName() == QLatin1String("photosets"))
0880         {
0881             e                    = node.toElement();
0882             QDomNode details     = e.firstChild();
0883             FPhotoSet fps;
0884             QDomNode detailsNode = details;
0885 
0886             while (!detailsNode.isNull())
0887             {
0888                 if (detailsNode.isElement())
0889                 {
0890                     e = detailsNode.toElement();
0891 
0892                     if (detailsNode.nodeName() == QLatin1String("photoset"))
0893                     {
0894                         qCDebug(KIPIPLUGINS_LOG) << "id=" << e.attribute(QLatin1String("id"));
0895                         photoSet_id              = e.attribute(QLatin1String("id"));     // this is what is obtained from data.
0896                         fps.id                   = photoSet_id;
0897                         QDomNode photoSetDetails = detailsNode.firstChild();
0898                         QDomElement e_detail;
0899 
0900                         while (!photoSetDetails.isNull())
0901                         {
0902                             e_detail = photoSetDetails.toElement();
0903 
0904                             if (photoSetDetails.nodeName() == QLatin1String("title"))
0905                             {
0906                                 qCDebug(KIPIPLUGINS_LOG) << "Title=" << e_detail.text();
0907                                 photoSet_title = e_detail.text();
0908                                 fps.title      = photoSet_title;
0909                             }
0910                             else if (photoSetDetails.nodeName() == QLatin1String("description"))
0911                             {
0912                                 qCDebug(KIPIPLUGINS_LOG) << "Description =" << e_detail.text();
0913                                 photoSet_description = e_detail.text();
0914                                 fps.description      = photoSet_description;
0915                             }
0916 
0917                             photoSetDetails = photoSetDetails.nextSibling();
0918                         }
0919 
0920                         m_photoSetsList->append(fps);
0921                     }
0922                 }
0923 
0924                 detailsNode = detailsNode.nextSibling();
0925             }
0926 
0927             details = details.nextSibling();
0928             success = true;
0929         }
0930 
0931         if (node.isElement() && node.nodeName() == QLatin1String("err"))
0932         {
0933             qCDebug(KIPIPLUGINS_LOG) << "Checking Error in response";
0934             QString code = node.toElement().attribute(QLatin1String("code"));
0935             qCDebug(KIPIPLUGINS_LOG) << "Error code=" << code;
0936             qCDebug(KIPIPLUGINS_LOG) << "Msg=" << node.toElement().attribute(QLatin1String("msg"));
0937             Q_EMIT signalError(code);
0938         }
0939 
0940         node = node.nextSibling();
0941     }
0942 
0943     qCDebug(KIPIPLUGINS_LOG) << "GetPhotoList finished";
0944 
0945     if (!success)
0946     {
0947         Q_EMIT signalListPhotoSetsFailed(i18n("Failed to fetch list of photo sets."));
0948     }
0949     else
0950     {
0951         Q_EMIT signalListPhotoSetsSucceeded();
0952         maxAllowedFileSize();
0953     }
0954 }
0955 
0956 void FlickrTalker::parseResponseListPhotos(const QByteArray& data)
0957 {
0958     QDomDocument doc(QLatin1String("getPhotosList"));
0959 
0960     if (!doc.setContent(data))
0961     {
0962         return;
0963     }
0964 
0965     QDomElement docElem = doc.documentElement();
0966     QDomNode node       = docElem.firstChild();
0967     //QDomElement e;
0968     //TODO
0969 }
0970 
0971 void FlickrTalker::parseResponseCreateAlbum(const QByteArray& data)
0972 {
0973     QDomDocument doc(QLatin1String("getCreateAlbum"));
0974 
0975     if (!doc.setContent(data))
0976     {
0977         return;
0978     }
0979 
0980     QDomElement docElem = doc.documentElement();
0981     QDomNode node       = docElem.firstChild();
0982 
0983     //TODO
0984 }
0985 
0986 void FlickrTalker::parseResponseAddPhoto(const QByteArray& data)
0987 {
0988     bool    success = false;
0989     QString line;
0990     QDomDocument doc(QLatin1String("AddPhoto Response"));
0991 
0992     if (!doc.setContent(data))
0993     {
0994         return;
0995     }
0996 
0997     QDomElement docElem = doc.documentElement();
0998     QDomNode node       = docElem.firstChild();
0999     QDomElement e;
1000     QString photoId;
1001 
1002     while (!node.isNull())
1003     {
1004         if (node.isElement() && node.nodeName() == QLatin1String("photoid"))
1005         {
1006             e                = node.toElement();           // try to convert the node to an element.
1007             QDomNode details = e.firstChild();
1008             photoId          = e.text();
1009             qCDebug(KIPIPLUGINS_LOG) << "Photoid= " << photoId;
1010             success          = true;
1011         }
1012 
1013         if (node.isElement() && node.nodeName() == QLatin1String("err"))
1014         {
1015             qCDebug(KIPIPLUGINS_LOG) << "Checking Error in response";
1016             QString code = node.toElement().attribute(QLatin1String("code"));
1017             qCDebug(KIPIPLUGINS_LOG) << "Error code=" << code;
1018             qCDebug(KIPIPLUGINS_LOG) << "Msg=" << node.toElement().attribute(QLatin1String("msg"));
1019             Q_EMIT signalError(code);
1020         }
1021 
1022         node = node.nextSibling();
1023     }
1024 
1025     if (!success)
1026     {
1027         Q_EMIT signalAddPhotoFailed(i18n("Failed to upload photo"));
1028     }
1029     else
1030     {
1031         QString photoSetId = m_selectedPhotoSet.id;
1032 
1033         if (photoSetId == QLatin1String("-1"))
1034         {
1035             qCDebug(KIPIPLUGINS_LOG) << "PhotoSet Id not set, not adding the photo to any photoset";
1036             Q_EMIT signalAddPhotoSucceeded();
1037         }
1038         else
1039         {
1040             addPhotoToPhotoSet(photoId, photoSetId);
1041         }
1042     }
1043 }
1044 
1045 void FlickrTalker::parseResponsePhotoProperty(const QByteArray& data)
1046 {
1047     bool         success = false;
1048     QString      line;
1049     QDomDocument doc(QLatin1String("Photos Properties"));
1050 
1051     if (!doc.setContent(data))
1052     {
1053         return;
1054     }
1055 
1056     QDomElement docElem = doc.documentElement();
1057     QDomNode    node    = docElem.firstChild();
1058     QDomElement e;
1059 
1060     while (!node.isNull())
1061     {
1062         if (node.isElement() && node.nodeName() == QLatin1String("photoid"))
1063         {
1064             e                = node.toElement();                 // try to convert the node to an element.
1065             QDomNode details = e.firstChild();
1066             success          = true;
1067             qCDebug(KIPIPLUGINS_LOG) << "Photoid=" << e.text();
1068         }
1069 
1070         if (node.isElement() && node.nodeName() == QLatin1String("err"))
1071         {
1072             qCDebug(KIPIPLUGINS_LOG) << "Checking Error in response";
1073             QString code = node.toElement().attribute(QLatin1String("code"));
1074             qCDebug(KIPIPLUGINS_LOG) << "Error code=" << code;
1075             qCDebug(KIPIPLUGINS_LOG) << "Msg=" << node.toElement().attribute(QLatin1String("msg"));
1076             Q_EMIT signalError(code);
1077         }
1078 
1079         node = node.nextSibling();
1080     }
1081 
1082     qCDebug(KIPIPLUGINS_LOG) << "GetToken finished";
1083 
1084     if (!success)
1085     {
1086         Q_EMIT signalAddPhotoFailed(i18n("Failed to query photo information"));
1087     }
1088     else
1089     {
1090         Q_EMIT signalAddPhotoSucceeded();
1091     }
1092 }
1093 
1094 void FlickrTalker::parseResponseAddPhotoToPhotoSet(const QByteArray& data)
1095 {
1096     qCDebug(KIPIPLUGINS_LOG) << "parseResponseListPhotosets" << data;
1097     Q_EMIT signalAddPhotoSucceeded();
1098 }
1099 
1100 } // namespace KIPIFlickrPlugin