-rw-r--r-- | library/network.cpp | 436 |
1 files changed, 436 insertions, 0 deletions
diff --git a/library/network.cpp b/library/network.cpp new file mode 100644 index 0000000..7d51016 --- a/dev/null +++ b/library/network.cpp | |||
@@ -0,0 +1,436 @@ | |||
1 | /********************************************************************** | ||
2 | ** Copyright (C) 2000 Trolltech AS. All rights reserved. | ||
3 | ** | ||
4 | ** This file is part of Qtopia Environment. | ||
5 | ** | ||
6 | ** This file may be distributed and/or modified under the terms of the | ||
7 | ** GNU General Public License version 2 as published by the Free Software | ||
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | ||
9 | ** packaging of this file. | ||
10 | ** | ||
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | ||
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | ||
13 | ** | ||
14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | ||
15 | ** | ||
16 | ** Contact info@trolltech.com if any conditions of this licensing are | ||
17 | ** not clear to you. | ||
18 | ** | ||
19 | **********************************************************************/ | ||
20 | |||
21 | #include "qpe/network.h" | ||
22 | #include "qpe/networkinterface.h" | ||
23 | #include "qpe/global.h" | ||
24 | #include "qpe/config.h" | ||
25 | #include "qpe/resource.h" | ||
26 | #include "qpe/qpeapplication.h" | ||
27 | #include <qpe/qcopenvelope_qws.h> | ||
28 | #include <qpe/qlibrary.h> | ||
29 | |||
30 | #include <qlistbox.h> | ||
31 | #include <qdir.h> | ||
32 | #include <qlayout.h> | ||
33 | #include <qdict.h> | ||
34 | #include <qtranslator.h> | ||
35 | |||
36 | #include <stdlib.h> | ||
37 | |||
38 | class NetworkEmitter : public QCopChannel { | ||
39 | Q_OBJECT | ||
40 | public: | ||
41 | NetworkEmitter() : QCopChannel("QPE/Network",qApp) | ||
42 | { | ||
43 | } | ||
44 | |||
45 | void receive(const QCString &msg, const QByteArray&) | ||
46 | { | ||
47 | if ( msg == "choicesChanged()" ) | ||
48 | emit changed(); | ||
49 | } | ||
50 | |||
51 | signals: | ||
52 | void changed(); | ||
53 | }; | ||
54 | |||
55 | /*! | ||
56 | \internal | ||
57 | |||
58 | Requests that the service \a choice be started. The \a password is | ||
59 | the password to use if required. | ||
60 | */ | ||
61 | void Network::start(const QString& choice, const QString& password) | ||
62 | { | ||
63 | QCopEnvelope e("QPE/Network", "start(QString,QString)"); | ||
64 | e << choice << password; | ||
65 | } | ||
66 | |||
67 | /*! | ||
68 | \class Network network.h | ||
69 | \brief The Network class provides network access functionality. | ||
70 | */ | ||
71 | |||
72 | // copy the proxy settings of the active config over to the Proxies.conf file | ||
73 | /*! | ||
74 | \internal | ||
75 | */ | ||
76 | void Network::writeProxySettings( Config &cfg ) | ||
77 | { | ||
78 | Config proxy( Network::settingsDir() + "/Proxies.conf", Config::File ); | ||
79 | proxy.setGroup("Properties"); | ||
80 | cfg.setGroup("Proxy"); | ||
81 | proxy.writeEntry("type", cfg.readEntry("type") ); | ||
82 | proxy.writeEntry("autoconfig", cfg.readEntry("autoconfig") ); | ||
83 | proxy.writeEntry("httphost", cfg.readEntry("httphost") ); | ||
84 | proxy.writeEntry("httpport", cfg.readEntry("httpport") ); | ||
85 | proxy.writeEntry("ftphost", cfg.readEntry("ftphost") ); | ||
86 | proxy.writeEntry("ftpport", cfg.readEntry("ftpport") ); | ||
87 | proxy.writeEntry("noproxies", cfg.readEntry("noproxies") ); | ||
88 | cfg.setGroup("Properties"); | ||
89 | } | ||
90 | |||
91 | |||
92 | |||
93 | /*! | ||
94 | \internal | ||
95 | |||
96 | Stops the current network service. | ||
97 | */ | ||
98 | void Network::stop() | ||
99 | { | ||
100 | QCopEnvelope e("QPE/Network", "stop()"); | ||
101 | } | ||
102 | |||
103 | static NetworkEmitter *emitter = 0; | ||
104 | |||
105 | /*! | ||
106 | \internal | ||
107 | */ | ||
108 | void Network::connectChoiceChange(QObject* receiver, const char* slot) | ||
109 | { | ||
110 | if ( !emitter ) | ||
111 | emitter = new NetworkEmitter; | ||
112 | QObject::connect(emitter,SIGNAL(changed()),receiver,slot); | ||
113 | } | ||
114 | |||
115 | /*! | ||
116 | \internal | ||
117 | */ | ||
118 | QString Network::settingsDir() | ||
119 | { | ||
120 | return Global::applicationFileName("Network", "modules"); | ||
121 | } | ||
122 | |||
123 | /*! | ||
124 | \internal | ||
125 | */ | ||
126 | QStringList Network::choices(QListBox* lb, const QString& dir) | ||
127 | { | ||
128 | QStringList list; | ||
129 | |||
130 | if ( lb ) | ||
131 | lb->clear(); | ||
132 | |||
133 | QString adir = dir.isEmpty() ? settingsDir() : dir; | ||
134 | QDir settingsdir(adir); | ||
135 | settingsdir.mkdir(adir); | ||
136 | |||
137 | QStringList files = settingsdir.entryList("*.conf"); | ||
138 | for (QStringList::ConstIterator it=files.begin(); it!=files.end(); ++it ) { | ||
139 | QString filename = settingsdir.filePath(*it); | ||
140 | Config cfg(filename, Config::File); | ||
141 | cfg.setGroup("Info"); | ||
142 | if ( lb ) | ||
143 | lb->insertItem(Resource::loadPixmap("Network/" + cfg.readEntry("Type")), | ||
144 | cfg.readEntry("Name")); | ||
145 | list.append(filename); | ||
146 | } | ||
147 | |||
148 | return list; | ||
149 | } | ||
150 | |||
151 | class NetworkServer : public QCopChannel { | ||
152 | Q_OBJECT | ||
153 | public: | ||
154 | NetworkServer(QObject* parent) : QCopChannel("QPE/Network",parent) | ||
155 | { | ||
156 | up = FALSE; | ||
157 | examineNetworks( TRUE ); | ||
158 | QCopChannel* card = new QCopChannel("QPE/Card",parent); | ||
159 | connect(card,SIGNAL(received(const QCString &, const QByteArray&)), | ||
160 | this,SLOT(cardMessage(const QCString &, const QByteArray&))); | ||
161 | } | ||
162 | |||
163 | ~NetworkServer() | ||
164 | { | ||
165 | stop(); | ||
166 | } | ||
167 | |||
168 | bool networkOnline() const | ||
169 | { | ||
170 | return up; | ||
171 | } | ||
172 | |||
173 | private: | ||
174 | void receive(const QCString &msg, const QByteArray& data) | ||
175 | { | ||
176 | if ( msg == "start(QString,QString)" ) { | ||
177 | QDataStream stream(data,IO_ReadOnly); | ||
178 | QString file,password; | ||
179 | stream >> file >> password; | ||
180 | if ( file.isEmpty() ) { | ||
181 | QStringList l = Network::choices(); | ||
182 | for (QStringList::ConstIterator i=l.begin(); i!=l.end(); ++i) { | ||
183 | Config cfg(*i,Config::File); | ||
184 | cfg.setGroup("Info"); | ||
185 | QString type = cfg.readEntry("Type"); | ||
186 | NetworkInterface* plugin = Network::loadPlugin(type); | ||
187 | cfg.setGroup("Properties"); | ||
188 | if ( plugin && plugin->isAvailable(cfg) ) { | ||
189 | file = *i; | ||
190 | break; | ||
191 | } | ||
192 | } | ||
193 | if ( file.isEmpty() ) { | ||
194 | QCopEnvelope("QPE/Network", "failed()"); | ||
195 | return; | ||
196 | } | ||
197 | } | ||
198 | start(file,password); | ||
199 | } else if ( msg == "stop()" ) { | ||
200 | stop(); | ||
201 | } else if ( msg == "choicesChanged()" ) { | ||
202 | examineNetworks(); | ||
203 | } | ||
204 | } | ||
205 | |||
206 | private slots: | ||
207 | void cardMessage(const QCString &msg, const QByteArray&) | ||
208 | { | ||
209 | if ( msg == "stabChanged()" ) | ||
210 | examineNetworks(); | ||
211 | } | ||
212 | |||
213 | private: | ||
214 | void examineNetworks( bool firstStart = FALSE ) | ||
215 | { | ||
216 | QStringList l = Network::choices(); | ||
217 | bool wasup = up; up=FALSE; | ||
218 | QStringList pavailable = available; | ||
219 | available.clear(); | ||
220 | for (QStringList::ConstIterator it=l.begin(); it!=l.end(); ++it) { | ||
221 | Config cfg(*it,Config::File); | ||
222 | cfg.setGroup("Info"); | ||
223 | QString type = cfg.readEntry("Type"); | ||
224 | NetworkInterface* plugin = Network::loadPlugin(type); | ||
225 | cfg.setGroup("Properties"); | ||
226 | if ( plugin ) { | ||
227 | if ( plugin->isActive(cfg) ) { | ||
228 | up = TRUE; | ||
229 | if ( firstStart ) | ||
230 | plugin->start( cfg ); | ||
231 | } | ||
232 | if ( plugin->isAvailable(cfg) ) | ||
233 | available.append(*it); | ||
234 | } | ||
235 | } | ||
236 | |||
237 | // Try to work around unreproducible bug whereby | ||
238 | // the netmon applet shows wrong state. | ||
239 | bool reannounce = wait<0; | ||
240 | |||
241 | if ( available != pavailable || reannounce ) { | ||
242 | QCopEnvelope e("QPE/Network", "available(QStringList)"); | ||
243 | e << available; | ||
244 | } | ||
245 | if ( up != wasup || reannounce ) { | ||
246 | QCopEnvelope("QPE/Network", up ? "up()" : "down()"); | ||
247 | } | ||
248 | } | ||
249 | |||
250 | void start( const QString& file, const QString& password ) | ||
251 | { | ||
252 | if ( !current.isEmpty() ) | ||
253 | stop(); | ||
254 | current = QString::null; | ||
255 | Config cfg(file, Config::File); | ||
256 | cfg.setGroup("Info"); | ||
257 | QString type = cfg.readEntry("Type"); | ||
258 | NetworkInterface* plugin = Network::loadPlugin(type); | ||
259 | bool started = FALSE; | ||
260 | if ( plugin ) { | ||
261 | cfg.setGroup("Properties"); | ||
262 | if ( plugin->start(cfg,password) ) { | ||
263 | Network::writeProxySettings( cfg ); | ||
264 | current = file; | ||
265 | wait=0; | ||
266 | startTimer(400); | ||
267 | started = TRUE; | ||
268 | } | ||
269 | } | ||
270 | if ( !started ) { | ||
271 | QCopEnvelope("QPE/Network", "failed()"); | ||
272 | } | ||
273 | } | ||
274 | |||
275 | void stop() | ||
276 | { | ||
277 | bool stopped = FALSE; | ||
278 | if ( !current.isEmpty() ) { | ||
279 | Config cfg(current, Config::File); | ||
280 | cfg.setGroup("Info"); | ||
281 | QString type = cfg.readEntry("Type"); | ||
282 | NetworkInterface* plugin = Network::loadPlugin(type); | ||
283 | if ( plugin ) { | ||
284 | cfg.setGroup("Properties"); | ||
285 | if ( plugin->stop(cfg) ) { | ||
286 | current = QString::null; | ||
287 | wait=0; | ||
288 | startTimer(400); | ||
289 | stopped = TRUE; | ||
290 | } | ||
291 | } | ||
292 | } | ||
293 | if ( !stopped ) { | ||
294 | QCopEnvelope("QPE/Network", "failed()"); | ||
295 | } | ||
296 | } | ||
297 | |||
298 | void timerEvent(QTimerEvent*) | ||
299 | { | ||
300 | examineNetworks(); | ||
301 | if ( wait >= 0 ) { | ||
302 | if ( up == !current.isNull() ) { | ||
303 | // done | ||
304 | killTimers(); | ||
305 | if ( up ) { | ||
306 | startTimer(3000); // monitor link | ||
307 | wait = -1; | ||
308 | } | ||
309 | } else { | ||
310 | wait++; | ||
311 | if ( wait == 600 ) { | ||
312 | killTimers(); // forget about it after 240 s | ||
313 | QCopEnvelope("QPE/Network", "failed()"); | ||
314 | up = !current.isNull(); | ||
315 | } | ||
316 | } | ||
317 | } else if ( !up ) { | ||
318 | killTimers(); | ||
319 | } | ||
320 | } | ||
321 | |||
322 | private: | ||
323 | QStringList available; | ||
324 | QString current; | ||
325 | bool up; | ||
326 | int wait; | ||
327 | }; | ||
328 | |||
329 | static NetworkServer* ns=0; | ||
330 | |||
331 | /*! | ||
332 | \internal | ||
333 | */ | ||
334 | QString Network::serviceName(const QString& service) | ||
335 | { | ||
336 | Config cfg(service, Config::File); | ||
337 | cfg.setGroup("Info"); | ||
338 | return cfg.readEntry("Name"); | ||
339 | } | ||
340 | |||
341 | /*! | ||
342 | \internal | ||
343 | */ | ||
344 | QString Network::serviceType(const QString& service) | ||
345 | { | ||
346 | Config cfg(service, Config::File); | ||
347 | cfg.setGroup("Info"); | ||
348 | return cfg.readEntry("Type"); | ||
349 | } | ||
350 | |||
351 | /*! | ||
352 | \internal | ||
353 | */ | ||
354 | bool Network::serviceNeedsPassword(const QString& service) | ||
355 | { | ||
356 | Config cfg(service,Config::File); | ||
357 | cfg.setGroup("Info"); | ||
358 | QString type = cfg.readEntry("Type"); | ||
359 | NetworkInterface* plugin = Network::loadPlugin(type); | ||
360 | cfg.setGroup("Properties"); | ||
361 | return plugin ? plugin->needPassword(cfg) : FALSE; | ||
362 | } | ||
363 | |||
364 | /*! | ||
365 | \internal | ||
366 | */ | ||
367 | bool Network::networkOnline() | ||
368 | { | ||
369 | return ns && ns->networkOnline(); | ||
370 | } | ||
371 | |||
372 | /*! | ||
373 | \internal | ||
374 | */ | ||
375 | void Network::createServer(QObject* parent) | ||
376 | { | ||
377 | ns = new NetworkServer(parent); | ||
378 | } | ||
379 | |||
380 | /*! | ||
381 | \internal | ||
382 | */ | ||
383 | int Network::addStateWidgets(QWidget* parent) | ||
384 | { | ||
385 | int n=0; | ||
386 | QStringList l = Network::choices(); | ||
387 | QVBoxLayout* vb = new QVBoxLayout(parent); | ||
388 | for (QStringList::ConstIterator it=l.begin(); it!=l.end(); ++it) { | ||
389 | Config cfg(*it,Config::File); | ||
390 | cfg.setGroup("Info"); | ||
391 | QString type = cfg.readEntry("Type"); | ||
392 | NetworkInterface* plugin = Network::loadPlugin(type); | ||
393 | cfg.setGroup("Properties"); | ||
394 | if ( plugin ) { | ||
395 | QWidget* w; | ||
396 | if ( (w=plugin->addStateWidget(parent,cfg)) ) { | ||
397 | n++; | ||
398 | vb->addWidget(w); | ||
399 | } | ||
400 | } | ||
401 | } | ||
402 | return n; | ||
403 | } | ||
404 | |||
405 | static QDict<NetworkInterface> *ifaces; | ||
406 | |||
407 | /*! | ||
408 | \internal | ||
409 | */ | ||
410 | NetworkInterface* Network::loadPlugin(const QString& type) | ||
411 | { | ||
412 | #ifndef QT_NO_COMPONENT | ||
413 | if ( !ifaces ) ifaces = new QDict<NetworkInterface>; | ||
414 | NetworkInterface *iface = ifaces->find(type); | ||
415 | if ( !iface ) { | ||
416 | QString libfile = QPEApplication::qpeDir() + "/plugins/network/lib" + type + ".so"; | ||
417 | QLibrary lib(libfile); | ||
418 | if ( !lib.queryInterface( IID_Network, (QUnknownInterface**)&iface ) == QS_OK ) | ||
419 | return 0; | ||
420 | ifaces->insert(type,iface); | ||
421 | QString lang = getenv( "LANG" ); | ||
422 | QTranslator * trans = new QTranslator(qApp); | ||
423 | QString tfn = QPEApplication::qpeDir()+"/i18n/"+lang+"/lib"+type+".qm"; | ||
424 | if ( trans->load( tfn )) | ||
425 | qApp->installTranslator( trans ); | ||
426 | else | ||
427 | delete trans; | ||
428 | |||
429 | } | ||
430 | return iface; | ||
431 | #else | ||
432 | return 0; | ||
433 | #endif | ||
434 | } | ||
435 | |||
436 | #include "network.moc" | ||