| # kabc Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# ldif.cpp

    00001 /*
    00002     This file is part of libkabc.
    00003     Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu>
    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 <kdebug.h>
    00022 #include <kmdcodec.h>
    00023
    00024 #include "ldif.h"
    00025
    00026 using namespace KABC;
    00027
    00028 LDIF::LDIF()
    00029 {
    00030   startParsing();
    00031 }
    00032
    00033 LDIF::~LDIF()
    00034 {
    00035 }
    00036
    00037 QCString LDIF::assembleLine( const QString &fieldname, const QByteArray &value,
    00038   uint linelen, bool url )
    00039 {
    00040   bool safe = false;
    00041   bool isDn;
    00042   QCString result;
    00043   uint i;
    00044
    00045   if ( url ) {
    00046     result = fieldname.utf8() + ":< " + QCString( value.data(), value.size()+1 );
    00047   } else {
    00048     isDn = fieldname.lower() == "dn";
    00049     //SAFE-INIT-CHAR
    00050     if ( value.size() > 0 && value[0] > 0 && value[0] != '\n' &&
    00051       value[0] != '\r' && value[0] != ':' && value[0] != '<' ) safe = true;
    00052
    00053     //SAFE-CHAR
    00054     if ( safe ) {
    00055       for ( i=1; i < value.size(); i++ ) {
    00056       //allow utf-8 in Distinguished Names
    00057         if ( ( isDn && value[i] == 0 ) ||
    00058              ( !isDn && value[i] <= 0 ) ||
    00059              value[i] == '\r' || value[i] == '\n' ) {
    00060           safe = false;
    00061           break;
    00062         }
    00063       }
    00064     }
    00065
    00066     if ( value.size() == 0 ) safe = true;
    00067
    00068     if( safe ) {
    00069       result = fieldname.utf8() + ": " + QCString( value.data(), value.size()+1 );
    00070     } else {
    00071       result = fieldname.utf8() + ":: " + KCodecs::base64Encode( value, false );
    00072     }
    00073
    00074     if ( linelen > 0 ) {
    00075       i = (fieldname.length()+2) > linelen ? fieldname.length()+2 : linelen;
    00076       while ( i < result.length() ) {
    00077         result.insert( i, "\n " );
    00078         i += linelen+2;
    00079       }
    00080     }
    00081   }
    00082   return result;
    00083 }
    00084
    00085 QCString LDIF::assembleLine( const QString &fieldname, const QCString &value,
    00086   uint linelen, bool url )
    00087 {
    00088   QCString ret;
    00089   QByteArray tmp;
    00090   uint valuelen = value.length();
    00091   const char *data = value.data();
    00092
    00093   tmp.setRawData( data, valuelen );
    00094   ret = assembleLine( fieldname, tmp, linelen, url );
    00095   tmp.resetRawData( data, valuelen );
    00096   return ret;
    00097
    00098 }
    00099
    00100 QCString LDIF::assembleLine( const QString &fieldname, const QString &value,
    00101   uint linelen, bool url )
    00102 {
    00103   return assembleLine( fieldname, value.utf8(), linelen, url );
    00104 }
    00105
    00106 bool LDIF::splitLine( const QCString &line, QString &fieldname, QByteArray &value )
    00107 {
    00108   int position;
    00109   QByteArray tmp;
    00110   int linelen;
    00111   const char *data;
    00112
    00113 //  kdDebug(5700) << "splitLine line: " << QString::fromUtf8(line) << endl;
    00114
    00115   position = line.find( ":" );
    00116   if ( position == -1 ) {
    00117     // strange: we did not find a fieldname
    00118     fieldname = "";
    00119     QCString str;
    00120     str = line.stripWhiteSpace();
    00121     linelen = str.length();
    00122     data = str.data();
    00123     tmp.setRawData( data, linelen );
    00124     value = tmp.copy();
    00125     tmp.resetRawData( data, linelen );
    00126 //    kdDebug(5700) << "value : " << value[0] << endl;
    00127     return false;
    00128   }
    00129
    00130   linelen = line.length();
    00131
    00132   if ( linelen > ( position + 1 ) && line[ position + 1 ] == ':' ) {
    00133     // String is BASE64 encoded -> decode it now.
    00134     fieldname = QString::fromUtf8(
    00135       line.left( position ).stripWhiteSpace() );
    00136     if ( linelen <= ( position + 3 ) ) {
    00137       value.resize( 0 );
    00138       return false;
    00139     }
    00140     data = &line.data()[ position + 3 ];
    00141     tmp.setRawData( data, linelen - position - 3 );
    00142     KCodecs::base64Decode( tmp, value );
    00143     tmp.resetRawData( data, linelen - position - 3 );
    00144     return false;
    00145   }
    00146
    00147   if ( linelen > ( position + 1 ) && line[ position + 1 ] == '<' ) {
    00148     // String is an URL.
    00149     fieldname = QString::fromUtf8(
    00150       line.left( position ).stripWhiteSpace() );
    00151     if ( linelen <= ( position + 3 ) ) {
    00152       value.resize( 0 );
    00153       return false;
    00154     }
    00155     data = &line.data()[ position + 3];
    00156     tmp.setRawData( data, linelen - position - 3 );
    00157     value = tmp.copy();
    00158     tmp.resetRawData( data, linelen - position - 3 );
    00159     return true;
    00160   }
    00161
    00162   fieldname = QString::fromUtf8(line.left( position ).stripWhiteSpace());
    00163   if ( linelen <= ( position + 2 ) ) {
    00164     value.resize( 0 );
    00165     return false;
    00166   }
    00167   data = &line.data()[ position + 2 ];
    00168   tmp.setRawData( data, linelen - position - 2 );
    00169   value = tmp.copy();
    00170   tmp.resetRawData( data, linelen - position - 2 );
    00171   return false;
    00172 }
    00173
    00174 bool LDIF::splitControl( const QCString &line, QString &oid, bool &critical,
    00175   QByteArray &value )
    00176 {
    00177   QString tmp;
    00178   critical = false;
    00179   bool url = splitLine( line, tmp, value );
    00180
    00181   kdDebug(5700) << "splitControl: value: " << QString::fromUtf8(value, value.size()) << endl;
    00182   if ( tmp.isEmpty() ) {
    00183     tmp = QString::fromUtf8( value, value.size() );
    00184     value.resize( 0 );
    00185   }
    00186   if ( tmp.right( 4 ) == "true" ) {
    00187     critical = true;
    00188     tmp.truncate( tmp.length() - 5 );
    00189   } else  if ( tmp.right( 5 ) == "false" ) {
    00190     critical = false;
    00191     tmp.truncate( tmp.length() - 6 );
    00192   }
    00193   oid = tmp;
    00194   return url;
    00195 }
    00196
    00197 LDIF::ParseVal LDIF::processLine()
    00198 {
    00199
    00200   if ( mIsComment ) return None;
    00201
    00202   ParseVal retval = None;
    00203   if ( mLastParseVal == EndEntry ) mEntryType = Entry_None;
    00204
    00205   mUrl = splitLine( line, mAttr, mVal );
    00206
    00207   QString attrLower = mAttr.lower();
    00208
    00209   switch ( mEntryType ) {
    00210     case Entry_None:
    00211       if ( attrLower == "version" ) {
    00212         if ( !mDn.isEmpty() ) retval = Err;
    00213       } else if ( attrLower == "dn" ) {
    00214         kdDebug(5700) << "ldapentry dn: " << QString::fromUtf8( mVal, mVal.size() ) << endl;
    00215         mDn = QString::fromUtf8( mVal, mVal.size() );
    00216         mModType = Mod_None;
    00217         retval = NewEntry;
    00218       } else if ( attrLower == "changetype" ) {
    00219         if ( mDn.isEmpty() )
    00220           retval = Err;
    00221         else {
    00222           QString tmpval = QString::fromUtf8( mVal, mVal.size() );
    00223           kdDebug(5700) << "changetype: " << tmpval << endl;
    00224           if ( tmpval == "add" ) mEntryType = Entry_Add;
    00225           else if ( tmpval == "delete" ) mEntryType = Entry_Del;
    00226           else if ( tmpval == "modrdn" || tmpval == "moddn" ) {
    00227             mNewRdn = "";
    00228             mNewSuperior = "";
    00229             mDelOldRdn = true;
    00230             mEntryType = Entry_Modrdn;
    00231           }
    00232           else if ( tmpval == "modify" ) mEntryType = Entry_Mod;
    00233           else retval = Err;
    00234         }
    00235       } else if ( attrLower == "control" ) {
    00236         mUrl = splitControl( QCString( mVal, mVal.size() + 1 ), mOid, mCritical, mVal );
    00237         retval = Control;
    00238       } else if ( !mAttr.isEmpty() && mVal.size() > 0 ) {
    00239         mEntryType = Entry_Add;
    00240         retval = Item;
    00241       }
    00242       break;
    00243     case Entry_Add:
    00244       if ( mAttr.isEmpty() && mVal.size() == 0 )
    00245         retval = EndEntry;
    00246       else
    00247         retval = Item;
    00248       break;
    00249     case Entry_Del:
    00250       if ( mAttr.isEmpty() && mVal.size() == 0 )
    00251         retval = EndEntry;
    00252       else
    00253         retval = Err;
    00254       break;
    00255     case Entry_Mod:
    00256       if ( mModType == Mod_None ) {
    00257         kdDebug(5700) << "kio_ldap: new modtype " << mAttr << endl;
    00258         if ( mAttr.isEmpty() && mVal.size() == 0 ) {
    00259           retval = EndEntry;
    00260         } else if ( attrLower == "add" ) {
    00261           mModType = Mod_Add;
    00262         } else if ( attrLower == "replace" ) {
    00263           mModType = Mod_Replace;
    00264           mAttr = QString::fromUtf8( mVal, mVal.size() );
    00265           mVal.resize( 0 );
    00266           retval = Item;
    00267         } else if ( attrLower == "delete" ) {
    00268           mModType = Mod_Del;
    00269           mAttr = QString::fromUtf8( mVal, mVal.size() );
    00270           mVal.resize( 0 );
    00271           retval = Item;
    00272         } else {
    00273           retval = Err;
    00274         }
    00275       } else {
    00276         if ( mAttr.isEmpty() ) {
    00277           if ( QString::fromUtf8( mVal, mVal.size() ) == "-" ) {
    00278             mModType = Mod_None;
    00279           } else if ( mVal.size() == 0 ) {
    00280             retval = EndEntry;
    00281           } else
    00282             retval = Err;
    00283         } else
    00284           retval = Item;
    00285       }
    00286       break;
    00287     case Entry_Modrdn:
    00288       if ( mAttr.isEmpty() && mVal.size() == 0 )
    00289         retval = EndEntry;
    00290       else if ( attrLower == "newrdn" )
    00291         mNewRdn = QString::fromUtf8( mVal, mVal.size() );
    00292       else if ( attrLower == "newsuperior" )
    00293         mNewSuperior = QString::fromUtf8( mVal, mVal.size() );
    00294       else if ( attrLower == "deleteoldrdn" ) {
    00295         if ( mVal.size() > 0 && mVal[0] == '0' )
    00296           mDelOldRdn = false;
    00297         else if ( mVal.size() > 0 && mVal[0] == '1' )
    00298           mDelOldRdn = true;
    00299         else
    00300           retval = Err;
    00301       } else
    00302         retval = Err;
    00303       break;
    00304   }
    00305   return retval;
    00306 }
    00307
    00308 LDIF::ParseVal LDIF::nextItem()
    00309 {
    00310   ParseVal retval = None;
    00311   char c=0;
    00312
    00313   while( retval == None ) {
    00314     if ( mPos < mLdif.size() ) {
    00315       c = mLdif[mPos];
    00316       mPos++;
    00317       if ( mIsNewLine && c == '\r' ) continue; //handle \n\r line end
    00318       if ( mIsNewLine && ( c == ' ' || c == '\t' ) ) { //line folding
    00319         mIsNewLine = false;
    00320         continue;
    00321       }
    00322       if ( mIsNewLine ) {
    00323         mIsNewLine = false;
    00324         retval = processLine();
    00325         mLastParseVal = retval;
    00326         line.resize( 0 );
    00327         mIsComment = ( c == '#' );
    00328       }
    00329       if ( c == '\n' || c == '\r' ) {
    00330         mLineNo++;
    00331         mIsNewLine = true;
    00332         continue;
    00333       }
    00334     } else {
    00335       retval = MoreData;
    00336       break;
    00337     }
    00338
    00339     if ( !mIsComment ) line += c;
    00340   }
    00341   return retval;
    00342 }
    00343
    00344 void LDIF::endLDIF()
    00345 {
    00346   QByteArray tmp( 3 );
    00347   tmp[ 0 ] = '\n';
    00348   tmp[ 1 ] = '\n';
    00349   tmp[ 2 ] = '\n';
    00350   mLdif = tmp;
    00351   mPos = 0;
    00352 }
    00353
    00354 void LDIF::startParsing()
    00355 {
    00356   mPos = mLineNo = 0;
    00357   mDelOldRdn = false;
    00358   mEntryType = Entry_None;
    00359   mModType = Mod_None;
    00360   mDn = mNewRdn = mNewSuperior = "";
    00361   line = "";
    00362   mIsNewLine = false;
    00363   mIsComment = false;
    00364   mLastParseVal = None;
    00365 }

This file is part of the documentation for kabc Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:31:30 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003