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