vcardparser.cpp00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <qregexp.h>
00022 #include <qtextcodec.h>
00023
00024 #include <kmdcodec.h>
00025
00026 #include "vcardparser.h"
00027
00028 #define FOLD_WIDTH 75
00029
00030 using namespace KABC;
00031
00032 static QString backslash( "\\\\" );
00033 static QString comma( "\\," );
00034 static QString newline( "\\n" );
00035 static QString cr( "\\r" );
00036
00037 static void addEscapes( QString &str )
00038 {
00039 str.replace( '\\', backslash );
00040 str.replace( ',', comma );
00041 str.replace( '\r', cr );
00042 str.replace( '\n', newline );
00043 }
00044
00045 static void removeEscapes( QString &str )
00046 {
00047 str.replace( cr, "\\r" );
00048 str.replace( newline, "\n" );
00049 str.replace( comma, "," );
00050 str.replace( backslash, "\\" );
00051 }
00052
00053 VCardParser::VCardParser()
00054 {
00055 }
00056
00057 VCardParser::~VCardParser()
00058 {
00059 }
00060
00061 VCard::List VCardParser::parseVCards( const QString& text )
00062 {
00063 static QRegExp sep( "[\x0d\x0a]" );
00064
00065 VCard currentVCard;
00066 VCard::List vCardList;
00067 QString currentLine;
00068
00069 const QStringList lines = QStringList::split( sep, text );
00070 QStringList::ConstIterator it;
00071
00072 bool inVCard = false;
00073 QStringList::ConstIterator linesEnd( lines.end() );
00074 for ( it = lines.begin(); it != linesEnd; ++it ) {
00075
00076 if ( (*it).isEmpty() )
00077 continue;
00078
00079 if ( (*it)[ 0 ] == ' ' || (*it)[ 0 ] == '\t' ) {
00080 currentLine += QString( *it ).remove( 0, 1 );
00081 continue;
00082 } else {
00083 if ( inVCard && !currentLine.isEmpty() ) {
00084 int colon = currentLine.find( ':' );
00085 if ( colon == -1 ) {
00086 currentLine = (*it);
00087 continue;
00088 }
00089
00090 VCardLine vCardLine;
00091 const QString key = currentLine.left( colon ).stripWhiteSpace();
00092 QString value = currentLine.mid( colon + 1 );
00093
00094 QStringList params = QStringList::split( ';', key );
00095
00096
00097 if ( params[0].find( '.' ) != -1 ) {
00098 const QStringList groupList = QStringList::split( '.', params[0] );
00099 vCardLine.setGroup( groupList[0] );
00100 vCardLine.setIdentifier( groupList[1] );
00101 } else
00102 vCardLine.setIdentifier( params[0] );
00103
00104 if ( params.count() > 1 ) {
00105 QStringList::ConstIterator paramIt = params.begin();
00106 for ( ++paramIt; paramIt != params.end(); ++paramIt ) {
00107 QStringList pair = QStringList::split( '=', *paramIt );
00108 if ( pair.size() == 1 ) {
00109
00110 if ( pair[0].lower() == "quoted-printable" ) {
00111 pair[0] = "encoding";
00112 pair[1] = "quoted-printable";
00113 } else if ( pair[0].lower() == "base64" ) {
00114 pair[0] = "encoding";
00115 pair[1] = "base64";
00116 } else {
00117 pair.prepend( "type" );
00118 }
00119 }
00120
00121 if ( pair[1].find( ',' ) != -1 ) {
00122 const QStringList args = QStringList::split( ',', pair[ 1 ] );
00123 QStringList::ConstIterator argIt;
00124 for ( argIt = args.begin(); argIt != args.end(); ++argIt )
00125 vCardLine.addParameter( pair[0].lower(), *argIt );
00126 } else
00127 vCardLine.addParameter( pair[0].lower(), pair[1] );
00128 }
00129 }
00130
00131 removeEscapes( value );
00132
00133 QByteArray output;
00134 bool wasBase64Encoded = false;
00135
00136 params = vCardLine.parameterList();
00137 if ( params.findIndex( "encoding" ) != -1 ) {
00138 QByteArray input;
00139 input = QCString(value.latin1());
00140 if ( vCardLine.parameter( "encoding" ).lower() == "b" ||
00141 vCardLine.parameter( "encoding" ).lower() == "base64" ) {
00142 KCodecs::base64Decode( input, output );
00143 wasBase64Encoded = true;
00144 }
00145 else if ( vCardLine.parameter( "encoding" ).lower() == "quoted-printable" ) {
00146
00147 while ( value.at( value.length() - 1 ) == '=' && it != linesEnd ) {
00148 value = value.remove( value.length() - 1, 1 ) + (*it);
00149 ++it;
00150 }
00151 input = QCString(value.latin1());
00152 KCodecs::quotedPrintableDecode( input, output );
00153 }
00154 } else {
00155 output = QCString(value.latin1());
00156 }
00157
00158 if ( params.findIndex( "charset" ) != -1 ) {
00159 QTextCodec *codec =
00160 QTextCodec::codecForName( vCardLine.parameter( "charset" ).latin1() );
00161 if ( codec ) {
00162 vCardLine.setValue( codec->toUnicode( output ) );
00163 } else {
00164 vCardLine.setValue( QString::fromUtf8( output ) );
00165 }
00166 } else if ( wasBase64Encoded ) {
00167 vCardLine.setValue( output );
00168 } else {
00169 vCardLine.setValue( QString::fromUtf8( output ) );
00170 }
00171
00172 currentVCard.addLine( vCardLine );
00173 }
00174
00175
00176 if ( (*it).lower().startsWith( "begin:vcard" ) ) {
00177 inVCard = true;
00178 currentLine.setLength( 0 );
00179 currentVCard.clear();
00180 continue;
00181 }
00182
00183 if ( (*it).lower().startsWith( "end:vcard" ) ) {
00184 inVCard = false;
00185 vCardList.append( currentVCard );
00186 currentLine.setLength( 0 );
00187 currentVCard.clear();
00188 continue;
00189 }
00190
00191 currentLine = (*it);
00192 }
00193 }
00194
00195 return vCardList;
00196 }
00197
00198 QString VCardParser::createVCards( const VCard::List& list )
00199 {
00200 QString text;
00201 QString textLine;
00202 QString encodingType;
00203 QStringList idents;
00204 QStringList params;
00205 QStringList values;
00206 QStringList::ConstIterator identIt;
00207 QStringList::Iterator paramIt;
00208 QStringList::ConstIterator valueIt;
00209
00210 VCardLine::List lines;
00211 VCardLine::List::ConstIterator lineIt;
00212 VCard::List::ConstIterator cardIt;
00213
00214 bool hasEncoding;
00215
00216 text.reserve( list.size() * 300 );
00217
00218
00219 VCard::List::ConstIterator listEnd( list.end() );
00220 for ( cardIt = list.begin(); cardIt != listEnd; ++cardIt ) {
00221 text.append( "BEGIN:VCARD\r\n" );
00222
00223 idents = (*cardIt).identifiers();
00224 for ( identIt = idents.constBegin(); identIt != idents.constEnd(); ++identIt ) {
00225 lines = (*cardIt).lines( (*identIt) );
00226
00227
00228 for ( lineIt = lines.constBegin(); lineIt != lines.constEnd(); ++lineIt ) {
00229 if ( !(*lineIt).value().asString().isEmpty() ) {
00230 if ( (*lineIt).hasGroup() )
00231 textLine = (*lineIt).group() + "." + (*lineIt).identifier();
00232 else
00233 textLine = (*lineIt).identifier();
00234
00235 params = (*lineIt).parameterList();
00236 hasEncoding = false;
00237 if ( params.count() > 0 ) {
00238 for ( paramIt = params.begin(); paramIt != params.end(); ++paramIt ) {
00239 if ( (*paramIt) == "encoding" ) {
00240 hasEncoding = true;
00241 encodingType = (*lineIt).parameter( "encoding" ).lower();
00242 }
00243
00244 values = (*lineIt).parameters( *paramIt );
00245 for ( valueIt = values.constBegin(); valueIt != values.constEnd(); ++valueIt ) {
00246 textLine.append( ";" + (*paramIt).upper() );
00247 if ( !(*valueIt).isEmpty() )
00248 textLine.append( "=" + (*valueIt) );
00249 }
00250 }
00251 }
00252
00253 if ( hasEncoding ) {
00254 QByteArray input, output;
00255 if ( encodingType == "b" ) {
00256 input = (*lineIt).value().toByteArray();
00257 KCodecs::base64Encode( input, output );
00258 } else if ( encodingType == "quoted-printable" ) {
00259 input = (*lineIt).value().toString().utf8();
00260 input.resize( input.size() - 1 );
00261 KCodecs::quotedPrintableEncode( input, output, false );
00262 }
00263
00264 QString value( output );
00265 addEscapes( value );
00266 textLine.append( ":" + value );
00267 } else {
00268 QString value( (*lineIt).value().asString() );
00269 addEscapes( value );
00270 textLine.append( ":" + value );
00271 }
00272
00273 if ( textLine.length() > FOLD_WIDTH ) {
00274 for ( uint i = 0; i <= ( textLine.length() / FOLD_WIDTH ); ++i )
00275 text.append( ( i == 0 ? "" : " " ) + textLine.mid( i * FOLD_WIDTH, FOLD_WIDTH ) + "\r\n" );
00276 } else
00277 text.append( textLine + "\r\n" );
00278 }
00279 }
00280 }
00281
00282 text.append( "END:VCARD\r\n" );
00283 text.append( "\r\n" );
00284 }
00285
00286 return text;
00287 }
|