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   VCard currentVCard;
00042   VCard::List vCardList;
00043   QString currentLine;
00044 
00045   QStringList lines = QStringList::split( QRegExp( "[\x0d\x0a]" ), text );
00046   QStringList::Iterator it;
00047 
00048   bool inVCard = false;
00049   for ( it = lines.begin(); it != lines.end(); ++it ) {
00050 
00051     if ( (*it).isEmpty() ) // empty line
00052       continue;
00053 
00054     if ( (*it)[ 0 ] == ' ' || (*it)[ 0 ] == '\t' ) { // folded line => append to previous
00055       currentLine += (*it).remove( 0, 1 );
00056       continue;
00057     } else {
00058       if ( inVCard && !currentLine.isEmpty() ) { // now parse the line
00059         int colon = currentLine.find( ':' );
00060         if ( colon == -1 ) { // invalid line
00061           currentLine = (*it);
00062           continue;
00063         }
00064 
00065         VCardLine vCardLine;
00066         QString key = currentLine.left( colon ).stripWhiteSpace();
00067         QString value = currentLine.mid( colon + 1 );
00068 
00069         QStringList params = QStringList::split( ';', key );
00070         vCardLine.setIdentifier( params[0] );
00071         if ( params.count() > 1 ) { // find all parameters
00072           for ( uint i = 1; i < params.count(); ++i ) {
00073             QStringList pair = QStringList::split( '=', params[i] );
00074             if ( pair.size() == 1 ) {
00075               // correct the fucking 2.1 'standard'
00076               if ( pair[0].lower() == "quoted-printable" ) {
00077                 pair[0] = "encoding";
00078                 pair[1] = "quoted-printable";
00079               } else {
00080                 pair.prepend( "type" );
00081               }
00082             }
00083             //This is pretty much a faster pair[1].contains( ',' )...
00084             if ( pair[1].find( ',' ) != -1 ) { // parameter in type=x,y,z format
00085               QStringList args = QStringList::split( ',', pair[ 1 ] );
00086               for ( uint j = 0; j < args.count(); ++j )
00087                 vCardLine.addParameter( pair[0].lower(), args[j] );
00088             } else
00089               vCardLine.addParameter( pair[0].lower(), pair[1] );
00090           }
00091         }
00092 
00093         params = vCardLine.parameterList();
00094         if ( params.findIndex( "encoding" ) != -1 ) { // have to decode the data
00095           QByteArray input, output;
00096           input = value.local8Bit();
00097           if ( vCardLine.parameter( "encoding" ).lower() == "b" ||
00098                vCardLine.parameter( "encoding" ).lower() == "base64" )
00099             KCodecs::base64Decode( input, output );
00100           else if ( vCardLine.parameter( "encoding" ).lower() == "quoted-printable" )
00101             KCodecs::quotedPrintableDecode( input, output );
00102 
00103           if ( vCardLine.parameter( "charset" ).lower() == "utf-8" ) {
00104             vCardLine.setValue( QString::fromUtf8( output.data(), output.size() ) );
00105           } else {
00106             vCardLine.setValue( output );
00107           }
00108         } else if ( vCardLine.parameter( "charset" ).lower() == "utf-8" ) {
00109           vCardLine.setValue( QString::fromUtf8( value.ascii() ) );
00110         } else
00111           vCardLine.setValue( value.replace( "\\n", "\n" ) );
00112 
00113         currentVCard.addLine( vCardLine );
00114       }
00115 
00116       // we do not save the start and end tag as vcardline
00117       if ( (*it).lower().startsWith( "begin:vcard" ) ) {
00118         inVCard = true;
00119         currentLine.setLength( 0 );
00120         currentVCard.clear(); // flush vcard
00121         continue;
00122       }
00123 
00124       if ( (*it).lower().startsWith( "end:vcard" ) ) {
00125         inVCard = false;
00126         vCardList.append( currentVCard );
00127         currentLine.setLength( 0 );
00128         currentVCard.clear(); // flush vcard
00129         continue;
00130       }
00131 
00132       currentLine = (*it);
00133     }
00134   }
00135 
00136   return vCardList;
00137 }
00138 
00139 QString VCardParser::createVCards( const VCard::List& list )
00140 {
00141   QString text;
00142   QString textLine;
00143   QString encodingType;
00144   QStringList idents;
00145   QStringList params;
00146   QStringList values;
00147   QStringList::ConstIterator identIt;
00148   QStringList::Iterator paramIt;
00149   QStringList::Iterator valueIt;
00150 
00151   VCardLine::List lines;
00152   VCardLine::List::Iterator lineIt;
00153   VCard::List::ConstIterator cardIt;
00154 
00155   bool hasEncoding;
00156 
00157 
00158   // iterate over the cards
00159   for ( cardIt = list.begin(); cardIt != list.end(); ++cardIt ) {
00160     text.append( "BEGIN:VCARD\r\n" );
00161 
00162     idents = (*cardIt).identifiers();
00163     for ( identIt = idents.begin(); identIt != idents.end(); ++identIt ) {
00164       VCard card = (*cardIt);
00165       lines = card.lines( (*identIt) );
00166 
00167       // iterate over the lines
00168       for ( lineIt = lines.begin(); lineIt != lines.end(); ++lineIt ) {
00169         if ( !(*lineIt).value().asString().isEmpty() ) {
00170           textLine = (*lineIt).identifier();
00171 
00172           params = (*lineIt).parameterList();
00173           hasEncoding = false;
00174           if ( params.count() > 0 ) { // we have parameters
00175             for ( paramIt = params.begin(); paramIt != params.end(); ++paramIt ) {
00176               if ( (*paramIt) == "encoding" ) {
00177                 hasEncoding = true;
00178                 encodingType = (*lineIt).parameter( "encoding" ).lower();
00179               }
00180 
00181               values = (*lineIt).parameters( *paramIt );
00182               for ( valueIt = values.begin(); valueIt != values.end(); ++valueIt ) {
00183                 textLine.append( ";" + (*paramIt).upper() );
00184                 if ( !(*valueIt).isEmpty() )
00185                   textLine.append( "=" + (*valueIt) );
00186               }
00187             }
00188           }
00189 
00190           if ( hasEncoding ) { // have to encode the data
00191             QByteArray input, output;
00192             input = (*lineIt).value().toByteArray();
00193             if ( encodingType == "b" )
00194               KCodecs::base64Encode( input, output );
00195             else if ( encodingType == "quoted-printable" )
00196               KCodecs::quotedPrintableEncode( input, output );
00197             textLine.append( ":" + QString( output ) );
00198           } else
00199             textLine.append( ":" + (*lineIt).value().asString().replace( "\n", "\\n" ) );
00200 
00201           if ( textLine.length() > FOLD_WIDTH ) { // we have to fold the line
00202             for ( uint i = 0; i <= ( textLine.length() / FOLD_WIDTH ); ++i )
00203               text.append( ( i == 0 ? "" : " " ) + textLine.mid( i * FOLD_WIDTH, FOLD_WIDTH ) + "\r\n" );
00204           } else
00205             text.append( textLine + "\r\n" );
00206         }
00207       }
00208     }
00209 
00210     text.append( "END:VCARD\r\n" );
00211     text.append( "\r\n" );
00212   }
00213 
00214   return text;
00215 }
KDE Logo
This file is part of the documentation for kabc Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Jul 22 10:18:13 2005 by doxygen 1.3.6 written by Dimitri van Heesch, © 1997-2003