1 /***************************************************************************
2 * Copyright (C) 2005-2009 by Rajko Albrecht ral@alwins-world.de *
3 * http://kdesvn.alwins-world.de/ *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
20
21 #include "kdesvnd.h"
22 #include "kdesvn-config.h"
23 #include "kdesvnd_listener.h"
24 #include "ksvnwidgets/authdialogimpl.h"
25 #include "ksvnwidgets/ssltrustprompt.h"
26 #include "ksvnwidgets/commitmsg_impl.h"
27 #include "ksvnwidgets/pwstorage.h"
28 #include "helpers/kdesvn_debug.h"
29
30 #include "settings/kdesvnsettings.h"
31 #include "svnqt/client.h"
32 #include "svnqt/revision.h"
33 #include "svnqt/status.h"
34 #include "svnqt/url.h"
35 #include "svnqt/svnqttypes.h"
36 #include "svnqt/client_parameter.h"
37 #include "helpers/ktranslateurl.h"
38 #include "helpers/stringhelper.h"
39 #include "kdesvndadaptor.h"
40 #include "ksvnjobview.h"
41
42 #include <KIO/Global>
43 #include <KLocalizedString>
44 #include <KNotification>
45 #include <KPasswordDialog>
46 #include <KPluginFactory>
47
48 #include <QFileDialog>
49 #include <QVariant>
50 #include <QDBusConnection>
51 #include <QApplication>
52
53 K_PLUGIN_FACTORY_WITH_JSON(KdeSvndFactory,
54 "kdesvnd.json",
55 registerPlugin<kdesvnd>();
56 )
57
58 #define CHECK_KIO if (!progressJobView.contains(kioid)) { \
59 return;\
60 }
61
kdesvnd(QObject * parent,const QList<QVariant> &)62 kdesvnd::kdesvnd(QObject *parent, const QList<QVariant> &) : KDEDModule(parent),
63 m_uiserver(QStringLiteral("org.kde.JobViewServer"), QStringLiteral("/JobViewServer"), QDBusConnection::sessionBus())
64 {
65 m_Listener = new KdesvndListener(this);
66 new KdesvndAdaptor(this);
67 }
68
~kdesvnd()69 kdesvnd::~kdesvnd()
70 {
71 delete m_Listener;
72 }
73
getTopLevelActionMenu(const QStringList & urlList) const74 QStringList kdesvnd::getTopLevelActionMenu(const QStringList &urlList) const
75 {
76 // we get correct urls here
77 QList<QUrl> urls;
78 urls.reserve(urlList.size());
79 for (const QString &str : urlList) {
80 if (str.contains(QLatin1Char('@')))
81 urls += QUrl(str + QLatin1Char('@'));
82 else
83 urls += QUrl(str);
84 }
85
86 return getActionMenu(urls, true);
87 }
88
getActionMenu(const QStringList & urlList) const89 QStringList kdesvnd::getActionMenu(const QStringList &urlList) const
90 {
91 // we get correct urls here
92 QList<QUrl> urls;
93 urls.reserve(urlList.size());
94 for (const QString &str : urlList) {
95 if (str.contains(QLatin1Char('@')))
96 urls += QUrl(str + QLatin1Char('@'));
97 else
98 urls += QUrl(str);
99 }
100 return getActionMenu(urls, false);
101 }
102
getActionMenu(const QList<QUrl> & list,bool toplevel) const103 QStringList kdesvnd::getActionMenu(const QList<QUrl> &list, bool toplevel) const
104 {
105 QStringList result;
106 Kdesvnsettings::self()->load();
107 if (Kdesvnsettings::no_konqueror_contextmenu() || list.isEmpty() ||
108 !list.at(0).isLocalFile() ||
109 (toplevel && Kdesvnsettings::no_konqueror_toplevelmenu())) {
110 return result;
111 }
112
113 const bool itemIsWc = isWorkingCopy(list[0]);
114
115 const QUrl _dir(list.at(0).adjusted(QUrl::RemoveFilename).adjusted(QUrl::StripTrailingSlash));
116 const bool parentIsWc = isWorkingCopy(_dir);
117
118 bool itemIsRepository = false;
119 if (!parentIsWc && !itemIsWc) {
120 itemIsRepository = isRepository(list[0]);
121 }
122
123 if (!itemIsWc) {
124 if (itemIsRepository) {
125 result << QStringLiteral("Export")
126 << QStringLiteral("Checkout");
127 } else {
128 result << QStringLiteral("Exportto")
129 << QStringLiteral("Checkoutto");
130 }
131 } else {
132 result << QStringLiteral("Update")
133 << QStringLiteral("Commit");
134 }
135
136 if (!parentIsWc && !itemIsWc) {
137 if (itemIsRepository) {
138 result << QStringLiteral("Log");
139 if (!toplevel) {
140 result << QStringLiteral("Info");
141 const QUrl upUrl = KIO::upUrl(list.at(0));
142 if (isRepository(upUrl)) {
143 result << QStringLiteral("Blame")
144 << QStringLiteral("Rename");
145 }
146 result << QStringLiteral("Tree");
147 }
148 }
149 } else if (!toplevel) {
150 if (!itemIsWc) {
151 result << QStringLiteral("Add");
152 return result;
153 }
154
155 result << QStringLiteral("Log")
156 << QStringLiteral("Tree")
157 << QStringLiteral("Info")
158 << QStringLiteral("Diff")
159 << QStringLiteral("Rename")
160 << QStringLiteral("Revert");
161
162 const QUrl url = list.at(0);
163 QFileInfo f(url.path());
164 if (f.isFile()) {
165 result << QStringLiteral("Blame");
166 }
167
168 if (f.isDir()) {
169 result << QStringLiteral("Addnew");
170 result << QStringLiteral("Switch");
171 }
172 }
173 return result;
174 }
175
getSingleActionMenu(const QString & what) const176 QStringList kdesvnd::getSingleActionMenu(const QString &what) const
177 {
178 QList<QUrl> l;
179 l.append(QUrl(what.contains(QLatin1Char('@')) ? what + QLatin1Char('@') : what));
180 return getActionMenu(l, false);
181 }
182
get_saved_login(const QString & realm,const QString & user) const183 QStringList kdesvnd::get_saved_login(const QString &realm, const QString &user) const
184 {
185 Q_UNUSED(user);
186 QString username;
187 QString password;
188 PwStorage::self()->getLogin(realm, username, password);
189 QStringList res;
190 res.append(username);
191 res.append(password);
192 return res;
193
194 }
195
get_login(const QString & realm,const QString & user) const196 QStringList kdesvnd::get_login(const QString &realm, const QString &user) const
197 {
198 QPointer<AuthDialogImpl> auth(new AuthDialogImpl(realm, user));
199 QStringList res;
200 if (auth->exec() == QDialog::Accepted) {
201 res.append(auth->Username());
202 res.append(auth->Password());
203 if (auth->maySave()) {
204 res.append(QStringLiteral("true"));
205 } else {
206 res.append(QStringLiteral("false"));
207 }
208 }
209 delete auth;
210 return res;
211 }
212
get_sslaccept(const QString & hostname,const QString & fingerprint,const QString & validFrom,const QString & validUntil,const QString & issuerDName,const QString & realm) const213 int kdesvnd::get_sslaccept(const QString &hostname,
214 const QString &fingerprint,
215 const QString &validFrom,
216 const QString &validUntil,
217 const QString &issuerDName,
218 const QString &realm) const
219 {
220 bool ok, saveit;
221 if (!SslTrustPrompt::sslTrust(
222 hostname,
223 fingerprint,
224 validFrom,
225 validUntil,
226 issuerDName,
227 realm,
228 QStringList(),
229 &ok, &saveit)) {
230 return -1;
231 }
232 if (!saveit) {
233 return 0;
234 }
235 return 1;
236 }
237
load_sslclientcertpw(const QString & realm) const238 QString kdesvnd::load_sslclientcertpw(const QString &realm) const
239 {
240 QString password;
241 if (!PwStorage::self()->getCertPw(realm, password)) {
242 return QString();
243 }
244 return password;
245 }
246
get_sslclientcertpw(const QString & realm) const247 QStringList kdesvnd::get_sslclientcertpw(const QString &realm) const
248 {
249 QStringList resList;
250 QPointer<KPasswordDialog> dlg(new KPasswordDialog(nullptr, KPasswordDialog::DomainReadOnly | KPasswordDialog::ShowKeepPassword));
251 dlg->setDomain(realm);
252 dlg->setWindowTitle(i18nc("@title:window", "Enter Password for Realm %1", realm));
253 dlg->setKeepPassword(true);
254 if (dlg->exec() == KPasswordDialog::Accepted) {
255 resList.append(dlg->password());
256 if (dlg->keepPassword()) {
257 resList.append(QStringLiteral("true"));
258 } else {
259 resList.append(QStringLiteral("false"));
260 }
261 }
262 delete dlg;
263 return resList;
264 }
265
get_sslclientcertfile() const266 QString kdesvnd::get_sslclientcertfile() const
267 {
268 return QFileDialog::getOpenFileName(nullptr, i18n("Open a file with a #PKCS12 certificate"));
269 }
270
get_logmsg() const271 QStringList kdesvnd::get_logmsg() const
272 {
273 QStringList res;
274 bool ok;
275 QString logMessage = Commitmsg_impl::getLogmessage(&ok, nullptr, nullptr, nullptr);
276 if (ok) {
277 res.append(logMessage);
278 }
279 return res;
280 }
281
cleanUrl(const QUrl & url)282 QString kdesvnd::cleanUrl(const QUrl &url)
283 {
284 return url.adjusted(QUrl::StripTrailingSlash|QUrl::NormalizePathSegments).path();
285 }
286
287 /* just simple name check of course - no network access! */
isRepository(const QUrl & url) const288 bool kdesvnd::isRepository(const QUrl &url) const
289 {
290 QString proto = svn::Url::transformProtokoll(url.scheme());
291 if (proto == QLatin1String("file")) {
292 // local access - may a repository
293 svn::StatusParameter params(svn::Path(QLatin1String("file://") + cleanUrl(url)));
294 try {
295 m_Listener->m_Svnclient->status(params.depth(svn::DepthEmpty).all(false).update(false).noIgnore(false).revision(svn::Revision::HEAD));
296 } catch (const svn::ClientException &e) {
297 qCDebug(KDESVN_LOG) << e.msg() << endl;
298 return false;
299 }
300 return true;
301 }
302 return svn::Url::isValid(proto);
303 }
304
isWorkingCopy(const QUrl & url) const305 bool kdesvnd::isWorkingCopy(const QUrl &url) const
306 {
307 if (url.isEmpty() || !url.isLocalFile() || url.scheme() != QLatin1String("file") || url.path() == QLatin1String("/")) {
308 return false;
309 }
310 svn::Revision peg(svn_opt_revision_unspecified);
311 svn::Revision rev(svn_opt_revision_unspecified);
312 svn::InfoEntries e;
313 try {
314 e = m_Listener->m_Svnclient->info(cleanUrl(url), svn::DepthEmpty, rev, peg);
315 } catch (const svn::ClientException &e) {
316 return false;
317 }
318 return true;
319 }
320
canceldKioOperation(qulonglong kioid)321 bool kdesvnd::canceldKioOperation(qulonglong kioid)
322 {
323 if (!progressJobView.contains(kioid)) {
324 return false;
325 }
326 return progressJobView[kioid]->state() == KsvnJobView::CANCELD;
327 }
328
maxTransferKioOperation(qulonglong kioid,qulonglong maxtransfer)329 void kdesvnd::maxTransferKioOperation(qulonglong kioid, qulonglong maxtransfer)
330 {
331 CHECK_KIO;
332 progressJobView[kioid]->setState(KsvnJobView::RUNNING);
333 progressJobView[kioid]->setTotal(maxtransfer);
334 }
335
registerKioFeedback(qulonglong kioid)336 void kdesvnd::registerKioFeedback(qulonglong kioid)
337 {
338 if (progressJobView.contains(kioid)) {
339 return;
340 }
341 QDBusReply<QDBusObjectPath> reply = m_uiserver.requestView(qApp->applicationName(),
342 qApp->applicationName(),
343 0x0003);
344 if (reply.isValid()) {
345 KsvnJobView *jobView = new KsvnJobView(kioid, QStringLiteral("org.kde.JobViewServer"),
346 reply.value().path(),
347 QDBusConnection::sessionBus());
348 progressJobView.insert(kioid, jobView);
349 qCDebug(KDESVN_LOG) << "Register " << kioid << endl;
350 } else {
351 qCDebug(KDESVN_LOG) << "Could not register " << kioid << endl;
352 }
353 }
354
titleKioOperation(qulonglong kioid,const QString & title,const QString & label)355 void kdesvnd::titleKioOperation(qulonglong kioid, const QString &title, const QString &label)
356 {
357 CHECK_KIO;
358 progressJobView[kioid]->setInfoMessage(title);
359 progressJobView[kioid]->setDescriptionField(0, i18n("Current task"), label);
360 }
361
transferredKioOperation(qulonglong kioid,qulonglong transferred)362 void kdesvnd::transferredKioOperation(qulonglong kioid, qulonglong transferred)
363 {
364 CHECK_KIO;
365 if (progressJobView[kioid]->max() > -1) {
366 progressJobView[kioid]->setProcessedAmount(transferred, QStringLiteral("bytes"));
367 progressJobView[kioid]->setPercent(progressJobView[kioid]->percent(transferred));
368 progressJobView[kioid]->clearDescriptionField(1);
369 } else {
370 progressJobView[kioid]->setPercent(100.0);
371 progressJobView[kioid]->setDescriptionField(1, i18n("Current transfer"), helpers::ByteToString(transferred));
372 }
373 }
374
unRegisterKioFeedback(qulonglong kioid)375 void kdesvnd::unRegisterKioFeedback(qulonglong kioid)
376 {
377 CHECK_KIO;
378 KsvnJobView *jobView = progressJobView.take(kioid);
379 delete jobView;
380 qCDebug(KDESVN_LOG) << "Removed " << kioid << endl;
381 }
382
notifyKioOperation(const QString & text)383 void kdesvnd::notifyKioOperation(const QString &text)
384 {
385 KNotification::event(
386 QLatin1String("kdesvn-kio"), text,
387 QPixmap(), nullptr, KNotification::CloseOnTimeout,
388 QLatin1String("kdesvn"));
389 }
390
errorKioOperation(const QString & text)391 void kdesvnd::errorKioOperation(const QString &text)
392 {
393 KNotification::event(
394 KNotification::Error, text,
395 QPixmap(), nullptr, KNotification::CloseOnTimeout
396 );
397 }
398
setKioStatus(qulonglong kioid,int status,const QString & message)399 void kdesvnd::setKioStatus(qulonglong kioid, int status, const QString &message)
400 {
401 CHECK_KIO;
402 switch (status) {
403 case 0:
404 progressJobView[kioid]->setState(KsvnJobView::STOPPED);
405 progressJobView[kioid]->terminate(message);
406 break;
407 case 2:
408 progressJobView[kioid]->setState(KsvnJobView::CANCELD);
409 progressJobView[kioid]->terminate(message);
410 break;
411 case 1:
412 progressJobView[kioid]->setState(KsvnJobView::RUNNING);
413 progressJobView[kioid]->setSuspended(false);
414 break;
415 }
416 }
417
418 #include "kdesvnd.moc"
419