~ubuntu-branches/ubuntu/utopic/psi/utopic

« back to all changes in this revision

Viewing changes to iris/example/conntest/conntest.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2009-09-25 17:49:51 UTC
  • mfrom: (6.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20090925174951-lvm7kdap82o8xhn3
Tags: 0.13-1
* Updated to upstream version 0.13
* Set Standards-Version to 3.8.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#include <qapplication.h>
2
 
#include "bconsole.h"
3
 
#include <QtCrypto>
4
 
#include "xmpp.h"
5
 
 
6
 
#include <stdio.h>
7
 
 
8
 
#define ROOTCERT_PATH "/usr/local/share/psi/certs/rootcert.xml"
9
 
 
10
 
QCA::Cert readCertXml(const QDomElement &e)
11
 
{
12
 
        QCA::Cert cert;
13
 
        // there should be one child data tag
14
 
        QDomElement data = e.elementsByTagName("data").item(0).toElement();
15
 
        if(!data.isNull())
16
 
                cert.fromDER(Base64::stringToArray(data.text()));
17
 
        return cert;
18
 
}
19
 
 
20
 
QPtrList<QCA::Cert> getRootCerts(const QString &store)
21
 
{
22
 
        QPtrList<QCA::Cert> list;
23
 
 
24
 
        // open the Psi rootcerts file
25
 
        QFile f(store);
26
 
        if(!f.open(IO_ReadOnly)) {
27
 
                printf("unable to open %s\n", f.name().latin1());
28
 
                return list;
29
 
        }
30
 
        QDomDocument doc;
31
 
        doc.setContent(&f);
32
 
        f.close();
33
 
 
34
 
        QDomElement base = doc.documentElement();
35
 
        if(base.tagName() != "store") {
36
 
                printf("wrong format of %s\n", f.name().latin1());
37
 
                return list;
38
 
        }
39
 
        QDomNodeList cl = base.elementsByTagName("certificate");
40
 
        if(cl.count() == 0) {
41
 
                printf("no certs found in %s\n", f.name().latin1());
42
 
                return list;
43
 
        }
44
 
 
45
 
        int num = 0;
46
 
        for(int n = 0; n < (int)cl.count(); ++n) {
47
 
                QCA::Cert *cert = new QCA::Cert(readCertXml(cl.item(n).toElement()));
48
 
                if(cert->isNull()) {
49
 
                        printf("error reading cert\n");
50
 
                        delete cert;
51
 
                        continue;
52
 
                }
53
 
 
54
 
                ++num;
55
 
                list.append(cert);
56
 
        }
57
 
        printf("imported %d root certs\n", num);
58
 
 
59
 
        return list;
60
 
}
61
 
 
62
 
static QString prompt(const QString &s)
63
 
{
64
 
        printf("* %s ", s.latin1());
65
 
        fflush(stdout);
66
 
        char line[256];
67
 
        fgets(line, 255, stdin);
68
 
        QString result = line;
69
 
        if(result[result.length()-1] == '\n')
70
 
                result.truncate(result.length()-1);
71
 
        return result;
72
 
}
73
 
 
74
 
static void showCertInfo(const QCA::Cert &cert)
75
 
{
76
 
        fprintf(stderr, "-- Cert --\n");
77
 
        fprintf(stderr, " CN: %s\n", cert.subject()["CN"].latin1());
78
 
        fprintf(stderr, " Valid from: %s, until %s\n",
79
 
                cert.notBefore().toString().latin1(),
80
 
                cert.notAfter().toString().latin1());
81
 
        fprintf(stderr, " PEM:\n%s\n", cert.toPEM().latin1());
82
 
}
83
 
 
84
 
static QString resultToString(int result)
85
 
{
86
 
        QString s;
87
 
        switch(result) {
88
 
                case QCA::TLS::NoCert:
89
 
                        s = QObject::tr("No certificate presented.");
90
 
                        break;
91
 
                case QCA::TLS::Valid:
92
 
                        break;
93
 
                case QCA::TLS::HostMismatch:
94
 
                        s = QObject::tr("Hostname mismatch.");
95
 
                        break;
96
 
                case QCA::TLS::Rejected:
97
 
                        s = QObject::tr("Root CA rejects the specified purpose.");
98
 
                        break;
99
 
                case QCA::TLS::Untrusted:
100
 
                        s = QObject::tr("Not trusted for the specified purpose.");
101
 
                        break;
102
 
                case QCA::TLS::SignatureFailed:
103
 
                        s = QObject::tr("Invalid signature.");
104
 
                        break;
105
 
                case QCA::TLS::InvalidCA:
106
 
                        s = QObject::tr("Invalid CA certificate.");
107
 
                        break;
108
 
                case QCA::TLS::InvalidPurpose:
109
 
                        s = QObject::tr("Invalid certificate purpose.");
110
 
                        break;
111
 
                case QCA::TLS::SelfSigned:
112
 
                        s = QObject::tr("Certificate is self-signed.");
113
 
                        break;
114
 
                case QCA::TLS::Revoked:
115
 
                        s = QObject::tr("Certificate has been revoked.");
116
 
                        break;
117
 
                case QCA::TLS::PathLengthExceeded:
118
 
                        s = QObject::tr("Maximum cert chain length exceeded.");
119
 
                        break;
120
 
                case QCA::TLS::Expired:
121
 
                        s = QObject::tr("Certificate has expired.");
122
 
                        break;
123
 
                case QCA::TLS::Unknown:
124
 
                default:
125
 
                        s = QObject::tr("General validation error.");
126
 
                        break;
127
 
        }
128
 
        return s;
129
 
}
130
 
 
131
 
class App : public QObject
132
 
{
133
 
        Q_OBJECT
134
 
public:
135
 
        XMPP::AdvancedConnector *conn;
136
 
        QCA::TLS *tls;
137
 
        XMPP::QCATLSHandler *tlsHandler;
138
 
        XMPP::ClientStream *stream;
139
 
        BConsole *c;
140
 
        XMPP::Jid jid;
141
 
        QPtrList<QCA::Cert> rootCerts;
142
 
 
143
 
        App(const XMPP::Jid &_jid, const XMPP::AdvancedConnector::Proxy &proxy, const QString &host, int port, bool opt_ssl, bool opt_probe)
144
 
        :QObject(0)
145
 
        {
146
 
                c = 0;
147
 
                jid = _jid;
148
 
 
149
 
                // Connector
150
 
                conn = new XMPP::AdvancedConnector;
151
 
                conn->setProxy(proxy);
152
 
                if(!host.isEmpty())
153
 
                        conn->setOptHostPort(host, port);
154
 
                conn->setOptProbe(opt_probe);
155
 
                conn->setOptSSL(opt_ssl);
156
 
 
157
 
                // TLSHandler
158
 
                tls = 0;
159
 
                tlsHandler = 0;
160
 
                rootCerts.setAutoDelete(true);
161
 
                if(QCA::isSupported(QCA::CAP_TLS)) {
162
 
                        rootCerts = getRootCerts(ROOTCERT_PATH);
163
 
                        tls = new QCA::TLS;
164
 
                        tls->setCertificateStore(rootCerts);
165
 
                        tlsHandler = new XMPP::QCATLSHandler(tls);
166
 
                        connect(tlsHandler, SIGNAL(tlsHandshaken()), SLOT(tls_handshaken()));
167
 
                }
168
 
 
169
 
                // Stream
170
 
                stream = new XMPP::ClientStream(conn, tlsHandler);
171
 
                connect(stream, SIGNAL(connected()), SLOT(cs_connected()));
172
 
                connect(stream, SIGNAL(securityLayerActivated(int)), SLOT(cs_securityLayerActivated()));
173
 
                connect(stream, SIGNAL(needAuthParams(bool, bool, bool)), SLOT(cs_needAuthParams(bool, bool, bool)));
174
 
                connect(stream, SIGNAL(authenticated()), SLOT(cs_authenticated()));
175
 
                connect(stream, SIGNAL(connectionClosed()), SLOT(cs_connectionClosed()));
176
 
                connect(stream, SIGNAL(readyRead()), SLOT(cs_readyRead()));
177
 
                connect(stream, SIGNAL(stanzaWritten()), SLOT(cs_stanzaWritten()));
178
 
                connect(stream, SIGNAL(warning(int)), SLOT(cs_warning(int)));
179
 
                connect(stream, SIGNAL(error(int)), SLOT(cs_error(int)));
180
 
 
181
 
                fprintf(stderr, "conntest: Connecting ...\n");
182
 
                stream->setSSFRange(0, 256);
183
 
                stream->connectToServer(jid);
184
 
        }
185
 
 
186
 
        ~App()
187
 
        {
188
 
                delete stream;
189
 
                delete tls; // this destroys the TLSHandler also
190
 
                delete conn;
191
 
                delete c;
192
 
        }
193
 
 
194
 
signals:
195
 
        void quit();
196
 
 
197
 
private slots:
198
 
        void tls_handshaken()
199
 
        {
200
 
                QCA::Cert cert = tls->peerCertificate();
201
 
                int vr = tls->certificateValidityResult();
202
 
 
203
 
                fprintf(stderr, "conntest: Successful TLS handshake.\n");
204
 
                if(!cert.isNull())
205
 
                        showCertInfo(cert);
206
 
                if(vr == QCA::TLS::Valid)
207
 
                        fprintf(stderr, "conntest: Valid certificate.\n");
208
 
                else
209
 
                        fprintf(stderr, "conntest: Invalid certificate: %s\n", resultToString(vr).latin1());
210
 
 
211
 
                tlsHandler->continueAfterHandshake();
212
 
        }
213
 
 
214
 
        void cs_connected()
215
 
        {
216
 
                fprintf(stderr, "conntest: Connected\n");
217
 
        }
218
 
 
219
 
        void cs_securityLayerActivated()
220
 
        {
221
 
                fprintf(stderr, "conntest: Security layer activated (%s)\n", tls->isHandshaken() ? "TLS": "SASL");
222
 
        }
223
 
 
224
 
        void cs_needAuthParams(bool user, bool pass, bool realm)
225
 
        {
226
 
                fprintf(stderr, "conntest: need auth params -");
227
 
                if(user)
228
 
                        fprintf(stderr, " (user)");
229
 
                if(pass)
230
 
                        fprintf(stderr, " (pass)");
231
 
                if(realm)
232
 
                        fprintf(stderr, " (realm)");
233
 
                fprintf(stderr, "\n");
234
 
 
235
 
                if(user)
236
 
                        stream->setUsername(jid.node());
237
 
                if(pass)
238
 
                        stream->setPassword(prompt("Password (not hidden!) :"));
239
 
                stream->continueAfterParams();
240
 
        }
241
 
 
242
 
        void cs_authenticated()
243
 
        {
244
 
                fprintf(stderr, "conntest: <<< Authenticated >>>\n");
245
 
 
246
 
                // console
247
 
                c = new BConsole;
248
 
                connect(c, SIGNAL(connectionClosed()), SLOT(con_connectionClosed()));
249
 
                connect(c, SIGNAL(readyRead()), SLOT(con_readyRead()));
250
 
        }
251
 
 
252
 
        void cs_connectionClosed()
253
 
        {
254
 
                fprintf(stderr, "conntest: Disconnected by peer\n");
255
 
                quit();
256
 
        }
257
 
 
258
 
        void cs_readyRead()
259
 
        {
260
 
                for(XMPP::Stanza s; !(s = stream->read()).isNull();) {
261
 
                        QString str = s.toString();
262
 
                        printf("%s\n", str.local8Bit().data());
263
 
                }
264
 
        }
265
 
 
266
 
        void cs_stanzaWritten()
267
 
        {
268
 
                fprintf(stderr, "conntest: Stanza written\n");
269
 
        }
270
 
 
271
 
        void cs_warning(int warn)
272
 
        {
273
 
                if(warn == XMPP::ClientStream::WarnOldVersion) {
274
 
                        fprintf(stderr, "conntest: Warning: pre-1.0 protocol server\n");
275
 
                }
276
 
                else if(warn == XMPP::ClientStream::WarnNoTLS) {
277
 
                        fprintf(stderr, "conntest: Warning: TLS not available!\n");
278
 
                }
279
 
                stream->continueAfterWarning();
280
 
        }
281
 
 
282
 
        void cs_error(int err)
283
 
        {
284
 
                if(err == XMPP::ClientStream::ErrParse) {
285
 
                        fprintf(stderr, "conntest: XML parsing error\n");
286
 
                }
287
 
                else if(err == XMPP::ClientStream::ErrProtocol) {
288
 
                        fprintf(stderr, "conntest: XMPP protocol error\n");
289
 
                }
290
 
                else if(err == XMPP::ClientStream::ErrStream) {
291
 
                        int x = stream->errorCondition();
292
 
                        QString s;
293
 
                        if(x == XMPP::Stream::GenericStreamError)
294
 
                                s = "generic stream error";
295
 
                        else if(x == XMPP::ClientStream::Conflict)
296
 
                                s = "conflict (remote login replacing this one)";
297
 
                        else if(x == XMPP::ClientStream::ConnectionTimeout)
298
 
                                s = "timed out from inactivity";
299
 
                        else if(x == XMPP::ClientStream::InternalServerError)
300
 
                                s = "internal server error";
301
 
                        else if(x == XMPP::ClientStream::InvalidXml)
302
 
                                s = "invalid XML";
303
 
                        else if(x == XMPP::ClientStream::PolicyViolation)
304
 
                                s = "policy violation.  go to jail!";
305
 
                        else if(x == XMPP::ClientStream::ResourceConstraint)
306
 
                                s = "server out of resources";
307
 
                        else if(x == XMPP::ClientStream::SystemShutdown)
308
 
                                s = "system is shutting down NOW";
309
 
                        fprintf(stderr, "conntest: XMPP stream error: %s\n", s.latin1());
310
 
                }
311
 
                else if(err == XMPP::ClientStream::ErrConnection) {
312
 
                        int x = conn->errorCode();
313
 
                        QString s;
314
 
                        if(x == XMPP::AdvancedConnector::ErrConnectionRefused)
315
 
                                s = "unable to connect to server";
316
 
                        else if(x == XMPP::AdvancedConnector::ErrHostNotFound)
317
 
                                s = "host not found";
318
 
                        else if(x == XMPP::AdvancedConnector::ErrProxyConnect)
319
 
                                s = "proxy connect";
320
 
                        else if(x == XMPP::AdvancedConnector::ErrProxyNeg)
321
 
                                s = "proxy negotiating";
322
 
                        else if(x == XMPP::AdvancedConnector::ErrProxyAuth)
323
 
                                s = "proxy authorization";
324
 
                        else if(x == XMPP::AdvancedConnector::ErrStream)
325
 
                                s = "stream error";
326
 
                        fprintf(stderr, "conntest: connection error: %s\n", s.latin1());
327
 
                }
328
 
                else if(err == XMPP::ClientStream::ErrNeg) {
329
 
                        int x = stream->errorCondition();
330
 
                        QString s;
331
 
                        if(x == XMPP::ClientStream::HostGone)
332
 
                                s = "host no longer hosted";
333
 
                        else if(x == XMPP::ClientStream::HostUnknown)
334
 
                                s = "host unknown";
335
 
                        else if(x == XMPP::ClientStream::RemoteConnectionFailed)
336
 
                                s = "a required remote connection failed";
337
 
                        else if(x == XMPP::ClientStream::SeeOtherHost)
338
 
                                s = QString("see other host: [%1]").arg(stream->errorText());
339
 
                        else if(x == XMPP::ClientStream::UnsupportedVersion)
340
 
                                s = "server does not support proper xmpp version";
341
 
                        fprintf(stderr, "conntest: stream negotiation error: %s\n", s.latin1());
342
 
                }
343
 
                else if(err == XMPP::ClientStream::ErrTLS) {
344
 
                        int x = stream->errorCondition();
345
 
                        QString s;
346
 
                        if(x == XMPP::ClientStream::TLSStart)
347
 
                                s = "server rejected STARTTLS";
348
 
                        else if(x == XMPP::ClientStream::TLSFail) {
349
 
                                int t = tlsHandler->tlsError();
350
 
                                if(t == QCA::TLS::ErrHandshake)
351
 
                                        s = "TLS handshake error";
352
 
                                else
353
 
                                        s = "broken security layer (TLS)";
354
 
                        }
355
 
                        fprintf(stderr, "conntest: %s\n", s.latin1());
356
 
                }
357
 
                else if(err == XMPP::ClientStream::ErrAuth) {
358
 
                        int x = stream->errorCondition();
359
 
                        QString s;
360
 
                        if(x == XMPP::ClientStream::GenericAuthError)
361
 
                                s = "unable to login";
362
 
                        else if(x == XMPP::ClientStream::NoMech)
363
 
                                s = "no appropriate auth mechanism available for given security settings";
364
 
                        else if(x == XMPP::ClientStream::BadProto)
365
 
                                s = "bad server response";
366
 
                        else if(x == XMPP::ClientStream::BadServ)
367
 
                                s = "server failed mutual authentication";
368
 
                        else if(x == XMPP::ClientStream::EncryptionRequired)
369
 
                                s = "encryption required for chosen SASL mechanism";
370
 
                        else if(x == XMPP::ClientStream::InvalidAuthzid)
371
 
                                s = "invalid authzid";
372
 
                        else if(x == XMPP::ClientStream::InvalidMech)
373
 
                                s = "invalid SASL mechanism";
374
 
                        else if(x == XMPP::ClientStream::InvalidRealm)
375
 
                                s = "invalid realm";
376
 
                        else if(x == XMPP::ClientStream::MechTooWeak)
377
 
                                s = "SASL mechanism too weak for authzid";
378
 
                        else if(x == XMPP::ClientStream::NotAuthorized)
379
 
                                s = "not authorized";
380
 
                        else if(x == XMPP::ClientStream::TemporaryAuthFailure)
381
 
                                s = "temporary auth failure";
382
 
                        fprintf(stderr, "conntest: auth error: %s\n", s.latin1());
383
 
                }
384
 
                else if(err == XMPP::ClientStream::ErrSecurityLayer)
385
 
                        fprintf(stderr, "conntest: broken security layer (SASL)\n");
386
 
                quit();
387
 
        }
388
 
 
389
 
        void con_connectionClosed()
390
 
        {
391
 
                fprintf(stderr, "conntest: Closing.\n");
392
 
                stream->close();
393
 
                quit();
394
 
        }
395
 
 
396
 
        void con_readyRead()
397
 
        {
398
 
                QByteArray a = c->read();
399
 
                QCString cs;
400
 
                cs.resize(a.size()+1);
401
 
                memcpy(cs.data(), a.data(), a.size());
402
 
                QString s = QString::fromLocal8Bit(cs);
403
 
                stream->writeDirect(s);
404
 
        }
405
 
};
406
 
 
407
 
#include "conntest.moc"
408
 
 
409
 
int main(int argc, char **argv)
410
 
{
411
 
        QApplication app(argc, argv, false);
412
 
 
413
 
        if(argc < 2) {
414
 
                printf("usage: conntest [options] [jid]\n");
415
 
                printf("   Options:\n");
416
 
                printf("     --host=host:port\n");
417
 
                printf("     --sslhost=host:port\n");
418
 
                printf("     --probe\n");
419
 
                printf("     --proxy=[https|poll|socks],host:port,url\n");
420
 
                printf("     --proxy-auth=user,pass\n");
421
 
                printf("\n");
422
 
                return 0;
423
 
        }
424
 
 
425
 
        bool have_tls = QCA::isSupported(QCA::CAP_TLS);
426
 
 
427
 
        XMPP::Jid jid;
428
 
        XMPP::AdvancedConnector::Proxy proxy;
429
 
        QString host;
430
 
        int port = 0;
431
 
        bool opt_ssl = false;
432
 
        bool opt_probe = false;
433
 
 
434
 
        for(int at = 1; at < argc; ++at) {
435
 
                QString s = argv[at];
436
 
 
437
 
                // is it an option?
438
 
                if(s.left(2) == "--") {
439
 
                        QString name;
440
 
                        QStringList args;
441
 
                        int n = s.find('=', 2);
442
 
                        if(n != -1) {
443
 
                                name = s.mid(2, n-2);
444
 
                                ++n;
445
 
                                args = QStringList::split(',', s.mid(n), true);
446
 
                        }
447
 
                        else {
448
 
                                name = s.mid(2);
449
 
                                args.clear();
450
 
                        }
451
 
 
452
 
                        // eat the arg
453
 
                        --argc;
454
 
                        for(int x = at; x < argc; ++x)
455
 
                                argv[x] = argv[x+1];
456
 
                        --at; // don't advance
457
 
 
458
 
                        // process option
459
 
                        if(name == "proxy") {
460
 
                                QString proxy_host;
461
 
                                int proxy_port = 0;
462
 
                                QString type = args[0];
463
 
                                QString s = args[1];
464
 
                                int n = s.find(':');
465
 
                                if(n == -1) {
466
 
                                        if(type != "poll") {
467
 
                                                printf("Invalid host:port for proxy\n");
468
 
                                                return 0;
469
 
                                        }
470
 
                                }
471
 
                                else {
472
 
                                        proxy_host = s.mid(0, n);
473
 
                                        ++n;
474
 
                                        proxy_port = s.mid(n).toInt();
475
 
                                }
476
 
 
477
 
                                if(type == "https") {
478
 
                                        proxy.setHttpConnect(proxy_host, proxy_port);
479
 
                                }
480
 
                                else if(type == "poll") {
481
 
                                        if(args.count() < 3) {
482
 
                                                printf("poll needs more args\n");
483
 
                                                return 0;
484
 
                                        }
485
 
                                        QString proxy_url = args[2];
486
 
                                        proxy.setHttpPoll(proxy_host, proxy_port, proxy_url);
487
 
                                }
488
 
                                else if(type == "socks") {
489
 
                                        proxy.setSocks(proxy_host, proxy_port);
490
 
                                }
491
 
                                else {
492
 
                                        printf("No such proxy type '%s'\n", type.latin1());
493
 
                                        return 0;
494
 
                                }
495
 
                        }
496
 
                        else if(name == "proxy-auth") {
497
 
                                proxy.setUserPass(args[0], args[1]);
498
 
                        }
499
 
                        else if(name == "host") {
500
 
                                QString s = args[0];
501
 
                                int n = s.find(':');
502
 
                                if(n == -1) {
503
 
                                        printf("Invalid host:port for host\n");
504
 
                                        return 0;
505
 
                                }
506
 
                                host = s.mid(0, n);
507
 
                                ++n;
508
 
                                port = s.mid(n).toInt();
509
 
                        }
510
 
                        else if(name == "sslhost") {
511
 
                                QString s = args[0];
512
 
                                int n = s.find(':');
513
 
                                if(n == -1) {
514
 
                                        printf("Invalid host:port for host\n");
515
 
                                        return 0;
516
 
                                }
517
 
                                host = s.mid(0, n);
518
 
                                ++n;
519
 
                                port = s.mid(n).toInt();
520
 
                                opt_ssl = true;
521
 
                        }
522
 
                        else if(name == "probe") {
523
 
                                opt_probe = true;
524
 
                        }
525
 
                        else {
526
 
                                printf("Unknown option '%s'\n", name.latin1());
527
 
                                return 0;
528
 
                        }
529
 
                }
530
 
        }
531
 
 
532
 
        if(argc < 2) {
533
 
                printf("No host specified!\n");
534
 
                return 0;
535
 
        }
536
 
        jid = argv[1];
537
 
 
538
 
        if((opt_ssl || opt_probe) && !have_tls) {
539
 
                printf("TLS not supported, so the sslhost and probe options are not allowed.\n");
540
 
                return 0;
541
 
        }
542
 
 
543
 
        printf("JID: %s\n", jid.full().latin1());
544
 
        if(proxy.type() != XMPP::AdvancedConnector::Proxy::None) {
545
 
                printf("Proxy: ");
546
 
                if(proxy.type() == XMPP::AdvancedConnector::Proxy::HttpConnect)
547
 
                        printf("HttpConnect (%s:%d)", proxy.host().latin1(), proxy.port());
548
 
                else if(proxy.type() == XMPP::AdvancedConnector::Proxy::HttpPoll) {
549
 
                        printf("HttpPoll {%s}", proxy.url().latin1());
550
 
                        if(!proxy.host().isEmpty()) {
551
 
                                printf(" (%s:%d)", proxy.host().latin1(), proxy.port());
552
 
                        }
553
 
                }
554
 
                else if(proxy.type() == XMPP::AdvancedConnector::Proxy::Socks)
555
 
                        printf("Socks (%s:%d)", proxy.host().latin1(), proxy.port());
556
 
                printf("\n");
557
 
        }
558
 
        if(proxy.type() != XMPP::AdvancedConnector::Proxy::HttpPoll) {
559
 
                if(!host.isEmpty()) {
560
 
                        printf("Host: %s:%d", host.latin1(), port);
561
 
                        if(opt_ssl)
562
 
                                printf(" (ssl)");
563
 
                        printf("\n");
564
 
                }
565
 
                else {
566
 
                        if(opt_probe)
567
 
                                printf("Probe active\n");
568
 
                }
569
 
        }
570
 
        printf("----------\n");
571
 
 
572
 
        App *a = new App(jid, proxy, host, port, opt_ssl, opt_probe);
573
 
        QObject::connect(a, SIGNAL(quit()), &app, SLOT(quit()));
574
 
        app.exec();
575
 
        delete a;
576
 
 
577
 
        return 0;
578
 
}