File indexing completed on 2025-01-05 03:53:25

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2008-12-26
0007  * Description : a tool to export items to Facebook web service
0008  *
0009  * SPDX-FileCopyrightText: 2008-2010 by Luka Renko <lure at kubuntu dot org>
0010  * SPDX-FileCopyrightText: 2011      by Dirk Tilger <dirk dot kde at miriup dot de>
0011  * SPDX-FileCopyrightText: 2008-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0012  * SPDX-FileCopyrightText: 2018      by Thanh Trung Dinh <dinhthanhtrung1996 at gmail dot com>
0013  *
0014  * SPDX-License-Identifier: GPL-2.0-or-later
0015  *
0016  * ============================================================ */
0017 
0018 #include "fbtalker_wizard.h"
0019 
0020 // Qt includes
0021 
0022 #include <QJsonDocument>
0023 #include <QJsonParseError>
0024 #include <QJsonObject>
0025 #include <QJsonValue>
0026 #include <QJsonArray>
0027 #include <QByteArray>
0028 #include <QDomDocument>
0029 #include <QDomElement>
0030 #include <QtAlgorithms>
0031 #include <QVBoxLayout>
0032 #include <QLineEdit>
0033 #include <QDesktopServices>
0034 #include <QApplication>
0035 #include <QPushButton>
0036 #include <QDialog>
0037 #include <QDialogButtonBox>
0038 #include <QUrlQuery>
0039 #include <QMessageBox>
0040 #include <QNetworkAccessManager>
0041 
0042 // Local includes
0043 
0044 #include "digikam_version.h"
0045 #include "fbmpform.h"
0046 #include "fbnewalbumdlg.h"
0047 #include "digikam_debug.h"
0048 #include "o0settingsstore.h"
0049 #include "wstoolutils.h"
0050 
0051 namespace DigikamGenericFaceBookPlugin
0052 {
0053 
0054 bool operator< (const FbUser& first, const FbUser& second)
0055 {
0056     return first.name < second.name;
0057 }
0058 
0059 bool operator< (const FbAlbum& first, const FbAlbum& second)
0060 {
0061     return first.title < second.title;
0062 }
0063 
0064 // -----------------------------------------------------------------------------
0065 
0066 class Q_DECL_HIDDEN FbTalker::Private
0067 {
0068 
0069 public:
0070 
0071     explicit Private(WSNewAlbumDialog* albumDlg)
0072       : dialog(0),
0073         parent(0),
0074         apiURL(QLatin1String("https://graph.facebook.com/%1/%2")),
0075         authUrl(QLatin1String("https://www.facebook.com/dialog/oauth")),
0076         tokenUrl(QLatin1String("https://graph.facebook.com/oauth/access_token")),
0077         scope(QLatin1String("user_photos,publish_pages,manage_pages")), //publish_to_groups,user_friends not necessary?
0078         apikey(QLatin1String("400589753481372")),
0079         clientSecret(QLatin1String("5b0b5cd096e110cd4f4c72f517e2c544")),
0080         loginInProgress(false),
0081         albumDlg(dynamic_cast<FbNewAlbumDlg*>(albumDlg)),
0082         o2(0)
0083     {
0084     }
0085 
0086     QDialog*               dialog;
0087     QWidget*               parent;
0088 
0089     QString                apiURL;
0090     QString                authUrl;
0091     QString                tokenUrl;
0092     QString                scope;
0093     QString                apikey;
0094     QString                clientSecret;
0095 
0096     bool                   loginInProgress;
0097 
0098     FbUser                 user;
0099     FbNewAlbumDlg* const   albumDlg; // Pointer to FbNewAlbumDlg* const so that no modification can impact this pointer
0100 
0101     //Ported to O2 here
0102     O2*                    o2;
0103 };
0104 
0105 // -----------------------------------------------------------------------------
0106 
0107 FbTalker::FbTalker(QWidget* const parent, WSNewAlbumDialog* albumDlg)
0108     : WSTalker(parent),
0109       d(new Private(albumDlg))
0110 {
0111     d->parent = parent;
0112 
0113     //TODO: Ported to O2 here
0114 
0115     d->o2     = new O2(this);
0116 
0117     d->o2->setClientId(d->apikey);
0118     d->o2->setClientSecret(d->clientSecret);
0119 
0120     d->o2->setRequestUrl(d->authUrl);
0121     d->o2->setTokenUrl(d->tokenUrl);
0122     d->o2->setRefreshTokenUrl(d->tokenUrl);
0123     d->o2->setLocalhostPolicy(QLatin1String("https://www.facebook.com/connect/login_success.html"));
0124     d->o2->setUseExternalWebInterceptor(true);
0125     d->o2->setLocalPort(8000);
0126     d->o2->setGrantFlow(O2::GrantFlow::GrantFlowImplicit);
0127     d->o2->setScope(d->scope);
0128 
0129     m_store->setGroupKey(QLatin1String("Facebook"));
0130     d->o2->setStore(m_store);
0131 
0132     connect(d->o2, SIGNAL(linkingFailed()),
0133             this, SLOT(slotLinkingFailed()));
0134 
0135     connect(d->o2, SIGNAL(linkingSucceeded()),
0136             this, SLOT(slotLinkingSucceeded()));
0137 
0138     connect(d->o2, SIGNAL(openBrowser(QUrl)),
0139             this, SLOT(slotOpenBrowser(QUrl)));
0140 
0141     connect(d->o2, SIGNAL(closeBrowser()),
0142             this, SLOT(slotCloseBrowser()));
0143 }
0144 
0145 FbTalker::~FbTalker()
0146 {
0147     if (m_reply)
0148     {
0149         m_reply->abort();
0150     }
0151 
0152     delete d;
0153 }
0154 
0155 //TODO: Ported to O2 here
0156 // ----------------------------------------------------------------------------------------------
0157 void FbTalker::link()
0158 {
0159     Q_EMIT signalBusy(true);
0160 
0161     d->loginInProgress = true;
0162     d->o2->link();
0163 }
0164 
0165 void FbTalker::unlink()
0166 {
0167     Q_EMIT signalBusy(true);
0168     d->o2->unlink();
0169 }
0170 
0171 void FbTalker::slotResponseTokenReceived(const QMap<QString, QString>& rep)
0172 {
0173     d->o2->onVerificationReceived(rep);
0174 }
0175 
0176 bool FbTalker::linked() const
0177 {
0178     return d->o2->linked();
0179 }
0180 
0181 void FbTalker::resetTalker(const QString& expire, const QString& accessToken, const QString& refreshToken)
0182 {
0183     m_store->setValue(QString::fromUtf8(O2_KEY_EXPIRES).arg(d->apikey), expire);
0184     m_store->setValue(QString::fromUtf8(O2_KEY_LINKED).arg(d->apikey), QLatin1String("1"));
0185     m_store->setValue(QString::fromUtf8(O2_KEY_REFRESH_TOKEN).arg(d->apikey), refreshToken);
0186     m_store->setValue(QString::fromUtf8(O2_KEY_TOKEN).arg(d->apikey), accessToken);
0187 }
0188 
0189 FbUser FbTalker::getUser() const
0190 {
0191     return d->user;
0192 }
0193 
0194 void FbTalker::authenticate()
0195 {
0196     d->loginInProgress = true;
0197     Q_EMIT signalLoginProgress(2, 9, i18n("Validate previous session..."));
0198 
0199     WSTalker::authenticate();
0200 }
0201 
0202 void FbTalker::getLoggedInUser()
0203 {
0204     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "getLoggedInUser called ";
0205 
0206     if (m_reply)
0207     {
0208         m_reply->abort();
0209         m_reply = 0;
0210     }
0211 
0212     Q_EMIT signalBusy(true);
0213     Q_EMIT signalLoginProgress(3);
0214 
0215     QUrl url(d->apiURL.arg(QLatin1String("me"))
0216                       .arg(QString()));
0217     QUrlQuery q;
0218 //     q.addQueryItem(QLatin1String("fields"), QLatin1String("id,name,link"));
0219     q.addQueryItem(QLatin1String("access_token"), d->o2->token());
0220     url.setQuery(q);
0221 
0222     QNetworkRequest netRequest(url);
0223     netRequest.setHeader(QNetworkRequest::ContentTypeHeader,
0224                         QLatin1String("application/x-www-form-urlencoded"));
0225 
0226     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "url = " << netRequest.url();
0227     m_reply = m_netMngr->get(netRequest);
0228 
0229     m_state = WSTalker::GETUSER;
0230 }
0231 
0232 // ----------------------------------------------------------------------------------------------
0233 
0234 /** Compute MD5 signature using url queries keys and values:
0235  *  wiki.developers.facebook.com/index.php/How_Facebook_Authenticates_Your_Application
0236  *  This method was used for the legacy authentication scheme and has been obsoleted with OAuth2 authentication.
0237  */
0238 /*
0239 QString FbTalker::getApiSig(const QMap<QString, QString>& args)
0240 {
0241     QString concat;
0242     // NOTE: QMap iterator will sort alphabetically
0243 
0244     for (QMap<QString, QString>::const_iterator it = args.constBegin() ;
0245          it != args.constEnd() ; ++it)
0246     {
0247         concat.append(it.key());
0248         concat.append("=");
0249         concat.append(it.value());
0250     }
0251 
0252     if (args["session_key"].isEmpty())
0253         concat.append(d->clientSecret);
0254     else
0255         concat.append(d->sessionSecret);
0256 
0257     KMD5 md5(concat.toUtf8());
0258     return md5.hexDigest().data();
0259 }
0260 */
0261 
0262 void FbTalker::logout()
0263 {
0264     if (m_reply)
0265     {
0266         m_reply->abort();
0267         m_reply = 0;
0268     }
0269 
0270     QMap<QString, QString> args;
0271     args[QLatin1String("next")]         = QLatin1String("https://www.digikam.org");
0272     args[QLatin1String("access_token")] = d->o2->token();
0273 
0274     QUrl url(QLatin1String("https://www.facebook.com/logout.php"));
0275     QUrlQuery q;
0276     q.addQueryItem(QLatin1String("next"), QLatin1String("https://www.digikam.org"));
0277     q.addQueryItem(QLatin1String("access_token"), d->o2->token());
0278     url.setQuery(q);
0279     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Logout URL: " << url;
0280     QDesktopServices::openUrl(url);
0281 
0282     Q_EMIT signalBusy(false);
0283 }
0284 
0285 //TODO: Ported to O2
0286 //----------------------------------------------------------------------------------------------------
0287 
0288 void FbTalker::listAlbums(long long userID)
0289 {
0290     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Requesting albums for user " << userID;
0291 
0292     if (m_reply)
0293     {
0294         m_reply->abort();
0295         m_reply = 0;
0296     }
0297 
0298     Q_EMIT signalBusy(true);
0299 
0300     QUrl url;
0301 
0302     /*
0303      * If userID is specified, load albums of that user,
0304      * else load albums of current user
0305      */
0306     if (!userID)
0307     {
0308         url = QUrl(d->apiURL.arg(d->user.id)
0309                             .arg(QLatin1String("albums")));
0310     }
0311     else
0312     {
0313         url = QUrl(d->apiURL.arg(userID)
0314                             .arg(QLatin1String("albums")));
0315     }
0316 
0317     QUrlQuery q;
0318     q.addQueryItem(QLatin1String("fields"),
0319                     QLatin1String("id,name,description,privacy,link,location"));
0320     q.addQueryItem(QLatin1String("access_token"), d->o2->token());
0321     url.setQuery(q);
0322 
0323     QNetworkRequest netRequest(url);
0324     netRequest.setHeader(QNetworkRequest::ContentTypeHeader,
0325                             QLatin1String("application/x-www-form-urlencoded"));
0326 
0327     m_reply = m_netMngr->get(netRequest);
0328 
0329     m_state = WSTalker::LISTALBUMS;
0330 }
0331 
0332 void FbTalker::createAlbum(const FbAlbum& album)
0333 {
0334     if (m_reply)
0335     {
0336         m_reply->abort();
0337         m_reply = 0;
0338     }
0339 
0340     Q_EMIT signalBusy(true);
0341 
0342     QUrlQuery params;
0343     params.addQueryItem(QLatin1String("access_token"), d->o2->token());
0344     params.addQueryItem(QLatin1String("name"), album.title);
0345 
0346     if (!album.location.isEmpty())
0347         params.addQueryItem(QLatin1String("location"), album.location);
0348     /*
0349      * description is deprecated and now a param of message
0350      */
0351     if (!album.description.isEmpty())
0352         params.addQueryItem(QLatin1String("message"), album.description);
0353 
0354     // TODO (Dirk): Wasn't that a requested feature in Bugzilla?
0355     switch (album.privacy)
0356     {
0357         case FB_ME:
0358             params.addQueryItem(QLatin1String("privacy"), QLatin1String("{'value':'SELF'}"));
0359             break;
0360         case FB_FRIENDS:
0361             params.addQueryItem(QLatin1String("privacy"), QLatin1String("{'value':'ALL_FRIENDS'}"));
0362             break;
0363         case FB_FRIENDS_OF_FRIENDS:
0364             params.addQueryItem(QLatin1String("privacy"), QLatin1String("{'value':'FRIENDS_OF_FRIENDS'}"));
0365             break;
0366         case FB_EVERYONE:
0367             params.addQueryItem(QLatin1String("privacy"), QLatin1String("{'value':'EVERYONE'}"));
0368             break;
0369         case FB_CUSTOM:
0370             //TODO
0371             params.addQueryItem(QLatin1String("privacy"), QLatin1String("{'value':'CUSTOM'}"));
0372             break;
0373     }
0374 
0375     QUrl url(QUrl(d->apiURL.arg(d->user.id)
0376                            .arg(QLatin1String("albums"))));
0377 //     url.setQuery(params);
0378 
0379     QNetworkRequest netRequest(url);
0380     netRequest.setHeader(QNetworkRequest::ContentTypeHeader,
0381                         QLatin1String("application/x-www-form-urlencoded"));
0382 
0383     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "url to create new album " << netRequest.url() << params.query();
0384 
0385     m_reply = m_netMngr->post(netRequest, params.query().toUtf8());
0386 
0387     m_state = WSTalker::CREATEALBUM;
0388 }
0389 
0390 void FbTalker::createNewAlbum()
0391 {
0392     FbAlbum album;
0393     d->albumDlg->getAlbumProperties(album);
0394     createAlbum(album);
0395 }
0396 
0397 void FbTalker::addPhoto(const QString& imgPath, const QString& albumID, const QString& caption)
0398 {
0399     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Adding photo " << imgPath << " to album with id "
0400                                      << albumID << " using caption '" << caption << "'";
0401 
0402     if (m_reply)
0403     {
0404         m_reply->abort();
0405         m_reply = 0;
0406     }
0407 
0408     Q_EMIT signalBusy(true);
0409 
0410     QMap<QString, QString> args;
0411     args[QLatin1String("access_token")] = d->o2->token();
0412 
0413     if (!caption.isEmpty())
0414         args[QLatin1String("message")]  = caption;
0415 
0416     FbMPForm form;
0417 
0418     for (QMap<QString, QString>::const_iterator it = args.constBegin() ;
0419         it != args.constEnd() ; ++it)
0420     {
0421         form.addPair(it.key(), it.value());
0422     }
0423 
0424     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "FORM: " << QT_ENDL << form.formData();
0425 
0426     if (!form.addFile(QUrl::fromLocalFile(imgPath).fileName(), imgPath))
0427     {
0428         Q_EMIT signalAddPhotoDone(666, i18n("Cannot open file"));
0429         Q_EMIT signalBusy(false);
0430         return;
0431     }
0432 
0433     form.finish();
0434 
0435     QVariant arg_1;
0436 
0437     if (albumID.isEmpty())
0438     {
0439         arg_1 = d->user.id;
0440     }
0441     else
0442     {
0443         arg_1 = albumID;
0444     }
0445 
0446     QNetworkRequest netRequest(QUrl(d->apiURL.arg(arg_1.toString()).arg(QLatin1String("photos"))));
0447     netRequest.setHeader(QNetworkRequest::ContentTypeHeader, form.contentType());
0448 
0449     m_reply = m_netMngr->post(netRequest, form.formData());
0450 
0451     m_state = WSTalker::ADDPHOTO;
0452 }
0453 
0454 //----------------------------------------------------------------------------------------------------
0455 
0456 QString FbTalker::errorToText(int errCode, const QString& errMsg)
0457 {
0458     QString transError;
0459     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "errorToText: " << errCode << ": " << errMsg;
0460 
0461     switch (errCode)
0462     {
0463         case 0:
0464             transError = QLatin1String("");
0465             break;
0466         case 2:
0467             transError = i18n("The service is not available at this time.");
0468             break;
0469         case 4:
0470             transError = i18n("The application has reached the maximum number of requests allowed.");
0471             break;
0472         case 102:
0473             transError = i18n("Invalid session key or session expired. Try to log in again.");
0474             break;
0475         case 120:
0476             transError = i18n("Invalid album ID.");
0477             break;
0478         case 321:
0479             transError = i18n("Album is full.");
0480             break;
0481         case 324:
0482             transError = i18n("Missing or invalid file.");
0483             break;
0484         case 325:
0485             transError = i18n("Too many unapproved photos pending.");
0486             break;
0487         default:
0488             transError = errMsg;
0489             break;
0490     }
0491 
0492     return transError;
0493 }
0494 
0495 /*
0496  * (Trung) This has to be adapted in slotFinished in WSTalker
0497  *
0498 void FbTalker::slotFinished(QNetworkReply* reply)
0499 {
0500     if (reply != m_reply)
0501     {
0502         return;
0503     }
0504 
0505     m_reply = 0;
0506 
0507     if (reply->error() != QNetworkReply::NoError)
0508     {
0509         if (d->loginInProgress)
0510         {
0511             authenticationDone(reply->error(), reply->errorString());
0512         }
0513         else if (d->state == Private::FB_ADDPHOTO)
0514         {
0515             Q_EMIT signalBusy(false);
0516             Q_EMIT signalAddPhotoDone(reply->error(), reply->errorString());
0517         }
0518         else
0519         {
0520             Q_EMIT signalBusy(false);
0521             QMessageBox::critical(QApplication::activeWindow(),
0522                                   i18nc("@title:window", "Error"), reply->errorString());
0523         }
0524 
0525         qCDebug(DIGIKAM_WEBSERVICES_LOG) << reply->error() << " text :"<< QString(reply->readAll());
0526 
0527         reply->deleteLater();
0528         return;
0529     }
0530 
0531     m_buffer.append(reply->readAll());
0532 
0533     switch (d->state)
0534     {
0535         case (Private::FB_GETLOGGEDINUSER):
0536             parseResponseGetLoggedInUser(m_buffer);
0537             break;
0538         case (Private::FB_LISTALBUMS):
0539             parseResponseListAlbums(m_buffer);
0540             break;
0541         case (Private::FB_CREATEALBUM):
0542             parseResponseCreateAlbum(m_buffer);
0543             break;
0544         case (Private::FB_ADDPHOTO):
0545             parseResponseAddPhoto(m_buffer);
0546             break;
0547     }
0548 
0549     reply->deleteLater();
0550 }
0551 */
0552 
0553 void FbTalker::authenticationDone(int errCode, const QString& errMsg)
0554 {
0555     if (errCode != 0)
0556     {
0557         d->user.clear();
0558     }
0559     else
0560     {
0561         saveUserAccount(d->user.name, d->user.id, d->o2->expires(), d->o2->token(), d->o2->refreshToken());
0562     }
0563 
0564     Q_EMIT signalLoginDone(errCode, errMsg);
0565     d->loginInProgress = false;
0566 
0567     WSTalker::authenticationDone(errCode, errMsg);
0568 }
0569 
0570 int FbTalker::parseErrorResponse(const QDomElement& e, QString& errMsg)
0571 {
0572     int errCode = -1;
0573 
0574     for (QDomNode node = e.firstChild() ;
0575          !node.isNull() ; node = node.nextSibling())
0576     {
0577         if (!node.isElement())
0578             continue;
0579 
0580         if (node.nodeName() == QLatin1String("error_code"))
0581         {
0582             errCode = node.toElement().text().toInt();
0583             qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Error Code:" << errCode;
0584         }
0585         else if (node.nodeName() == QLatin1String("error_msg"))
0586         {
0587             errMsg = node.toElement().text();
0588             qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Error Text:" << errMsg;
0589         }
0590     }
0591 
0592     return errCode;
0593 }
0594 
0595 //TODO: Port to O2
0596 void FbTalker::parseResponseGetLoggedInUser(const QByteArray& data)
0597 {
0598     QString errMsg;
0599     QJsonParseError err;
0600     QJsonDocument doc = QJsonDocument::fromJson(data, &err);
0601 
0602     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Logged in data " << doc;
0603 
0604     if (err.error != QJsonParseError::NoError)
0605     {
0606         Q_EMIT signalBusy(false);
0607         return;
0608     }
0609 
0610     QJsonObject jsonObject = doc.object();
0611     d->user.id             = jsonObject[QLatin1String("id")].toString();
0612 
0613     if (!(QString::compare(jsonObject[QLatin1String("id")].toString(), QLatin1String(""), Qt::CaseInsensitive) == 0))
0614     {
0615         qCDebug(DIGIKAM_WEBSERVICES_LOG) << "ID found in response of GetLoggedInUser";
0616     }
0617 
0618     d->user.name       = jsonObject[QLatin1String("name")].toString();
0619     m_userName         = d->user.name;
0620 
0621     d->user.profileURL = jsonObject[QLatin1String("link")].toString();
0622 }
0623 
0624 void FbTalker::parseResponseAddPhoto(const QByteArray& data)
0625 {
0626     qCDebug(DIGIKAM_WEBSERVICES_LOG) <<"Parse Add Photo data is "<<data;
0627     int errCode       = -1;
0628     QString errMsg;
0629     QJsonParseError err;
0630     QJsonDocument doc = QJsonDocument::fromJson(data, &err);
0631 
0632     if (err.error != QJsonParseError::NoError)
0633     {
0634         Q_EMIT signalBusy(false);
0635         return;
0636     }
0637 
0638     QJsonObject jsonObject = doc.object();
0639 
0640     if (jsonObject.contains(QLatin1String("id")))
0641     {
0642         qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Id of photo exported is" << jsonObject[QLatin1String("id")].toString();
0643         errCode = 0;
0644     }
0645 
0646     if (jsonObject.contains(QLatin1String("error")))
0647     {
0648         QJsonObject obj = jsonObject[QLatin1String("error")].toObject();
0649         errCode         = obj[QLatin1String("code")].toInt();
0650         errMsg          = obj[QLatin1String("message")].toString();
0651     }
0652 
0653     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "add photo : " << doc;
0654 
0655     Q_EMIT signalBusy(false);
0656     Q_EMIT signalAddPhotoDone(errCode, errorToText(errCode, errMsg));
0657 }
0658 
0659 void FbTalker::parseResponseCreateAlbum(const QByteArray& data)
0660 {
0661     qCDebug(DIGIKAM_WEBSERVICES_LOG) <<"Parse Create album data is"<<data;
0662     int errCode       = -1;
0663     QString errMsg;
0664     QString newAlbumID;
0665     QJsonParseError err;
0666     QJsonDocument doc = QJsonDocument::fromJson(data, &err);
0667 
0668     if (err.error != QJsonParseError::NoError)
0669     {
0670         Q_EMIT signalBusy(false);
0671         return;
0672     }
0673 
0674     QJsonObject jsonObject = doc.object();
0675 
0676     if (jsonObject.contains(QLatin1String("id")))
0677     {
0678         newAlbumID = jsonObject[QLatin1String("id")].toString();
0679         qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Id of album created is" << newAlbumID;
0680         errCode    = 0;
0681     }
0682 
0683     if (jsonObject.contains(QLatin1String("error")))
0684     {
0685         QJsonObject obj = jsonObject[QLatin1String("error")].toObject();
0686         errCode         = obj[QLatin1String("code")].toInt();
0687         errMsg          = obj[QLatin1String("message")].toString();
0688     }
0689 
0690     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "error create photo : " << doc;
0691 
0692     Q_EMIT signalBusy(false);
0693     Q_EMIT signalCreateAlbumDone(errCode, errorToText(errCode, errMsg),
0694                                newAlbumID);
0695 }
0696 
0697 void FbTalker::parseResponseListAlbums(const QByteArray& data)
0698 {
0699     int errCode = -1;
0700     QString errMsg;
0701     QJsonParseError err;
0702     QList<WSAlbum> albumsList; // QList <FbAlbum> albumsList;
0703     QJsonDocument doc = QJsonDocument::fromJson(data, &err);
0704 
0705     if (err.error != QJsonParseError::NoError)
0706     {
0707         Q_EMIT signalBusy(false);
0708         return;
0709     }
0710 
0711     QJsonObject jsonObject = doc.object();
0712 
0713     if (jsonObject.contains(QLatin1String("data")))
0714     {
0715         QJsonArray jsonArray = jsonObject[QLatin1String("data")].toArray();
0716 
0717         Q_FOREACH (const QJsonValue& value, jsonArray)
0718         {
0719             QJsonObject obj   = value.toObject();
0720             WSAlbum album; //FbAlbum album;
0721             album.id          = obj[QLatin1String("id")].toString();
0722             album.title       = obj[QLatin1String("name")].toString();
0723             album.location    = obj[QLatin1String("location")].toString();
0724             album.url         = obj[QLatin1String("link")].toString();
0725             album.description = obj[QLatin1String("description")].toString();
0726             album.uploadable  = obj[QLatin1String("can_upload")].toBool();
0727 
0728             qCDebug(DIGIKAM_WEBSERVICES_LOG) << "can_upload " << album.uploadable;
0729 /*
0730             if (QString::compare(obj[QLatin1String("privacy")].toString(),
0731                                  QLatin1String("ALL_FRIENDS"), Qt::CaseInsensitive) == 0)
0732             {
0733                 album.privacy = FB_FRIENDS;
0734             }
0735             else if (QString::compare(obj[QLatin1String("privacy")].toString(),
0736                                       QLatin1String("FRIENDS_OF_FRIENDS"), Qt::CaseInsensitive) == 0)
0737             {
0738                 album.privacy = FB_FRIENDS;
0739             }
0740             else if (QString::compare(obj[QLatin1String("privacy")].toString(),
0741                                       QLatin1String("EVERYONE"), Qt::CaseInsensitive) == 0)
0742             {
0743                 album.privacy = FB_EVERYONE;
0744             }
0745             else if (QString::compare(obj[QLatin1String("privacy")].toString(),
0746                                       QLatin1String("CUSTOM"), Qt::CaseInsensitive) == 0)
0747             {
0748                 album.privacy = FB_CUSTOM;
0749             }
0750             else if (QString::compare(obj[QLatin1String("privacy")].toString(),
0751                                       QLatin1String("SELF"), Qt::CaseInsensitive) == 0)
0752             {
0753                 album.privacy = FB_ME;
0754             }
0755 */
0756             albumsList.append(album);
0757         }
0758 
0759         errCode = 0;
0760     }
0761 
0762     if (jsonObject.contains(QLatin1String("error")))
0763     {
0764         QJsonObject obj = jsonObject[QLatin1String("error")].toObject();
0765         errCode         = obj[QLatin1String("code")].toInt();
0766         errMsg          = obj[QLatin1String("message")].toString();
0767     }
0768 
0769     /* std::sort(albumsList.begin(), albumsList.end());
0770      * This function is replaced by method below which is defined in WSTalker as a virtual method for further evolution if needed
0771      */
0772     sortAlbumsList(albumsList);
0773 
0774     Q_EMIT signalBusy(false);
0775     Q_EMIT signalListAlbumsDone(errCode, errorToText(errCode, errMsg),
0776                               albumsList);
0777 }
0778 
0779 } // namespace DigikamGenericFaceBookPlugin
0780 
0781 #include "moc_fbtalker_wizard.cpp"