21 #include "vcardparser.h"
24 #include <QtCore/QTextCodec>
30 static void addEscapes( QByteArray &str,
bool excludeEscapteComma )
32 str.replace(
'\\', (
char *)
"\\\\" );
33 if ( !excludeEscapteComma ) {
34 str.replace(
',', (
char *)
"\\," );
36 str.replace(
'\r', (
char *)
"\\r" );
37 str.replace(
'\n', (
char *)
"\\n" );
40 static void removeEscapes( QByteArray &str )
42 str.replace( (
char *)
"\\n",
"\n" );
43 str.replace( (
char *)
"\\N",
"\n" );
44 str.replace( (
char *)
"\\r",
"\r" );
45 str.replace( (
char *)
"\\,",
"," );
46 str.replace( (
char *)
"\\\\",
"\\" );
49 VCardParser::VCardParser()
54 VCardParser::~VCardParser()
58 VCard::List VCardParser::parseVCards(
const QByteArray &text )
61 VCard::List vCardList;
62 QByteArray currentLine;
64 QList<QByteArray> lines = text.split(
'\n' );
67 QList<QByteArray>::Iterator it( lines.begin() );
68 QList<QByteArray>::Iterator linesEnd( lines.end() );
69 for ( ; it != linesEnd; ++it ) {
71 if ( ( *it ).endsWith(
'\r' ) ) {
75 if ( ( *it ).startsWith(
' ' ) ||
76 ( *it ).startsWith(
'\t' ) ) {
77 currentLine.append( ( *it ).mid( 1 ) );
80 if ( ( *it ).trimmed().isEmpty() ) {
83 if ( inVCard && !currentLine.isEmpty() ) {
84 int colon = currentLine.indexOf(
':' );
86 currentLine = ( *it );
91 const QByteArray key = currentLine.left( colon ).trimmed();
92 QByteArray value = currentLine.mid( colon + 1 );
94 QList<QByteArray> params = key.split(
';' );
97 int groupPos = params[ 0 ].indexOf(
'.' );
98 if ( groupPos != -1 ) {
99 vCardLine.setGroup( QString::fromLatin1( params[ 0 ].left( groupPos ) ) );
100 vCardLine.setIdentifier( QString::fromLatin1( params[ 0 ].mid( groupPos + 1 ) ) );
102 vCardLine.setIdentifier( QString::fromLatin1( params[ 0 ] ) );
105 if ( params.count() > 1 ) {
106 QList<QByteArray>::ConstIterator paramIt( params.constBegin() );
107 for ( ++paramIt; paramIt != params.constEnd(); ++paramIt ) {
108 QList<QByteArray> pair = ( *paramIt ).split(
'=' );
109 if ( pair.count() == 1 ) {
111 if ( pair[ 0 ].toLower() ==
"quoted-printable" ) {
112 pair[ 0 ] =
"encoding";
113 pair.append(
"quoted-printable" );
114 }
else if ( pair[ 0 ].toLower() ==
"base64" ) {
115 pair[ 0 ] =
"encoding";
116 pair.append(
"base64" );
118 pair.prepend(
"type" );
121 if ( pair[ 1 ].indexOf(
',' ) != -1 ) {
122 const QList<QByteArray> args = pair[ 1 ].split(
',' );
123 QList<QByteArray>::ConstIterator argIt;
124 QList<QByteArray>::ConstIterator argEnd( args.constEnd() );
125 for ( argIt = args.constBegin(); argIt != argEnd; ++argIt ) {
126 vCardLine.addParameter( QString::fromLatin1( pair[ 0 ].toLower() ),
127 QString::fromLatin1( *argIt ) );
130 vCardLine.addParameter( QString::fromLatin1( pair[ 0 ].toLower() ),
131 QString::fromLatin1( pair[ 1 ] ) );
136 removeEscapes( value );
139 bool wasBase64Encoded =
false;
141 if ( vCardLine.parameterList().contains( QLatin1String(
"encoding" ) ) ) {
142 const QString encoding = vCardLine.parameter( QLatin1String(
"encoding" ) ).toLower();
145 if ( encoding == QLatin1String(
"b" ) || encoding == QLatin1String(
"base64" ) ) {
146 output = QByteArray::fromBase64( value );
147 wasBase64Encoded =
true;
149 else if ( encoding == QLatin1String(
"quoted-printable" ) ) {
151 while ( value.endsWith(
'=' ) && it != linesEnd ) {
156 KCodecs::quotedPrintableDecode( value, output );
157 }
else if ( encoding == QLatin1String(
"8bit" ) ) {
160 qDebug(
"Unknown vcard encoding type!" );
166 if ( vCardLine.parameterList().contains( QLatin1String(
"charset" ) ) ) {
168 QTextCodec *codec = QTextCodec::codecForName(
169 vCardLine.parameter( QLatin1String(
"charset" ) ).toLatin1() );
171 vCardLine.setValue( codec->toUnicode( output ) );
173 vCardLine.setValue( QString::fromUtf8( output ) );
175 }
else if ( wasBase64Encoded ) {
176 vCardLine.setValue( output );
178 vCardLine.setValue( QString::fromUtf8( output ) );
181 currentVCard.addLine( vCardLine );
185 if ( ( *it ).toLower().startsWith(
"begin:vcard" ) ) {
188 currentVCard.clear();
192 if ( ( *it ).toLower().startsWith(
"end:vcard" ) ) {
194 vCardList.append( currentVCard );
196 currentVCard.clear();
200 currentLine = ( *it );
207 QByteArray VCardParser::createVCards(
const VCard::List &list )
211 QString encodingType;
215 QStringList::ConstIterator identIt;
216 QStringList::Iterator paramIt;
217 QStringList::ConstIterator valueIt;
219 VCardLine::List lines;
220 VCardLine::List::ConstIterator lineIt;
221 VCard::List::ConstIterator cardIt;
225 text.reserve( list.size() * 300 );
228 VCard::List::ConstIterator listEnd( list.end() );
229 for ( cardIt = list.begin(); cardIt != listEnd; ++cardIt ) {
230 text.append(
"BEGIN:VCARD\r\n" );
232 idents = ( *cardIt ).identifiers();
233 for ( identIt = idents.constBegin(); identIt != idents.constEnd(); ++identIt ) {
234 lines = ( *cardIt ).lines( ( *identIt ) );
237 for ( lineIt = lines.constBegin(); lineIt != lines.constEnd(); ++lineIt ) {
238 QVariant val = ( *lineIt ).value();
239 if ( val.isValid() ) {
240 if ( ( *lineIt ).hasGroup() ) {
241 textLine = ( *lineIt ).group().toLatin1() +
'.' + ( *lineIt ).identifier().toLatin1();
243 textLine = ( *lineIt ).identifier().toLatin1();
246 params = ( *lineIt ).parameterList();
248 if ( !params.isEmpty() ) {
249 for ( paramIt = params.begin(); paramIt != params.end(); ++paramIt ) {
250 if ( ( *paramIt ) == QLatin1String(
"encoding" ) ) {
252 encodingType = ( *lineIt ).parameter( QLatin1String(
"encoding" ) ).toLower();
255 values = ( *lineIt ).parameters( *paramIt );
256 for ( valueIt = values.constBegin(); valueIt != values.constEnd(); ++valueIt ) {
257 textLine.append(
';' + ( *paramIt ).toLatin1().toUpper() );
258 if ( !( *valueIt ).isEmpty() ) {
259 textLine.append(
'=' + ( *valueIt ).toLatin1() );
265 QByteArray input, output;
268 if ( ( *lineIt ).parameterList().contains( QLatin1String(
"charset" ) ) ) {
270 const QString value = ( *lineIt ).value().toString();
271 QTextCodec *codec = QTextCodec::codecForName(
272 ( *lineIt ).parameter( QLatin1String(
"charset" ) ).toLatin1() );
274 input = codec->fromUnicode( value );
276 input = value.toUtf8();
278 }
else if ( ( *lineIt ).value().type() == QVariant::ByteArray ) {
279 input = ( *lineIt ).value().toByteArray();
281 input = ( *lineIt ).value().toString().toUtf8();
286 if ( encodingType == QLatin1String(
"b" ) ) {
287 output = input.toBase64();
288 }
else if ( encodingType == QLatin1String(
"quoted-printable" ) ) {
289 KCodecs::quotedPrintableEncode( input, output,
false );
294 addEscapes( output, ( *lineIt ).identifier() == QLatin1String(
"CATEGORIES" ) );
296 if ( !output.isEmpty() ) {
297 textLine.append(
':' + output );
299 if ( textLine.length() > FOLD_WIDTH ) {
300 for (
int i = 0; i <= ( textLine.length() / FOLD_WIDTH ); ++i ) {
302 ( i == 0 ?
"" :
" " ) + textLine.mid( i * FOLD_WIDTH, FOLD_WIDTH ) +
"\r\n" );
305 text.append( textLine +
"\r\n" );
312 text.append(
"END:VCARD\r\n" );
313 text.append(
"\r\n" );