File indexing completed on 2024-05-05 17:50:47
0001 /*************************************************************************** 0002 * Copyright (C) 2005-2009 by Rajko Albrecht ral@alwins-world.de * 0003 * http://kdesvn.alwins-world.de/ * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 * * 0010 * This program is distributed in the hope that it will be useful, * 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0013 * GNU General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU General Public License * 0016 * along with this program; if not, write to the * 0017 * Free Software Foundation, Inc., * 0018 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 0019 ***************************************************************************/ 0020 0021 #include "kdesvnd.h" 0022 #include "kdesvn-config.h" 0023 #include "kdesvnd_listener.h" 0024 #include "ksvnwidgets/authdialogimpl.h" 0025 #include "ksvnwidgets/ssltrustprompt.h" 0026 #include "ksvnwidgets/commitmsg_impl.h" 0027 #include "ksvnwidgets/pwstorage.h" 0028 #include "helpers/kdesvn_debug.h" 0029 0030 #include "settings/kdesvnsettings.h" 0031 #include "svnqt/client.h" 0032 #include "svnqt/revision.h" 0033 #include "svnqt/status.h" 0034 #include "svnqt/url.h" 0035 #include "svnqt/svnqttypes.h" 0036 #include "svnqt/client_parameter.h" 0037 #include "helpers/ktranslateurl.h" 0038 #include "helpers/stringhelper.h" 0039 #include "kdesvndadaptor.h" 0040 #include "ksvnjobview.h" 0041 0042 #include <KIO/Global> 0043 #include <KLocalizedString> 0044 #include <KNotification> 0045 #include <KPasswordDialog> 0046 #include <KPluginFactory> 0047 0048 #include <QFileDialog> 0049 #include <QVariant> 0050 #include <QDBusConnection> 0051 #include <QApplication> 0052 0053 K_PLUGIN_FACTORY_WITH_JSON(KdeSvndFactory, 0054 "kdesvnd.json", 0055 registerPlugin<kdesvnd>(); 0056 ) 0057 0058 #define CHECK_KIO if (!progressJobView.contains(kioid)) { \ 0059 return;\ 0060 } 0061 0062 kdesvnd::kdesvnd(QObject *parent, const QList<QVariant> &) : KDEDModule(parent), 0063 m_uiserver(QStringLiteral("org.kde.JobViewServer"), QStringLiteral("/JobViewServer"), QDBusConnection::sessionBus()) 0064 { 0065 m_Listener = new KdesvndListener(this); 0066 new KdesvndAdaptor(this); 0067 } 0068 0069 kdesvnd::~kdesvnd() 0070 { 0071 delete m_Listener; 0072 } 0073 0074 QStringList kdesvnd::getTopLevelActionMenu(const QStringList &urlList) const 0075 { 0076 // we get correct urls here 0077 QList<QUrl> urls; 0078 urls.reserve(urlList.size()); 0079 for (const QString &str : urlList) { 0080 if (str.contains(QLatin1Char('@'))) 0081 urls += QUrl(str + QLatin1Char('@')); 0082 else 0083 urls += QUrl(str); 0084 } 0085 0086 return getActionMenu(urls, true); 0087 } 0088 0089 QStringList kdesvnd::getActionMenu(const QStringList &urlList) const 0090 { 0091 // we get correct urls here 0092 QList<QUrl> urls; 0093 urls.reserve(urlList.size()); 0094 for (const QString &str : urlList) { 0095 if (str.contains(QLatin1Char('@'))) 0096 urls += QUrl(str + QLatin1Char('@')); 0097 else 0098 urls += QUrl(str); 0099 } 0100 return getActionMenu(urls, false); 0101 } 0102 0103 QStringList kdesvnd::getActionMenu(const QList<QUrl> &list, bool toplevel) const 0104 { 0105 QStringList result; 0106 Kdesvnsettings::self()->load(); 0107 if (Kdesvnsettings::no_konqueror_contextmenu() || list.isEmpty() || 0108 !list.at(0).isLocalFile() || 0109 (toplevel && Kdesvnsettings::no_konqueror_toplevelmenu())) { 0110 return result; 0111 } 0112 0113 const bool itemIsWc = isWorkingCopy(list[0]); 0114 0115 const QUrl _dir(list.at(0).adjusted(QUrl::RemoveFilename).adjusted(QUrl::StripTrailingSlash)); 0116 const bool parentIsWc = isWorkingCopy(_dir); 0117 0118 bool itemIsRepository = false; 0119 if (!parentIsWc && !itemIsWc) { 0120 itemIsRepository = isRepository(list[0]); 0121 } 0122 0123 if (!itemIsWc) { 0124 if (itemIsRepository) { 0125 result << QStringLiteral("Export") 0126 << QStringLiteral("Checkout"); 0127 } else { 0128 result << QStringLiteral("Exportto") 0129 << QStringLiteral("Checkoutto"); 0130 } 0131 } else { 0132 result << QStringLiteral("Update") 0133 << QStringLiteral("Commit"); 0134 } 0135 0136 if (!parentIsWc && !itemIsWc) { 0137 if (itemIsRepository) { 0138 result << QStringLiteral("Log"); 0139 if (!toplevel) { 0140 result << QStringLiteral("Info"); 0141 const QUrl upUrl = KIO::upUrl(list.at(0)); 0142 if (isRepository(upUrl)) { 0143 result << QStringLiteral("Blame") 0144 << QStringLiteral("Rename"); 0145 } 0146 result << QStringLiteral("Tree"); 0147 } 0148 } 0149 } else if (!toplevel) { 0150 if (!itemIsWc) { 0151 result << QStringLiteral("Add"); 0152 return result; 0153 } 0154 0155 result << QStringLiteral("Log") 0156 << QStringLiteral("Tree") 0157 << QStringLiteral("Info") 0158 << QStringLiteral("Diff") 0159 << QStringLiteral("Rename") 0160 << QStringLiteral("Revert"); 0161 0162 const QUrl url = list.at(0); 0163 QFileInfo f(url.path()); 0164 if (f.isFile()) { 0165 result << QStringLiteral("Blame"); 0166 } 0167 0168 if (f.isDir()) { 0169 result << QStringLiteral("Addnew"); 0170 result << QStringLiteral("Switch"); 0171 } 0172 } 0173 return result; 0174 } 0175 0176 QStringList kdesvnd::getSingleActionMenu(const QString &what) const 0177 { 0178 QList<QUrl> l; 0179 l.append(QUrl(what.contains(QLatin1Char('@')) ? what + QLatin1Char('@') : what)); 0180 return getActionMenu(l, false); 0181 } 0182 0183 QStringList kdesvnd::get_saved_login(const QString &realm, const QString &user) const 0184 { 0185 Q_UNUSED(user); 0186 QString username; 0187 QString password; 0188 PwStorage::self()->getLogin(realm, username, password); 0189 QStringList res; 0190 res.append(username); 0191 res.append(password); 0192 return res; 0193 0194 } 0195 0196 QStringList kdesvnd::get_login(const QString &realm, const QString &user) const 0197 { 0198 QPointer<AuthDialogImpl> auth(new AuthDialogImpl(realm, user)); 0199 QStringList res; 0200 if (auth->exec() == QDialog::Accepted) { 0201 res.append(auth->Username()); 0202 res.append(auth->Password()); 0203 if (auth->maySave()) { 0204 res.append(QStringLiteral("true")); 0205 } else { 0206 res.append(QStringLiteral("false")); 0207 } 0208 } 0209 delete auth; 0210 return res; 0211 } 0212 0213 int kdesvnd::get_sslaccept(const QString &hostname, 0214 const QString &fingerprint, 0215 const QString &validFrom, 0216 const QString &validUntil, 0217 const QString &issuerDName, 0218 const QString &realm) const 0219 { 0220 bool ok, saveit; 0221 if (!SslTrustPrompt::sslTrust( 0222 hostname, 0223 fingerprint, 0224 validFrom, 0225 validUntil, 0226 issuerDName, 0227 realm, 0228 QStringList(), 0229 &ok, &saveit)) { 0230 return -1; 0231 } 0232 if (!saveit) { 0233 return 0; 0234 } 0235 return 1; 0236 } 0237 0238 QString kdesvnd::load_sslclientcertpw(const QString &realm) const 0239 { 0240 QString password; 0241 if (!PwStorage::self()->getCertPw(realm, password)) { 0242 return QString(); 0243 } 0244 return password; 0245 } 0246 0247 QStringList kdesvnd::get_sslclientcertpw(const QString &realm) const 0248 { 0249 QStringList resList; 0250 QPointer<KPasswordDialog> dlg(new KPasswordDialog(nullptr, KPasswordDialog::DomainReadOnly | KPasswordDialog::ShowKeepPassword)); 0251 dlg->setDomain(realm); 0252 dlg->setWindowTitle(i18nc("@title:window", "Enter Password for Realm %1", realm)); 0253 dlg->setKeepPassword(true); 0254 if (dlg->exec() == KPasswordDialog::Accepted) { 0255 resList.append(dlg->password()); 0256 if (dlg->keepPassword()) { 0257 resList.append(QStringLiteral("true")); 0258 } else { 0259 resList.append(QStringLiteral("false")); 0260 } 0261 } 0262 delete dlg; 0263 return resList; 0264 } 0265 0266 QString kdesvnd::get_sslclientcertfile() const 0267 { 0268 return QFileDialog::getOpenFileName(nullptr, i18n("Open a file with a #PKCS12 certificate")); 0269 } 0270 0271 QStringList kdesvnd::get_logmsg() const 0272 { 0273 QStringList res; 0274 bool ok; 0275 QString logMessage = Commitmsg_impl::getLogmessage(&ok, nullptr, nullptr, nullptr); 0276 if (ok) { 0277 res.append(logMessage); 0278 } 0279 return res; 0280 } 0281 0282 QString kdesvnd::cleanUrl(const QUrl &url) 0283 { 0284 return url.adjusted(QUrl::StripTrailingSlash|QUrl::NormalizePathSegments).path(); 0285 } 0286 0287 /* just simple name check of course - no network access! */ 0288 bool kdesvnd::isRepository(const QUrl &url) const 0289 { 0290 QString proto = svn::Url::transformProtokoll(url.scheme()); 0291 if (proto == QLatin1String("file")) { 0292 // local access - may a repository 0293 svn::StatusParameter params(svn::Path(QLatin1String("file://") + cleanUrl(url))); 0294 try { 0295 m_Listener->m_Svnclient->status(params.depth(svn::DepthEmpty).all(false).update(false).noIgnore(false).revision(svn::Revision::HEAD)); 0296 } catch (const svn::ClientException &e) { 0297 qCDebug(KDESVN_LOG) << e.msg() << endl; 0298 return false; 0299 } 0300 return true; 0301 } 0302 return svn::Url::isValid(proto); 0303 } 0304 0305 bool kdesvnd::isWorkingCopy(const QUrl &url) const 0306 { 0307 if (url.isEmpty() || !url.isLocalFile() || url.scheme() != QLatin1String("file") || url.path() == QLatin1String("/")) { 0308 return false; 0309 } 0310 svn::Revision peg(svn_opt_revision_unspecified); 0311 svn::Revision rev(svn_opt_revision_unspecified); 0312 svn::InfoEntries e; 0313 try { 0314 e = m_Listener->m_Svnclient->info(cleanUrl(url), svn::DepthEmpty, rev, peg); 0315 } catch (const svn::ClientException &e) { 0316 return false; 0317 } 0318 return true; 0319 } 0320 0321 bool kdesvnd::canceldKioOperation(qulonglong kioid) 0322 { 0323 if (!progressJobView.contains(kioid)) { 0324 return false; 0325 } 0326 return progressJobView[kioid]->state() == KsvnJobView::CANCELD; 0327 } 0328 0329 void kdesvnd::maxTransferKioOperation(qulonglong kioid, qulonglong maxtransfer) 0330 { 0331 CHECK_KIO; 0332 progressJobView[kioid]->setState(KsvnJobView::RUNNING); 0333 progressJobView[kioid]->setTotal(maxtransfer); 0334 } 0335 0336 void kdesvnd::registerKioFeedback(qulonglong kioid) 0337 { 0338 if (progressJobView.contains(kioid)) { 0339 return; 0340 } 0341 QDBusReply<QDBusObjectPath> reply = m_uiserver.requestView(qApp->applicationName(), 0342 qApp->applicationName(), 0343 0x0003); 0344 if (reply.isValid()) { 0345 KsvnJobView *jobView = new KsvnJobView(kioid, QStringLiteral("org.kde.JobViewServer"), 0346 reply.value().path(), 0347 QDBusConnection::sessionBus()); 0348 progressJobView.insert(kioid, jobView); 0349 qCDebug(KDESVN_LOG) << "Register " << kioid << endl; 0350 } else { 0351 qCDebug(KDESVN_LOG) << "Could not register " << kioid << endl; 0352 } 0353 } 0354 0355 void kdesvnd::titleKioOperation(qulonglong kioid, const QString &title, const QString &label) 0356 { 0357 CHECK_KIO; 0358 progressJobView[kioid]->setInfoMessage(title); 0359 progressJobView[kioid]->setDescriptionField(0, i18n("Current task"), label); 0360 } 0361 0362 void kdesvnd::transferredKioOperation(qulonglong kioid, qulonglong transferred) 0363 { 0364 CHECK_KIO; 0365 if (progressJobView[kioid]->max() > -1) { 0366 progressJobView[kioid]->setProcessedAmount(transferred, QStringLiteral("bytes")); 0367 progressJobView[kioid]->setPercent(progressJobView[kioid]->percent(transferred)); 0368 progressJobView[kioid]->clearDescriptionField(1); 0369 } else { 0370 progressJobView[kioid]->setPercent(100.0); 0371 progressJobView[kioid]->setDescriptionField(1, i18n("Current transfer"), helpers::ByteToString(transferred)); 0372 } 0373 } 0374 0375 void kdesvnd::unRegisterKioFeedback(qulonglong kioid) 0376 { 0377 CHECK_KIO; 0378 KsvnJobView *jobView = progressJobView.take(kioid); 0379 delete jobView; 0380 qCDebug(KDESVN_LOG) << "Removed " << kioid << endl; 0381 } 0382 0383 void kdesvnd::notifyKioOperation(const QString &text) 0384 { 0385 KNotification::event( 0386 QLatin1String("kdesvn-kio"), text, 0387 QPixmap(), nullptr, KNotification::CloseOnTimeout, 0388 QLatin1String("kdesvn")); 0389 } 0390 0391 void kdesvnd::errorKioOperation(const QString &text) 0392 { 0393 KNotification::event( 0394 KNotification::Error, text, 0395 QPixmap(), nullptr, KNotification::CloseOnTimeout 0396 ); 0397 } 0398 0399 void kdesvnd::setKioStatus(qulonglong kioid, int status, const QString &message) 0400 { 0401 CHECK_KIO; 0402 switch (status) { 0403 case 0: 0404 progressJobView[kioid]->setState(KsvnJobView::STOPPED); 0405 progressJobView[kioid]->terminate(message); 0406 break; 0407 case 2: 0408 progressJobView[kioid]->setState(KsvnJobView::CANCELD); 0409 progressJobView[kioid]->terminate(message); 0410 break; 0411 case 1: 0412 progressJobView[kioid]->setState(KsvnJobView::RUNNING); 0413 progressJobView[kioid]->setSuspended(false); 0414 break; 0415 } 0416 } 0417 0418 #include "kdesvnd.moc"