1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2010-2011 Werner Mahr (Vollstrecker) <amule@vollstreckernet.de>
5 //
6 // Any parts of this program contributed by third-party developers are copyrighted
7 // by their respective authors.
8 //
9 // This program is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation; either version 3 of the License, or
12 // (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with this program; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 //
23
24 #include "plasma-engine-plasmamule.h"
25 #include "qt-emc.h"
26
27 #include <kdebug.h>
28 #include <knotification.h>
29
30 #include <kio/scheduler.h>
31
32 #include <plasma/datacontainer.h>
33
34 #include <QDir>
35 #include <QTimer>
36
37 #include <QtDBus/QDBusInterface>
38
PlasmaMuleEngine(QObject * parent,const QVariantList & args)39 PlasmaMuleEngine::PlasmaMuleEngine (QObject* parent, const QVariantList& args)
40 : Plasma::DataEngine (parent, args)
41 {
42 Q_UNUSED (args)
43 setMinimumPollingInterval (0);
44 }
45
sourceRequestEvent(const QString & name)46 bool PlasmaMuleEngine::sourceRequestEvent (const QString &name)
47 {
48 return updateSourceEvent (name);
49 }
50
sources() const51 QStringList PlasmaMuleEngine::sources() const
52 {
53 return QStringList() << "cat_dirs"
54 << "cat_names"
55 << "clients_in_up_queue"
56 << "config_found"
57 << "down_speed"
58 << "ed2k_state"
59 << "ed2k_server_name"
60 << "ed2k_server_ip"
61 << "ed2k_server_port"
62 << "ed2k_id_high_low"
63 << "kad_status"
64 << "nickname"
65 << "os_active"
66 << "session_bytes_downloaded"
67 << "session_bytes_uploaded"
68 << "shared_files_count"
69 << "total_bytes_downloaded"
70 << "total_bytes_uploaded"
71 << "up_speed"
72 << "uptime"
73 << "version";
74 }
75
init()76 void PlasmaMuleEngine::init ()
77 {
78 Home = QDir::homePath();
79
80 QTimer *timer = new QTimer(this);
81 connect(timer, SIGNAL(timeout()), this, SLOT(timeout()));
82 timer->start(60000);
83 m_timer = TRUE;
84 setData(I18N_NOOP("uptime"), 0);
85
86 if (!Home.endsWith("/"))
87 {
88 Home += "/";
89 }
90
91 m_debugChannel = KDebug::registerArea ("plasmamule-engine",
92 #ifdef __DEBUG__
93 true
94 #else
95 false
96 #endif
97 );
98
99 regDbus();
100 initVals();
101 }
102
regDbus()103 void PlasmaMuleEngine::regDbus ()
104 {
105 new EngineAdaptor(this);
106 QDBusConnection dbus = QDBusConnection::sessionBus();
107 dbus.registerObject("/Link", this);
108 kDebug(m_debugChannel) << "Registerred dbus: " << dbus.registerService("org.amule.engine");
109 }
110
downloadFinished(KIO::Job * job,const QByteArray & data)111 void PlasmaMuleEngine::downloadFinished (KIO::Job* job,const QByteArray& data)
112 {
113
114 if (data.length() == 0)
115 {
116 KNotification::event(KNotification::Notification, QString("Download of %1 failed.").arg(job->queryMetaData("Name")));
117 return;
118 }
119
120 kDebug(m_debugChannel) << QString("Finished download of %1").arg(job->queryMetaData("Name"));
121
122 QString downloadFileName(QString("/tmp/plasmamule-download-%1.emulecollection").arg(qrand()));
123
124 QFile downloadFile(downloadFileName);
125
126 if (!downloadFile.open (QIODevice::WriteOnly | QIODevice::Append))
127 {
128 KNotification::event(KNotification::Notification, QString("%1 can't be written to temp-file.").arg(job->queryMetaData("Name")));
129 return;
130 }
131
132 QDataStream out(&downloadFile);
133 out.writeRawData(data, data.length());
134 downloadFile.close();
135
136 engine_add_link (downloadFileName, job->queryMetaData("Category").toInt(), job->queryMetaData("Name"));
137
138 downloadFile.remove();
139 }
140
engine_add_link(const QString & link,const int & category,const QString & printname)141 void PlasmaMuleEngine::engine_add_link (const QString &link, const int &category, const QString &printname)
142 {
143 kDebug(m_debugChannel) << "Received Link " << link << " with cat " << category;
144
145 QString link_to_write;
146
147
148 if (link.startsWith("ed2k:") || link.startsWith("magnet:"))
149 {
150 link_to_write = link;
151
152 if (category > 0)
153 {
154 link_to_write.append(QString(":%1").arg(category));
155 }
156
157 link_to_write.append("\n");
158 } else if (link.contains(".emulecollection") && KUrl(link).isLocalFile())
159 {
160 qtEmc* collection = new qtEmc(link);
161 if (collection->isValid())
162 {
163 QStringList links = collection->getLinks();
164 for (QStringList::const_iterator constIterator = links.constBegin(); constIterator != links.constEnd(); ++constIterator)
165 {
166 link_to_write.append(*constIterator);
167
168 if (category > 0)
169 {
170 link_to_write.append(QString(":%1").arg(category));
171 }
172
173 link_to_write.append("\n");
174 }
175 } else {
176 KNotification::event(KNotification::Notification, collection->getErrorMessage());
177 }
178
179 delete collection;
180 } else {
181 KIO::TransferJob *job = KIO::get(KUrl(link));
182 job->addMetaData("Name", link);
183 job->addMetaData("Category", QString(category));
184 connect (job, SIGNAL(data(KIO::Job *, const QByteArray&)), this,
185 SLOT(downloadFinished(KIO::Job *,const QByteArray&)));
186 kDebug(m_debugChannel) << QString("Starting download of %1").arg(printname);
187 return;
188 }
189
190 QFile link_file (Home + ".aMule/ED2KLinks");
191
192 if (!link_file.open (QIODevice::WriteOnly | QIODevice::Append))
193 {
194 KNotification::event(KNotification::Notification, QString("Problem opening %1 for writing").arg(link_file.fileName()));
195 return;
196 }
197
198 QTextStream out (&link_file);
199 out << link_to_write;
200 out.flush();
201 link_file.close();
202
203 KNotification::event(KNotification::Notification, QString("Downloading %1").arg(printname));
204
205 }
206
initVals()207 void PlasmaMuleEngine::initVals ()
208 {
209 QStringList catDir;
210 QStringList catName;
211 QStringList tempIncomingDirs;
212 QStringList cleanedIncomingDirs;
213 QStringList::const_iterator constIterator;
214
215 QFile config_file (Home + ".aMule/amule.conf");
216
217 catName.append("Default");
218 if (!config_file.open (QIODevice::ReadOnly | QIODevice::Text))
219 {
220 setData(I18N_NOOP ("config_found"), FALSE);
221 return;
222 }
223
224 QTextStream in (&config_file);
225 while (!in.atEnd())
226 {
227 QString line = in.readLine();
228 if (line.startsWith ("OnlineSignature="))
229 {
230 if (line.remove (0,line.indexOf ("=")+1) == "1")
231 {
232 m_OSActive = TRUE;
233 } else {
234 m_OSActive = FALSE;
235 }
236
237 setData(I18N_NOOP ("os_active"), m_OSActive);
238 } else if (line.contains ("OSDirectory"))
239 {
240 m_OSFile.setFileName(line.remove (0,line.indexOf ("=")+1) + "amulesig.dat");
241
242 } else if (line.contains ("Incoming"))
243 {
244 if (!tempIncomingDirs.contains(line.remove (0,line.indexOf ("=")+1)))
245 {
246 tempIncomingDirs.append(line.remove (0,line.indexOf ("=")+1));
247 }
248
249 catDir.append(line.remove (0,line.indexOf ("=")+1));
250 } else if (line.startsWith ("Title"))
251 {
252 catName.append(line.remove (0,line.indexOf ("=")+1));
253 }
254 }
255
256 setData(I18N_NOOP ("cat_names"), catName);
257 setData(I18N_NOOP ("cat_dirs"), catDir);
258
259 if (m_OSActive && !m_dirwatcher.contains(m_OSFile.fileName()))
260 {
261 kDebug(m_debugChannel) << "Registering: " << m_OSFile.fileName() << " for monitoring";
262 m_dirwatcher.addFile (m_OSFile.fileName());
263 connect (&m_dirwatcher, SIGNAL (dirty (const QString &)), SLOT (file_changed (const QString&)));
264 connect (&m_dirwatcher, SIGNAL (created (const QString &)), SLOT (new_file (const QString&)));
265 }
266
267 for (constIterator = tempIncomingDirs.constBegin(); constIterator != tempIncomingDirs.constEnd(); ++constIterator)
268 {
269 if (!m_dirwatcher.contains(*constIterator))
270 {
271 kDebug(m_debugChannel) << "Registering: " << *constIterator << " for monitoring";
272 cleanedIncomingDirs.append (*constIterator);
273 m_dirwatcher.addDir (*constIterator, KDirWatch::WatchFiles);
274 } else {
275 cleanedIncomingDirs.append (*constIterator);
276 }
277 }
278
279 for (constIterator = m_incoming_dirs.constBegin(); constIterator != m_incoming_dirs.constEnd(); ++constIterator)
280 {
281 if (!cleanedIncomingDirs.contains (*constIterator))
282 {
283 kDebug(m_debugChannel) << "Removing " << *constIterator << " from monitored dirs";
284 m_dirwatcher.removeDir (*constIterator);
285 }
286 }
287
288 m_incoming_dirs = cleanedIncomingDirs;
289 config_file.close ();
290 setName("plasmamule");
291 setData(I18N_NOOP ("config_found"), TRUE);
292 scheduleSourcesUpdated();
293 }
294
file_changed(const QString & path)295 void PlasmaMuleEngine::file_changed (const QString &path)
296 {
297 if (path == m_OSFile.fileName())
298 {
299 kDebug(m_debugChannel) << "Rereading " << path;
300 updateSourceEvent ("dummy");
301 }
302 }
303
new_file(const QString & path)304 void PlasmaMuleEngine::new_file (const QString &path)
305 {
306 if (path != m_OSFile.fileName())
307 {
308 kDebug(m_debugChannel) << "File " << path << "was created";
309 KNotification::event(KNotification::Notification, QString("Finished Download of %1").arg(path));
310 } else {
311 kDebug(m_debugChannel) << "Rereading " << path;
312 updateSourceEvent ("dummy");
313 }
314 }
315
timeout()316 void PlasmaMuleEngine::timeout()
317 {
318 initVals();
319 }
320
updateSourceEvent(const QString & name)321 bool PlasmaMuleEngine::updateSourceEvent(const QString &name)
322 {
323 Q_UNUSED (name)
324
325 if (m_OSFile.open (QIODevice::ReadOnly | QIODevice::Text) && m_OSActive)
326 {
327 QTextStream in (&m_OSFile);
328 setData(I18N_NOOP("ed2k_state"), in.readLine().toInt());
329 setData(I18N_NOOP("ed2k_server_name"), in.readLine());
330 setData(I18N_NOOP("ed2k_server_ip"), in.readLine());
331 setData(I18N_NOOP("ed2k_server_port"), in.readLine().toInt());
332 setData(I18N_NOOP("ed2k_id_high_low"), in.readLine());
333 setData(I18N_NOOP("kad_status"), in.readLine().toInt());
334 setData(I18N_NOOP("down_speed"), in.readLine().toDouble());
335 setData(I18N_NOOP("up_speed"), in.readLine().toDouble());
336 setData(I18N_NOOP("clients_in_up_queue"), in.readLine().toInt());
337 setData(I18N_NOOP("shared_files_count"), in.readLine().toInt());
338 setData(I18N_NOOP("nickname"), in.readLine());
339 setData(I18N_NOOP("total_bytes_downloaded"), in.readLine().toLongLong());
340 setData(I18N_NOOP("total_bytes_uploaded"), in.readLine().toLongLong());
341 setData(I18N_NOOP("version"), in.readLine());
342 setData(I18N_NOOP("session_bytes_downloaded"), in.readLine().toLongLong());
343 setData(I18N_NOOP("session_bytes_uploaded"), in.readLine().toLongLong());
344 setData(I18N_NOOP("uptime"), in.readLine().toInt());
345 m_OSFile.close();
346 scheduleSourcesUpdated();
347 return true;
348 } else {
349 return false;
350 }
351 }
352
K_EXPORT_PLASMA_DATAENGINE(plasmamule,PlasmaMuleEngine)353 K_EXPORT_PLASMA_DATAENGINE(plasmamule, PlasmaMuleEngine)
354
355 EngineAdaptor::EngineAdaptor(QObject *parent): QDBusAbstractAdaptor(parent)
356 {
357 setAutoRelaySignals(true);
358 }
359
~EngineAdaptor()360 EngineAdaptor::~EngineAdaptor()
361 {
362 }
363
engine_add_link(const QString & link,const int & category)364 void EngineAdaptor::engine_add_link(const QString &link, const int &category)
365 {
366 QMetaObject::invokeMethod(parent(), "engine_add_link", Q_ARG(QString, link), Q_ARG(int, category), Q_ARG(QString, link));
367 }
368
369 #include "plasma-engine-plasmamule.moc"
370