1 /* ============================================================
2  *
3  * This file is a part of KDE project
4  *
5  *
6  * Date        : 2005-07-07
7  * Description : a kipi plugin to export images to Flickr web service
8  *
9  * Copyright (C) 2005-2009 by Vardhman Jain <vardhman at gmail dot com>
10  * Copyright (C) 2009-2018 by Gilles Caulier <caulier dot gilles at gmail dot com>
11  * Copyright (C) 2017      by Maik Qualmann <metzpinguin at gmail dot com>
12  *
13  * This program is free software; you can redistribute it
14  * and/or modify it under the terms of the GNU General
15  * Public License as published by the Free Software Foundation;
16  * either version 2, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * ============================================================ */
24 
25 #include "flickrtalker.h"
26 
27 // Qt includes
28 
29 #include <QByteArray>
30 #include <QDomDocument>
31 #include <QDomElement>
32 #include <QFile>
33 #include <QFileInfo>
34 #include <QImage>
35 #include <QMap>
36 #include <QStringList>
37 #include <QProgressDialog>
38 #include <QStandardPaths>
39 #include <QApplication>
40 #include <QDesktopServices>
41 #include <QMessageBox>
42 
43 // Libkipi includes
44 
45 #include <KIPI/PluginLoader>
46 
47 // Local includes
48 
49 #include "kputil.h"
50 #include "kpversion.h"
51 #include "mpform.h"
52 #include "flickritem.h"
53 #include "flickrwindow.h"
54 #include "kipiplugins_debug.h"
55 
56 using namespace KIPIPlugins;
57 
58 namespace KIPIFlickrPlugin
59 {
60 
FlickrTalker(QWidget * const parent,const QString & serviceName)61 FlickrTalker::FlickrTalker(QWidget* const parent, const QString& serviceName)
62 {
63     m_parent          = parent;
64     m_netMngr         = nullptr;
65     m_reply           = nullptr;
66     m_settings        = nullptr;
67     m_photoSetsList   = nullptr;
68     m_authProgressDlg = nullptr;
69     m_state           = FE_LOGOUT;
70     m_serviceName     = serviceName;
71     m_iface           = nullptr;
72     m_o1              = nullptr;
73     m_store           = nullptr;
74     m_requestor       = nullptr;
75 
76     PluginLoader* const pl = PluginLoader::instance();
77 
78     if (pl)
79     {
80         m_iface = pl->interface();
81     }
82 
83     if (serviceName == QLatin1String("23"))
84     {
85         m_apiUrl    = QLatin1String("http://www.23hq.com/services/rest/");
86         m_authUrl   = QLatin1String("http://www.23hq.com/services/auth/");
87         m_uploadUrl = QLatin1String("http://www.23hq.com/services/upload/");
88 
89         // bshanks: do 23 and flickr really share API keys? or does 23 not need
90         // one?
91         m_apikey    = QLatin1String("49d585bafa0758cb5c58ab67198bf632");
92         m_secret    = QLatin1String("34b39925e6273ffd");
93     }
94     else
95     {
96         m_apiUrl    = QLatin1String("https://www.flickr.com/services/rest/");
97         m_authUrl   = QLatin1String("https://www.flickr.com/services/oauth/authorize?perms=write");
98         m_tokenUrl  = QLatin1String("https://www.flickr.com/services/oauth/request_token");
99         m_accessUrl = QLatin1String("https://www.flickr.com/services/oauth/access_token");
100         m_uploadUrl = QLatin1String("https://up.flickr.com/services/upload/");
101 
102         m_apikey    = QLatin1String("49d585bafa0758cb5c58ab67198bf632");
103         m_secret    = QLatin1String("34b39925e6273ffd");
104     }
105 
106     m_netMngr = new QNetworkAccessManager(this);
107 
108     connect(m_netMngr, SIGNAL(finished(QNetworkReply*)),
109             this, SLOT(slotFinished(QNetworkReply*)));
110 
111     /* Initialize selected photo set as empty. */
112     m_selectedPhotoSet = FPhotoSet();
113     /* Initialize photo sets list. */
114     m_photoSetsList    = new QLinkedList<FPhotoSet>();
115 
116     m_o1 = new O1(this);
117 
118     m_o1->setClientId(m_apikey);
119     m_o1->setClientSecret(m_secret);
120     m_o1->setAuthorizeUrl(QUrl(m_authUrl));
121     m_o1->setAccessTokenUrl(QUrl(m_accessUrl));
122     m_o1->setRequestTokenUrl(QUrl(m_tokenUrl));
123 
124     QString kipioauth = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1String("/kipioauthrc");
125 
126     m_settings = new QSettings(kipioauth, QSettings::IniFormat, this);
127     m_store    = new O0SettingsStore(m_settings, QLatin1String(O2_ENCRYPTION_KEY), this);
128     m_store->setGroupKey(m_serviceName);
129     m_o1->setStore(m_store);
130 
131     connect(m_o1, SIGNAL(linkingFailed()),
132             this, SLOT(slotLinkingFailed()));
133 
134     connect(m_o1, SIGNAL(linkingSucceeded()),
135             this, SLOT(slotLinkingSucceeded()));
136 
137     connect(m_o1, SIGNAL(openBrowser(QUrl)),
138             this, SLOT(slotOpenBrowser(QUrl)));
139 
140     m_requestor = new O1Requestor(m_netMngr, m_o1, this);
141 }
142 
~FlickrTalker()143 FlickrTalker::~FlickrTalker()
144 {
145     if (m_reply)
146     {
147         m_reply->abort();
148     }
149 
150     delete m_photoSetsList;
151 
152     removeTemporaryDir(m_serviceName.toLatin1().constData());
153 }
154 
link(const QString & userName)155 void FlickrTalker::link(const QString& userName)
156 {
157     emit signalBusy(true);
158 
159     if (userName.isEmpty())
160     {
161         m_store->setGroupKey(m_serviceName);
162     }
163     else
164     {
165         m_store->setGroupKey(m_serviceName + userName);
166     }
167 
168     m_o1->link();
169 }
170 
unLink()171 void FlickrTalker::unLink()
172 {
173     m_o1->unlink();
174 }
175 
removeUserName(const QString & userName)176 void FlickrTalker::removeUserName(const QString& userName)
177 {
178     if (userName.startsWith(m_serviceName))
179     {
180         m_settings->beginGroup(userName);
181         m_settings->remove(QString());
182         m_settings->endGroup();
183     }
184 }
185 
slotLinkingFailed()186 void FlickrTalker::slotLinkingFailed()
187 {
188     qCDebug(KIPIPLUGINS_LOG) << "LINK to Flickr fail";
189     m_username = QString();
190     emit signalBusy(false);
191 }
192 
slotLinkingSucceeded()193 void FlickrTalker::slotLinkingSucceeded()
194 {
195     if (!m_o1->linked())
196     {
197         qCDebug(KIPIPLUGINS_LOG) << "UNLINK to Flickr ok";
198         m_username = QString();
199         return;
200     }
201 
202     qCDebug(KIPIPLUGINS_LOG) << "LINK to Flickr ok";
203 
204     m_username = m_o1->extraTokens()[QLatin1String("username")].toString();
205     m_userId   = m_o1->extraTokens()[QLatin1String("user_nsid")].toString();
206 
207     if (m_store->groupKey() == m_serviceName)
208     {
209         m_settings->beginGroup(m_serviceName);
210         QStringList keys = m_settings->allKeys();
211         m_settings->endGroup();
212 
213         foreach(const QString& key, keys)
214         {
215             m_settings->beginGroup(m_serviceName);
216             QVariant value = m_settings->value(key);
217             m_settings->endGroup();
218             m_settings->beginGroup(m_serviceName + m_username);
219             m_settings->setValue(key, value);
220             m_settings->endGroup();
221         }
222 
223         m_store->setGroupKey(m_serviceName + m_username);
224         removeUserName(m_serviceName);
225     }
226 
227     emit signalLinkingSucceeded();
228 }
229 
slotOpenBrowser(const QUrl & url)230 void FlickrTalker::slotOpenBrowser(const QUrl& url)
231 {
232     qCDebug(KIPIPLUGINS_LOG) << "Open Browser...";
233     QDesktopServices::openUrl(url);
234 }
235 
getMaxAllowedFileSize()236 QString FlickrTalker::getMaxAllowedFileSize()
237 {
238     return m_maxSize;
239 }
240 
maxAllowedFileSize()241 void FlickrTalker::maxAllowedFileSize()
242 {
243     if (m_reply)
244     {
245         m_reply->abort();
246         m_reply = nullptr;
247     }
248 
249     if (!m_o1->linked())
250         return;
251 
252     QUrl url(m_apiUrl);
253     QNetworkRequest netRequest(url);
254     QList<O0RequestParameter> reqParams = QList<O0RequestParameter>();
255 
256     netRequest.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String(O2_MIME_TYPE_XFORM));
257 
258     reqParams << O0RequestParameter("method", "flickr.people.getLimits");
259 
260     QByteArray postData = O1::createQueryParameters(reqParams);
261 
262     m_reply = m_requestor->post(netRequest, reqParams, postData);
263 
264     m_state = FE_GETMAXSIZE;
265     m_authProgressDlg->setLabelText(i18n("Getting the maximum allowed file size."));
266     m_authProgressDlg->setMaximum(4);
267     m_authProgressDlg->setValue(1);
268     m_buffer.resize(0);
269     emit signalBusy(true);
270 }
271 
listPhotoSets()272 void FlickrTalker::listPhotoSets()
273 {
274     if (m_reply)
275     {
276         m_reply->abort();
277         m_reply = nullptr;
278     }
279 
280     if (!m_o1->linked())
281         return;
282 
283     qCDebug(KIPIPLUGINS_LOG) << "List photoset invoked";
284 
285     QUrl url(m_apiUrl);
286     QNetworkRequest netRequest(url);
287     QList<O0RequestParameter> reqParams = QList<O0RequestParameter>();
288 
289     netRequest.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String(O2_MIME_TYPE_XFORM));
290 
291     reqParams << O0RequestParameter("method", "flickr.photosets.getList");
292 
293     QByteArray postData = O1::createQueryParameters(reqParams);
294 
295     m_reply = m_requestor->post(netRequest, reqParams, postData);
296 
297     m_state = FE_LISTPHOTOSETS;
298     m_buffer.resize(0);
299     emit signalBusy(true);
300 }
301 
getPhotoProperty(const QString & method,const QStringList & argList)302 void FlickrTalker::getPhotoProperty(const QString& method, const QStringList& argList)
303 {
304     if (m_reply)
305     {
306         m_reply->abort();
307         m_reply = nullptr;
308     }
309 
310     if (!m_o1->linked())
311         return;
312 
313     QUrl url(m_apiUrl);
314     QNetworkRequest netRequest(url);
315     QList<O0RequestParameter> reqParams = QList<O0RequestParameter>();
316 
317     netRequest.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String(O2_MIME_TYPE_XFORM));
318 
319     reqParams << O0RequestParameter("method", method.toLatin1());
320 
321     for (QStringList::const_iterator it = argList.constBegin(); it != argList.constEnd(); ++it)
322     {
323         QStringList str = (*it).split(QLatin1Char('='), QString::SkipEmptyParts);
324         reqParams << O0RequestParameter(str[0].toLatin1(), str[1].toLatin1());
325     }
326 
327     QByteArray postData = O1::createQueryParameters(reqParams);
328 
329     m_reply = m_requestor->post(netRequest, reqParams, postData);
330 
331     m_state = FE_GETPHOTOPROPERTY;
332     m_buffer.resize(0);
333     emit signalBusy(true);
334 }
335 
listPhotos(const QString &)336 void FlickrTalker::listPhotos(const QString& /*albumName*/)
337 {
338     // TODO
339 }
340 
createPhotoSet(const QString &,const QString & albumTitle,const QString & albumDescription,const QString & primaryPhotoId)341 void FlickrTalker::createPhotoSet(const QString& /*albumName*/, const QString& albumTitle,
342                                   const QString& albumDescription, const QString& primaryPhotoId)
343 {
344     if (m_reply)
345     {
346         m_reply->abort();
347         m_reply = nullptr;
348     }
349 
350     if (!m_o1->linked())
351         return;
352 
353     qCDebug(KIPIPLUGINS_LOG) << "Create photoset invoked";
354 
355     QUrl url(m_apiUrl);
356     QNetworkRequest netRequest(url);
357     QList<O0RequestParameter> reqParams = QList<O0RequestParameter>();
358 
359     netRequest.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String(O2_MIME_TYPE_XFORM));
360 
361     reqParams << O0RequestParameter("method", "flickr.photosets.create");
362     reqParams << O0RequestParameter("title", albumTitle.toLatin1());
363     reqParams << O0RequestParameter("description", albumDescription.toLatin1());
364     reqParams << O0RequestParameter("primary_photo_id", primaryPhotoId.toLatin1());
365 
366     QByteArray postData = O1::createQueryParameters(reqParams);
367 
368     m_reply = m_requestor->post(netRequest, reqParams, postData);
369 
370     m_state = FE_CREATEPHOTOSET;
371     m_buffer.resize(0);
372     emit signalBusy(true);
373 }
374 
addPhotoToPhotoSet(const QString & photoId,const QString & photoSetId)375 void FlickrTalker::addPhotoToPhotoSet(const QString& photoId,
376                                       const QString& photoSetId)
377 {
378     if (m_reply)
379     {
380         m_reply->abort();
381         m_reply = nullptr;
382     }
383 
384     if (!m_o1->linked())
385         return;
386 
387     qCDebug(KIPIPLUGINS_LOG) << "AddPhotoToPhotoSet invoked";
388 
389     /* If the photoset id starts with the special string "UNDEFINED_", it means
390      * it doesn't exist yet on Flickr and needs to be created. Note that it's
391      * not necessary to subsequently add the photo to the photo set, as this
392      * is done in the set creation call to Flickr. */
393     if (photoSetId.startsWith(QLatin1String("UNDEFINED_")))
394     {
395         createPhotoSet(QLatin1String(""), m_selectedPhotoSet.title, m_selectedPhotoSet.description, photoId);
396     }
397     else
398     {
399         QUrl url(m_apiUrl);
400         QNetworkRequest netRequest(url);
401         QList<O0RequestParameter> reqParams = QList<O0RequestParameter>();
402 
403         netRequest.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String(O2_MIME_TYPE_XFORM));
404 
405         reqParams << O0RequestParameter("method", "flickr.photosets.addPhoto");
406         reqParams << O0RequestParameter("photoset_id", photoSetId.toLatin1());
407         reqParams << O0RequestParameter("photo_id", photoId.toLatin1());
408 
409         QByteArray postData = O1::createQueryParameters(reqParams);
410 
411         m_reply = m_requestor->post(netRequest, reqParams, postData);
412 
413         m_state = FE_ADDPHOTOTOPHOTOSET;
414         m_buffer.resize(0);
415         emit signalBusy(true);
416     }
417 }
418 
addPhoto(const QString & photoPath,const FPhotoInfo & info,bool original,bool rescale,int maxDim,int imageQuality)419 bool FlickrTalker::addPhoto(const QString& photoPath, const FPhotoInfo& info,
420                             bool original, bool rescale, int maxDim, int imageQuality)
421 {
422     if (m_reply)
423     {
424         m_reply->abort();
425         m_reply = nullptr;
426     }
427 
428     if (!m_o1->linked())
429         return false;
430 
431     QUrl url(m_uploadUrl);
432     QNetworkRequest netRequest(url);
433     QList<O0RequestParameter> reqParams = QList<O0RequestParameter>();
434 
435     QString path = photoPath;
436     MPForm  form;
437 
438     QString ispublic = (info.is_public == 1) ? QLatin1String("1") : QLatin1String("0");
439     form.addPair(QLatin1String("is_public"), ispublic, QLatin1String("text/plain"));
440     reqParams << O0RequestParameter("is_public", ispublic.toLatin1());
441 
442     QString isfamily = (info.is_family == 1) ? QLatin1String("1") : QLatin1String("0");
443     form.addPair(QLatin1String("is_family"), isfamily, QLatin1String("text/plain"));
444     reqParams << O0RequestParameter("is_family", isfamily.toLatin1());
445 
446     QString isfriend = (info.is_friend == 1) ? QLatin1String("1") : QLatin1String("0");
447     form.addPair(QLatin1String("is_friend"), isfriend, QLatin1String("text/plain"));
448     reqParams << O0RequestParameter("is_friend", isfriend.toLatin1());
449 
450     QString safetyLevel = QString::number(static_cast<int>(info.safety_level));
451     form.addPair(QLatin1String("safety_level"), safetyLevel, QLatin1String("text/plain"));
452     reqParams << O0RequestParameter("safety_level", safetyLevel.toLatin1());
453 
454     QString contentType = QString::number(static_cast<int>(info.content_type));
455     form.addPair(QLatin1String("content_type"), contentType, QLatin1String("text/plain"));
456     reqParams << O0RequestParameter("content_type", contentType.toLatin1());
457 
458     QString tags = QLatin1String("\"") + info.tags.join(QLatin1String("\" \"")) + QLatin1String("\"");
459 
460     if (tags.length() > 0)
461     {
462         form.addPair(QLatin1String("tags"), tags, QLatin1String("text/plain"));
463         reqParams << O0RequestParameter("tags", tags.toUtf8());
464     }
465 
466     if (!info.title.isEmpty())
467     {
468         form.addPair(QLatin1String("title"), info.title, QLatin1String("text/plain"));
469         reqParams << O0RequestParameter("title", info.title.toUtf8());
470     }
471 
472     if (!info.description.isEmpty())
473     {
474         form.addPair(QLatin1String("description"), info.description, QLatin1String("text/plain"));
475         reqParams << O0RequestParameter("description", info.description.toUtf8());
476     }
477 
478     if (!original)
479     {
480         QImage image;
481 
482         if (m_iface)
483         {
484             image = m_iface->preview(QUrl::fromLocalFile(photoPath));
485         }
486 
487         if (image.isNull())
488         {
489             image.load(photoPath);
490         }
491 
492         if (!image.isNull())
493         {
494             if (!m_lastTmpFile.isEmpty())
495             {
496                 QFile::remove(m_lastTmpFile);
497             }
498 
499             path = makeTemporaryDir(m_serviceName.toLatin1().constData()).filePath(QFileInfo(photoPath)
500                                                                          .baseName().trimmed() + QLatin1String(".jpg"));
501 
502             if (rescale)
503             {
504                 if (image.width() > maxDim || image.height() > maxDim)
505                     image = image.scaled(maxDim, maxDim, Qt::KeepAspectRatio, Qt::SmoothTransformation);
506             }
507 
508             image.save(path, "JPEG", imageQuality);
509             m_lastTmpFile = path;
510 
511             // Restore all metadata.
512 
513             if (m_iface)
514             {
515                 QPointer<MetadataProcessor> meta = m_iface->createMetadataProcessor();
516 
517                 if (meta && meta->load(QUrl::fromLocalFile(photoPath)))
518                 {
519                     meta->setImageDimensions(image.size());
520                     meta->setImageOrientation(MetadataProcessor::NORMAL);
521 
522                     // NOTE: see bug #153207: Flickr use IPTC keywords to create Tags in web interface
523                     //       As IPTC do not support UTF-8, we need to remove it.
524                     //       This function call remove all Application2 Tags.
525                     meta->removeIptcTags(QStringList() << QLatin1String("Application2"));
526                     // NOTE: see bug # 384260: Flickr use Xmp.dc.subject to create Tags
527                     //       in web interface, we need to remove it.
528                     //       This function call remove all Dublin Core Tags.
529                     meta->removeXmpTags(QStringList() << QLatin1String("dc"));
530 
531                     meta->setImageProgramId(QLatin1String("Kipi-plugins"), kipipluginsVersion());
532                     meta->save(QUrl::fromLocalFile(path), true);
533                 }
534                 else
535                 {
536                     qCWarning(KIPIPLUGINS_LOG) << "flickrExport::Image doesn't have metadata";
537                 }
538             }
539 
540             qCDebug(KIPIPLUGINS_LOG) << "Resizing and saving to temp file: " << path;
541         }
542     }
543 
544     QFileInfo tempFileInfo(path);
545 
546     qCDebug(KIPIPLUGINS_LOG) << "QUrl path is " << QUrl::fromLocalFile(path) << "Image size (in bytes) is "<< tempFileInfo.size();
547 
548     if (tempFileInfo.size() > (getMaxAllowedFileSize().toLongLong()))
549     {
550         emit signalAddPhotoFailed(i18n("File Size exceeds maximum allowed file size."));
551         return false;
552     }
553 
554     if (!form.addFile(QLatin1String("photo"), path))
555     {
556         return false;
557     }
558 
559     form.finish();
560 
561     netRequest.setHeader(QNetworkRequest::ContentTypeHeader, form.contentType());
562 
563     m_reply = m_requestor->post(netRequest, reqParams, form.formData());
564 
565     m_state = FE_ADDPHOTO;
566     m_buffer.resize(0);
567     emit signalBusy(true);
568     return true;
569 }
570 
getUserName() const571 QString FlickrTalker::getUserName() const
572 {
573     return m_username;
574 }
575 
getUserId() const576 QString FlickrTalker::getUserId() const
577 {
578     return m_userId;
579 }
580 
cancel()581 void FlickrTalker::cancel()
582 {
583     if (m_reply)
584     {
585         m_reply->abort();
586         m_reply = nullptr;
587     }
588 
589     if (m_authProgressDlg && !m_authProgressDlg->isHidden())
590     {
591         m_authProgressDlg->hide();
592     }
593 }
594 
slotError(const QString & error)595 void FlickrTalker::slotError(const QString& error)
596 {
597     QString transError;
598     int errorNo = error.toInt();
599 
600     switch (errorNo)
601     {
602         case 2:
603             transError = i18n("No photo specified");
604             break;
605 
606         case 3:
607             transError = i18n("General upload failure");
608             break;
609 
610         case 4:
611             transError = i18n("Filesize was zero");
612             break;
613 
614         case 5:
615             transError = i18n("Filetype was not recognized");
616             break;
617 
618         case 6:
619             transError = i18n("User exceeded upload limit");
620             break;
621 
622         case 96:
623             transError = i18n("Invalid signature");
624             break;
625 
626         case 97:
627             transError = i18n("Missing signature");
628             break;
629 
630         case 98:
631             transError = i18n("Login Failed / Invalid auth token");
632             break;
633 
634         case 100:
635             transError = i18n("Invalid API Key");
636             break;
637 
638         case 105:
639             transError = i18n("Service currently unavailable");
640             break;
641 
642         case 108:
643             transError = i18n("Invalid Frob");
644             break;
645 
646         case 111:
647             transError = i18n("Format \"xxx\" not found");
648             break;
649 
650         case 112:
651             transError = i18n("Method \"xxx\" not found");
652             break;
653 
654         case 114:
655             transError = i18n("Invalid SOAP envelope");
656             break;
657 
658         case 115:
659             transError = i18n("Invalid XML-RPC Method Call");
660             break;
661 
662         case 116:
663             transError = i18n("The POST method is now required for all setters");
664             break;
665 
666         default:
667             transError = i18n("Unknown error");
668             break;
669     };
670 
671     QMessageBox::critical(QApplication::activeWindow(),
672                           i18n("Error"),
673                           i18n("Error Occurred: %1\nCannot proceed any further.", transError));
674 }
675 
slotFinished(QNetworkReply * reply)676 void FlickrTalker::slotFinished(QNetworkReply* reply)
677 {
678     emit signalBusy(false);
679 
680     if (reply != m_reply)
681     {
682         return;
683     }
684 
685     m_reply = nullptr;
686 
687     if (reply->error() != QNetworkReply::NoError)
688     {
689         if (m_state == FE_ADDPHOTO)
690         {
691             emit signalAddPhotoFailed(reply->errorString());
692         }
693         else
694         {
695             QMessageBox::critical(QApplication::activeWindow(),
696                                   i18n("Error"), reply->errorString());
697         }
698 
699         reply->deleteLater();
700         return;
701     }
702 
703     m_buffer.append(reply->readAll());
704 
705     switch (m_state)
706     {
707         case (FE_LOGIN):
708             //parseResponseLogin(m_buffer);
709             break;
710 
711         case (FE_LISTPHOTOSETS):
712             parseResponseListPhotoSets(m_buffer);
713             break;
714 
715         case (FE_LISTPHOTOS):
716             parseResponseListPhotos(m_buffer);
717             break;
718 
719         case (FE_GETPHOTOPROPERTY):
720             parseResponsePhotoProperty(m_buffer);
721             break;
722 
723         case (FE_ADDPHOTO):
724             parseResponseAddPhoto(m_buffer);
725             break;
726 
727         case (FE_ADDPHOTOTOPHOTOSET):
728             parseResponseAddPhotoToPhotoSet(m_buffer);
729             break;
730 
731         case (FE_CREATEPHOTOSET):
732             parseResponseCreatePhotoSet(m_buffer);
733             break;
734 
735         case (FE_GETMAXSIZE):
736             parseResponseMaxSize(m_buffer);
737             break;
738 
739         default:  // FR_LOGOUT
740             break;
741     }
742 
743     reply->deleteLater();
744 }
745 
parseResponseMaxSize(const QByteArray & data)746 void FlickrTalker::parseResponseMaxSize(const QByteArray& data)
747 {
748     QString errorString;
749     QDomDocument doc(QLatin1String("mydocument"));
750 
751     if (!doc.setContent(data))
752     {
753         return;
754     }
755 
756     QDomElement docElem = doc.documentElement();
757     QDomNode node       = docElem.firstChild();
758 
759     QDomElement e;
760 
761     while (!node.isNull())
762     {
763         if (node.isElement() && node.nodeName() == QLatin1String("person"))
764         {
765             e                = node.toElement();
766             QDomNode details = e.firstChild();
767 
768             while (!details.isNull())
769             {
770                 if (details.isElement())
771                 {
772                     e = details.toElement();
773 
774                     if (details.nodeName() == QLatin1String("photos"))
775                     {
776                         QDomAttr a = e.attributeNode(QLatin1String("maxupload"));
777                         m_maxSize = a.value();
778                         qCDebug(KIPIPLUGINS_LOG) << "Max upload size is"<<m_maxSize;
779                     }
780                 }
781 
782                 details = details.nextSibling();
783             }
784         }
785 
786         if (node.isElement() && node.nodeName() == QLatin1String("err"))
787         {
788             qCDebug(KIPIPLUGINS_LOG) << "Checking Error in response";
789             errorString = node.toElement().attribute(QLatin1String("code"));
790             qCDebug(KIPIPLUGINS_LOG) << "Error code=" << errorString;
791             qCDebug(KIPIPLUGINS_LOG) << "Msg=" << node.toElement().attribute(QLatin1String("msg"));
792         }
793 
794         node = node.nextSibling();
795     }
796 
797     m_authProgressDlg->hide();
798 }
799 
parseResponseCreatePhotoSet(const QByteArray & data)800 void FlickrTalker::parseResponseCreatePhotoSet(const QByteArray& data)
801 {
802     qCDebug(KIPIPLUGINS_LOG) << "Parse response create photoset received " << data;
803 
804     //bool success = false;
805 
806     QDomDocument doc(QLatin1String("getListPhotoSets"));
807 
808     if (!doc.setContent(data))
809     {
810         return;
811     }
812 
813     QDomElement docElem = doc.documentElement();
814     QDomNode    node    = docElem.firstChild();
815     QDomElement e;
816 
817     while (!node.isNull())
818     {
819         if (node.isElement() && node.nodeName() == QLatin1String("photoset"))
820         {
821             // Parse the id from the response.
822             QString new_id = node.toElement().attribute(QLatin1String("id"));
823 
824             // Set the new id in the photo sets list.
825             QLinkedList<FPhotoSet>::iterator it = m_photoSetsList->begin();
826 
827             while (it != m_photoSetsList->end())
828             {
829                 if (it->id == m_selectedPhotoSet.id)
830                 {
831                     it->id = new_id;
832                     break;
833                 }
834 
835                 ++it;
836             }
837 
838             // Set the new id in the selected photo set.
839             m_selectedPhotoSet.id = new_id;
840 
841             qCDebug(KIPIPLUGINS_LOG) << "PhotoSet created successfully with id" << new_id;
842             emit signalAddPhotoSetSucceeded();
843         }
844 
845         if (node.isElement() && node.nodeName() == QLatin1String("err"))
846         {
847             qCDebug(KIPIPLUGINS_LOG) << "Checking Error in response";
848             QString code = node.toElement().attribute(QLatin1String("code"));
849             qCDebug(KIPIPLUGINS_LOG) << "Error code=" << code;
850             QString msg = node.toElement().attribute(QLatin1String("msg"));
851             qCDebug(KIPIPLUGINS_LOG) << "Msg=" << msg;
852             QMessageBox::critical(QApplication::activeWindow(), i18n("Error"), i18n("PhotoSet creation failed: ") + msg);
853         }
854 
855         node = node.nextSibling();
856     }
857 }
858 
parseResponseListPhotoSets(const QByteArray & data)859 void FlickrTalker::parseResponseListPhotoSets(const QByteArray& data)
860 {
861     qCDebug(KIPIPLUGINS_LOG) << "parseResponseListPhotosets" << data;
862     bool success = false;
863     QDomDocument doc(QLatin1String("getListPhotoSets"));
864 
865     if (!doc.setContent(data))
866     {
867         return;
868     }
869 
870     QDomElement docElem = doc.documentElement();
871     QDomNode    node    = docElem.firstChild();
872     QDomElement e;
873 
874     QString photoSet_id, photoSet_title, photoSet_description;
875     m_photoSetsList->clear();
876 
877     while (!node.isNull())
878     {
879         if (node.isElement() && node.nodeName() == QLatin1String("photosets"))
880         {
881             e                    = node.toElement();
882             QDomNode details     = e.firstChild();
883             FPhotoSet fps;
884             QDomNode detailsNode = details;
885 
886             while (!detailsNode.isNull())
887             {
888                 if (detailsNode.isElement())
889                 {
890                     e = detailsNode.toElement();
891 
892                     if (detailsNode.nodeName() == QLatin1String("photoset"))
893                     {
894                         qCDebug(KIPIPLUGINS_LOG) << "id=" << e.attribute(QLatin1String("id"));
895                         photoSet_id              = e.attribute(QLatin1String("id"));     // this is what is obtained from data.
896                         fps.id                   = photoSet_id;
897                         QDomNode photoSetDetails = detailsNode.firstChild();
898                         QDomElement e_detail;
899 
900                         while (!photoSetDetails.isNull())
901                         {
902                             e_detail = photoSetDetails.toElement();
903 
904                             if (photoSetDetails.nodeName() == QLatin1String("title"))
905                             {
906                                 qCDebug(KIPIPLUGINS_LOG) << "Title=" << e_detail.text();
907                                 photoSet_title = e_detail.text();
908                                 fps.title      = photoSet_title;
909                             }
910                             else if (photoSetDetails.nodeName() == QLatin1String("description"))
911                             {
912                                 qCDebug(KIPIPLUGINS_LOG) << "Description =" << e_detail.text();
913                                 photoSet_description = e_detail.text();
914                                 fps.description      = photoSet_description;
915                             }
916 
917                             photoSetDetails = photoSetDetails.nextSibling();
918                         }
919 
920                         m_photoSetsList->append(fps);
921                     }
922                 }
923 
924                 detailsNode = detailsNode.nextSibling();
925             }
926 
927             details = details.nextSibling();
928             success = true;
929         }
930 
931         if (node.isElement() && node.nodeName() == QLatin1String("err"))
932         {
933             qCDebug(KIPIPLUGINS_LOG) << "Checking Error in response";
934             QString code = node.toElement().attribute(QLatin1String("code"));
935             qCDebug(KIPIPLUGINS_LOG) << "Error code=" << code;
936             qCDebug(KIPIPLUGINS_LOG) << "Msg=" << node.toElement().attribute(QLatin1String("msg"));
937             emit signalError(code);
938         }
939 
940         node = node.nextSibling();
941     }
942 
943     qCDebug(KIPIPLUGINS_LOG) << "GetPhotoList finished";
944 
945     if (!success)
946     {
947         emit signalListPhotoSetsFailed(i18n("Failed to fetch list of photo sets."));
948     }
949     else
950     {
951         emit signalListPhotoSetsSucceeded();
952         maxAllowedFileSize();
953     }
954 }
955 
parseResponseListPhotos(const QByteArray & data)956 void FlickrTalker::parseResponseListPhotos(const QByteArray& data)
957 {
958     QDomDocument doc(QLatin1String("getPhotosList"));
959 
960     if (!doc.setContent(data))
961     {
962         return;
963     }
964 
965     QDomElement docElem = doc.documentElement();
966     QDomNode node       = docElem.firstChild();
967     //QDomElement e;
968     //TODO
969 }
970 
parseResponseCreateAlbum(const QByteArray & data)971 void FlickrTalker::parseResponseCreateAlbum(const QByteArray& data)
972 {
973     QDomDocument doc(QLatin1String("getCreateAlbum"));
974 
975     if (!doc.setContent(data))
976     {
977         return;
978     }
979 
980     QDomElement docElem = doc.documentElement();
981     QDomNode node       = docElem.firstChild();
982 
983     //TODO
984 }
985 
parseResponseAddPhoto(const QByteArray & data)986 void FlickrTalker::parseResponseAddPhoto(const QByteArray& data)
987 {
988     bool    success = false;
989     QString line;
990     QDomDocument doc(QLatin1String("AddPhoto Response"));
991 
992     if (!doc.setContent(data))
993     {
994         return;
995     }
996 
997     QDomElement docElem = doc.documentElement();
998     QDomNode node       = docElem.firstChild();
999     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             emit signalError(code);
1020         }
1021 
1022         node = node.nextSibling();
1023     }
1024 
1025     if (!success)
1026     {
1027         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             emit signalAddPhotoSucceeded();
1037         }
1038         else
1039         {
1040             addPhotoToPhotoSet(photoId, photoSetId);
1041         }
1042     }
1043 }
1044 
parseResponsePhotoProperty(const QByteArray & data)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             emit signalError(code);
1077         }
1078 
1079         node = node.nextSibling();
1080     }
1081 
1082     qCDebug(KIPIPLUGINS_LOG) << "GetToken finished";
1083 
1084     if (!success)
1085     {
1086         emit signalAddPhotoFailed(i18n("Failed to query photo information"));
1087     }
1088     else
1089     {
1090         emit signalAddPhotoSucceeded();
1091     }
1092 }
1093 
parseResponseAddPhotoToPhotoSet(const QByteArray & data)1094 void FlickrTalker::parseResponseAddPhotoToPhotoSet(const QByteArray& data)
1095 {
1096     qCDebug(KIPIPLUGINS_LOG) << "parseResponseListPhotosets" << data;
1097     emit signalAddPhotoSucceeded();
1098 }
1099 
1100 } // namespace KIPIFlickrPlugin
1101