• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • KDE Home
  • Contact Us
 

KLDAP Library

ldif.cpp

00001 /*
00002   This file is part of libkldap.
00003   Copyright (c) 2004-2006 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., 51 Franklin Street, Fifth Floor,
00018   Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "ldif.h"
00022 
00023 #include <kdebug.h>
00024 
00025 using namespace KLDAP;
00026 
00027 class Ldif::LdifPrivate
00028 {
00029   public:
00030     int mModType;
00031     bool mDelOldRdn, mUrl;
00032     LdapDN mDn;
00033     QString mAttr, mNewRdn, mNewSuperior, mOid;
00034     QByteArray mLdif, mValue;
00035     EntryType mEntryType;
00036 
00037     bool mIsNewLine, mIsComment, mCritical;
00038     ParseValue mLastParseValue;
00039     uint mPos, mLineNumber;
00040     QByteArray mLine;
00041 };
00042 
00043 Ldif::Ldif() : d( new LdifPrivate )
00044 {
00045   startParsing();
00046 }
00047 
00048 Ldif::Ldif( const Ldif &that ) : d( new LdifPrivate )
00049 {
00050   *d = *that.d;
00051 
00052   startParsing();
00053 }
00054 
00055 Ldif &Ldif::operator=( const Ldif &that )
00056 {
00057   if ( this == &that ) {
00058     return *this;
00059   }
00060 
00061   *d = *that.d;
00062 
00063   return *this;
00064 }
00065 
00066 Ldif::~Ldif()
00067 {
00068   delete d;
00069 }
00070 
00071 QByteArray Ldif::assembleLine( const QString &fieldname,
00072                                const QByteArray &value,
00073                                uint linelen, bool url )
00074 {
00075   bool safe = false;
00076   bool isDn;
00077   QByteArray result;
00078 
00079   if ( url ) {
00080     result = fieldname.toUtf8() + ":< " + value;
00081   } else {
00082     isDn = fieldname.toLower() == "dn";
00083     //SAFE-INIT-CHAR
00084     if ( value.size() > 0 && value[0] > 0 && value[0] != '\n' &&
00085          value[0] != '\r' && value[0] != ':' && value[0] != '<' ) safe = true;
00086 
00087     //SAFE-CHAR
00088     if ( safe ) {
00089       for ( int i=1; i < value.size(); i++ ) {
00090         //allow utf-8 in Distinguished Names
00091         if ( ( isDn && value[i] == 0 ) ||
00092              ( !isDn && value[i] <= 0 ) ||
00093              value[i] == '\r' || value[i] == '\n' ) {
00094           safe = false;
00095           break;
00096         }
00097       }
00098     }
00099 
00100     if ( value.size() == 0 ) {
00101       safe = true;
00102     }
00103 
00104     if ( safe ) {
00105       result = fieldname.toUtf8() + ": " + value;
00106     } else {
00107       result = fieldname.toUtf8() + ":: " + value.toBase64();
00108     }
00109 
00110     if ( linelen > 0 ) {
00111       int i = (uint)( fieldname.length() + 2 ) > linelen ? fieldname.length() + 2 : linelen;
00112       while ( i < result.length() ) {
00113         result.insert( i, "\n " );
00114         i += linelen+2;
00115       }
00116     }
00117   }
00118   return result;
00119 }
00120 
00121 QByteArray Ldif::assembleLine( const QString &fieldname, const QString &value,
00122                                uint linelen, bool url )
00123 {
00124   return assembleLine( fieldname, value.toUtf8(), linelen, url );
00125 }
00126 
00127 bool Ldif::splitLine( const QByteArray &line, QString &fieldname, QByteArray &value )
00128 {
00129   int position;
00130   QByteArray tmp;
00131   int linelen;
00132 
00133 //  kDebug() << "line:" << QString::fromUtf8(line);
00134 
00135   position = line.indexOf( ":" );
00136   if ( position == -1 ) {
00137     // strange: we did not find a fieldname
00138     fieldname = "";
00139     value = line.trimmed();
00140 //    kDebug() << "value :" << value[0];
00141     return false;
00142   }
00143 
00144   linelen = line.size();
00145   fieldname = QString::fromUtf8( line.left( position ).trimmed() );
00146 
00147   if ( linelen > ( position + 1 ) && line[ position + 1 ] == ':' ) {
00148     // String is BASE64 encoded -> decode it now.
00149     if ( linelen <= ( position + 3 ) ) {
00150       value.resize( 0 );
00151       return false;
00152     }
00153     value = QByteArray::fromBase64( line.mid( position + 3 ) );
00154     return false;
00155   }
00156 
00157   if ( linelen > ( position + 1 ) && line[ position + 1 ] == '<' ) {
00158     // String is an URL.
00159     if ( linelen <= ( position + 3 ) ) {
00160       value.resize( 0 );
00161       return false;
00162     }
00163     value = QByteArray::fromBase64( line.mid( position + 3 ) );
00164     return true;
00165   }
00166 
00167   if ( linelen <= ( position + 2 ) ) {
00168     value.resize( 0 );
00169     return false;
00170   }
00171   value = line.mid( position + 2 );
00172   return false;
00173 }
00174 
00175 bool Ldif::splitControl( const QByteArray &line, QString &oid, bool &critical,
00176                          QByteArray &value )
00177 {
00178   QString tmp;
00179   critical = false;
00180   bool url = splitLine( line, tmp, value );
00181 
00182   kDebug() << "value:" << QString::fromUtf8( value, value.size() );
00183   if ( tmp.isEmpty() ) {
00184     tmp = QString::fromUtf8( value, value.size() );
00185     value.resize( 0 );
00186   }
00187   if ( tmp.endsWith( QLatin1String( "true" ) ) ) {
00188     critical = true;
00189     tmp.truncate( tmp.length() - 5 );
00190   } else if ( tmp.endsWith( QLatin1String( "false" ) ) ) {
00191     critical = false;
00192     tmp.truncate( tmp.length() - 6 );
00193   }
00194   oid = tmp;
00195   return url;
00196 }
00197 
00198 Ldif::ParseValue Ldif::processLine()
00199 {
00200 
00201   if ( d->mIsComment ) {
00202     return None;
00203   }
00204 
00205   ParseValue retval = None;
00206   if ( d->mLastParseValue == EndEntry ) {
00207     d->mEntryType = Entry_None;
00208   }
00209 
00210   d->mUrl = splitLine( d->mLine, d->mAttr, d->mValue );
00211 
00212   QString attrLower = d->mAttr.toLower();
00213 
00214   switch ( d->mEntryType ) {
00215   case Entry_None:
00216     if ( attrLower == "version" ) {
00217       if ( !d->mDn.isEmpty() ) {
00218         retval = Err;
00219       }
00220     } else if ( attrLower == "dn" ) {
00221       kDebug() << "ldapentry dn:" << QString::fromUtf8( d->mValue, d->mValue.size() );
00222       d->mDn = LdapDN( QString::fromUtf8( d->mValue, d->mValue.size() ) );
00223       d->mModType = Mod_None;
00224       retval = NewEntry;
00225     } else if ( attrLower == "changetype" ) {
00226       if ( d->mDn.isEmpty() ) {
00227         retval = Err;
00228       } else {
00229         QString tmpval = QString::fromUtf8( d->mValue, d->mValue.size() );
00230         kDebug() << "changetype:" << tmpval;
00231         if ( tmpval == "add" ) {
00232           d->mEntryType = Entry_Add;
00233         } else if ( tmpval == "delete" ) {
00234           d->mEntryType = Entry_Del;
00235         } else if ( tmpval == "modrdn" || tmpval == "moddn" ) {
00236           d->mNewRdn = "";
00237           d->mNewSuperior = "";
00238           d->mDelOldRdn = true;
00239           d->mEntryType = Entry_Modrdn;
00240         } else if ( tmpval == "modify" ) {
00241           d->mEntryType = Entry_Mod;
00242         } else {
00243           retval = Err;
00244         }
00245       }
00246     } else if ( attrLower == "control" ) {
00247       d->mUrl = splitControl( d->mValue, d->mOid, d->mCritical, d->mValue );
00248       retval = Control;
00249     } else if ( !d->mAttr.isEmpty() && d->mValue.size() > 0 ) {
00250       d->mEntryType = Entry_Add;
00251       retval = Item;
00252     }
00253     break;
00254   case Entry_Add:
00255     if ( d->mAttr.isEmpty() && d->mValue.size() == 0 ) {
00256       retval = EndEntry;
00257     } else {
00258       retval = Item;
00259     }
00260     break;
00261   case Entry_Del:
00262     if ( d->mAttr.isEmpty() && d->mValue.size() == 0 ) {
00263       retval = EndEntry;
00264     } else {
00265       retval = Err;
00266     }
00267     break;
00268   case Entry_Mod:
00269     if ( d->mModType == Mod_None ) {
00270       kDebug() << "new modtype" << d->mAttr;
00271       if ( d->mAttr.isEmpty() && d->mValue.size() == 0 ) {
00272         retval = EndEntry;
00273       } else if ( attrLower == "add" ) {
00274         d->mModType = Mod_Add;
00275       } else if ( attrLower == "replace" ) {
00276         d->mModType = Mod_Replace;
00277         d->mAttr = QString::fromUtf8( d->mValue, d->mValue.size() );
00278         d->mValue = QByteArray();
00279         retval = Item;
00280       } else if ( attrLower == "delete" ) {
00281         d->mModType = Mod_Del;
00282         d->mAttr = QString::fromUtf8( d->mValue, d->mValue.size() );
00283         d->mValue = QByteArray();
00284         retval = Item;
00285       } else {
00286         retval = Err;
00287       }
00288     } else {
00289       if ( d->mAttr.isEmpty() ) {
00290         if ( QString::fromUtf8( d->mValue, d->mValue.size() ) == "-" ) {
00291           d->mModType = Mod_None;
00292         } else if ( d->mValue.size() == 0 ) {
00293           retval = EndEntry;
00294         } else {
00295           retval = Err;
00296         }
00297       } else {
00298         retval = Item;
00299       }
00300     }
00301     break;
00302   case Entry_Modrdn:
00303     if ( d->mAttr.isEmpty() && d->mValue.size() == 0 ) {
00304       retval = EndEntry;
00305     } else if ( attrLower == "newrdn" ) {
00306       d->mNewRdn = QString::fromUtf8( d->mValue, d->mValue.size() );
00307     } else if ( attrLower == "newsuperior" ) {
00308       d->mNewSuperior = QString::fromUtf8( d->mValue, d->mValue.size() );
00309     } else if ( attrLower == "deleteoldrdn" ) {
00310       if ( d->mValue.size() > 0 && d->mValue[0] == '0' ) {
00311         d->mDelOldRdn = false;
00312       } else if ( d->mValue.size() > 0 && d->mValue[0] == '1' ) {
00313         d->mDelOldRdn = true;
00314       } else {
00315         retval = Err;
00316       }
00317     } else {
00318       retval = Err;
00319     }
00320     break;
00321   }
00322   return retval;
00323 }
00324 
00325 Ldif::ParseValue Ldif::nextItem()
00326 {
00327   ParseValue retval = None;
00328   char c=0;
00329 
00330   while ( retval == None ) {
00331     if ( d->mPos < (uint)d->mLdif.size() ) {
00332       c = d->mLdif[d->mPos];
00333       d->mPos++;
00334       if ( d->mIsNewLine && c == '\r' ) {
00335         continue; //handle \n\r line end
00336       }
00337       if ( d->mIsNewLine && ( c == ' ' || c == '\t' ) ) { //line folding
00338         d->mIsNewLine = false;
00339         continue;
00340       }
00341       if ( d->mIsNewLine ) {
00342         d->mIsNewLine = false;
00343         retval = processLine();
00344         d->mLastParseValue = retval;
00345         d->mLine.resize( 0 );
00346         d->mIsComment = ( c == '#' );
00347       }
00348       if ( c == '\n' || c == '\r' ) {
00349         d->mLineNumber++;
00350         d->mIsNewLine = true;
00351         continue;
00352       }
00353     } else {
00354       retval = MoreData;
00355       break;
00356     }
00357 
00358     if ( !d->mIsComment ) {
00359       d->mLine += c;
00360     }
00361   }
00362   return retval;
00363 }
00364 
00365 void Ldif::endLdif()
00366 {
00367   QByteArray tmp( 3, '\n' );
00368   d->mLdif = tmp;
00369   d->mPos = 0;
00370 }
00371 
00372 void Ldif::startParsing()
00373 {
00374   d->mPos = d->mLineNumber = 0;
00375   d->mDelOldRdn = false;
00376   d->mEntryType = Entry_None;
00377   d->mModType = Mod_None;
00378   d->mDn = LdapDN();
00379   d->mNewRdn.clear();
00380   d->mNewSuperior.clear();
00381   d->mLine = QByteArray();
00382   d->mIsNewLine = false;
00383   d->mIsComment = false;
00384   d->mLastParseValue = None;
00385 }
00386 
00387 void Ldif::setLdif( const QByteArray &ldif )
00388 {
00389   d->mLdif = ldif;
00390   d->mPos = 0;
00391 }
00392 
00393 Ldif::EntryType Ldif::entryType() const
00394 {
00395   return d->mEntryType;
00396 }
00397 
00398 int Ldif::modType() const
00399 {
00400   return d->mModType;
00401 }
00402 
00403 LdapDN Ldif::dn() const
00404 {
00405   return d->mDn;
00406 }
00407 
00408 QString Ldif::newRdn() const
00409 {
00410   return d->mNewRdn;
00411 }
00412 
00413 QString Ldif::newSuperior() const
00414 {
00415   return d->mNewSuperior;
00416 }
00417 
00418 bool Ldif::delOldRdn() const
00419 {
00420   return d->mDelOldRdn;
00421 }
00422 
00423 QString Ldif::attr() const
00424 {
00425   return d->mAttr;
00426 }
00427 
00428 QByteArray Ldif::value() const
00429 {
00430   return d->mValue;
00431 }
00432 
00433 bool Ldif::isUrl() const
00434 {
00435   return d->mUrl;
00436 }
00437 
00438 bool Ldif::isCritical() const
00439 {
00440   return d->mCritical;
00441 }
00442 
00443 QString Ldif::oid() const
00444 {
00445   return d->mOid;
00446 }
00447 
00448 uint Ldif::lineNumber() const
00449 {
00450   return d->mLineNumber;
00451 }

KLDAP Library

Skip menu "KLDAP Library"
  • Main Page
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal