File indexing completed on 2024-06-23 04:03:43
0001 /* 0002 * xmpp_xdata.cpp - a class for jabber:x:data forms 0003 * Copyright (C) 2003-2004 Michail Pishchagin 0004 * 0005 * This program is free software; you can redistribute it and/or 0006 * modify it under the terms of the GNU General Public License 0007 * as published by the Free Software Foundation; either version 2 0008 * of the License, or (at your option) any later version. 0009 * 0010 * This program is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0013 * GNU General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU General Public License 0016 * along with this library; if not, write to the Free Software 0017 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 0018 * 0019 */ 0020 0021 #include "xmpp_xdata.h" 0022 #include "xmpp_xmlcommon.h" 0023 #include "xmpp/jid/jid.h" 0024 0025 0026 using namespace XMPP; 0027 using namespace XMLHelper; 0028 0029 // TODO: report, item 0030 0031 //---------------------------------------------------------------------------- 0032 // XData::Field 0033 //---------------------------------------------------------------------------- 0034 XData::Field::Field() 0035 { 0036 } 0037 0038 XData::Field::~Field() 0039 { 0040 } 0041 0042 QString XData::Field::desc() const 0043 { 0044 return _desc; 0045 } 0046 0047 void XData::Field::setDesc(const QString &d) 0048 { 0049 _desc = d; 0050 } 0051 0052 XData::Field::OptionList XData::Field::options() const 0053 { 0054 return _options; 0055 } 0056 0057 void XData::Field::setOptions(XData::Field::OptionList o) 0058 { 0059 _options = o; 0060 } 0061 0062 bool XData::Field::required() const 0063 { 0064 return _required; 0065 } 0066 0067 void XData::Field::setRequired(bool r) 0068 { 0069 _required = r; 0070 } 0071 0072 QString XData::Field::label() const 0073 { 0074 return _label; 0075 } 0076 0077 void XData::Field::setLabel(const QString &l) 0078 { 0079 _label = l; 0080 } 0081 0082 QString XData::Field::var() const 0083 { 0084 return _var; 0085 } 0086 0087 void XData::Field::setVar(const QString &v) 0088 { 0089 _var = v; 0090 } 0091 0092 QStringList XData::Field::value() const 0093 { 0094 return _value; 0095 } 0096 0097 void XData::Field::setValue(const QStringList &v) 0098 { 0099 _value = v; 0100 } 0101 0102 XData::Field::Type XData::Field::type() const 0103 { 0104 return _type; 0105 } 0106 0107 void XData::Field::setType(XData::Field::Type t) 0108 { 0109 _type = t; 0110 } 0111 0112 bool XData::Field::isValid() const 0113 { 0114 if ( _required && _value.isEmpty() ) 0115 return false; 0116 0117 if ( _type == Field_Hidden || _type == Field_Fixed) { 0118 return true; 0119 } 0120 if ( _type == Field_Boolean ) { 0121 if ( _value.count() != 1 ) 0122 return false; 0123 0124 QString str = _value.first(); 0125 if ( str == "0" || str == "1" || str == "true" || str == "false" || str == "yes" || str == "no" ) 0126 return true; 0127 } 0128 if ( _type == Field_TextSingle || _type == Field_TextPrivate ) { 0129 if ( _value.count() == 1 ) 0130 return true; 0131 } 0132 if ( _type == Field_TextMulti ) { 0133 //no particular test. empty/required case already caught (see above) 0134 return true; 0135 } 0136 if ( _type == Field_ListSingle || _type == Field_ListMulti ) { 0137 //no particular test. empty/required case already caught (see above) 0138 return true; 0139 } 0140 if ( _type == Field_JidSingle ) { 0141 if ( _value.count() != 1 ) 0142 return false; 0143 0144 Jid j( _value.first() ); 0145 return j.isValid(); 0146 } 0147 if ( _type == Field_JidMulti ) { 0148 QStringList::ConstIterator it = _value.begin(); 0149 bool allValid = true; 0150 for ( ; it != _value.end(); ++it) { 0151 Jid j(*it); 0152 if ( !j.isValid() ) { 0153 allValid = false; 0154 break; 0155 } 0156 } 0157 return allValid; 0158 } 0159 0160 return false; 0161 } 0162 0163 void XData::Field::fromXml(const QDomElement &e) 0164 { 0165 if ( e.tagName() != "field" ) 0166 return; 0167 0168 _var = e.attribute("var"); 0169 _label = e.attribute("label"); 0170 0171 QString type = e.attribute("type"); 0172 if ( type == "boolean" ) 0173 _type = Field_Boolean; 0174 else if ( type == "fixed" ) 0175 _type = Field_Fixed; 0176 else if ( type == "hidden" ) 0177 _type = Field_Hidden; 0178 else if ( type == "jid-multi" ) 0179 _type = Field_JidMulti; 0180 else if ( type == "jid-single" ) 0181 _type = Field_JidSingle; 0182 else if ( type == "list-multi" ) 0183 _type = Field_ListMulti; 0184 else if ( type == "list-single" ) 0185 _type = Field_ListSingle; 0186 else if ( type == "text-multi" ) 0187 _type = Field_TextMulti; 0188 else if ( type == "text-private" ) 0189 _type = Field_TextPrivate; 0190 else 0191 _type = Field_TextSingle; 0192 0193 _required = false; 0194 _desc = QString(); 0195 _options.clear(); 0196 _value.clear(); 0197 0198 QDomNode n = e.firstChild(); 0199 for ( ; !n.isNull(); n = n.nextSibling() ) { 0200 QDomElement i = n.toElement(); 0201 if ( i.isNull() ) 0202 continue; 0203 0204 QString tag = i.tagName(); 0205 if ( tag == "required" ) 0206 _required = true; 0207 else if ( tag == "desc" ) 0208 _desc = i.text().trimmed(); 0209 else if ( tag == "option" ) { 0210 Option o; 0211 bool found; 0212 o.label = i.attribute("label"); 0213 0214 QDomElement e = findSubTag( i, "value", &found ); 0215 o.value = ( found ? e.text() : QString("") ); 0216 _options.append(o); 0217 } 0218 else if ( tag == "value" ) { 0219 _value.append(i.text()); 0220 } 0221 } 0222 } 0223 0224 QDomElement XData::Field::toXml(QDomDocument *doc, bool submitForm) const 0225 { 0226 QDomElement f = doc->createElement("field"); 0227 0228 // setting attributes... 0229 if ( !_var.isEmpty() ) 0230 f.setAttribute("var", _var); 0231 if ( !submitForm && !_label.isEmpty() ) 0232 f.setAttribute("label", _label); 0233 0234 // now we're gonna get the 'type' 0235 QString type = "text-single"; 0236 if ( _type == Field_Boolean ) 0237 type = "boolean"; 0238 else if ( _type == Field_Fixed ) 0239 type = "fixed"; 0240 else if ( _type == Field_Hidden ) 0241 type = "hidden"; 0242 else if ( _type == Field_JidMulti ) 0243 type = "jid-multi"; 0244 else if ( _type == Field_JidSingle ) 0245 type = "jid-single"; 0246 else if ( _type == Field_ListMulti ) 0247 type = "list-multi"; 0248 else if ( _type == Field_ListSingle ) 0249 type = "list-single"; 0250 else if ( _type == Field_TextMulti ) 0251 type = "text-multi"; 0252 else if ( _type == Field_TextPrivate ) 0253 type = "text-private"; 0254 0255 f.setAttribute("type", type); 0256 0257 // now, setting nested tags... 0258 if ( !submitForm && _required ) 0259 f.appendChild( emptyTag(doc, "required") ); 0260 0261 if ( !submitForm && !_desc.isEmpty() ) 0262 f.appendChild( textTag(doc, "desc", _desc) ); 0263 0264 if ( !submitForm && !_options.isEmpty() ) { 0265 OptionList::ConstIterator it = _options.begin(); 0266 for ( ; it != _options.end(); ++it) { 0267 QDomElement o = doc->createElement("option"); 0268 o.appendChild(textTag(doc, "value", (*it).value)); 0269 if ( !(*it).label.isEmpty() ) 0270 o.setAttribute("label", (*it).label); 0271 f.appendChild(o); 0272 } 0273 } 0274 0275 if ( !_value.isEmpty() ) { 0276 QStringList::ConstIterator it = _value.begin(); 0277 for ( ; it != _value.end(); ++it) 0278 f.appendChild( textTag(doc, "value", *it) ); 0279 } 0280 0281 return f; 0282 } 0283 0284 //---------------------------------------------------------------------------- 0285 // XData 0286 //---------------------------------------------------------------------------- 0287 0288 XData::XData() 0289 { 0290 d = new Private; 0291 d->type = Data_Form; 0292 } 0293 0294 QString XData::title() const 0295 { 0296 return d->title; 0297 } 0298 0299 void XData::setTitle(const QString &t) 0300 { 0301 d->title = t; 0302 } 0303 0304 QString XData::instructions() const 0305 { 0306 return d->instructions; 0307 } 0308 0309 void XData::setInstructions(const QString &i) 0310 { 0311 d->instructions = i; 0312 } 0313 0314 XData::Type XData::type() const 0315 { 0316 return d->type; 0317 } 0318 0319 void XData::setType(Type t) 0320 { 0321 d->type = t; 0322 } 0323 0324 XData::FieldList XData::fields() const 0325 { 0326 return d->fields; 0327 } 0328 0329 void XData::setFields(const FieldList &f) 0330 { 0331 d->fields = f; 0332 } 0333 0334 void XData::fromXml(const QDomElement &e) 0335 { 0336 if ( (e.attribute("xmlns") != "jabber:x:data") && (e.namespaceURI() != "jabber:x:data") ) 0337 return; 0338 0339 QString type = e.attribute("type"); 0340 if ( type == "result" ) 0341 d->type = Data_Result; 0342 else if ( type == "submit" ) 0343 d->type = Data_Submit; 0344 else if ( type == "cancel" ) 0345 d->type = Data_Cancel; 0346 else 0347 d->type = Data_Form; 0348 0349 d->title = subTagText(e, "title"); 0350 d->instructions = subTagText(e, "instructions"); 0351 0352 d->fields.clear(); 0353 0354 QDomNode n = e.firstChild(); 0355 for ( ; !n.isNull(); n = n.nextSibling() ) { 0356 QDomElement i = n.toElement(); 0357 if ( i.isNull() ) 0358 continue; 0359 0360 if ( i.tagName() == "field" ) { 0361 Field f; 0362 f.fromXml(i); 0363 d->fields.append(f); 0364 } 0365 else if ( i.tagName() == "reported" ) { 0366 d->report.clear(); 0367 d->reportItems.clear(); 0368 0369 QDomNode nn = i.firstChild(); 0370 for ( ; !nn.isNull(); nn = nn.nextSibling() ) { 0371 QDomElement ii = nn.toElement(); 0372 if ( ii.isNull() ) 0373 continue; 0374 0375 if ( ii.tagName() == "field" ) { 0376 d->report.append( ReportField( ii.attribute("label"), ii.attribute("var") ) ); 0377 } 0378 } 0379 } 0380 else if ( i.tagName() == "item" ) { 0381 ReportItem item; 0382 0383 QDomNode nn = i.firstChild(); 0384 for ( ; !nn.isNull(); nn = nn.nextSibling() ) { 0385 QDomElement ii = nn.toElement(); 0386 if ( ii.isNull() ) 0387 continue; 0388 0389 if ( ii.tagName() == "field" ) { 0390 QString name = ii.attribute("var"); 0391 QString value; 0392 0393 bool found; 0394 QDomElement e = findSubTag( ii, "value", &found ); 0395 if ( found ) 0396 value = e.text(); 0397 0398 item[name] = value; 0399 } 0400 } 0401 0402 d->reportItems.append( item ); 0403 } 0404 } 0405 } 0406 0407 QDomElement XData::toXml(QDomDocument *doc, bool submitForm) const 0408 { 0409 QDomElement x = doc->createElementNS("jabber:x:data", "x"); 0410 x.setAttribute("xmlns", "jabber:x:data"); 0411 0412 QString type = "form"; 0413 if ( d->type == Data_Result ) 0414 type = "result"; 0415 else if ( d->type == Data_Submit ) 0416 type = "submit"; 0417 else if ( d->type == Data_Cancel ) 0418 type = "cancel"; 0419 0420 x.setAttribute("type", type); 0421 0422 if ( !submitForm && !d->title.isEmpty() ) 0423 x.appendChild( textTag(doc, "title", d->title) ); 0424 if ( !submitForm && !d->instructions.isEmpty() ) 0425 x.appendChild( textTag(doc, "instructions", d->instructions) ); 0426 0427 if ( !d->fields.isEmpty() ) { 0428 FieldList::ConstIterator it = d->fields.begin(); 0429 for ( ; it != d->fields.end(); ++it) { 0430 Field f = *it; 0431 if ( !(submitForm && f.var().isEmpty()) ) 0432 x.appendChild( f.toXml(doc, submitForm) ); 0433 } 0434 } 0435 0436 return x; 0437 } 0438 0439 const QList<XData::ReportField> &XData::report() const 0440 { 0441 return d->report; 0442 } 0443 0444 const QList<XData::ReportItem> &XData::reportItems() const 0445 { 0446 return d->reportItems; 0447 } 0448 0449 bool XData::isValid() const 0450 { 0451 foreach(Field f, d->fields) { 0452 if (!f.isValid()) 0453 return false; 0454 } 0455 return true; 0456 }