-rw-r--r-- | kabc/vcard21parser.cpp | 606 |
1 files changed, 606 insertions, 0 deletions
diff --git a/kabc/vcard21parser.cpp b/kabc/vcard21parser.cpp new file mode 100644 index 0000000..b02aac4 --- a/dev/null +++ b/kabc/vcard21parser.cpp | |||
@@ -0,0 +1,606 @@ | |||
1 | /* | ||
2 | This file is part of libkabc. | ||
3 | Copyright (c) 2001 Mark Westcott <mark@houseoffish.org> | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Library General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library 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 GNU | ||
13 | Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public License | ||
16 | along with this library; see the file COPYING.LIB. If not, write to | ||
17 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | Enhanced Version of the file for platform independent KDE tools. | ||
23 | Copyright (c) 2004 Ulf Schenk | ||
24 | |||
25 | $Id$ | ||
26 | */ | ||
27 | |||
28 | #include <qmap.h> | ||
29 | #include <qregexp.h> | ||
30 | #include <kmdcodec.h> | ||
31 | |||
32 | #include "vcard21parser.h" | ||
33 | #include "vcardconverter.h" | ||
34 | |||
35 | using namespace KABC; | ||
36 | |||
37 | bool VCardLineX::isValid() const | ||
38 | { | ||
39 | // Invalid: if it is "begin:vcard" or "end:vcard" | ||
40 | if ( name == VCARD_BEGIN_N || name == VCARD_END_N ) | ||
41 | return false; | ||
42 | |||
43 | if ( name[0] == 'x' && name[1] == '-' ) // A custom x- line | ||
44 | return true; | ||
45 | |||
46 | // This is long but it makes it a bit faster (and saves me from using | ||
47 | // a tree which is probably the ideal situation, but a bit memory heavy) | ||
48 | switch( name[0] ) { | ||
49 | case 'a': | ||
50 | if ( name == VCARD_ADR && qualified && | ||
51 | (qualifiers.contains(VCARD_ADR_DOM) || | ||
52 | qualifiers.contains(VCARD_ADR_INTL) || | ||
53 | qualifiers.contains(VCARD_ADR_POSTAL) || | ||
54 | qualifiers.contains(VCARD_ADR_HOME) || | ||
55 | qualifiers.contains(VCARD_ADR_WORK) || | ||
56 | qualifiers.contains(VCARD_ADR_PREF) | ||
57 | ) ) | ||
58 | return true; | ||
59 | |||
60 | if ( name == VCARD_AGENT ) | ||
61 | return true; | ||
62 | break; | ||
63 | |||
64 | case 'b': | ||
65 | if ( name == VCARD_BDAY ) | ||
66 | return true; | ||
67 | break; | ||
68 | |||
69 | case 'c': | ||
70 | if ( name == VCARD_CATEGORIES ) | ||
71 | return true; | ||
72 | if ( name == VCARD_CLASS && qualified && | ||
73 | (qualifiers.contains(VCARD_CLASS_PUBLIC) || | ||
74 | qualifiers.contains(VCARD_CLASS_PRIVATE) || | ||
75 | qualifiers.contains(VCARD_CLASS_CONFIDENTIAL) | ||
76 | ) ) | ||
77 | return true; | ||
78 | break; | ||
79 | |||
80 | case 'e': | ||
81 | if ( name == VCARD_EMAIL && qualified && | ||
82 | (qualifiers.contains(VCARD_EMAIL_INTERNET) || | ||
83 | qualifiers.contains(VCARD_EMAIL_PREF) || | ||
84 | qualifiers.contains(VCARD_EMAIL_X400) | ||
85 | ) ) | ||
86 | return true; | ||
87 | break; | ||
88 | |||
89 | case 'f': | ||
90 | if ( name == VCARD_FN ) | ||
91 | return true; | ||
92 | break; | ||
93 | |||
94 | case 'g': | ||
95 | if ( name == VCARD_GEO ) | ||
96 | return true; | ||
97 | break; | ||
98 | |||
99 | case 'k': | ||
100 | if ( name == VCARD_KEY && qualified && | ||
101 | (qualifiers.contains(VCARD_KEY_X509) || | ||
102 | qualifiers.contains(VCARD_KEY_PGP) | ||
103 | ) ) | ||
104 | return true; | ||
105 | break; | ||
106 | |||
107 | case 'l': | ||
108 | if ( name == VCARD_LABEL ) | ||
109 | return true; | ||
110 | if ( name == VCARD_LOGO ) | ||
111 | return true; | ||
112 | break; | ||
113 | |||
114 | case 'm': | ||
115 | if ( name == VCARD_MAILER ) | ||
116 | return true; | ||
117 | break; | ||
118 | |||
119 | case 'n': | ||
120 | if ( name == VCARD_N ) | ||
121 | return true; | ||
122 | if ( name == VCARD_NAME ) | ||
123 | return true; | ||
124 | if ( name == VCARD_NICKNAME ) | ||
125 | return true; | ||
126 | if ( name == VCARD_NOTE ) | ||
127 | return true; | ||
128 | break; | ||
129 | |||
130 | case 'o': | ||
131 | if ( name == VCARD_ORG ) | ||
132 | return true; | ||
133 | break; | ||
134 | |||
135 | case 'p': | ||
136 | if ( name == VCARD_PHOTO ) | ||
137 | return true; | ||
138 | if ( name == VCARD_PROFILE ) | ||
139 | return true; | ||
140 | if ( name == VCARD_PRODID ) | ||
141 | return true; | ||
142 | break; | ||
143 | |||
144 | case 'r': | ||
145 | if ( name == VCARD_ROLE ) | ||
146 | return true; | ||
147 | if ( name == VCARD_REV ) | ||
148 | return true; | ||
149 | break; | ||
150 | |||
151 | case 's': | ||
152 | if ( name == VCARD_SOURCE ) | ||
153 | return true; | ||
154 | if ( name == VCARD_SOUND ) | ||
155 | return true; | ||
156 | break; | ||
157 | |||
158 | case 't': | ||
159 | if ( name == VCARD_TEL && qualified && | ||
160 | (qualifiers.contains(VCARD_TEL_HOME) || | ||
161 | qualifiers.contains(VCARD_TEL_WORK) || | ||
162 | qualifiers.contains(VCARD_TEL_PREF) || | ||
163 | qualifiers.contains(VCARD_TEL_VOICE) || | ||
164 | qualifiers.contains(VCARD_TEL_FAX) || | ||
165 | qualifiers.contains(VCARD_TEL_MSG) || | ||
166 | qualifiers.contains(VCARD_TEL_CELL) || | ||
167 | qualifiers.contains(VCARD_TEL_PAGER) || | ||
168 | qualifiers.contains(VCARD_TEL_BBS) || | ||
169 | qualifiers.contains(VCARD_TEL_MODEM) || | ||
170 | qualifiers.contains(VCARD_TEL_CAR) || | ||
171 | qualifiers.contains(VCARD_TEL_ISDN) || | ||
172 | qualifiers.contains(VCARD_TEL_VIDEO) || | ||
173 | qualifiers.contains(VCARD_TEL_PCS) | ||
174 | ) ) | ||
175 | return true; | ||
176 | if ( name == VCARD_TZ ) | ||
177 | return true; | ||
178 | if ( name == VCARD_TITLE ) | ||
179 | return true; | ||
180 | break; | ||
181 | |||
182 | case 'u': | ||
183 | if ( name == VCARD_URL ) | ||
184 | return true; | ||
185 | if ( name == VCARD_UID ) | ||
186 | return true; | ||
187 | break; | ||
188 | |||
189 | case 'v': | ||
190 | if ( name == VCARD_VERSION ) | ||
191 | return true; | ||
192 | break; | ||
193 | default: | ||
194 | break; | ||
195 | } | ||
196 | |||
197 | return false; | ||
198 | } | ||
199 | |||
200 | |||
201 | VCard21Parser::VCard21Parser() | ||
202 | { | ||
203 | } | ||
204 | |||
205 | VCard21Parser::~VCard21Parser() | ||
206 | { | ||
207 | } | ||
208 | |||
209 | void VCard21Parser::readFromString(KABC::AddressBook *addressbook, const QString &data) | ||
210 | { | ||
211 | KABC::Addressee mAddressee = readFromString(data); | ||
212 | addressbook->insertAddressee(mAddressee); | ||
213 | } | ||
214 | |||
215 | KABC::Addressee VCard21Parser::readFromString( const QString &data) | ||
216 | { | ||
217 | KABC::Addressee addressee; | ||
218 | VCard21ParserImpl *mVCard = VCard21ParserImpl::parseVCard(data); | ||
219 | QString tmpStr; | ||
220 | |||
221 | // Check if parsing failed | ||
222 | if (mVCard == 0) | ||
223 | { | ||
224 | kdDebug() << "Parsing failed" << endl; | ||
225 | return addressee; | ||
226 | } | ||
227 | //set the addressees name and formated name | ||
228 | QStringList tmpList = mVCard->getValues(VCARD_N); | ||
229 | QString formattedName = ""; | ||
230 | if (tmpList.count() > 0) | ||
231 | addressee.setFamilyName(tmpList[0]); | ||
232 | if (tmpList.count() > 1) | ||
233 | addressee.setGivenName(tmpList[1]); | ||
234 | if (tmpList.count() > 2) | ||
235 | addressee.setAdditionalName(tmpList[2]); | ||
236 | if (tmpList.count() > 3) | ||
237 | addressee.setPrefix(tmpList[3]); | ||
238 | if (tmpList.count() > 4) | ||
239 | addressee.setSuffix(tmpList[4]); | ||
240 | |||
241 | tmpStr = (mVCard->getValue(VCARD_FN)); | ||
242 | if (!tmpStr.isEmpty()) | ||
243 | addressee.setFormattedName(tmpStr); | ||
244 | |||
245 | //set the addressee's nick name | ||
246 | tmpStr = mVCard->getValue(VCARD_NICKNAME); | ||
247 | addressee.setNickName(tmpStr); | ||
248 | //set the addressee's organisation | ||
249 | tmpStr = mVCard->getValue(VCARD_ORG); | ||
250 | addressee.setOrganization(tmpStr); | ||
251 | //set the addressee's title | ||
252 | tmpStr = mVCard->getValue(VCARD_TITLE); | ||
253 | addressee.setTitle(tmpStr); | ||
254 | //set the addressee's email - we can only deal with two. The preferenced one and one other. | ||
255 | tmpStr = mVCard->getValue(VCARD_EMAIL, VCARD_EMAIL_INTERNET); | ||
256 | addressee.insertEmail(tmpStr, false); | ||
257 | tmpStr = mVCard->getValue(VCARD_EMAIL,VCARD_EMAIL_PREF); | ||
258 | addressee.insertEmail(tmpStr, true); | ||
259 | //set the addressee's url | ||
260 | tmpStr = mVCard->getValue(VCARD_URL); | ||
261 | if (tmpStr.isEmpty()) tmpStr = mVCard->getValue(VCARD_URL, VCARD_ADR_WORK); | ||
262 | if (tmpStr.isEmpty()) tmpStr = mVCard->getValue(VCARD_URL, VCARD_ADR_HOME); | ||
263 | if (!tmpStr.isEmpty()) { | ||
264 | addressee.setUrl(KURL(tmpStr)); | ||
265 | } | ||
266 | |||
267 | //set the addressee's birthday | ||
268 | tmpStr = mVCard->getValue(VCARD_BDAY); | ||
269 | addressee.setBirthday(VCardStringToDate(tmpStr)); | ||
270 | |||
271 | //set the addressee's phone numbers | ||
272 | for ( QValueListIterator<VCardLineX> i = mVCard->_vcdata->begin();i != mVCard->_vcdata->end(); ++i ) { | ||
273 | if ( (*i).name == VCARD_TEL ) { | ||
274 | int type = 0; | ||
275 | if ( (*i).qualified ) { | ||
276 | if ( (*i).qualifiers.contains( VCARD_TEL_HOME ) ) | ||
277 | type |= PhoneNumber::Home; | ||
278 | if ( (*i).qualifiers.contains( VCARD_TEL_WORK ) ) | ||
279 | type |= PhoneNumber::Work; | ||
280 | if ( (*i).qualifiers.contains( VCARD_TEL_PREF ) ) | ||
281 | type |= PhoneNumber::Pref; | ||
282 | // if ( (*i).qualifiers.contains( VCARD_TEL_VOICE ) ) | ||
283 | // type |= PhoneNumber::Voice; | ||
284 | if ( (*i).qualifiers.contains( VCARD_TEL_FAX ) ) | ||
285 | type |= PhoneNumber::Fax; | ||
286 | if ( (*i).qualifiers.contains( VCARD_TEL_MSG ) ) | ||
287 | type |= PhoneNumber::Msg; | ||
288 | if ( (*i).qualifiers.contains( VCARD_TEL_CELL ) ) | ||
289 | type |= PhoneNumber::Cell; | ||
290 | if ( (*i).qualifiers.contains( VCARD_TEL_PAGER ) ) | ||
291 | type |= PhoneNumber::Pager; | ||
292 | if ( (*i).qualifiers.contains( VCARD_TEL_BBS ) ) | ||
293 | type |= PhoneNumber::Bbs; | ||
294 | if ( (*i).qualifiers.contains( VCARD_TEL_MODEM ) ) | ||
295 | type |= PhoneNumber::Modem; | ||
296 | if ( (*i).qualifiers.contains( VCARD_TEL_CAR ) ) | ||
297 | type |= PhoneNumber::Car; | ||
298 | if ( (*i).qualifiers.contains( VCARD_TEL_ISDN ) ) | ||
299 | type |= PhoneNumber::Isdn; | ||
300 | if ( (*i).qualifiers.contains( VCARD_TEL_VIDEO ) ) | ||
301 | type |= PhoneNumber::Video; | ||
302 | if ( (*i).qualifiers.contains( VCARD_TEL_PCS ) ) | ||
303 | type |= PhoneNumber::Pcs; | ||
304 | } | ||
305 | addressee.insertPhoneNumber( PhoneNumber( (*i).parameters[ 0 ], type ) ); | ||
306 | } | ||
307 | } | ||
308 | |||
309 | //set the addressee's addresses | ||
310 | for ( QValueListIterator<VCardLineX> i = mVCard->_vcdata->begin();i != mVCard->_vcdata->end(); ++i ) { | ||
311 | if ( (*i).name == VCARD_ADR ) { | ||
312 | int type = 0; | ||
313 | if ( (*i).qualified ) { | ||
314 | if ( (*i).qualifiers.contains( VCARD_ADR_DOM ) ) | ||
315 | type |= Address::Dom; | ||
316 | if ( (*i).qualifiers.contains( VCARD_ADR_INTL ) ) | ||
317 | type |= Address::Intl; | ||
318 | if ( (*i).qualifiers.contains( VCARD_ADR_POSTAL ) ) | ||
319 | type |= Address::Postal; | ||
320 | if ( (*i).qualifiers.contains( VCARD_ADR_PARCEL ) ) | ||
321 | type |= Address::Parcel; | ||
322 | if ( (*i).qualifiers.contains( VCARD_ADR_HOME ) ) | ||
323 | type |= Address::Home; | ||
324 | if ( (*i).qualifiers.contains( VCARD_ADR_WORK ) ) | ||
325 | type |= Address::Work; | ||
326 | if ( (*i).qualifiers.contains( VCARD_ADR_PREF ) ) | ||
327 | type |= Address::Pref; | ||
328 | } | ||
329 | addressee.insertAddress( readAddressFromQStringList( (*i).parameters, type ) ); | ||
330 | } | ||
331 | } | ||
332 | |||
333 | //set the addressee's delivery label | ||
334 | tmpStr = mVCard->getValue(VCARD_LABEL); | ||
335 | if (!tmpStr.isEmpty()) { | ||
336 | qDebug("VCard21Parser::readFromString please verify if replace is correct"); | ||
337 | //US tmpStr.replace("\r\n","\n"); | ||
338 | tmpStr.replace( QRegExp("\r\n"), "\n" ); | ||
339 | Address tmpAddress; | ||
340 | tmpAddress.setLabel(tmpStr); | ||
341 | addressee.insertAddress(tmpAddress); | ||
342 | } | ||
343 | |||
344 | //set the addressee's notes | ||
345 | tmpStr = mVCard->getValue(VCARD_NOTE); | ||
346 | qDebug("VCard21Parser::readFromString please verify if correct"); | ||
347 | //US tmpStr.replace("\r\n","\n"); | ||
348 | tmpStr.replace( QRegExp("\r\n"), "\n" ); | ||
349 | addressee.setNote(tmpStr); | ||
350 | |||
351 | //set the addressee's timezone | ||
352 | tmpStr = mVCard->getValue(VCARD_TZ); | ||
353 | TimeZone tmpZone(tmpStr.toInt()); | ||
354 | addressee.setTimeZone(tmpZone); | ||
355 | |||
356 | //set the addressee's geographical position | ||
357 | tmpList = mVCard->getValues(VCARD_GEO); | ||
358 | if (tmpList.count()==2) | ||
359 | { | ||
360 | tmpStr = tmpList[0]; | ||
361 | float glat = tmpStr.toFloat(); | ||
362 | tmpStr = tmpList[1]; | ||
363 | float glong = tmpStr.toFloat(); | ||
364 | Geo tmpGeo(glat,glong); | ||
365 | addressee.setGeo(tmpGeo); | ||
366 | } | ||
367 | |||
368 | //set the last revision date | ||
369 | tmpStr = mVCard->getValue(VCARD_REV); | ||
370 | addressee.setRevision(VCardStringToDate(tmpStr)); | ||
371 | |||
372 | //set the role of the addressee | ||
373 | tmpStr = mVCard->getValue(VCARD_ROLE); | ||
374 | addressee.setRole(tmpStr); | ||
375 | |||
376 | return addressee; | ||
377 | } | ||
378 | |||
379 | |||
380 | |||
381 | KABC::Address VCard21Parser::readAddressFromQStringList ( const QStringList &data, const int type ) | ||
382 | { | ||
383 | KABC::Address mAddress; | ||
384 | mAddress.setType( type ); | ||
385 | |||
386 | if ( data.count() > 0 ) | ||
387 | mAddress.setPostOfficeBox( data[0] ); | ||
388 | if ( data.count() > 1 ) | ||
389 | mAddress.setExtended( data[1] ); | ||
390 | if ( data.count() > 2 ) | ||
391 | mAddress.setStreet( data[2] ); | ||
392 | if ( data.count() > 3 ) | ||
393 | mAddress.setLocality( data[3] ); | ||
394 | if ( data.count() > 4 ) | ||
395 | mAddress.setRegion( data[4] ); | ||
396 | if ( data.count() > 5 ) | ||
397 | mAddress.setPostalCode( data[5] ); | ||
398 | if ( data.count() > 6 ) | ||
399 | mAddress.setCountry( data[6] ); | ||
400 | |||
401 | return mAddress; | ||
402 | } | ||
403 | |||
404 | |||
405 | VCard21ParserImpl *VCard21ParserImpl::parseVCard( const QString& vc, int *err ) | ||
406 | { | ||
407 | int _err = 0; | ||
408 | int _state = VC_STATE_BEGIN; | ||
409 | |||
410 | QValueList<VCardLineX> *_vcdata; | ||
411 | QValueList<QString> lines; | ||
412 | |||
413 | _vcdata = new QValueList<VCardLineX>; | ||
414 | |||
415 | lines = QStringList::split( QRegExp( "[\x0d\x0a]" ), vc ); | ||
416 | |||
417 | // for each line in the vCard | ||
418 | for ( QStringList::Iterator j = lines.begin(); j != lines.end(); ++j ) { | ||
419 | VCardLineX _vcl; | ||
420 | |||
421 | // take spaces off the end - ugly but necessary hack | ||
422 | for ( int g = (*j).length()-1; g > 0 && (*j)[g].isSpace(); --g ) | ||
423 | (*j)[g] = 0; | ||
424 | |||
425 | // first token: | ||
426 | // verify state, update if necessary | ||
427 | if ( _state & VC_STATE_BEGIN) { | ||
428 | if ( !qstricmp( (*j).latin1(), VCARD_BEGIN ) ) { | ||
429 | _state = VC_STATE_BODY; | ||
430 | continue; | ||
431 | } else { | ||
432 | _err = VC_ERR_NO_BEGIN; | ||
433 | break; | ||
434 | } | ||
435 | } else if ( _state & VC_STATE_BODY ) { | ||
436 | if ( !qstricmp( (*j).latin1(), VCARD_END ) ) { | ||
437 | _state |= VC_STATE_END; | ||
438 | break; | ||
439 | } | ||
440 | |||
441 | // split into two tokens | ||
442 | int colon = (*j).find( ':' ); | ||
443 | if ( colon < 0 ) { | ||
444 | _err = VC_ERR_INVALID_LINE; | ||
445 | break; | ||
446 | } | ||
447 | |||
448 | QString key = (*j).left( colon ); | ||
449 | QString value = (*j).mid( colon + 1 ); | ||
450 | |||
451 | // check for qualifiers and | ||
452 | // set name, qualified, qualifier(s) | ||
453 | QStringList keyTokens = QStringList::split( ';', key ); | ||
454 | bool qp = false, first_pass = true; | ||
455 | bool b64 = false; | ||
456 | |||
457 | if ( keyTokens.count() > 0 ) { | ||
458 | _vcl.qualified = false; | ||
459 | _vcl.name = keyTokens[ 0 ].lower(); | ||
460 | |||
461 | for ( QStringList::Iterator z = keyTokens.begin(); z != keyTokens.end(); ++z ) { | ||
462 | QString zz = (*z).lower(); | ||
463 | if ( zz == VCARD_QUOTED_PRINTABLE || zz == VCARD_ENCODING_QUOTED_PRINTABLE ) { | ||
464 | qp = true; | ||
465 | } else if ( zz == VCARD_BASE64 ) { | ||
466 | b64 = true; | ||
467 | } else if ( !first_pass ) { | ||
468 | _vcl.qualified = true; | ||
469 | _vcl.qualifiers.append( zz ); | ||
470 | } | ||
471 | first_pass = false; | ||
472 | } | ||
473 | } else { | ||
474 | _err = VC_ERR_INVALID_LINE; | ||
475 | } | ||
476 | |||
477 | if ( _err != 0 ) | ||
478 | break; | ||
479 | |||
480 | if ( _vcl.name == VCARD_VERSION ) | ||
481 | _state |= VC_STATE_HAVE_VERSION; | ||
482 | |||
483 | if ( _vcl.name == VCARD_N || _vcl.name == VCARD_FN ) | ||
484 | _state |= VC_STATE_HAVE_N; | ||
485 | |||
486 | // second token: | ||
487 | // split into tokens by ; | ||
488 | // add to parameters vector | ||
489 | if ( b64 ) { | ||
490 | if ( value.at( value.length() - 1 ) != '=' ) | ||
491 | do { | ||
492 | value += *( ++j ); | ||
493 | } while ( (*j).at( (*j).length() - 1 ) != '=' ); | ||
494 | } else { | ||
495 | if ( qp ) { // join any split lines | ||
496 | while ( value.at( value.length() - 1 ) == '=' ) { | ||
497 | value.remove( value.length() - 1, 1 ); | ||
498 | value.append(*( ++j )); | ||
499 | } | ||
500 | } | ||
501 | _vcl.parameters = QStringList::split( ';', value, true ); | ||
502 | if ( qp ) { // decode the quoted printable | ||
503 | for ( QStringList::Iterator z = _vcl.parameters.begin(); z != _vcl.parameters.end(); ++z ) | ||
504 | *z = KCodecs::quotedPrintableDecode( (*z).latin1() ); | ||
505 | } | ||
506 | } | ||
507 | } else { | ||
508 | _err = VC_ERR_INTERNAL; | ||
509 | break; | ||
510 | } | ||
511 | |||
512 | // validate VCardLineX | ||
513 | if ( !_vcl.isValid() ) { | ||
514 | _err = VC_ERR_INVALID_LINE; | ||
515 | break; | ||
516 | } | ||
517 | |||
518 | // add to vector | ||
519 | _vcdata->append( _vcl ); | ||
520 | } | ||
521 | |||
522 | // errors to check at the last minute (exit state related) | ||
523 | if ( _err == 0 ) { | ||
524 | if ( !( _state & VC_STATE_END ) ) // we have to have an end!! | ||
525 | _err = VC_ERR_NO_END; | ||
526 | |||
527 | if ( !( _state & VC_STATE_HAVE_N ) || // we have to have the mandatories! | ||
528 | !( _state & VC_STATE_HAVE_VERSION ) ) | ||
529 | _err = VC_ERR_MISSING_MANDATORY; | ||
530 | } | ||
531 | |||
532 | // set the error message if we can, and only return an object | ||
533 | // if the vCard was valid. | ||
534 | if ( err ) | ||
535 | *err = _err; | ||
536 | |||
537 | if ( _err != 0 ) { | ||
538 | delete _vcdata; | ||
539 | return 0; | ||
540 | } | ||
541 | |||
542 | return new VCard21ParserImpl( _vcdata ); | ||
543 | } | ||
544 | |||
545 | VCard21ParserImpl::VCard21ParserImpl(QValueList<VCardLineX> *_vcd) : _vcdata(_vcd) | ||
546 | { | ||
547 | } | ||
548 | |||
549 | |||
550 | QString VCard21ParserImpl::getValue(const QString& name, const QString& qualifier) | ||
551 | { | ||
552 | QString failed; | ||
553 | const QString lowname = name.lower(); | ||
554 | const QString lowqualifier = qualifier.lower(); | ||
555 | |||
556 | for (QValueListIterator<VCardLineX> i = _vcdata->begin();i != _vcdata->end();++i) { | ||
557 | if ((*i).name == lowname && (*i).qualified && (*i).qualifiers.contains(lowqualifier)) { | ||
558 | if ((*i).parameters.count() > 0) | ||
559 | return (*i).parameters[0]; | ||
560 | else return failed; | ||
561 | } | ||
562 | } | ||
563 | return failed; | ||
564 | } | ||
565 | |||
566 | |||
567 | QString VCard21ParserImpl::getValue(const QString& name) | ||
568 | { | ||
569 | QString failed; | ||
570 | const QString lowname = name.lower(); | ||
571 | |||
572 | for (QValueListIterator<VCardLineX> i = _vcdata->begin();i != _vcdata->end();++i) { | ||
573 | if ((*i).name == lowname && !(*i).qualified) { | ||
574 | if ((*i).parameters.count() > 0) | ||
575 | return (*i).parameters[0]; | ||
576 | else return failed; | ||
577 | } | ||
578 | } | ||
579 | return failed; | ||
580 | } | ||
581 | |||
582 | |||
583 | QStringList VCard21ParserImpl::getValues(const QString& name) | ||
584 | { | ||
585 | const QString lowname = name.lower(); | ||
586 | for (QValueListIterator<VCardLineX> i = _vcdata->begin();i != _vcdata->end();++i) { | ||
587 | if ((*i).name == lowname && !(*i).qualified) | ||
588 | return (*i).parameters; | ||
589 | } | ||
590 | // failed. | ||
591 | return QStringList(); | ||
592 | } | ||
593 | |||
594 | QStringList VCard21ParserImpl::getValues(const QString& name, const QString& qualifier) | ||
595 | { | ||
596 | const QString lowname = name.lower(); | ||
597 | const QString lowqualifier = qualifier.lower(); | ||
598 | for (QValueListIterator<VCardLineX> i = _vcdata->begin();i != _vcdata->end();++i) { | ||
599 | if ((*i).name == lowname && (*i).qualified && (*i).qualifiers.contains(lowqualifier)) | ||
600 | return (*i).parameters; | ||
601 | } | ||
602 | // failed. | ||
603 | return QStringList(); | ||
604 | } | ||
605 | |||
606 | |||