kabc Library API Documentation

vcardparser.cpp

00001 /* 00002 This file is part of libkabc. 00003 Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00018 Boston, MA 02111-1307, USA. 00019 */ 00020 00021 #include <qregexp.h> 00022 00023 #include <kmdcodec.h> 00024 00025 #include "vcardparser.h" 00026 00027 #define FOLD_WIDTH 75 00028 00029 using namespace KABC; 00030 00031 VCardParser::VCardParser() 00032 { 00033 } 00034 00035 VCardParser::~VCardParser() 00036 { 00037 } 00038 00039 VCard::List VCardParser::parseVCards( const QString& text ) 00040 { 00041 static QRegExp sep( "[\x0d\x0a]" ); 00042 00043 VCard currentVCard; 00044 VCard::List vCardList; 00045 QString currentLine; 00046 00047 const QStringList lines = QStringList::split( sep, text ); 00048 QStringList::ConstIterator it; 00049 00050 bool inVCard = false; 00051 QStringList::ConstIterator linesEnd( lines.end() ); 00052 for ( it = lines.begin(); it != linesEnd; ++it ) { 00053 00054 if ( (*it).isEmpty() ) // empty line 00055 continue; 00056 00057 if ( (*it)[ 0 ] == ' ' || (*it)[ 0 ] == '\t' ) { // folded line => append to previous 00058 currentLine += QString( *it ).remove( 0, 1 ); 00059 continue; 00060 } else { 00061 if ( inVCard && !currentLine.isEmpty() ) { // now parse the line 00062 int colon = currentLine.find( ':' ); 00063 if ( colon == -1 ) { // invalid line 00064 currentLine = (*it); 00065 continue; 00066 } 00067 00068 VCardLine vCardLine; 00069 const QString key = currentLine.left( colon ).stripWhiteSpace(); 00070 QString value = currentLine.mid( colon + 1 ); 00071 00072 QStringList params = QStringList::split( ';', key ); 00073 00074 // check for group 00075 if ( params[0].find( '.' ) != -1 ) { 00076 const QStringList groupList = QStringList::split( '.', params[0] ); 00077 vCardLine.setGroup( groupList[0] ); 00078 vCardLine.setIdentifier( groupList[1] ); 00079 } else 00080 vCardLine.setIdentifier( params[0] ); 00081 00082 if ( params.count() > 1 ) { // find all parameters 00083 QStringList::ConstIterator paramIt = params.begin(); 00084 for ( ++paramIt; paramIt != params.end(); ++paramIt ) { 00085 QStringList pair = QStringList::split( '=', *paramIt ); 00086 if ( pair.size() == 1 ) { 00087 // correct the fucking 2.1 'standard' 00088 if ( pair[0].lower() == "quoted-printable" ) { 00089 pair[0] = "encoding"; 00090 pair[1] = "quoted-printable"; 00091 } else if ( pair[0].lower() == "base64" ) { 00092 pair[0] = "encoding"; 00093 pair[1] = "base64"; 00094 } else { 00095 pair.prepend( "type" ); 00096 } 00097 } 00098 // This is pretty much a faster pair[1].contains( ',' )... 00099 if ( pair[1].find( ',' ) != -1 ) { // parameter in type=x,y,z format 00100 const QStringList args = QStringList::split( ',', pair[ 1 ] ); 00101 QStringList::ConstIterator argIt; 00102 for ( argIt = args.begin(); argIt != args.end(); ++argIt ) 00103 vCardLine.addParameter( pair[0].lower(), *argIt ); 00104 } else 00105 vCardLine.addParameter( pair[0].lower(), pair[1] ); 00106 } 00107 } 00108 00109 params = vCardLine.parameterList(); 00110 if ( params.findIndex( "encoding" ) != -1 ) { // have to decode the data 00111 QByteArray input, output; 00112 input = value.local8Bit(); 00113 if ( vCardLine.parameter( "encoding" ).lower() == "b" || 00114 vCardLine.parameter( "encoding" ).lower() == "base64" ) 00115 KCodecs::base64Decode( input, output ); 00116 else if ( vCardLine.parameter( "encoding" ).lower() == "quoted-printable" ) 00117 KCodecs::quotedPrintableDecode( input, output ); 00118 00119 if ( vCardLine.parameter( "charset" ).lower() == "utf-8" ) { 00120 vCardLine.setValue( QString::fromUtf8( output.data(), output.size() ) ); 00121 } else { 00122 vCardLine.setValue( output ); 00123 } 00124 } else if ( vCardLine.parameter( "charset" ).lower() == "utf-8" ) { 00125 vCardLine.setValue( QString::fromUtf8( value.ascii() ) ); 00126 } else 00127 vCardLine.setValue( value.replace( "\\n", "\n" ) ); 00128 00129 currentVCard.addLine( vCardLine ); 00130 } 00131 00132 // we do not save the start and end tag as vcardline 00133 if ( (*it).lower().startsWith( "begin:vcard" ) ) { 00134 inVCard = true; 00135 currentLine.setLength( 0 ); 00136 currentVCard.clear(); // flush vcard 00137 continue; 00138 } 00139 00140 if ( (*it).lower().startsWith( "end:vcard" ) ) { 00141 inVCard = false; 00142 vCardList.append( currentVCard ); 00143 currentLine.setLength( 0 ); 00144 currentVCard.clear(); // flush vcard 00145 continue; 00146 } 00147 00148 currentLine = (*it); 00149 } 00150 } 00151 00152 return vCardList; 00153 } 00154 00155 QString VCardParser::createVCards( const VCard::List& list ) 00156 { 00157 QString text; 00158 QString textLine; 00159 QString encodingType; 00160 QStringList idents; 00161 QStringList params; 00162 QStringList values; 00163 QStringList::ConstIterator identIt; 00164 QStringList::Iterator paramIt; 00165 QStringList::ConstIterator valueIt; 00166 00167 VCardLine::List lines; 00168 VCardLine::List::ConstIterator lineIt; 00169 VCard::List::ConstIterator cardIt; 00170 00171 bool hasEncoding; 00172 00173 text.reserve( list.size() * 300 ); // reserve memory to be more efficient 00174 00175 // iterate over the cards 00176 VCard::List::ConstIterator listEnd( list.end() ); 00177 for ( cardIt = list.begin(); cardIt != listEnd; ++cardIt ) { 00178 text.append( "BEGIN:VCARD\r\n" ); 00179 00180 idents = (*cardIt).identifiers(); 00181 for ( identIt = idents.constBegin(); identIt != idents.constEnd(); ++identIt ) { 00182 lines = (*cardIt).lines( (*identIt) ); 00183 00184 // iterate over the lines 00185 for ( lineIt = lines.constBegin(); lineIt != lines.constEnd(); ++lineIt ) { 00186 if ( !(*lineIt).value().asString().isEmpty() ) { 00187 if ( (*lineIt).hasGroup() ) 00188 textLine = (*lineIt).group() + "." + (*lineIt).identifier(); 00189 else 00190 textLine = (*lineIt).identifier(); 00191 00192 params = (*lineIt).parameterList(); 00193 hasEncoding = false; 00194 if ( params.count() > 0 ) { // we have parameters 00195 for ( paramIt = params.begin(); paramIt != params.end(); ++paramIt ) { 00196 if ( (*paramIt) == "encoding" ) { 00197 hasEncoding = true; 00198 encodingType = (*lineIt).parameter( "encoding" ).lower(); 00199 } 00200 00201 values = (*lineIt).parameters( *paramIt ); 00202 for ( valueIt = values.constBegin(); valueIt != values.constEnd(); ++valueIt ) { 00203 textLine.append( ";" + (*paramIt).upper() ); 00204 if ( !(*valueIt).isEmpty() ) 00205 textLine.append( "=" + (*valueIt) ); 00206 } 00207 } 00208 } 00209 00210 if ( hasEncoding ) { // have to encode the data 00211 QByteArray input, output; 00212 if ( encodingType == "b" ) { 00213 input = (*lineIt).value().toByteArray(); 00214 KCodecs::base64Encode( input, output ); 00215 } else if ( encodingType == "quoted-printable" ) { 00216 input = (*lineIt).value().toString().utf8(); 00217 input.resize( input.size() - 1 ); // strip \0 00218 KCodecs::quotedPrintableEncode( input, output, false ); 00219 } 00220 textLine.append( ":" + QString( output ) ); 00221 } else 00222 textLine.append( ":" + (*lineIt).value().asString().replace( "\n", "\\n" ) ); 00223 00224 if ( textLine.length() > FOLD_WIDTH ) { // we have to fold the line 00225 for ( uint i = 0; i <= ( textLine.length() / FOLD_WIDTH ); ++i ) 00226 text.append( ( i == 0 ? "" : " " ) + textLine.mid( i * FOLD_WIDTH, FOLD_WIDTH ) + "\r\n" ); 00227 } else 00228 text.append( textLine + "\r\n" ); 00229 } 00230 } 00231 } 00232 00233 text.append( "END:VCARD\r\n" ); 00234 text.append( "\r\n" ); 00235 } 00236 00237 return text; 00238 }
KDE Logo
This file is part of the documentation for kabc Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Apr 12 23:27:24 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003