libkdepim 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 KPIM;
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         retval = NewEntry;
00210       } else if ( attrLower == "changetype" ) {
00211         if ( mDn.isEmpty() )
00212           retval = Err;
00213         else {
00214           QString tmpval = QString::fromUtf8( mVal, mVal.size() );
00215           kdDebug(5700) << "changetype: " << tmpval << endl;
00216           if ( tmpval == "add" ) mEntryType = Entry_Add;
00217           else if ( tmpval == "delete" ) mEntryType = Entry_Del;
00218           else if ( tmpval == "modrdn" || tmpval == "moddn" ) {
00219             mNewRdn = "";
00220             mNewSuperior = "";
00221             mDelOldRdn = true;
00222             mEntryType = Entry_Modrdn;
00223           }
00224           else if ( tmpval == "modify" ) mEntryType = Entry_Mod;
00225           else retval = Err;
00226         }
00227       } else if ( attrLower == "control" ) {
00228         mUrl = splitControl( QCString( mVal, mVal.size() + 1 ), mOid, mCritical, mVal );
00229         retval = Control;
00230       } else if ( !mAttr.isEmpty() && mVal.size() > 0 ) {
00231         mEntryType = Entry_Add;
00232         retval = Item;
00233       }
00234       break;
00235     case Entry_Add:
00236       if ( mAttr.isEmpty() && mVal.size() == 0 )
00237         retval = EndEntry;
00238       else
00239         retval = Item;
00240       break;
00241     case Entry_Del:
00242       if ( mAttr.isEmpty() && mVal.size() == 0 )
00243         retval = EndEntry;
00244       else
00245         retval = Err;
00246       break;
00247     case Entry_Mod:
00248       if ( mModType == Mod_None ) {
00249         kdDebug(5700) << "kio_ldap: new modtype " << mAttr << endl;
00250         if ( mAttr.isEmpty() && mVal.size() == 0 ) {
00251           retval = EndEntry;
00252         } else if ( attrLower == "add" ) {
00253           mModType = Mod_Add;
00254         } else if ( attrLower == "replace" ) {
00255           mModType = Mod_Replace;
00256           mAttr = QString::fromUtf8( mVal, mVal.size() );
00257           mVal.resize( 0 );
00258           retval = Item;
00259         } else if ( attrLower == "delete" ) {
00260           mModType = Mod_Del;
00261           mAttr = QString::fromUtf8( mVal, mVal.size() );
00262           mVal.resize( 0 );
00263           retval = Item;
00264         } else {
00265           retval = Err;
00266         }
00267       } else {
00268         if ( mAttr.isEmpty() ) {
00269           if ( QString::fromUtf8( mVal, mVal.size() ) == "-" ) {
00270             mModType = Mod_None;
00271           } else if ( mVal.size() == 0 ) {
00272             retval = EndEntry;
00273           } else
00274             retval = Err;
00275         } else
00276           retval = Item;
00277       }
00278       break;
00279     case Entry_Modrdn:
00280       if ( mAttr.isEmpty() && mVal.size() == 0 )
00281         retval = EndEntry;
00282       else if ( attrLower == "newrdn" )
00283         mNewRdn = QString::fromUtf8( mVal, mVal.size() );
00284       else if ( attrLower == "newsuperior" )
00285         mNewSuperior = QString::fromUtf8( mVal, mVal.size() );
00286       else if ( attrLower == "deleteoldrdn" ) {
00287         if ( mVal.size() > 0 && mVal[0] == '0' )
00288           mDelOldRdn = false;
00289         else if ( mVal.size() > 0 && mVal[0] == '1' )
00290           mDelOldRdn = true;
00291         else
00292           retval = Err;
00293       } else
00294         retval = Err;
00295       break;
00296   }
00297   return retval;
00298 }
00299 
00300 LDIF::ParseVal LDIF::nextItem()
00301 {
00302   ParseVal retval = None;
00303   char c=0;
00304 
00305   while( retval == None ) {
00306     if ( mPos < mLdif.size() ) {
00307       c = mLdif[mPos];
00308       mPos++;
00309       if ( mIsNewLine && c == '\r' ) continue; //handle \n\r line end
00310       if ( mIsNewLine && ( c == ' ' || c == '\t' ) ) { //line folding
00311         mIsNewLine = false;
00312         continue;
00313       }
00314       if ( mIsNewLine ) {
00315         mIsNewLine = false;
00316         retval = processLine();
00317         mLastParseVal = retval;
00318         line.resize( 0 );
00319         mIsComment = ( c == '#' );
00320       }
00321       if ( c == '\n' || c == '\r' ) {
00322         mLineNo++;
00323         mIsNewLine = true;
00324         continue;
00325       }
00326     } else {
00327       retval = MoreData;
00328       break;
00329     }
00330 
00331     if ( !mIsComment ) line += c;
00332   }
00333   return retval;
00334 }
00335 
00336 void LDIF::endLDIF()
00337 {
00338   mLdif.resize( 3 );  
00339   mLdif[ 0 ] = '\n';
00340   mLdif[ 1 ] = '\n';
00341   mLdif[ 2 ] = '\n';
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 libkdepim Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Mar 23 22:40:52 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003