~ubuntu-branches/ubuntu/oneiric/psi/oneiric

« back to all changes in this revision

Viewing changes to src/xmpp_xdata.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2005-01-10 17:41:43 UTC
  • mfrom: (1.2.1 upstream) (2.1.2 hoary)
  • Revision ID: james.westby@ubuntu.com-20050110174143-ltocv5zapl6blf5d
Tags: 0.9.3-1
* New upstream release
* Cleaned up debian/rules (some things are done by upstream Makefiles now)
* Fixed some lintian warnings:
  - removed executable bit from some .png files
  - moved psi.desktop to /usr/share/applications
* Updated menu files

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * xmpp_xdata.cpp - a class for jabber:x:data forms
 
3
 * Copyright (C) 2003-2004  Michail Pishchagin
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU General Public License
 
7
 * as published by the Free Software Foundation; either version 2
 
8
 * of the License, or (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 library; if not, write to the Free Software
 
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 *
 
19
 */
 
20
 
 
21
#include "xmpp_xdata.h"
 
22
 
 
23
#include <qshared.h>
 
24
 
 
25
#include "im.h" // for JID validation
 
26
#include "xmpp_xmlcommon.h"
 
27
 
 
28
using namespace XMPP;
 
29
using namespace XMLHelper;
 
30
 
 
31
// TODO: report, item
 
32
 
 
33
//----------------------------------------------------------------------------
 
34
// XData::Field
 
35
//----------------------------------------------------------------------------
 
36
XData::Field::Field()
 
37
{
 
38
}
 
39
 
 
40
XData::Field::~Field()
 
41
{
 
42
}
 
43
 
 
44
QString XData::Field::desc() const
 
45
{
 
46
        return _desc;
 
47
}
 
48
 
 
49
void XData::Field::setDesc(const QString &d)
 
50
{
 
51
        _desc = d;
 
52
}
 
53
 
 
54
XData::Field::OptionList XData::Field::options() const
 
55
{
 
56
        return _options;
 
57
}
 
58
 
 
59
void XData::Field::setOptions(XData::Field::OptionList o)
 
60
{
 
61
        _options = o;
 
62
}
 
63
 
 
64
bool XData::Field::required() const
 
65
{
 
66
        return _required;
 
67
}
 
68
 
 
69
void XData::Field::setRequired(bool r)
 
70
{
 
71
        _required = r;
 
72
}
 
73
 
 
74
QString XData::Field::label() const
 
75
{
 
76
        return _label;
 
77
}
 
78
 
 
79
void XData::Field::setLabel(const QString &l)
 
80
{
 
81
        _label = l;
 
82
}
 
83
 
 
84
QString XData::Field::var() const
 
85
{
 
86
        return _var;
 
87
}
 
88
 
 
89
void XData::Field::setVar(const QString &v)
 
90
{
 
91
        _var = v;
 
92
}
 
93
 
 
94
QStringList XData::Field::value() const
 
95
{
 
96
        return _value;
 
97
}
 
98
 
 
99
void XData::Field::setValue(const QStringList &v)
 
100
{
 
101
        _value = v;
 
102
}
 
103
 
 
104
XData::Field::Type XData::Field::type() const
 
105
{
 
106
        return _type;
 
107
}
 
108
 
 
109
void XData::Field::setType(XData::Field::Type t)
 
110
{
 
111
        _type = t;
 
112
}
 
113
 
 
114
bool XData::Field::isValid() const
 
115
{
 
116
        if ( _required && _value.isEmpty() )
 
117
                return false;
 
118
 
 
119
        if ( _type == Field_Boolean ) {
 
120
                if ( _value.count() != 1 )
 
121
                        return false;
 
122
 
 
123
                QString str = _value.first();
 
124
                if ( str == "0" || str == "1" || str == "true" || str == "false" || str == "yes" || str == "no" )
 
125
                        return true;
 
126
        }
 
127
        if ( _type == Field_TextSingle || _type == Field_TextPrivate ) {
 
128
                if ( _value.count() == 1 )
 
129
                        return true;
 
130
        }
 
131
        if ( _type == Field_JidSingle ) {
 
132
                if ( _value.count() != 1 )
 
133
                        return false;
 
134
 
 
135
                Jid j( _value.first() );
 
136
                return j.isValid();
 
137
        }
 
138
        if ( _type == Field_JidMulti ) {
 
139
                QStringList::ConstIterator it = _value.begin();
 
140
                bool allValid = true;
 
141
                for ( ; it != _value.end(); ++it) {
 
142
                        Jid j(*it);
 
143
                        if ( !j.isValid() ) {
 
144
                                allValid = false;
 
145
                                break;
 
146
                        }
 
147
                }
 
148
                return allValid;
 
149
        }
 
150
 
 
151
        return false;
 
152
}
 
153
 
 
154
void XData::Field::fromXml(const QDomElement &e)
 
155
{
 
156
        if ( e.tagName() != "field" )
 
157
                return;
 
158
 
 
159
        _var = e.attribute("var");
 
160
        _label = e.attribute("label");
 
161
 
 
162
        QString type = e.attribute("type");
 
163
        if ( type == "boolean" )
 
164
                _type = Field_Boolean;
 
165
        else if ( type == "fixed" )
 
166
                _type = Field_Fixed;
 
167
        else if ( type == "hidden" )
 
168
                _type = Field_Hidden;
 
169
        else if ( type == "jid-multi" )
 
170
                _type = Field_JidMulti;
 
171
        else if ( type == "jid-single" )
 
172
                _type = Field_JidSingle;
 
173
        else if ( type == "list-multi" )
 
174
                _type = Field_ListMulti;
 
175
        else if ( type == "list-single" )
 
176
                _type = Field_ListSingle;
 
177
        else if ( type == "text-multi" )
 
178
                _type = Field_TextMulti;
 
179
        else if ( type == "text-private" )
 
180
                _type = Field_TextPrivate;
 
181
        else
 
182
                _type = Field_TextSingle;
 
183
 
 
184
        _required = false;
 
185
        _desc     = QString::null;
 
186
        _options.clear();
 
187
        _value.clear();
 
188
 
 
189
        QDomNode n = e.firstChild();
 
190
        for ( ; !n.isNull(); n = n.nextSibling() ) {
 
191
                QDomElement i = n.toElement();
 
192
                if ( i.isNull() )
 
193
                        continue;
 
194
 
 
195
                QString tag = i.tagName();
 
196
                if ( tag == "required" )
 
197
                        _required = true;
 
198
                else if ( tag == "desc" )
 
199
                        _desc = i.text().simplifyWhiteSpace();
 
200
                else if ( tag == "option" ) {
 
201
                        Option o;
 
202
                        bool found;
 
203
                        o.label = i.attribute("label");
 
204
 
 
205
                        QDomElement e = findSubTag( i, "value", &found );
 
206
                        o.value = ( found ? e.text() : QString("") );
 
207
                        _options.append(o);
 
208
                }
 
209
                else if ( tag == "value" ) {
 
210
                        _value.append(i.text());
 
211
                }
 
212
        }
 
213
}
 
214
 
 
215
QDomElement XData::Field::toXml(QDomDocument *doc, bool submitForm) const
 
216
{
 
217
        QDomElement f = doc->createElement("field");
 
218
 
 
219
        // setting attributes...
 
220
        if ( !_var.isEmpty() )
 
221
                f.setAttribute("var", _var);
 
222
        if ( !submitForm && !_label.isEmpty() )
 
223
                f.setAttribute("label", _label);
 
224
 
 
225
        // now we're gonna get the 'type'
 
226
        QString type = "text-single";
 
227
        if ( _type == Field_Boolean )
 
228
                type = "boolean";
 
229
        else if ( _type == Field_Fixed )
 
230
                type = "fixed";
 
231
        else if ( _type == Field_Hidden )
 
232
                type = "hidden";
 
233
        else if ( _type == Field_JidMulti )
 
234
                type = "jid-multi";
 
235
        else if ( _type == Field_JidSingle )
 
236
                type = "jid-single";
 
237
        else if ( _type == Field_ListMulti )
 
238
                type = "list-multi";
 
239
        else if ( _type == Field_ListSingle )
 
240
                type = "list-single";
 
241
        else if ( _type == Field_TextMulti )
 
242
                type = "text-multi";
 
243
        else if ( _type == Field_TextPrivate )
 
244
                type = "text-private";
 
245
 
 
246
        f.setAttribute("type", type);
 
247
 
 
248
        // now, setting nested tags...
 
249
        if ( !submitForm && _required )
 
250
                f.appendChild( emptyTag(doc, "required") );
 
251
 
 
252
        if ( !submitForm && !_desc.isEmpty() )
 
253
                f.appendChild( textTag(doc, "desc", _desc) );
 
254
 
 
255
        if ( !submitForm && !_options.isEmpty() ) {
 
256
                OptionList::ConstIterator it = _options.begin();
 
257
                for ( ; it != _options.end(); ++it) {
 
258
                        QDomElement o = doc->createElement("option");
 
259
                        o.appendChild(textTag(doc, "value", (*it).value));
 
260
                        if ( !(*it).label.isEmpty() )
 
261
                                o.setAttribute("label", (*it).label);
 
262
                        f.appendChild(o);
 
263
                }
 
264
        }
 
265
 
 
266
        if ( !_value.isEmpty() ) {
 
267
                QStringList::ConstIterator it = _value.begin();
 
268
                for ( ; it != _value.end(); ++it) 
 
269
                        f.appendChild( textTag(doc, "value", *it) );
 
270
        }
 
271
 
 
272
        return f;
 
273
}
 
274
 
 
275
//----------------------------------------------------------------------------
 
276
// XData
 
277
//----------------------------------------------------------------------------
 
278
class XData::Private : public QShared {
 
279
public:
 
280
        QString title, instructions;
 
281
        XData::Type type;
 
282
        FieldList fields;
 
283
        QValueList<ReportField> report;
 
284
        QValueList<ReportItem>  reportItems;
 
285
};
 
286
 
 
287
XData::XData()
 
288
{
 
289
        d = new Private;
 
290
}
 
291
 
 
292
XData::~XData()
 
293
{
 
294
        if ( d->deref() )
 
295
                delete d;
 
296
}
 
297
 
 
298
XData::XData(const XData &x)
 
299
{
 
300
        d = x.d;
 
301
        d->ref();
 
302
}
 
303
 
 
304
QString XData::title() const
 
305
{
 
306
        return d->title;
 
307
}
 
308
 
 
309
void XData::setTitle(const QString &t)
 
310
{
 
311
        detach();
 
312
        d->title = t;
 
313
}
 
314
 
 
315
QString XData::instructions() const
 
316
{
 
317
        return d->instructions;
 
318
}
 
319
 
 
320
void XData::setInstructions(const QString &i)
 
321
{
 
322
        detach();
 
323
        d->instructions = i;
 
324
}
 
325
 
 
326
XData::Type XData::type() const
 
327
{
 
328
        return d->type;
 
329
}
 
330
 
 
331
void XData::setType(Type t)
 
332
{
 
333
        detach();
 
334
        d->type = t;
 
335
}
 
336
 
 
337
XData::FieldList XData::fields() const
 
338
{
 
339
        return d->fields;
 
340
}
 
341
 
 
342
void XData::setFields(const FieldList &f)
 
343
{
 
344
        detach();
 
345
        d->fields = f;
 
346
}
 
347
 
 
348
void XData::fromXml(const QDomElement &e)
 
349
{
 
350
        if ( e.attribute("xmlns") != "jabber:x:data" )
 
351
                return;
 
352
 
 
353
        detach();
 
354
 
 
355
        QString type = e.attribute("type");
 
356
        if ( type == "result" )
 
357
                d->type = Data_Result;
 
358
        else if ( type == "submit" )
 
359
                d->type = Data_Submit;
 
360
        else if ( type == "cancel" )
 
361
                d->type = Data_Cancel;
 
362
        else
 
363
                d->type = Data_Form;
 
364
 
 
365
        d->title        = subTagText(e, "title");
 
366
        d->instructions = subTagText(e, "instructions");
 
367
 
 
368
        d->fields.clear();
 
369
 
 
370
        QDomNode n = e.firstChild();
 
371
        for ( ; !n.isNull(); n = n.nextSibling() ) {
 
372
                QDomElement i = n.toElement();
 
373
                if ( i.isNull() )
 
374
                        continue;
 
375
 
 
376
                if ( i.tagName() == "field" ) {
 
377
                        Field f;
 
378
                        f.fromXml(i);
 
379
                        d->fields.append(f);
 
380
                }
 
381
                else if ( i.tagName() == "reported" ) {
 
382
                        d->report.clear();
 
383
                        d->reportItems.clear();
 
384
 
 
385
                        QDomNode nn = i.firstChild();
 
386
                        for ( ; !nn.isNull(); nn = nn.nextSibling() ) {
 
387
                                QDomElement ii = nn.toElement();
 
388
                                if ( ii.isNull() )
 
389
                                        continue;
 
390
 
 
391
                                if ( ii.tagName() == "field" ) {
 
392
                                        d->report.append( ReportField( ii.attribute("label"), ii.attribute("var") ) );
 
393
                                }
 
394
                        }
 
395
                }
 
396
                else if ( i.tagName() == "item" ) {
 
397
                        ReportItem item;
 
398
 
 
399
                        QDomNode nn = i.firstChild();
 
400
                        for ( ; !nn.isNull(); nn = nn.nextSibling() ) {
 
401
                                QDomElement ii = nn.toElement();
 
402
                                if ( ii.isNull() )
 
403
                                        continue;
 
404
 
 
405
                                if ( ii.tagName() == "field" ) {
 
406
                                        QString name = ii.attribute("var");
 
407
                                        QString value;
 
408
 
 
409
                                        bool found;
 
410
                                        QDomElement e = findSubTag( ii, "value", &found );
 
411
                                        if ( found )
 
412
                                                value = e.text();
 
413
 
 
414
                                        item[name] = value;
 
415
                                }
 
416
                        }
 
417
 
 
418
                        d->reportItems.append( item );
 
419
                }
 
420
        }
 
421
}
 
422
 
 
423
QDomElement XData::toXml(QDomDocument *doc, bool submitForm) const
 
424
{
 
425
        QDomElement x = doc->createElement("x");
 
426
        x.setAttribute("xmlns", "jabber:x:data");
 
427
 
 
428
        QString type = "form";
 
429
        if ( d->type == Data_Result )
 
430
                type = "result";
 
431
        else if ( d->type == Data_Submit )
 
432
                type = "submit";
 
433
        else if ( d->type == Data_Cancel )
 
434
                type = "cancel";
 
435
 
 
436
        x.setAttribute("type", type);
 
437
 
 
438
        if ( !submitForm && !d->title.isEmpty() )
 
439
                x.appendChild( textTag(doc, "title", d->title) );
 
440
        if ( !submitForm && !d->instructions.isEmpty() )
 
441
                x.appendChild( textTag(doc, "instructions", d->instructions) );
 
442
 
 
443
        if ( !d->fields.isEmpty() ) {
 
444
                FieldList::ConstIterator it = d->fields.begin();
 
445
                for ( ; it != d->fields.end(); ++it) {
 
446
                        Field f = *it;
 
447
                        if ( !(submitForm && f.var().isEmpty()) )
 
448
                                x.appendChild( f.toXml(doc, submitForm) );
 
449
                }
 
450
        }
 
451
 
 
452
        return x;
 
453
}
 
454
 
 
455
XData &XData::operator= (const XData &from)
 
456
{
 
457
        if ( d->deref() )
 
458
                delete d;
 
459
 
 
460
        d = from.d;
 
461
        d->ref();
 
462
 
 
463
        return *this;
 
464
}
 
465
 
 
466
XData XData::copy() const
 
467
{
 
468
        XData foo;
 
469
        delete foo.d;
 
470
        foo.d = new Private( *this->d );
 
471
 
 
472
        return foo;
 
473
}
 
474
 
 
475
void XData::detach()
 
476
{
 
477
        if ( d->count != 1 ) // only if >1 reference
 
478
                *this = copy();
 
479
}
 
480
 
 
481
const QValueList<XData::ReportField> &XData::report() const
 
482
{
 
483
        return d->report;
 
484
}
 
485
 
 
486
const QValueList<XData::ReportItem> &XData::reportItems() const
 
487
{
 
488
        return d->reportItems;
 
489
}