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