File indexing completed on 2023-10-03 07:22:42
0001 /* ============================================================ 0002 * 0003 * This file is a part of KDE project 0004 * 0005 * 0006 * Date : 2008-12-26 0007 * Description : a kipi plugin to export images to Facebook web service 0008 * 0009 * Copyright (C) 2008-2010 by Luka Renko <lure at kubuntu dot org> 0010 * Copyright (c) 2011 by Dirk Tilger <dirk.kde@miriup.de> 0011 * 0012 * This program is free software; you can redistribute it 0013 * and/or modify it under the terms of the GNU General 0014 * Public License as published by the Free Software Foundation; 0015 * either version 2, or (at your option) any later version. 0016 * 0017 * This program is distributed in the hope that it will be useful, 0018 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0019 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0020 * GNU General Public License for more details. 0021 * 0022 * ============================================================ */ 0023 0024 #include "fbtalker.h" 0025 0026 // C++ includes 0027 0028 #include <ctime> 0029 0030 // Qt includes 0031 0032 #include <QJsonDocument> 0033 #include <QJsonParseError> 0034 #include <QJsonObject> 0035 #include <QJsonValue> 0036 #include <QJsonArray> 0037 #include <QByteArray> 0038 #include <QDomDocument> 0039 #include <QDomElement> 0040 #include <QtAlgorithms> 0041 #include <QVBoxLayout> 0042 #include <QLineEdit> 0043 #include <QPlainTextEdit> 0044 #include <QList> 0045 #include <QDesktopServices> 0046 #include <QApplication> 0047 #include <QPushButton> 0048 #include <QDialog> 0049 #include <QDialogButtonBox> 0050 #include <QUrlQuery> 0051 #include <QMessageBox> 0052 0053 // Local includes 0054 0055 #include "kpversion.h" 0056 #include "fbitem.h" 0057 #include "mpform.h" 0058 #include "kipiplugins_debug.h" 0059 0060 namespace KIPIFacebookPlugin 0061 { 0062 0063 bool operator< (const FbUser& first, const FbUser& second) 0064 { 0065 return first.name < second.name; 0066 } 0067 0068 bool operator< (const FbAlbum& first, const FbAlbum& second) 0069 { 0070 return first.title < second.title; 0071 } 0072 0073 // ----------------------------------------------------------------------------- 0074 0075 FbTalker::FbTalker(QWidget* const parent) 0076 { 0077 m_parent = parent; 0078 m_loginInProgress = 0; 0079 m_sessionExpires = 0; 0080 m_state = FB_GETLOGGEDINUSER; 0081 0082 m_apiVersion = QString::fromLatin1("2.4"); 0083 m_apiURL = QUrl(QString::fromLatin1("https://graph.facebook.com")); 0084 m_secretKey = QString::fromLatin1("5b0b5cd096e110cd4f4c72f517e2c544"); 0085 m_appID = QString::fromLatin1("400589753481372"); 0086 m_dialog = nullptr; 0087 m_reply = nullptr; 0088 0089 m_netMngr = new QNetworkAccessManager(this); 0090 0091 connect(m_netMngr, SIGNAL(finished(QNetworkReply*)), 0092 this, SLOT(slotFinished(QNetworkReply*))); 0093 } 0094 0095 FbTalker::~FbTalker() 0096 { 0097 // do not logout - may reuse session for next upload 0098 0099 if (m_reply) 0100 { 0101 m_reply->abort(); 0102 } 0103 } 0104 0105 bool FbTalker::loggedIn() const 0106 { 0107 return !m_accessToken.isEmpty(); 0108 } 0109 0110 QString FbTalker::getAccessToken() const 0111 { 0112 return m_accessToken; 0113 } 0114 0115 unsigned int FbTalker::getSessionExpires() const 0116 { 0117 return m_sessionExpires; 0118 } 0119 0120 FbUser FbTalker::getUser() const 0121 { 0122 return m_user; 0123 } 0124 0125 void FbTalker::cancel() 0126 { 0127 if (m_reply) 0128 { 0129 m_reply->abort(); 0130 m_reply = nullptr; 0131 } 0132 0133 Q_EMIT signalBusy(false); 0134 } 0135 0136 /** Compute MD5 signature using url queries keys and values: 0137 http://wiki.developers.facebook.com/index.php/How_Facebook_Authenticates_Your_Application 0138 This method was used for the legacy authentication scheme and has been obsoleted with OAuth2 authentication. 0139 */ 0140 /* 0141 QString FbTalker::getApiSig(const QMap<QString, QString>& args) 0142 { 0143 QString concat; 0144 // NOTE: QMap iterator will sort alphabetically 0145 for (QMap<QString, QString>::const_iterator it = args.constBegin(); 0146 it != args.constEnd(); 0147 ++it) 0148 { 0149 concat.append(it.key()); 0150 concat.append("="); 0151 concat.append(it.value()); 0152 } 0153 if (args["session_key"].isEmpty()) 0154 concat.append(m_secretKey); 0155 else 0156 concat.append(m_sessionSecret); 0157 0158 KMD5 md5(concat.toUtf8()); 0159 return md5.hexDigest().data(); 0160 } 0161 */ 0162 0163 QString FbTalker::getCallString(const QMap<QString, QString>& args) 0164 { 0165 QString concat; 0166 QUrl url; 0167 QUrlQuery q; 0168 0169 // NOTE: QMap iterator will sort alphabetically 0170 for (QMap<QString, QString>::const_iterator it = args.constBegin(); 0171 it != args.constEnd(); 0172 ++it) 0173 { 0174 /*if (!concat.isEmpty()) 0175 concat.append("&");*/ 0176 0177 /*concat.append(it.key()); 0178 concat.append("="); 0179 concat.append(it.value());*/ 0180 q.addQueryItem(it.key(), it.value()); 0181 url.setQuery(q); 0182 } 0183 concat.append(url.query()); 0184 0185 qCDebug(KIPIPLUGINS_LOG) << "CALL: " << concat; 0186 0187 return concat; 0188 } 0189 0190 void FbTalker::authenticate(const QString &accessToken, unsigned int sessionExpires) 0191 { 0192 m_loginInProgress = true; 0193 0194 if (!accessToken.isEmpty() && ( sessionExpires == 0 || sessionExpires > (unsigned int)(time(nullptr) + 900))) 0195 { 0196 // sessionKey seems to be still valid for at least 15 minutes 0197 // - check if it still works 0198 m_accessToken = accessToken; 0199 m_sessionExpires = sessionExpires; 0200 0201 Q_EMIT signalLoginProgress(2, 9, i18n("Validate previous session...")); 0202 0203 // get logged in user - this will check if session is still valid 0204 getLoggedInUser(); 0205 } 0206 else 0207 { 0208 // session expired -> get new authorization token and session 0209 doOAuth(); 0210 } 0211 } 0212 0213 /** 0214 * upgrade session key to OAuth 0215 * 0216 * This method (or step) can be removed after June 2012 (a year after its 0217 * implementation), since it is only a convenience method for those people 0218 * who just upgraded and have an active session using the old authentication. 0219 */ 0220 void FbTalker::exchangeSession(const QString& sessionKey) 0221 { 0222 if (m_reply) 0223 { 0224 m_reply->abort(); 0225 m_reply = nullptr; 0226 } 0227 0228 Q_EMIT signalBusy(true); 0229 Q_EMIT signalLoginProgress(1, 9, i18n("Upgrading to OAuth...")); 0230 0231 QMap<QString, QString> args; 0232 args[QString::fromLatin1("client_id")] = m_appID; 0233 args[QString::fromLatin1("client_secret")] = m_secretKey; 0234 args[QString::fromLatin1("sessions")] = sessionKey; 0235 0236 QByteArray tmp(getCallString(args).toUtf8()); 0237 0238 QNetworkRequest netRequest(QUrl(QLatin1String("https://graph.facebook.com/oauth/exchange_sessions"))); 0239 netRequest.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String("application/x-www-form-urlencoded")); 0240 0241 m_reply = m_netMngr->post(netRequest, tmp); 0242 0243 m_state = FB_EXCHANGESESSION; 0244 m_buffer.resize(0); 0245 } 0246 0247 /** 0248 * Authenticate using OAuth 0249 * 0250 * TODO (Dirk): There's some GUI code slipped in here, 0251 * that really doesn't feel like it's belonging here. 0252 */ 0253 void FbTalker::doOAuth() 0254 { 0255 // just in case 0256 m_loginInProgress = true; 0257 0258 // TODO (Dirk): 0259 // Find out whether this signalBusy is used here appropriately. 0260 Q_EMIT signalBusy(true); 0261 0262 QUrl url(QString::fromLatin1("https://www.facebook.com/dialog/oauth")); 0263 QUrlQuery q(url); 0264 q.addQueryItem(QString::fromLatin1("client_id"), m_appID); 0265 q.addQueryItem(QString::fromLatin1("redirect_uri"), 0266 QString::fromLatin1("https://www.facebook.com/connect/login_success.html")); 0267 // TODO (Dirk): Check which of these permissions can be optional. 0268 q.addQueryItem(QString::fromLatin1("scope"), 0269 QString::fromLatin1("user_photos,publish_actions,user_friends")); 0270 q.addQueryItem(QString::fromLatin1("response_type"), QString::fromLatin1("token")); 0271 url.setQuery(q); 0272 qCDebug(KIPIPLUGINS_LOG) << "OAuth URL: " << url; 0273 QDesktopServices::openUrl(url); 0274 0275 Q_EMIT signalBusy(false); 0276 0277 m_dialog = new QDialog(QApplication::activeWindow(), {}); 0278 m_dialog->setModal(true); 0279 m_dialog->setWindowTitle(i18n("Facebook Application Authorization")); 0280 QLineEdit* const textbox = new QLineEdit(); 0281 QDialogButtonBox* const buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, m_dialog); 0282 buttons->button(QDialogButtonBox::Ok)->setDefault(true); 0283 0284 m_dialog->connect(buttons, SIGNAL(accepted()), 0285 this, SLOT(slotAccept())); 0286 0287 m_dialog->connect(buttons, SIGNAL(rejected()), 0288 this, SLOT(slotReject())); 0289 0290 QPlainTextEdit* const infobox = new QPlainTextEdit(i18n("Please follow the instructions in the browser window. " 0291 "When done, copy the Internet address from your browser into the textbox below and press \"OK\".")); 0292 infobox->setReadOnly(true); 0293 0294 QVBoxLayout* const vbx = new QVBoxLayout(m_dialog); 0295 vbx->addWidget(infobox); 0296 vbx->addWidget(textbox); 0297 vbx->addWidget(buttons); 0298 m_dialog->setLayout(vbx); 0299 0300 m_dialog->exec(); 0301 0302 if( m_dialog->result() == QDialog::Accepted ) 0303 { 0304 // Error code and reason from the Facebook service 0305 QString errorReason; 0306 QString errorCode; 0307 0308 url = QUrl( textbox->text() ); 0309 QString fragment = url.fragment(); 0310 qCDebug(KIPIPLUGINS_LOG) << "Split out the fragment from the URL: " << fragment; 0311 QStringList params = fragment.split(QLatin1Char('&')); 0312 QList<QString>::iterator i = params.begin(); 0313 0314 while( i != params.end() ) 0315 { 0316 QStringList keyvalue = (*i).split(QLatin1Char('=')); 0317 0318 if( keyvalue.size() == 2 ) 0319 { 0320 if( ! keyvalue[0].compare( QString::fromLatin1("access_token") ) ) 0321 { 0322 m_accessToken = keyvalue[1]; 0323 } 0324 else if( ! keyvalue[0].compare( QString::fromLatin1("expires_in") ) ) 0325 { 0326 m_sessionExpires = keyvalue[1].toUInt(); 0327 0328 if( m_sessionExpires != 0 ) 0329 { 0330 m_sessionExpires += QDateTime::currentMSecsSinceEpoch() / 1000; 0331 } 0332 } 0333 else if( ! keyvalue[0].compare( QString::fromLatin1("error_reason") ) ) 0334 { 0335 errorReason = keyvalue[1]; 0336 } 0337 else if( ! keyvalue[0].compare( QString::fromLatin1("error") ) ) 0338 { 0339 errorCode = keyvalue[1]; 0340 } 0341 } 0342 0343 ++i; 0344 } 0345 0346 if( !m_accessToken.isEmpty() && errorCode.isEmpty() && errorReason.isEmpty() ) 0347 { 0348 return getLoggedInUser(); 0349 } 0350 } 0351 0352 authenticationDone(-1, i18n("Canceled by user.")); 0353 0354 // TODO (Dirk): Correct? 0355 Q_EMIT signalBusy(false); 0356 } 0357 0358 void FbTalker::getLoggedInUser() 0359 { 0360 if (m_reply) 0361 { 0362 m_reply->abort(); 0363 m_reply = nullptr; 0364 } 0365 0366 Q_EMIT signalBusy(true); 0367 Q_EMIT signalLoginProgress(3); 0368 0369 QUrl url(QString::fromLatin1("https://graph.facebook.com/me")); 0370 QUrlQuery q; 0371 q.addQueryItem(QString::fromLatin1("access_token"), m_accessToken); 0372 q.addQueryItem(QString::fromLatin1("fields"), QString::fromLatin1("id,name,link")); 0373 url.setQuery(q); 0374 0375 QNetworkRequest netRequest(url); 0376 netRequest.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String("application/x-www-form-urlencoded")); 0377 0378 m_reply = m_netMngr->get(netRequest); 0379 0380 m_state = FB_GETLOGGEDINUSER; 0381 m_buffer.resize(0); 0382 } 0383 0384 void FbTalker::logout() 0385 { 0386 if (m_reply) 0387 { 0388 m_reply->abort(); 0389 m_reply = nullptr; 0390 } 0391 0392 QMap<QString, QString> args; 0393 args[QString::fromLatin1("next")] = QString::fromLatin1("http://www.kde.org"); 0394 args[QString::fromLatin1("access_token")] = m_accessToken; 0395 0396 QUrl url(QString::fromLatin1("https://www.facebook.com/logout.php")); 0397 QUrlQuery q; 0398 q.addQueryItem(QString::fromLatin1("next"), QString::fromLatin1("http://www.kde.org")); 0399 q.addQueryItem(QString::fromLatin1("access_token"), m_accessToken); 0400 url.setQuery(q); 0401 qCDebug(KIPIPLUGINS_LOG) << "Logout URL: " << url; 0402 QDesktopServices::openUrl(url); 0403 0404 Q_EMIT signalBusy(false); 0405 } 0406 0407 void FbTalker::listAlbums(long long userID) 0408 { 0409 qCDebug(KIPIPLUGINS_LOG) << "Requesting albums for user " << userID; 0410 0411 if (m_reply) 0412 { 0413 m_reply->abort(); 0414 m_reply = nullptr; 0415 } 0416 0417 Q_EMIT signalBusy(true); 0418 0419 QUrl url(QString::fromLatin1("https://graph.facebook.com/me/albums")); 0420 QUrlQuery q; 0421 q.addQueryItem(QString::fromLatin1("fields"), 0422 QString::fromLatin1("id,name,description,privacy,link,location")); 0423 q.addQueryItem(QString::fromLatin1("access_token"), m_accessToken); 0424 url.setQuery(q); 0425 0426 QNetworkRequest netRequest(url); 0427 netRequest.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String("application/x-www-form-urlencoded")); 0428 0429 m_reply = m_netMngr->get(netRequest); 0430 0431 m_state = FB_LISTALBUMS; 0432 m_buffer.resize(0); 0433 } 0434 0435 void FbTalker::createAlbum(const FbAlbum& album) 0436 { 0437 if (m_reply) 0438 { 0439 m_reply->abort(); 0440 m_reply = nullptr; 0441 } 0442 0443 Q_EMIT signalBusy(true); 0444 0445 QMap<QString, QString> args; 0446 args[QString::fromLatin1("access_token")] = m_accessToken; 0447 args[QString::fromLatin1("name")] = album.title; 0448 0449 if (!album.location.isEmpty()) 0450 args[QString::fromLatin1("location")] = album.location; 0451 if (!album.description.isEmpty()) 0452 args[QString::fromLatin1("description")] = album.description; 0453 0454 // TODO (Dirk): Wasn't that a requested feature in Bugzilla? 0455 switch (album.privacy) 0456 { 0457 case FB_ME: 0458 args[QString::fromLatin1("privacy")] = QString::fromLatin1("{'value':'SELF'}"); 0459 break; 0460 case FB_FRIENDS: 0461 args[QString::fromLatin1("visible")] = QString::fromLatin1("friends"); 0462 break; 0463 case FB_FRIENDS_OF_FRIENDS: 0464 args[QString::fromLatin1("visible")] = QString::fromLatin1("friends-of-friends"); 0465 break; 0466 case FB_NETWORKS: 0467 args[QString::fromLatin1("visible")] = QString::fromLatin1("networks"); 0468 break; 0469 case FB_EVERYONE: 0470 args[QString::fromLatin1("visible")] = QString::fromLatin1("everyone"); 0471 break; 0472 case FB_CUSTOM: 0473 //TODO 0474 args[QString::fromLatin1("privacy")] = QString::fromLatin1("{'value':'CUSTOM'}"); 0475 break; 0476 } 0477 0478 QByteArray tmp(getCallString(args).toUtf8()); 0479 0480 QNetworkRequest netRequest(QUrl(QLatin1String("https://graph.facebook.com/me/albums"))); 0481 netRequest.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String("application/x-www-form-urlencoded")); 0482 0483 m_reply = m_netMngr->post(netRequest, tmp); 0484 0485 m_state = FB_CREATEALBUM; 0486 m_buffer.resize(0); 0487 } 0488 0489 bool FbTalker::addPhoto(const QString& imgPath, const QString& albumID, const QString& caption) 0490 { 0491 qCDebug(KIPIPLUGINS_LOG) << "Adding photo " << imgPath << " to album with id " 0492 << albumID << " using caption '" << caption << "'"; 0493 0494 if (m_reply) 0495 { 0496 m_reply->abort(); 0497 m_reply = nullptr; 0498 } 0499 0500 Q_EMIT signalBusy(true); 0501 0502 QMap<QString, QString> args; 0503 args[QString::fromLatin1("access_token")] = m_accessToken; 0504 0505 if (!caption.isEmpty()) 0506 args[QString::fromLatin1("message")] = caption; 0507 0508 MPForm form; 0509 0510 for (QMap<QString, QString>::const_iterator it = args.constBegin(); 0511 it != args.constEnd(); 0512 ++it) 0513 { 0514 form.addPair(it.key(), it.value()); 0515 } 0516 0517 if (!form.addFile(QUrl::fromLocalFile(imgPath).fileName(), imgPath)) 0518 { 0519 Q_EMIT signalBusy(false); 0520 return false; 0521 } 0522 0523 form.finish(); 0524 0525 qCDebug(KIPIPLUGINS_LOG) << "FORM: " << Qt::endl << form.formData(); 0526 0527 QNetworkRequest netRequest(QUrl(QLatin1String("https://graph.facebook.com/v2.4/") + 0528 albumID + QLatin1String("/photos"))); 0529 netRequest.setHeader(QNetworkRequest::ContentTypeHeader, form.contentType()); 0530 0531 m_reply = m_netMngr->post(netRequest, form.formData()); 0532 0533 m_state = FB_ADDPHOTO; 0534 m_buffer.resize(0); 0535 return true; 0536 } 0537 0538 QString FbTalker::errorToText(int errCode, const QString &errMsg) 0539 { 0540 QString transError; 0541 qCDebug(KIPIPLUGINS_LOG) << "errorToText: " << errCode << ": " << errMsg; 0542 0543 switch (errCode) 0544 { 0545 case 0: 0546 transError = QString::fromLatin1(""); 0547 break; 0548 case 2: 0549 transError = i18n("The service is not available at this time."); 0550 break; 0551 case 4: 0552 transError = i18n("The application has reached the maximum number of requests allowed."); 0553 break; 0554 case 102: 0555 transError = i18n("Invalid session key or session expired. Try to log in again."); 0556 break; 0557 case 120: 0558 transError = i18n("Invalid album ID."); 0559 break; 0560 case 321: 0561 transError = i18n("Album is full."); 0562 break; 0563 case 324: 0564 transError = i18n("Missing or invalid file."); 0565 break; 0566 case 325: 0567 transError = i18n("Too many unapproved photos pending."); 0568 break; 0569 default: 0570 transError = errMsg; 0571 break; 0572 } 0573 0574 return transError; 0575 } 0576 0577 void FbTalker::slotFinished(QNetworkReply* reply) 0578 { 0579 if (reply != m_reply) 0580 { 0581 return; 0582 } 0583 0584 m_reply = nullptr; 0585 0586 if (reply->error() != QNetworkReply::NoError) 0587 { 0588 if (m_loginInProgress) 0589 { 0590 authenticationDone(reply->error(), reply->errorString()); 0591 } 0592 else if (m_state == FB_ADDPHOTO) 0593 { 0594 Q_EMIT signalBusy(false); 0595 Q_EMIT signalAddPhotoDone(reply->error(), reply->errorString()); 0596 } 0597 else 0598 { 0599 Q_EMIT signalBusy(false); 0600 QMessageBox::critical(QApplication::activeWindow(), 0601 i18n("Error"), reply->errorString()); 0602 } 0603 0604 reply->deleteLater(); 0605 return; 0606 } 0607 0608 m_buffer.append(reply->readAll()); 0609 0610 switch(m_state) 0611 { 0612 case (FB_EXCHANGESESSION): 0613 parseExchangeSession(m_buffer); 0614 break; 0615 case (FB_GETLOGGEDINUSER): 0616 parseResponseGetLoggedInUser(m_buffer); 0617 break; 0618 case (FB_LISTALBUMS): 0619 parseResponseListAlbums(m_buffer); 0620 break; 0621 case (FB_CREATEALBUM): 0622 parseResponseCreateAlbum(m_buffer); 0623 break; 0624 case (FB_ADDPHOTO): 0625 parseResponseAddPhoto(m_buffer); 0626 break; 0627 } 0628 0629 reply->deleteLater(); 0630 } 0631 0632 void FbTalker::authenticationDone(int errCode, const QString &errMsg) 0633 { 0634 if (errCode != 0) 0635 { 0636 m_accessToken.clear(); 0637 m_user.clear(); 0638 } 0639 0640 Q_EMIT signalBusy(false); 0641 Q_EMIT signalLoginDone(errCode, errMsg); 0642 m_loginInProgress = false; 0643 } 0644 0645 int FbTalker::parseErrorResponse(const QDomElement& e, QString& errMsg) 0646 { 0647 int errCode = -1; 0648 0649 for (QDomNode node = e.firstChild(); 0650 !node.isNull(); 0651 node = node.nextSibling()) 0652 { 0653 if (!node.isElement()) 0654 continue; 0655 0656 if (node.nodeName() == QString::fromLatin1("error_code")) 0657 { 0658 errCode = node.toElement().text().toInt(); 0659 qCDebug(KIPIPLUGINS_LOG) << "Error Code:" << errCode; 0660 } 0661 else if (node.nodeName() == QString::fromLatin1("error_msg")) 0662 { 0663 errMsg = node.toElement().text(); 0664 qCDebug(KIPIPLUGINS_LOG) << "Error Text:" << errMsg; 0665 } 0666 } 0667 0668 return errCode; 0669 } 0670 0671 void FbTalker::parseExchangeSession(const QByteArray& data) 0672 { 0673 qCDebug(KIPIPLUGINS_LOG) << "Parse exchange_session response:" << Qt::endl << data; 0674 QJsonParseError err; 0675 QJsonDocument doc = QJsonDocument::fromJson(data, &err); 0676 0677 if(err.error == QJsonParseError::NoError) 0678 { 0679 QJsonObject jsonObject = doc.object(); 0680 m_accessToken = jsonObject[QString::fromLatin1("access_token")].toString(); 0681 m_sessionExpires = jsonObject[QString::fromLatin1("expires")].toInt(); 0682 if( m_sessionExpires != 0 ) 0683 { 0684 m_sessionExpires += QDateTime::currentMSecsSinceEpoch() / 1000; 0685 } 0686 0687 if( m_accessToken.isEmpty() ) 0688 // Session did not convert. Reauthenticate. 0689 doOAuth(); 0690 else 0691 // Session converted to OAuth. Proceed normally. 0692 getLoggedInUser(); 0693 } 0694 else 0695 { 0696 int errCode = -1; 0697 QString errMsg(QString::fromLatin1("Parse Error")); 0698 authenticationDone(errCode, errorToText(errCode, errMsg)); 0699 } 0700 } 0701 0702 void FbTalker::parseResponseGetLoggedInUser(const QByteArray& data) 0703 { 0704 qCDebug(KIPIPLUGINS_LOG)<<"Logged in data "<<data; 0705 int errCode = -1; 0706 QString errMsg; 0707 QJsonParseError err; 0708 QJsonDocument doc = QJsonDocument::fromJson(data, &err); 0709 0710 if(err.error != QJsonParseError::NoError) 0711 { 0712 Q_EMIT signalBusy(false); 0713 return; 0714 } 0715 0716 QJsonObject jsonObject = doc.object(); 0717 m_user.id = jsonObject[QString::fromLatin1("id")].toString().toLongLong(); 0718 0719 if (!(QString::compare(jsonObject[QString::fromLatin1("id")].toString(), 0720 QString::fromLatin1(""), Qt::CaseInsensitive) == 0)) 0721 { 0722 errCode = 0; 0723 } 0724 0725 m_user.name = jsonObject[QString::fromLatin1("name")].toString(); 0726 m_user.profileURL = jsonObject[QString::fromLatin1("link")].toString(); 0727 0728 if(errCode!=0) 0729 { 0730 // it seems that session expired -> create new token and session 0731 m_accessToken.clear(); 0732 m_sessionExpires = 0; 0733 m_user.clear(); 0734 0735 doOAuth(); 0736 } 0737 else 0738 authenticationDone(0, QString::fromLatin1("")); 0739 } 0740 0741 void FbTalker::parseResponseAddPhoto(const QByteArray& data) 0742 { 0743 qCDebug(KIPIPLUGINS_LOG) <<"Parse Add Photo data is "<<data; 0744 int errCode = -1; 0745 QString errMsg; 0746 QJsonParseError err; 0747 QJsonDocument doc = QJsonDocument::fromJson(data, &err); 0748 0749 if(err.error != QJsonParseError::NoError) 0750 { 0751 Q_EMIT signalBusy(false); 0752 return; 0753 } 0754 0755 QJsonObject jsonObject = doc.object(); 0756 0757 if(jsonObject.contains(QString::fromLatin1("id"))) 0758 { 0759 qCDebug(KIPIPLUGINS_LOG) << "Id of photo exported is" << jsonObject[QString::fromLatin1("id")].toString(); 0760 errCode = 0; 0761 } 0762 0763 if(jsonObject.contains(QString::fromLatin1("error"))) 0764 { 0765 QJsonObject obj = jsonObject[QString::fromLatin1("error")].toObject(); 0766 errCode = obj[QString::fromLatin1("code")].toInt(); 0767 errMsg = obj[QString::fromLatin1("message")].toString(); 0768 } 0769 0770 Q_EMIT signalBusy(false); 0771 Q_EMIT signalAddPhotoDone(errCode, errorToText(errCode, errMsg)); 0772 } 0773 0774 void FbTalker::parseResponseCreateAlbum(const QByteArray& data) 0775 { 0776 qCDebug(KIPIPLUGINS_LOG) <<"Parse Create album data is"<<data; 0777 int errCode = -1; 0778 QString errMsg; 0779 QString newAlbumID; 0780 QJsonParseError err; 0781 QJsonDocument doc = QJsonDocument::fromJson(data, &err); 0782 0783 if(err.error != QJsonParseError::NoError) 0784 { 0785 Q_EMIT signalBusy(false); 0786 return; 0787 } 0788 0789 QJsonObject jsonObject = doc.object(); 0790 0791 if(jsonObject.contains(QString::fromLatin1("id"))) 0792 { 0793 newAlbumID = jsonObject[QString::fromLatin1("id")].toString(); 0794 qCDebug(KIPIPLUGINS_LOG) << "Id of album created is" << newAlbumID; 0795 errCode = 0; 0796 } 0797 0798 if(jsonObject.contains(QString::fromLatin1("error"))) 0799 { 0800 QJsonObject obj = jsonObject[QString::fromLatin1("error")].toObject(); 0801 errCode = obj[QString::fromLatin1("code")].toInt(); 0802 errMsg = obj[QString::fromLatin1("message")].toString(); 0803 } 0804 0805 Q_EMIT signalBusy(false); 0806 Q_EMIT signalCreateAlbumDone(errCode, errorToText(errCode, errMsg), 0807 newAlbumID); 0808 } 0809 0810 void FbTalker::parseResponseListAlbums(const QByteArray& data) 0811 { 0812 int errCode = -1; 0813 QString errMsg; 0814 QJsonParseError err; 0815 QList <FbAlbum> albumsList; 0816 QJsonDocument doc = QJsonDocument::fromJson(data, &err); 0817 0818 if(err.error != QJsonParseError::NoError) 0819 { 0820 Q_EMIT signalBusy(false); 0821 return; 0822 } 0823 0824 QJsonObject jsonObject = doc.object(); 0825 0826 if (jsonObject.contains(QString::fromLatin1("data"))) 0827 { 0828 QJsonArray jsonArray = jsonObject[QString::fromLatin1("data")].toArray(); 0829 foreach (const QJsonValue & value, jsonArray) 0830 { 0831 QJsonObject obj = value.toObject(); 0832 FbAlbum album; 0833 album.id = obj[QString::fromLatin1("id")].toString(); 0834 album.title = obj[QString::fromLatin1("name")].toString(); 0835 album.location = obj[QString::fromLatin1("location")].toString(); 0836 album.url = obj[QString::fromLatin1("link")].toString(); 0837 album.description = obj[QString::fromLatin1("description")].toString(); 0838 if (QString::compare(obj[QString::fromLatin1("privacy")].toString(), 0839 QString::fromLatin1("friends"), Qt::CaseInsensitive) == 0) 0840 { 0841 album.privacy = FB_FRIENDS; 0842 } 0843 else if (QString::compare(obj[QString::fromLatin1("privacy")].toString(), 0844 QString::fromLatin1("custom"), Qt::CaseInsensitive) == 0) 0845 { 0846 album.privacy = FB_CUSTOM; 0847 } 0848 else if (QString::compare(obj[QString::fromLatin1("privacy")].toString(), 0849 QString::fromLatin1("everyone"), Qt::CaseInsensitive) == 0) 0850 { 0851 album.privacy = FB_EVERYONE; 0852 } 0853 0854 albumsList.append(album); 0855 } 0856 errCode = 0; 0857 } 0858 0859 if (jsonObject.contains(QString::fromLatin1("error"))) 0860 { 0861 QJsonObject obj = jsonObject[QString::fromLatin1("error")].toObject(); 0862 errCode = obj[QString::fromLatin1("code")].toInt(); 0863 errMsg = obj[QString::fromLatin1("message")].toString(); 0864 } 0865 0866 std::sort(albumsList.begin(), albumsList.end()); 0867 0868 Q_EMIT signalBusy(false); 0869 Q_EMIT signalListAlbumsDone(errCode, errorToText(errCode, errMsg), 0870 albumsList); 0871 } 0872 0873 void FbTalker::slotAccept() 0874 { 0875 m_dialog->close(); 0876 m_dialog->setResult(QDialog::Accepted); 0877 } 0878 0879 void FbTalker::slotReject() 0880 { 0881 m_dialog->close(); 0882 m_dialog->setResult(QDialog::Rejected); 0883 } 0884 0885 } // namespace KIPIFacebookPlugin 0886 0887 #include "moc_fbtalker.cpp"