kabc Library API Documentation

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   tmp.setRawData( value, valuelen );
00092   ret = assembleLine( fieldname, tmp, linelen, url );
00093   tmp.resetRawData( value, valuelen );
00094   return ret;
00095 
00096 }
00097 
00098 QCString LDIF::assembleLine( const QString &fieldname, const QString &value,
00099   uint linelen, bool url )
00100 {
00101   return assembleLine( fieldname, value.utf8(), linelen, url );
00102 }
00103 
00104 bool LDIF::splitLine( const QCString &line, QString &fieldname, QByteArray &value )
00105 {
00106   int position;
00107   QByteArray tmp;
00108   int linelen;
00109 
00110 //  kdDebug(5700) << "splitLine line: " << QString::fromUtf8(line) << endl;
00111 
00112   position = line.find( ":" );
00113   if ( position == -1 ) {
00114     // strange: we did not find a fieldname
00115     fieldname = "";
00116     QCString str;
00117     str = line.stripWhiteSpace();
00118     linelen = str.length();
00119     tmp.setRawData( str.data(), linelen );
00120     value = tmp.copy();
00121     tmp.resetRawData( str.data(), linelen );
00122 //    kdDebug(5700) << "value : " << value[0] << endl;
00123     return false;
00124   }
00125 
00126   linelen = line.length();
00127 
00128   if ( linelen > ( position + 1 ) && line[ position + 1 ] == ':' ) {
00129     // String is BASE64 encoded -> decode it now.
00130     fieldname = QString::fromUtf8(
00131       line.left( position ).stripWhiteSpace() );
00132     if ( linelen <= ( position + 3 ) ) {
00133       value.resize( 0 );
00134       return false;
00135     }
00136     tmp.setRawData( &line.data()[ position + 3 ], linelen - position - 3 );
00137     KCodecs::base64Decode( tmp, value );
00138     tmp.resetRawData( &line.data()[ position + 3 ], linelen - position - 3 );
00139     return false;
00140   }
00141 
00142   if ( linelen > ( position + 1 ) && line[ position + 1 ] == '<' ) {
00143     // String is an URL.
00144     fieldname = QString::fromUtf8(
00145       line.left( position ).stripWhiteSpace() );
00146     if ( linelen <= ( position + 3 ) ) {
00147       value.resize( 0 );
00148       return false;
00149     }
00150     tmp.setRawData( &line.data()[ position + 3 ], linelen - position - 3 );
00151     value = tmp.copy();
00152     tmp.resetRawData( &line.data()[ position + 3 ], linelen - position - 3 );
00153     return true;
00154   }
00155 
00156   fieldname = QString::fromUtf8(line.left( position ).stripWhiteSpace());
00157   if ( linelen <= ( position + 2 ) ) {
00158     value.resize( 0 );
00159     return false;
00160   }
00161   tmp.setRawData( &line.data()[ position + 2 ], linelen - position - 2 );
00162   value = tmp.copy();
00163   tmp.resetRawData( &line.data()[ position + 2 ], linelen - position - 2 );
00164   return false;
00165 }
00166 
00167 bool LDIF::splitControl( const QCString &line, QString &oid, bool &critical, 
00168   QByteArray &value )
00169 {
00170   QString tmp;
00171   critical = false;
00172   bool url = splitLine( line, tmp, value );
00173   
00174   kdDebug(5700) << "splitControl: value: " << QString::fromUtf8(value, value.size()) << endl;
00175   if ( tmp.isEmpty() ) {
00176     tmp = QString::fromUtf8( value, value.size() );
00177     value.resize( 0 );
00178   }
00179   if ( tmp.right( 4 ) == "true" ) {
00180     critical = true;
00181     tmp.truncate( tmp.length() - 5 );
00182   } else  if ( tmp.right( 5 ) == "false" ) {
00183     critical = false;
00184     tmp.truncate( tmp.length() - 6 );
00185   }
00186   oid = tmp;
00187   return url;
00188 }
00189 
00190 LDIF::ParseVal LDIF::processLine() 
00191 {
00192 
00193   if ( mIsComment ) return None;
00194 
00195   ParseVal retval = None;
00196   if ( mLastParseVal == EndEntry ) mEntryType = Entry_None;
00197 
00198   mUrl = splitLine( line, mAttr, mVal );
00199 
00200   QString attrLower = mAttr.lower();
00201 
00202   switch ( mEntryType ) {
00203     case Entry_None:
00204       if ( attrLower == "version" ) {
00205         if ( !mDn.isEmpty() ) retval = Err;
00206       } else if ( attrLower == "dn" ) {
00207         kdDebug(5700) << "ldapentry dn: " << QString::fromUtf8( mVal, mVal.size() ) << endl;
00208         mDn = QString::fromUtf8( mVal, mVal.size() );
00209         mModType = Mod_None;
00210         retval = NewEntry;
00211       } else if ( attrLower == "changetype" ) {
00212         if ( mDn.isEmpty() )
00213           retval = Err;
00214         else {
00215           QString tmpval = QString::fromUtf8( mVal, mVal.size() );
00216           kdDebug(5700) << "changetype: " << tmpval << endl;
00217           if ( tmpval == "add" ) mEntryType = Entry_Add;
00218           else if ( tmpval == "delete" ) mEntryType = Entry_Del;
00219           else if ( tmpval == "modrdn" || tmpval == "moddn" ) {
00220             mNewRdn = "";
00221             mNewSuperior = "";
00222             mDelOldRdn = true;
00223             mEntryType = Entry_Modrdn;
00224           }
00225           else if ( tmpval == "modify" ) mEntryType = Entry_Mod;
00226           else retval = Err;
00227         }
00228       } else if ( attrLower == "control" ) {
00229         mUrl = splitControl( QCString( mVal, mVal.size() + 1 ), mOid, mCritical, mVal );
00230         retval = Control;
00231       } else if ( !mAttr.isEmpty() && mVal.size() > 0 ) {
00232         mEntryType = Entry_Add;
00233         retval = Item;
00234       }
00235       break;
00236     case Entry_Add:
00237       if ( mAttr.isEmpty() && mVal.size() == 0 )
00238         retval = EndEntry;
00239       else
00240         retval = Item;
00241       break;
00242     case Entry_Del:
00243       if ( mAttr.isEmpty() && mVal.size() == 0 )
00244         retval = EndEntry;
00245       else
00246         retval = Err;
00247       break;
00248     case Entry_Mod:
00249       if ( mModType == Mod_None ) {
00250         kdDebug(5700) << "kio_ldap: new modtype " << mAttr << endl;
00251         if ( mAttr.isEmpty() && mVal.size() == 0 ) {
00252           retval = EndEntry;
00253         } else if ( attrLower == "add" ) {
00254           mModType = Mod_Add;
00255         } else if ( attrLower == "replace" ) {
00256           mModType = Mod_Replace;
00257           mAttr = QString::fromUtf8( mVal, mVal.size() );
00258           mVal.resize( 0 );
00259           retval = Item;
00260         } else if ( attrLower == "delete" ) {
00261           mModType = Mod_Del;
00262           mAttr = QString::fromUtf8( mVal, mVal.size() );
00263           mVal.resize( 0 );
00264           retval = Item;
00265         } else {
00266           retval = Err;
00267         }
00268       } else {
00269         if ( mAttr.isEmpty() ) {
00270           if ( QString::fromUtf8( mVal, mVal.size() ) == "-" ) {
00271             mModType = Mod_None;
00272           } else if ( mVal.size() == 0 ) {
00273             retval = EndEntry;
00274           } else
00275             retval = Err;
00276         } else
00277           retval = Item;
00278       }
00279       break;
00280     case Entry_Modrdn:
00281       if ( mAttr.isEmpty() && mVal.size() == 0 )
00282         retval = EndEntry;
00283       else if ( attrLower == "newrdn" )
00284         mNewRdn = QString::fromUtf8( mVal, mVal.size() );
00285       else if ( attrLower == "newsuperior" )
00286         mNewSuperior = QString::fromUtf8( mVal, mVal.size() );
00287       else if ( attrLower == "deleteoldrdn" ) {
00288         if ( mVal.size() > 0 && mVal[0] == '0' )
00289           mDelOldRdn = false;
00290         else if ( mVal.size() > 0 && mVal[0] == '1' )
00291           mDelOldRdn = true;
00292         else
00293           retval = Err;
00294       } else
00295         retval = Err;
00296       break;
00297   }
00298   return retval;
00299 }
00300 
00301 LDIF::ParseVal LDIF::nextItem()
00302 {
00303   ParseVal retval = None;
00304   char c=0;
00305 
00306   while( retval == None ) {
00307     if ( mPos < mLdif.size() ) {
00308       c = mLdif[mPos];
00309       mPos++;
00310       if ( mIsNewLine && c == '\r' ) continue; //handle \n\r line end
00311       if ( mIsNewLine && ( c == ' ' || c == '\t' ) ) { //line folding
00312         mIsNewLine = false;
00313         continue;
00314       }
00315       if ( mIsNewLine ) {
00316         mIsNewLine = false;
00317         retval = processLine();
00318         mLastParseVal = retval;
00319         line.resize( 0 );
00320         mIsComment = ( c == '#' );
00321       }
00322       if ( c == '\n' || c == '\r' ) {
00323         mLineNo++;
00324         mIsNewLine = true;
00325         continue;
00326       }
00327     } else {
00328       retval = MoreData;
00329       break;
00330     }
00331 
00332     if ( !mIsComment ) line += c;
00333   }
00334   return retval;
00335 }
00336 
00337 void LDIF::endLDIF()
00338 {
00339   mLdif.resize( 3 );  
00340   mLdif[ 0 ] = '\n';
00341   mLdif[ 1 ] = '\n';
00342   mLdif[ 2 ] = '\n';
00343   mPos = 0;
00344 }
00345 
00346 void LDIF::startParsing()
00347 {
00348   mPos = mLineNo = 0;
00349   mDelOldRdn = false;
00350   mEntryType = Entry_None;
00351   mModType = Mod_None;
00352   mDn = mNewRdn = mNewSuperior = "";
00353   line = "";
00354   mIsNewLine = false;
00355   mIsComment = false;
00356   mLastParseVal = None;
00357 }
KDE Logo
This file is part of the documentation for kabc Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Nov 27 13:49:42 2004 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003