Ejemplo n.º 1
0
VCard::List VCardParser::parseVCards( const QByteArray &text )
{
  VCard currentVCard;
  VCard::List vCardList;
  QByteArray currentLine;

  QList<QByteArray> lines = text.split( '\n' );

  bool inVCard = false;
  QList<QByteArray>::Iterator it( lines.begin() );
  QList<QByteArray>::Iterator linesEnd( lines.end() );
  for ( ; it != linesEnd; ++it ) {
    // remove the trailing \r, left from \r\n
    if ( ( *it ).endsWith( '\r' ) ) {
        ( *it ).chop( 1 );
    }

    if ( ( *it ).startsWith( ' ' ) ||
         ( *it ).startsWith( '\t' ) ) { //folded line => append to previous
      currentLine.append( ( *it ).mid( 1 ) );
      continue;
    } else {
      if ( ( *it ).trimmed().isEmpty() ) { // empty line
        continue;
      }
      if ( inVCard && !currentLine.isEmpty() ) { // now parse the line
        int colon = currentLine.indexOf( ':' );
        if ( colon == -1 ) { // invalid line
          currentLine = ( *it );
          continue;
        }

        VCardLine vCardLine;
        const QByteArray key = currentLine.left( colon ).trimmed();
        QByteArray value = currentLine.mid( colon + 1 );

        QList<QByteArray> params = key.split( ';' );

        // check for group
        int groupPos = params[ 0 ].indexOf( '.' );
        if ( groupPos != -1 ) {
          vCardLine.setGroup( QString::fromLatin1( params[ 0 ].left( groupPos ) ) );
          vCardLine.setIdentifier( QString::fromLatin1( params[ 0 ].mid( groupPos + 1 ) ) );
        } else {
          vCardLine.setIdentifier( QString::fromLatin1( params[ 0 ] ) );
        }

        if ( params.count() > 1 ) { // find all parameters
          QList<QByteArray>::ConstIterator paramIt( params.constBegin() );
          for ( ++paramIt; paramIt != params.constEnd(); ++paramIt ) {
            QList<QByteArray> pair = ( *paramIt ).split( '=' );
            if ( pair.count() == 1 ) {
              // correct the f*****g 2.1 'standard'
              if ( pair[ 0 ].toLower() == "quoted-printable" ) {
                pair[ 0 ] = "encoding";
                pair.append( "quoted-printable" );
              } else if ( pair[ 0 ].toLower() == "base64" ) {
                pair[ 0 ] = "encoding";
                pair.append( "base64" );
              } else {
                pair.prepend( "type" );
              }
            }
            if ( pair[ 1 ].indexOf( ',' ) != -1 ) { // parameter in type=x,y,z format
              const QList<QByteArray> args = pair[ 1 ].split( ',' );
              QList<QByteArray>::ConstIterator argIt;
              QList<QByteArray>::ConstIterator argEnd( args.constEnd() );
              for ( argIt = args.constBegin(); argIt != argEnd; ++argIt ) {
                vCardLine.addParameter( QString::fromLatin1( pair[ 0 ].toLower() ),
                                        QString::fromLatin1( *argIt ) );
              }
            } else {
              vCardLine.addParameter( QString::fromLatin1( pair[ 0 ].toLower() ),
                                      QString::fromLatin1( pair[ 1 ] ) );
            }
          }
        }

        removeEscapes( value );

        QByteArray output;
        bool wasBase64Encoded = false;

        if ( vCardLine.parameterList().contains( QLatin1String( "encoding" ) ) ) {
          const QString encoding = vCardLine.parameter( QLatin1String( "encoding" ) ).toLower();

          // have to decode the data
          if ( encoding == QLatin1String( "b" ) || encoding == QLatin1String( "base64" ) ) {
            output = QByteArray::fromBase64( value );
            wasBase64Encoded = true;
          }
          else if ( encoding == QLatin1String( "quoted-printable" ) ) {
            // join any qp-folded lines
            while ( value.endsWith( '=' ) && it != linesEnd ) {
              value.chop( 1 ); // remove the '='
              value.append( *it );
              ++it;
            }
            KCodecs::quotedPrintableDecode( value, output );
          } else if ( encoding == QLatin1String( "8bit" ) ) {
            output = value;
          } else {
            qDebug( "Unknown vcard encoding type!" );
          }
        } else {
          output = value;
        }

        if ( vCardLine.parameterList().contains( QLatin1String( "charset" ) ) ) {
          // have to convert the data
          QTextCodec *codec = QTextCodec::codecForName(
            vCardLine.parameter( QLatin1String( "charset" ) ).toLatin1() );
          if ( codec ) {
            vCardLine.setValue( codec->toUnicode( output ) );
          } else {
            vCardLine.setValue( QString::fromUtf8( output ) );
          }
        } else if ( wasBase64Encoded ) {
            vCardLine.setValue( output );
        } else {
            vCardLine.setValue( QString::fromUtf8( output ) );
        }

        currentVCard.addLine( vCardLine );
      }

      // we do not save the start and end tag as vcardline
      if ( ( *it ).toLower().startsWith( "begin:vcard" ) ) { //krazy:exclude=strings
        inVCard = true;
        currentLine.clear();
        currentVCard.clear(); // flush vcard
        continue;
      }

      if ( ( *it ).toLower().startsWith( "end:vcard" ) ) { //krazy:exclude=strings
        inVCard = false;
        vCardList.append( currentVCard );
        currentLine.clear();
        currentVCard.clear(); // flush vcard
        continue;
      }

      currentLine = ( *it );
    }
  }

  return vCardList;
}
Ejemplo n.º 2
0
VCard::List VCardParser::parseVCards( const QString& text )
{
  static QRegExp sep( "[\x0d\x0a]" );

  VCard currentVCard;
  VCard::List vCardList;
  QString currentLine;

  const QStringList lines = QStringList::split( sep, text );
  QStringList::ConstIterator it;

  bool inVCard = false;
  QStringList::ConstIterator linesEnd( lines.end() );
  for ( it = lines.begin(); it != linesEnd; ++it ) {

    if ( (*it).isEmpty() ) // empty line
      continue;

    if ( (*it)[ 0 ] == ' ' || (*it)[ 0 ] == '\t' ) { // folded line => append to previous
      currentLine += QString( *it ).remove( 0, 1 );
      continue;
    } else {
      if ( inVCard && !currentLine.isEmpty() ) { // now parse the line
        int colon = currentLine.find( ':' );
        if ( colon == -1 ) { // invalid line
          currentLine = (*it);
          continue;
        }

        VCardLine vCardLine;
        const QString key = currentLine.left( colon ).stripWhiteSpace();
        QString value = currentLine.mid( colon + 1 );

        QStringList params = QStringList::split( ';', key );

        // check for group
        if ( params[0].find( '.' ) != -1 ) {
          const QStringList groupList = QStringList::split( '.', params[0] );
          vCardLine.setGroup( groupList[0] );
          vCardLine.setIdentifier( groupList[1] );
        } else
          vCardLine.setIdentifier( params[0] );

        if ( params.count() > 1 ) { // find all parameters
          QStringList::ConstIterator paramIt = params.begin();
          for ( ++paramIt; paramIt != params.end(); ++paramIt ) {
            QStringList pair = QStringList::split( '=', *paramIt );
            if ( pair.size() == 1 ) {
              // correct the f*****g 2.1 'standard'
              if ( pair[0].lower() == "quoted-printable" ) {
                pair[0] = "encoding";
                pair[1] = "quoted-printable";
              } else if ( pair[0].lower() == "base64" ) {
                pair[0] = "encoding";
                pair[1] = "base64";
              } else {
                pair.prepend( "type" );
              }
            }
            // This is pretty much a faster pair[1].contains( ',' )...
            if ( pair[1].find( ',' ) != -1 ) { // parameter in type=x,y,z format
              const QStringList args = QStringList::split( ',', pair[ 1 ] );
              QStringList::ConstIterator argIt;
              for ( argIt = args.begin(); argIt != args.end(); ++argIt )
                vCardLine.addParameter( pair[0].lower(), *argIt );
            } else
              vCardLine.addParameter( pair[0].lower(), pair[1] );
          }
        }

        removeEscapes( value );

        QByteArray output;
        bool wasBase64Encoded = false;

        params = vCardLine.parameterList();
        if ( params.findIndex( "encoding" ) != -1 ) { // have to decode the data
          QByteArray input;
          input = QCString(value.latin1());
          if ( vCardLine.parameter( "encoding" ).lower() == "b" ||
               vCardLine.parameter( "encoding" ).lower() == "base64" ) {
            KCodecs::base64Decode( input, output );
            wasBase64Encoded = true;
          }
          else if ( vCardLine.parameter( "encoding" ).lower() == "quoted-printable" ) {
            // join any qp-folded lines
            while ( value.at( value.length() - 1 ) == '=' && it != linesEnd ) {
              value = value.remove( value.length() - 1, 1 ) + (*it);
              ++it;
            }
            input = QCString(value.latin1());
            KCodecs::quotedPrintableDecode( input, output );
          }
        } else {
          output = QCString(value.latin1());
        }

        if ( params.findIndex( "charset" ) != -1 ) { // have to convert the data
          QTextCodec *codec =
            QTextCodec::codecForName( vCardLine.parameter( "charset" ).latin1() );
          if ( codec ) {
            vCardLine.setValue( codec->toUnicode( output ) );
          } else {
            vCardLine.setValue( QString::fromUtf8( output ) );
          }
        } else if ( wasBase64Encoded ) {
            vCardLine.setValue( output );
        } else {  // if charset not given, assume it's in UTF-8 (as used in previous KDE versions)
            vCardLine.setValue( QString::fromUtf8( output ) );
        }

        currentVCard.addLine( vCardLine );
      }

      // we do not save the start and end tag as vcardline
      if ( (*it).lower().startsWith( "begin:vcard" ) ) {
        inVCard = true;
        currentLine.setLength( 0 );
        currentVCard.clear(); // flush vcard
        continue;
      }

      if ( (*it).lower().startsWith( "end:vcard" ) ) {
        inVCard = false;
        vCardList.append( currentVCard );
        currentLine.setLength( 0 );
        currentVCard.clear(); // flush vcard
        continue;
      }

      currentLine = (*it);
    }
  }

  return vCardList;
}