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