1 /***************************************************************************
2  *   Copyright (C) 2005-2009 by Rajko Albrecht                             *
3  *   ral@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 #include "kiolistener.h"
21 #include "kiosvn.h"
22 #include "kdesvndinterface.h"
23 #include "kio_macros.h"
24 #include "helpers/kdesvn_debug.h"
25 
26 #include <klocalizedstring.h>
27 
28 namespace KIO
29 {
30 
KioListener(KIO::kio_svnProtocol * _par)31 KioListener::KioListener(KIO::kio_svnProtocol *_par)
32     : svn::ContextListener(), m_notifyCounter(0), m_External(false), m_HasChanges(false), m_FirstTxDelta(false), m_Canceld(false)
33 {
34     par = _par;
35 }
36 
~KioListener()37 KioListener::~KioListener()
38 {
39 }
40 
41 /*!
42     \fn KioListener::contextCancel()
43  */
contextCancel()44 bool KioListener::contextCancel()
45 {
46     return par->wasKilled() || m_Canceld;
47 }
48 
49 /*!
50     \fn KioListener::contextGetLogMessage (QString & msg)
51  */
contextGetLogMessage(QString & msg,const svn::CommitItemList & _items)52 bool KioListener::contextGetLogMessage(QString &msg, const svn::CommitItemList &_items)
53 {
54     Q_UNUSED(_items);
55     CON_DBUS_VAL(false);
56 
57     QDBusReply<QStringList> res = kdesvndInterface.get_logmsg();
58 
59     if (!res.isValid()) {
60         qWarning() << "Didn't get a valid reply!" << endl;
61         return false;
62     }
63     QStringList lt = res.value();
64 
65     if (lt.count() != 1) {
66         msg = i18n("Wrong or missing log (may cancel pressed).");
67         qCDebug(KDESVN_LOG) << msg << endl;
68         return false;
69     }
70     msg = lt[0];
71 
72     return true;
73 }
74 
75 /*! the content of that method is taken from the notify in kio::svn in KDE SDK */
76 /* this moment we don't use it full 'cause not all is made via KIO */
contextNotify(const char * _path,svn_wc_notify_action_t action,svn_node_kind_t kind,const char * mime_type,svn_wc_notify_state_t content_state,svn_wc_notify_state_t prop_state,svn_revnum_t revision)77 void KioListener::contextNotify(const char *_path, svn_wc_notify_action_t action, svn_node_kind_t kind , const char *mime_type , svn_wc_notify_state_t content_state, svn_wc_notify_state_t prop_state, svn_revnum_t revision)
78 {
79     if (par->wasKilled()) {
80         return;
81     }
82     if (par->checkKioCancel()) {
83         m_Canceld = true;
84     }
85     QString userstring;
86     const QString path(_path ? QString::fromUtf8(_path) : QString());
87 
88     switch (action) {
89     case svn_wc_notify_add: {
90         if (mime_type && (svn_mime_type_is_binary(mime_type))) {
91             userstring = i18n("A (bin) %1", path);
92         } else {
93             userstring = i18n("A %1", path);
94         }
95         break;
96     }
97     break;
98     case svn_wc_notify_copy: //copy
99         break;
100     case svn_wc_notify_delete: //delete
101         m_HasChanges = true;
102         userstring = i18n("D %1", path);
103         break;
104     case svn_wc_notify_restore : //restore
105         userstring = i18n("Restored %1.", path);
106         break;
107     case svn_wc_notify_revert : //revert
108         userstring = i18n("Reverted %1.", path);
109         break;
110     case svn_wc_notify_failed_revert: //failed revert
111         userstring = i18n("Failed to revert %1.\nTry updating instead.", path);
112         break;
113     case svn_wc_notify_resolved: //resolved
114         userstring = i18n("Resolved conflicted state of %1.", path);
115         break;
116     case svn_wc_notify_skip: //skip
117         if (content_state == svn_wc_notify_state_missing) {
118             userstring = i18n("Skipped missing target %1.", path);
119         } else {
120             userstring = i18n("Skipped %1.", path);
121         }
122         break;
123     case svn_wc_notify_update_delete: //update_delete
124         m_HasChanges = true;
125         userstring = i18n("D %1", path);
126         break;
127     case svn_wc_notify_update_add: //update_add
128         m_HasChanges = true;
129         userstring = i18n("A %1", path);
130         break;
131     case svn_wc_notify_update_update: { //update_update
132         /* If this is an inoperative dir change, do no notification.
133            An inoperative dir change is when a directory gets closed
134            without any props having been changed. */
135         if (!((kind == svn_node_dir)
136                 && ((prop_state == svn_wc_notify_state_inapplicable)
137                     || (prop_state == svn_wc_notify_state_unknown)
138                     || (prop_state == svn_wc_notify_state_unchanged)))) {
139             m_HasChanges = true;
140 
141             if (kind == svn_node_file) {
142                 if (content_state == svn_wc_notify_state_conflicted) {
143                     userstring = QLatin1Char('C');
144                 } else if (content_state == svn_wc_notify_state_merged) {
145                     userstring = QLatin1Char('G');
146                 } else if (content_state == svn_wc_notify_state_changed) {
147                     userstring = QLatin1Char('U');
148                 }
149             }
150 
151             if (prop_state == svn_wc_notify_state_conflicted) {
152                 userstring += QLatin1Char('C');
153             } else if (prop_state == svn_wc_notify_state_merged) {
154                 userstring += QLatin1Char('G');
155             } else if (prop_state == svn_wc_notify_state_changed) {
156                 userstring += QLatin1Char('U');
157             } else {
158                 userstring += QLatin1Char(' ');
159             }
160 
161             if (!((content_state == svn_wc_notify_state_unchanged
162                     || content_state == svn_wc_notify_state_unknown)
163                     && (prop_state == svn_wc_notify_state_unchanged
164                         || prop_state == svn_wc_notify_state_unknown))) {
165                 userstring += QLatin1Char(' ') + path;
166             }
167         }
168         break;
169     }
170     case svn_wc_notify_update_completed: { //update_completed
171         if (!m_External) {
172             if (SVN_IS_VALID_REVNUM(revision)) {
173                 userstring = i18n("Finished at revision %1.", revision);
174             } else {
175                 userstring = i18n("Update finished.");
176             }
177         } else {
178             if (SVN_IS_VALID_REVNUM(revision)) {
179                 userstring = i18n("Finished external at revision %1.", revision);
180             } else {
181                 userstring = i18n("Finished external.");
182             }
183         }
184     }
185     if (m_External) {
186         m_External = false;
187     }
188     break;
189     case svn_wc_notify_update_external: //update_external
190         m_External = true;
191         userstring = i18n("Fetching external item into %1.", path);
192         break;
193     case svn_wc_notify_status_completed: //status_completed
194         if (SVN_IS_VALID_REVNUM(revision)) {
195             userstring = i18n("Status against revision: %1.", revision);
196         }
197         break;
198     case svn_wc_notify_status_external: //status_external
199         userstring = i18n("Performing status on external item at %1.", path);
200         break;
201     case svn_wc_notify_commit_modified: //commit_modified
202         userstring = i18n("Sending %1.", path);
203         break;
204     case svn_wc_notify_commit_added: //commit_added
205         if (mime_type && svn_mime_type_is_binary(mime_type)) {
206             userstring = i18n("Adding (bin) %1.", path);
207         } else {
208             userstring = i18n("Adding %1.", path);
209         }
210         break;
211     case svn_wc_notify_commit_deleted: //commit_deleted
212         userstring = i18n("Deleting %1.", path);
213         break;
214     case svn_wc_notify_commit_replaced: //commit_replaced
215         userstring = i18n("Replacing %1.", path);
216         break;
217     case svn_wc_notify_commit_postfix_txdelta: //commit_postfix_txdelta
218         if (!m_FirstTxDelta) {
219             m_FirstTxDelta = true;
220             // check fullstops!
221             userstring = i18n("Transmitting file data ");
222         } else {
223             userstring = QLatin1Char('.');
224         }
225         break;
226     case svn_wc_notify_blame_revision: //blame_revision
227         break;
228     default:
229         break;
230     }
231     const QString num(QString::number(counter()).rightJustified(10, QLatin1Char('0')));
232     par->setMetaData(num + QStringLiteral("path"), path);
233     par->setMetaData(num + QStringLiteral("action"), QString::number(action));
234     par->setMetaData(num + QStringLiteral("kind"), QString::number(kind));
235     par->setMetaData(num + QStringLiteral("mime_t"), QString::fromUtf8(mime_type));
236     par->setMetaData(num + QStringLiteral("content"), QString::number(content_state));
237     par->setMetaData(num + QStringLiteral("prop"), QString::number(prop_state));
238     par->setMetaData(num + QStringLiteral("rev"), QString::number(revision));
239     par->setMetaData(num + QStringLiteral("string"), userstring);
240     incCounter();
241 }
242 
contextNotify(const svn_wc_notify_t * action)243 void KioListener::contextNotify(const svn_wc_notify_t *action)
244 {
245     if (!action) {
246         return;
247     }
248 //    if (action->action<svn_wc_notify_locked) {
249     contextNotify(action->path, action->action, action->kind, action->mime_type,
250                   action->content_state, action->prop_state, action->revision);
251 //        return;
252 //    }
253 //    QString aString = NotifyAction(action->action);
254 }
255 
256 svn::ContextListener::SslServerTrustAnswer
contextSslServerTrustPrompt(const SslServerTrustData & data,apr_uint32_t & acceptedFailures)257 KioListener::contextSslServerTrustPrompt(const SslServerTrustData &data, apr_uint32_t &acceptedFailures)
258 {
259     Q_UNUSED(acceptedFailures);
260     QDBusReply<int> res;
261 
262     CON_DBUS_VAL(DONT_ACCEPT);
263     res = kdesvndInterface.get_sslaccept(data.hostname,
264                                          data.fingerprint, data.validFrom, data.validUntil, data.issuerDName, data.realm);
265 
266     if (!res.isValid()) {
267         qWarning() << "Unexpected reply type";
268         return DONT_ACCEPT;
269     }
270 
271     switch (res.value()) {
272     case -1:
273         return DONT_ACCEPT;
274         break;
275     case 1:
276         return ACCEPT_PERMANENTLY;
277         break;
278     default:
279     case 0:
280         return ACCEPT_TEMPORARILY;
281         break;
282     }
283     /* avoid compiler warnings */
284     return ACCEPT_TEMPORARILY;
285 }
286 
contextLoadSslClientCertPw(QString & password,const QString & realm)287 bool KioListener::contextLoadSslClientCertPw(QString &password, const QString &realm)
288 {
289     QDBusReply<QString> res;
290 
291     CON_DBUS_VAL(false);
292     res = kdesvndInterface.load_sslclientcertpw(realm);
293     if (!res.isValid()) {
294         qWarning() << "Unexpected reply type";
295         return false;
296     }
297     password = res.value();
298     return true;
299 }
300 
contextSslClientCertPrompt(QString & certFile)301 bool KioListener::contextSslClientCertPrompt(QString &certFile)
302 {
303     QDBusReply<QString> res;
304 
305     CON_DBUS_VAL(false);
306     res = kdesvndInterface.get_sslclientcertfile();
307     if (!res.isValid()) {
308         qWarning() << "Unexpected reply type";
309         return false;
310     }
311     certFile = res.value();
312     if (certFile.isEmpty()) {
313         return false;
314     }
315     return true;
316 }
317 
contextSslClientCertPwPrompt(QString & password,const QString & realm,bool & maySave)318 bool KioListener::contextSslClientCertPwPrompt(QString &password,
319         const QString &realm, bool &maySave)
320 {
321     Q_UNUSED(password);
322     Q_UNUSED(realm);
323     Q_UNUSED(maySave);
324     return false;
325 }
326 
contextGetSavedLogin(const QString & realm,QString & username,QString & password)327 bool KioListener::contextGetSavedLogin(const QString &realm, QString &username, QString &password)
328 {
329     QDBusReply<QStringList> res;
330 
331     CON_DBUS_VAL(false);
332     res = kdesvndInterface.get_saved_login(realm, username);
333     if (!res.isValid()) {
334         qWarning() << "Unexpected reply type";
335         return false;
336     }
337     QStringList lt = res.value();
338     if (lt.count() != 2) {
339         qCDebug(KDESVN_LOG) << "Wrong or missing auth list." << endl;
340         return false;
341     }
342     username = lt[0];
343     password = lt[1];
344     return true;
345 }
346 
contextGetCachedLogin(const QString & realm,QString & username,QString & password)347 bool KioListener::contextGetCachedLogin(const QString &realm, QString &username, QString &password)
348 {
349     Q_UNUSED(realm);
350     Q_UNUSED(username);
351     Q_UNUSED(password);
352     return true;
353 }
354 
contextGetLogin(const QString & realm,QString & username,QString & password,bool & maySave)355 bool KioListener::contextGetLogin(const QString &realm, QString &username, QString &password, bool &maySave)
356 {
357     QDBusReply<QStringList> res;
358 
359     CON_DBUS_VAL(false);
360     res = kdesvndInterface.get_login(realm, username);
361     if (!res.isValid()) {
362         qWarning() << "Unexpected reply type";
363         return false;
364     }
365     QStringList lt = res.value();
366     if (lt.count() != 3) {
367         qCDebug(KDESVN_LOG) << "Wrong or missing auth list (may cancel pressed)." << endl;
368         return false;
369     }
370     username = lt[0];
371     password = lt[1];
372     maySave = lt[2] == QLatin1String("true");
373     return true;
374 }
375 
contextAddListItem(svn::DirEntries * entries,const svn_dirent_t * dirent,const svn_lock_t * lock,const QString & path)376 bool KioListener::contextAddListItem(svn::DirEntries *entries, const svn_dirent_t *dirent, const svn_lock_t *lock, const QString &path)
377 {
378     Q_UNUSED(entries);
379     if (!dirent || path.isEmpty()) {
380         // the path itself? is a problem within kio
381         return false;
382     }
383     if (par) {
384         if (par->checkKioCancel()) {
385             m_Canceld = true;
386         }
387         par->listSendDirEntry(svn::DirEntry(path, dirent, lock));
388         return true;
389     }
390     return false;
391 }
392 
393 /*!
394     \fn KioListener::contextProgress(long long int current, long long int max)
395  */
contextProgress(long long int cur,long long int max)396 void KioListener::contextProgress(long long int cur, long long int max)
397 {
398     if (par) {
399         if (par->checkKioCancel()) {
400             m_Canceld = true;
401         }
402         par->contextProgress(cur, max);
403     }
404 }
405 
406 } // namespace KIO
407