File indexing completed on 2024-05-12 04:57:44
0001 /* 0002 This file is part of Choqok, the KDE micro-blogging client 0003 0004 SPDX-FileCopyrightText: 2010-2012 Andrey Esin <gmlastik@gmail.com> 0005 0006 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0007 */ 0008 0009 #include "flickrconfig.h" 0010 0011 #include <QCheckBox> 0012 #include <QCryptographicHash> 0013 #include <QDomDocument> 0014 #include <QDomElement> 0015 #include <QPushButton> 0016 #include <QRadioButton> 0017 #include <QVBoxLayout> 0018 0019 #include <KAboutData> 0020 #include <KConfigGroup> 0021 #include <KIO/StoredTransferJob> 0022 #include <KLocalizedString> 0023 #include <KMessageBox> 0024 #include <KPluginFactory> 0025 #include <KSharedConfig> 0026 0027 #include "choqoktools.h" 0028 #include "passwordmanager.h" 0029 0030 #include "flickrsettings.h" 0031 0032 K_PLUGIN_CLASS_WITH_JSON(FlickrConfig, "choqok_flickr_config.json") 0033 0034 const QString apiKey = QLatin1String("13f602e6e705834d8cdd5dd2ccb19651"); 0035 const QString apiSecret = QLatin1String("98c89dbe39ae3bea"); 0036 const QString apiKeSec = apiSecret + QLatin1String("api_key") + apiKey; 0037 0038 FlickrConfig::FlickrConfig(QWidget *parent, const QVariantList &) 0039 : KCModule(parent) 0040 { 0041 QVBoxLayout *layout = new QVBoxLayout(this); 0042 QWidget *wd = new QWidget(this); 0043 wd->setObjectName(QLatin1String("mFlickrCtl")); 0044 ui.setupUi(wd); 0045 addConfig(FlickrSettings::self(), wd); 0046 layout->addWidget(wd); 0047 0048 connect(ui.authButton, &QPushButton::clicked, this, &FlickrConfig::slotAuthButton_clicked); 0049 connect(ui.cfg_shorturl, &QCheckBox::stateChanged, this, &FlickrConfig::emitChanged); 0050 connect(ui.cfg_forprivate, &QRadioButton::clicked, this, &FlickrConfig::emitChanged); 0051 connect(ui.cfg_forfriends, &QCheckBox::stateChanged, this, &FlickrConfig::emitChanged); 0052 connect(ui.cfg_forfamily, &QCheckBox::stateChanged, this, &FlickrConfig::emitChanged); 0053 connect(ui.cfg_forpublic, &QRadioButton::clicked, this, &FlickrConfig::emitChanged); 0054 connect(ui.cfg_safe, &QRadioButton::clicked, this, &FlickrConfig::emitChanged); 0055 connect(ui.cfg_moderate, &QRadioButton::clicked, this, &FlickrConfig::emitChanged); 0056 connect(ui.cfg_restricted, &QRadioButton::clicked, this, &FlickrConfig::emitChanged); 0057 connect(ui.cfg_hidefromsearch, &QCheckBox::stateChanged, this, &FlickrConfig::emitChanged); 0058 } 0059 0060 FlickrConfig::~FlickrConfig() 0061 { 0062 } 0063 0064 void FlickrConfig::load() 0065 { 0066 KCModule::load(); 0067 KConfigGroup grp(KSharedConfig::openConfig(), "Flickr Uploader"); 0068 m_nsid = grp.readEntry("nsid", ""); 0069 m_username = grp.readEntry("username", ""); 0070 m_fullname = grp.readEntry("fullname", ""); 0071 ui.cfg_shorturl->setChecked(grp.readEntry("shorturl", true)); 0072 ui.cfg_forprivate->setChecked(grp.readEntry("forprivate", false)); 0073 ui.cfg_forfriends->setChecked(grp.readEntry("forfriends", false)); 0074 ui.cfg_forfamily->setChecked(grp.readEntry("forfamily", false)); 0075 ui.cfg_forpublic->setChecked(grp.readEntry("forpublic", true)); 0076 ui.cfg_safe->setChecked(grp.readEntry("safe", true)); 0077 ui.cfg_moderate->setChecked(grp.readEntry("moderate", false)); 0078 ui.cfg_restricted->setChecked(grp.readEntry("restricted", false)); 0079 ui.cfg_hidefromsearch->setChecked(grp.readEntry("hidefromsearch", false)); 0080 m_token = Choqok::PasswordManager::self()->readPassword(QStringLiteral("flickr_%1") 0081 .arg(m_username)); 0082 setAuthenticated(!m_token.isEmpty()); 0083 } 0084 0085 void FlickrConfig::save() 0086 { 0087 KCModule::save(); 0088 KConfigGroup grp(KSharedConfig::openConfig(), "Flickr Uploader"); 0089 grp.writeEntry("nsid", m_nsid); 0090 grp.writeEntry("username", m_username); 0091 grp.writeEntry("fullname", m_fullname); 0092 grp.writeEntry("shorturl", ui.cfg_shorturl->isChecked()); 0093 grp.writeEntry("forprivate", ui.cfg_forprivate->isChecked()); 0094 grp.writeEntry("forfriends", ui.cfg_forfriends->isChecked()); 0095 grp.writeEntry("forfamily", ui.cfg_forfamily->isChecked()); 0096 grp.writeEntry("forpublic", ui.cfg_forpublic->isChecked()); 0097 grp.writeEntry("safe", ui.cfg_safe->isChecked()); 0098 grp.writeEntry("moderate", ui.cfg_moderate->isChecked()); 0099 grp.writeEntry("restricted", ui.cfg_restricted->isChecked()); 0100 grp.writeEntry("hidefromsearch", ui.cfg_hidefromsearch->isChecked()); 0101 Choqok::PasswordManager::self()->writePassword(QStringLiteral("flickr_%1").arg(m_username), 0102 m_token); 0103 } 0104 0105 void FlickrConfig::emitChanged() 0106 { 0107 ui.cfg_forfamily->setEnabled(ui.cfg_forprivate->isChecked()); 0108 ui.cfg_forfriends->setEnabled(ui.cfg_forprivate->isChecked()); 0109 Q_EMIT changed(true); 0110 } 0111 0112 void FlickrConfig::getFrob() 0113 { 0114 m_frob.clear(); 0115 QUrl url(QLatin1String("https://flickr.com/services/rest/")); 0116 QUrlQuery urlQuery; 0117 urlQuery.addQueryItem(QLatin1String("method"), QLatin1String("flickr.auth.getFrob")); 0118 urlQuery.addQueryItem(QLatin1String("api_key"), QLatin1String(apiKey.toUtf8())); 0119 urlQuery.addQueryItem(QLatin1String("api_sig"), QLatin1String(createSign("methodflickr.auth.getFrob"))); 0120 url.setQuery(urlQuery); 0121 0122 QString errMsg; 0123 KIO::StoredTransferJob *job = KIO::storedGet(url, KIO::Reload, KIO::HideProgressInfo); 0124 job->exec(); 0125 if (!job->error()) { 0126 QDomDocument rep; 0127 rep.setContent(job->data()); 0128 QDomElement element = rep.documentElement(); 0129 if (element.tagName() == QLatin1String("rsp")) { 0130 QString res; 0131 res = element.attribute(QLatin1String("stat") , QLatin1String("fail")); 0132 QDomNode node = element.firstChild(); 0133 while (!node.isNull()) { 0134 QDomElement elem = node.toElement(); 0135 if (res == QLatin1String("ok")) { 0136 if (elem.tagName() == QLatin1String("frob")) { 0137 m_frob = elem.text(); 0138 } 0139 return; 0140 } else if (res == QLatin1String("fail")) { 0141 if (elem.tagName() == QLatin1String("err")) { 0142 errMsg = elem.text(); 0143 int errCode = elem.attribute(QLatin1String("code") , QLatin1String("0")).toInt(); 0144 switch (errCode) { 0145 case 96: 0146 case 97: 0147 errMsg = i18n("Signature problem. Please try again later"); 0148 break; 0149 case 105: 0150 errMsg = i18n("The requested service is temporarily unavailable. Try again later"); 0151 break; 0152 default: 0153 errMsg = i18n("Unknown Error:%1. Please try again later", errCode); 0154 break; 0155 } 0156 } 0157 } else { 0158 errMsg = i18n("Malformed response"); 0159 } 0160 node = node.nextSibling(); 0161 } 0162 } else { 0163 errMsg = i18n("Malformed response"); 0164 } 0165 } else { 0166 errMsg = job->errorString(); 0167 } 0168 if (!errMsg.isEmpty()) { 0169 KMessageBox::error(ui.gridLayout->widget(), errMsg, i18n("Flickr authorization")); 0170 } 0171 } 0172 0173 void FlickrConfig::getToken() 0174 { 0175 m_token.clear(); 0176 QUrl url(QLatin1String("https://flickr.com/services/rest/")); 0177 QUrlQuery urlQuery; 0178 urlQuery.addQueryItem(QLatin1String("method"), QLatin1String("flickr.auth.getToken")); 0179 urlQuery.addQueryItem(QLatin1String("api_key"), QLatin1String(apiKey.toUtf8())); 0180 urlQuery.addQueryItem(QLatin1String("frob"), QLatin1String(m_frob.toUtf8())); 0181 urlQuery.addQueryItem(QLatin1String("api_sig"), QLatin1String(createSign("frob" + m_frob.toUtf8() + "methodflickr.auth.getToken"))); 0182 url.setQuery(urlQuery); 0183 0184 QString errMsg; 0185 KIO::StoredTransferJob *job = KIO::storedGet(url, KIO::Reload, KIO::HideProgressInfo); 0186 job->exec(); 0187 0188 if (!job->error()) { 0189 QDomDocument rep; 0190 rep.setContent(job->data()); 0191 QDomElement element = rep.documentElement(); 0192 if (element.tagName() == QLatin1String("rsp")) { 0193 QString res; 0194 res = element.attribute(QLatin1String("stat") , QLatin1String("fail")); 0195 QDomNode node = element.firstChild(); 0196 while (!node.isNull()) { 0197 QDomElement elem = node.toElement(); 0198 if (res == QLatin1String("ok")) { 0199 QDomNode authNode = node.firstChild(); 0200 while (!authNode.isNull()) { 0201 QDomElement elem = authNode.toElement(); 0202 if (elem.tagName() == QLatin1String("token")) { 0203 m_token = elem.text(); 0204 } 0205 0206 if (elem.tagName() == QLatin1String("user")) { 0207 m_nsid = elem.attribute(QLatin1String("nsid")); 0208 m_username = elem.attribute(QLatin1String("username")); 0209 m_fullname = elem.attribute(QLatin1String("fullname")); 0210 } 0211 authNode = authNode.nextSibling(); 0212 } 0213 } else if (res == QLatin1String("fail")) { 0214 if (elem.tagName() == QLatin1String("err")) { 0215 errMsg = elem.text(); 0216 int errCode = elem.attribute(QLatin1String("code") , QLatin1String("0")).toInt(); 0217 switch (errCode) { 0218 case 96: 0219 case 97: 0220 case 108: 0221 errMsg = i18n("Something happens with signature. Please retry"); 0222 break; 0223 case 105: 0224 errMsg = i18n("The requested service is temporarily unavailable. Try again later"); 0225 break; 0226 default: 0227 errMsg = i18n("Something happens wrong. Error %1. Try again later", errCode); 0228 break; 0229 } 0230 } 0231 } else { 0232 errMsg = i18n("Malformed response"); 0233 } 0234 node = node.nextSibling(); 0235 } 0236 } else { 0237 errMsg = i18n("Malformed response"); 0238 } 0239 } else { 0240 errMsg = job->errorString(); 0241 } 0242 0243 if (!errMsg.isEmpty()) { 0244 KMessageBox::error(ui.gridLayout->widget(), errMsg, i18n("Flickr authorization")); 0245 return; 0246 } 0247 0248 if (!m_token.isEmpty()) { 0249 setAuthenticated(true); 0250 FlickrConfig::save(); 0251 ui.tabWidget->setCurrentIndex(1); 0252 } else { 0253 setAuthenticated(false); 0254 } 0255 ui.authButton->setEnabled(true); 0256 } 0257 0258 void FlickrConfig::setAuthenticated(bool authenticated) 0259 { 0260 isAuthenticated = authenticated; 0261 if (authenticated) { 0262 ui.authButton->setIcon(QIcon::fromTheme(QLatin1String("object-unlocked"))); 0263 ui.authLed->on(); 0264 ui.authLabel->setText(i18n("Authorized as %1", m_username)); 0265 if (!m_fullname.isEmpty()) { 0266 ui.authLabel->setText(ui.authLabel->text() + QStringLiteral(" (%1)").arg(m_fullname.toHtmlEscaped())); 0267 } 0268 } else { 0269 ui.authButton->setIcon(QIcon::fromTheme(QLatin1String("object-locked"))); 0270 ui.authLed->off(); 0271 ui.authLabel->setText(i18n("Not authorized")); 0272 } 0273 } 0274 0275 void FlickrConfig::slotAuthButton_clicked() 0276 { 0277 getFrob(); 0278 if (!m_frob.isEmpty()) { 0279 QUrl oUrl(QLatin1String("https://flickr.com/services/auth/?")); 0280 oUrl.setPath(oUrl.path() + QLatin1String("api_key=") + apiKey + 0281 QLatin1String("&perms=write&frob=") + m_frob + 0282 QLatin1String("&api_sig=") + QLatin1String(createSign("frob" + m_frob.toUtf8() + "permswrite"))); 0283 Choqok::openUrl(oUrl); 0284 0285 QPushButton *btn = new QPushButton(QIcon::fromTheme(QLatin1String("dialog-ok")), i18n("Click here when you authorized Choqok"), this); 0286 connect(btn, &QPushButton::clicked, this, &FlickrConfig::getToken); 0287 btn->setWindowFlags(Qt::Dialog); 0288 ui.authTab->layout()->addWidget(btn); 0289 ui.authButton->setEnabled(false); 0290 } else { 0291 return; 0292 } 0293 } 0294 0295 QByteArray FlickrConfig::createSign(QByteArray req) 0296 { 0297 return QCryptographicHash::hash(apiKeSec.toUtf8().append(req), QCryptographicHash::Md5).toHex(); 0298 } 0299 0300 #include "flickrconfig.moc" 0301 #include "moc_flickrconfig.cpp"