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 *)
"\\," );
35 str.replace(
'\r', (
char *)
"\\r" );
36 str.replace(
'\n', (
char *)
"\\n" );
39 static void removeEscapes( QByteArray &str )
41 str.replace( (
char *)
"\\n",
"\n" );
42 str.replace( (
char *)
"\\N",
"\n" );
43 str.replace( (
char *)
"\\r",
"\r" );
44 str.replace( (
char *)
"\\,",
"," );
45 str.replace( (
char *)
"\\\\",
"\\" );
48 VCardParser::VCardParser()
52 VCardParser::~VCardParser()
56 VCard::List VCardParser::parseVCards(
const QByteArray &text )
59 VCard::List vCardList;
60 QByteArray currentLine;
62 QList<QByteArray> lines = text.split(
'\n' );
65 QList<QByteArray>::Iterator it( lines.begin() );
66 QList<QByteArray>::Iterator linesEnd( lines.end() );
67 for ( ; it != linesEnd; ++it ) {
69 if ( (*it).endsWith(
'\r' ) ) {
73 if ( (*it).startsWith(
' ' ) || (*it).startsWith(
'\t' ) ) {
74 currentLine.append( (*it).mid( 1 ) );
77 if ( (*it).trimmed().isEmpty() ) {
80 if ( inVCard && !currentLine.isEmpty() ) {
81 int colon = currentLine.indexOf(
':' );
88 const QByteArray key = currentLine.left( colon ).trimmed();
89 QByteArray value = currentLine.mid( colon + 1 );
91 QList<QByteArray> params = key.split(
';' );
94 int groupPos = params[ 0 ].indexOf(
'.' );
95 if ( groupPos != -1 ) {
96 vCardLine.setGroup( QString::fromLatin1( params[ 0 ].left( groupPos ) ) );
97 vCardLine.setIdentifier( QString::fromLatin1( params[ 0 ].mid( groupPos + 1 ) ) );
99 vCardLine.setIdentifier( QString::fromLatin1( params[ 0 ] ) );
102 if ( params.count() > 1 ) {
103 QList<QByteArray>::ConstIterator paramIt( params.constBegin() );
104 for ( ++paramIt; paramIt != params.constEnd(); ++paramIt ) {
105 QList<QByteArray> pair = (*paramIt).split(
'=' );
106 if ( pair.count() == 1 ) {
108 if ( pair[ 0 ].toLower() ==
"quoted-printable" ) {
109 pair[ 0 ] =
"encoding";
110 pair.append(
"quoted-printable" );
111 }
else if ( pair[ 0 ].toLower() ==
"base64" ) {
112 pair[ 0 ] =
"encoding";
113 pair.append(
"base64" );
115 pair.prepend(
"type" );
118 if ( pair[ 1 ].indexOf(
',' ) != -1 ) {
119 const QList<QByteArray> args = pair[ 1 ].split(
',' );
120 QList<QByteArray>::ConstIterator argIt;
121 for ( argIt = args.constBegin(); argIt != args.constEnd(); ++argIt ) {
122 vCardLine.addParameter( QString::fromLatin1( pair[ 0 ].toLower() ),
123 QString::fromLatin1( *argIt ) );
126 vCardLine.addParameter( QString::fromLatin1( pair[ 0 ].toLower() ),
127 QString::fromLatin1( pair[ 1 ] ) );
132 removeEscapes( value );
135 bool wasBase64Encoded =
false;
137 if ( vCardLine.parameterList().contains( QLatin1String(
"encoding" ) ) ) {
138 const QString encoding = vCardLine.parameter( QLatin1String(
"encoding" ) ).toLower();
141 if ( encoding == QLatin1String(
"b" ) || encoding == QLatin1String(
"base64" ) ) {
142 output = QByteArray::fromBase64( value );
143 wasBase64Encoded =
true;
145 else if ( encoding == QLatin1String(
"quoted-printable" ) ) {
147 while ( value.endsWith(
'=' ) && it != linesEnd ) {
152 KCodecs::quotedPrintableDecode( value, output );
153 }
else if ( encoding == QLatin1String(
"8bit" ) ) {
156 qDebug(
"Unknown vcard encoding type!" );
162 if ( vCardLine.parameterList().contains( QLatin1String(
"charset" ) ) ) {
164 QTextCodec *codec = QTextCodec::codecForName(
165 vCardLine.parameter( QLatin1String(
"charset" ) ).toLatin1() );
167 vCardLine.setValue( codec->toUnicode( output ) );
169 vCardLine.setValue( QString::fromUtf8( output ) );
171 }
else if ( wasBase64Encoded ) {
172 vCardLine.setValue( output );
174 vCardLine.setValue( QString::fromUtf8( output ) );
177 currentVCard.addLine( vCardLine );
181 if ( (*it).toLower().startsWith(
"begin:vcard" ) ) {
184 currentVCard.clear();
188 if ( (*it).toLower().startsWith(
"end:vcard" ) ) {
190 vCardList.append( currentVCard );
192 currentVCard.clear();
203 QByteArray VCardParser::createVCards(
const VCard::List &list )
207 QString encodingType;
211 QStringList::ConstIterator identIt;
212 QStringList::Iterator paramIt;
213 QStringList::ConstIterator valueIt;
215 VCardLine::List lines;
216 VCardLine::List::ConstIterator lineIt;
217 VCard::List::ConstIterator cardIt;
221 text.reserve( list.size() * 300 );
224 VCard::List::ConstIterator listEnd( list.end() );
225 for ( cardIt = list.begin(); cardIt != listEnd; ++cardIt ) {
226 text.append(
"BEGIN:VCARD\r\n" );
228 idents = (*cardIt).identifiers();
229 for ( identIt = idents.constBegin(); identIt != idents.constEnd(); ++identIt ) {
230 lines = (*cardIt).lines( (*identIt) );
233 for ( lineIt = lines.constBegin(); lineIt != lines.constEnd(); ++lineIt ) {
234 QVariant val = (*lineIt).value();
235 if ( val.isValid() ) {
236 if ( (*lineIt).hasGroup() ) {
237 textLine = (*lineIt).group().toLatin1() +
'.' + (*lineIt).identifier().toLatin1();
239 textLine = (*lineIt).identifier().toLatin1();
242 params = (*lineIt).parameterList();
244 if ( params.count() > 0 ) {
245 for ( paramIt = params.begin(); paramIt != params.end(); ++paramIt ) {
246 if ( (*paramIt) == QLatin1String(
"encoding" ) ) {
248 encodingType = (*lineIt).parameter( QLatin1String(
"encoding" ) ).toLower();
251 values = (*lineIt).parameters( *paramIt );
252 for ( valueIt = values.constBegin(); valueIt != values.constEnd(); ++valueIt ) {
253 textLine.append(
';' + (*paramIt).toLatin1().toUpper() );
254 if ( !(*valueIt).isEmpty() ) {
255 textLine.append(
'=' + (*valueIt).toLatin1() );
261 QByteArray input, output;
264 if ( (*lineIt).parameterList().contains( QLatin1String(
"charset" ) ) ) {
266 const QString value = (*lineIt).value().toString();
267 QTextCodec *codec = QTextCodec::codecForName(
268 (*lineIt).parameter( QLatin1String(
"charset" ) ).toLatin1() );
270 input = codec->fromUnicode( value );
272 input = value.toUtf8();
274 }
else if ( (*lineIt).value().type() == QVariant::ByteArray ) {
275 input = (*lineIt).value().toByteArray();
277 input = (*lineIt).value().toString().toUtf8();
282 if ( encodingType == QLatin1String(
"b" ) ) {
283 output = input.toBase64();
284 }
else if ( encodingType == QLatin1String(
"quoted-printable" ) ) {
285 KCodecs::quotedPrintableEncode( input, output,
false );
290 addEscapes( output, (*lineIt).identifier() == QLatin1String(
"CATEGORIES") );
292 if ( !output.isEmpty() ) {
293 textLine.append(
':' + output );
295 if ( textLine.length() > FOLD_WIDTH ) {
296 for (
int i = 0; i <= ( textLine.length() / FOLD_WIDTH ); ++i ) {
298 ( i == 0 ?
"" :
" " ) + textLine.mid( i * FOLD_WIDTH, FOLD_WIDTH ) +
"\r\n" );
301 text.append( textLine +
"\r\n" );
308 text.append(
"END:VCARD\r\n" );
309 text.append(
"\r\n" );