• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • 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   int i;
00079 
00080   if ( url ) {
00081     result = fieldname.toUtf8() + ":< " + value;
00082   } else {
00083     isDn = fieldname.toLower() == "dn";
00084     //SAFE-INIT-CHAR
00085     if ( value.size() > 0 && value[0] > 0 && value[0] != '\n' &&
00086          value[0] != '\r' && value[0] != ':' && value[0] != '<' ) safe = true;
00087 
00088     //SAFE-CHAR
00089     if ( safe ) {
00090       for ( i=1; i < value.size(); i++ ) {
00091         //allow utf-8 in Distinguished Names
00092         if ( ( isDn && value[i] == 0 ) ||
00093              ( !isDn && value[i] <= 0 ) ||
00094              value[i] == '\r' || value[i] == '\n' ) {
00095           safe = false;
00096           break;
00097         }
00098       }
00099     }
00100 
00101     if ( value.size() == 0 ) {
00102       safe = true;
00103     }
00104 
00105     if ( safe ) {
00106       result = fieldname.toUtf8() + ": " + value;
00107     } else {
00108       result = fieldname.toUtf8() + ":: " + value.toBase64();
00109     }
00110 
00111     if ( linelen > 0 ) {
00112       i = (uint)( fieldname.length() + 2 ) > linelen ? fieldname.length()+2 : linelen;
00113       while ( i < result.length() ) {
00114         result.insert( i, "\n " );
00115         i += linelen+2;
00116       }
00117     }
00118   }
00119   return result;
00120 }
00121 
00122 QByteArray Ldif::assembleLine( const QString &fieldname, const QString &value,
00123                                uint linelen, bool url )
00124 {
00125   return assembleLine( fieldname, value.toUtf8(), linelen, url );
00126 }
00127 
00128 bool Ldif::splitLine( const QByteArray &line, QString &fieldname, QByteArray &value )
00129 {
00130   int position;
00131   QByteArray tmp;
00132   int linelen;
00133 
00134 //  kDebug() << "line:" << QString::fromUtf8(line);
00135 
00136   position = line.indexOf( ":" );
00137   if ( position == -1 ) {
00138     // strange: we did not find a fieldname
00139     fieldname = "";
00140     value = line.trimmed();
00141 //    kDebug() << "value :" << value[0];
00142     return false;
00143   }
00144 
00145   linelen = line.size();
00146   fieldname = QString::fromUtf8( line.left( position ).trimmed() );
00147 
00148   if ( linelen > ( position + 1 ) && line[ position + 1 ] == ':' ) {
00149     // String is BASE64 encoded -> decode it now.
00150     if ( linelen <= ( position + 3 ) ) {
00151       value.resize( 0 );
00152       return false;
00153     }
00154     value = QByteArray::fromBase64( line.mid( position + 3 ) );
00155     return false;
00156   }
00157 
00158   if ( linelen > ( position + 1 ) && line[ position + 1 ] == '<' ) {
00159     // String is an URL.
00160     if ( linelen <= ( position + 3 ) ) {
00161       value.resize( 0 );
00162       return false;
00163     }
00164     value = QByteArray::fromBase64( line.mid( position + 3 ) );
00165     return true;
00166   }
00167 
00168   if ( linelen <= ( position + 2 ) ) {
00169     value.resize( 0 );
00170     return false;
00171   }
00172   value = line.mid( position + 2 );
00173   return false;
00174 }
00175 
00176 bool Ldif::splitControl( const QByteArray &line, QString &oid, bool &critical,
00177                          QByteArray &value )
00178 {
00179   QString tmp;
00180   critical = false;
00181   bool url = splitLine( line, tmp, value );
00182 
00183   kDebug() << "value:" << QString::fromUtf8( value, value.size() );
00184   if ( tmp.isEmpty() ) {
00185     tmp = QString::fromUtf8( value, value.size() );
00186     value.resize( 0 );
00187   }
00188   if ( tmp.endsWith( "true" ) ) {
00189     critical = true;
00190     tmp.truncate( tmp.length() - 5 );
00191   } else if ( tmp.endsWith( "false" ) ) {
00192     critical = false;
00193     tmp.truncate( tmp.length() - 6 );
00194   }
00195   oid = tmp;
00196   return url;
00197 }
00198 
00199 Ldif::ParseValue Ldif::processLine()
00200 {
00201 
00202   if ( d->mIsComment ) {
00203     return None;
00204   }
00205 
00206   ParseValue retval = None;
00207   if ( d->mLastParseValue == EndEntry ) {
00208     d->mEntryType = Entry_None;
00209   }
00210 
00211   d->mUrl = splitLine( d->mLine, d->mAttr, d->mValue );
00212 
00213   QString attrLower = d->mAttr.toLower();
00214 
00215   switch ( d->mEntryType ) {
00216   case Entry_None:
00217     if ( attrLower == "version" ) {
00218       if ( !d->mDn.isEmpty() ) {
00219         retval = Err;
00220       }
00221     } else if ( attrLower == "dn" ) {
00222       kDebug() << "ldapentry dn:" << QString::fromUtf8( d->mValue, d->mValue.size() );
00223       d->mDn = LdapDN( QString::fromUtf8( d->mValue, d->mValue.size() ) );
00224       d->mModType = Mod_None;
00225       retval = NewEntry;
00226     } else if ( attrLower == "changetype" ) {
00227       if ( d->mDn.isEmpty() ) {
00228         retval = Err;
00229       } else {
00230         QString tmpval = QString::fromUtf8( d->mValue, d->mValue.size() );
00231         kDebug() << "changetype:" << tmpval;
00232         if ( tmpval == "add" ) {
00233           d->mEntryType = Entry_Add;
00234         } else if ( tmpval == "delete" ) {
00235           d->mEntryType = Entry_Del;
00236         } else if ( tmpval == "modrdn" || tmpval == "moddn" ) {
00237           d->mNewRdn = "";
00238           d->mNewSuperior = "";
00239           d->mDelOldRdn = true;
00240           d->mEntryType = Entry_Modrdn;
00241         } else if ( tmpval == "modify" ) {
00242           d->mEntryType = Entry_Mod;
00243         } else {
00244           retval = Err;
00245         }
00246       }
00247     } else if ( attrLower == "control" ) {
00248       d->mUrl = splitControl( d->mValue, d->mOid, d->mCritical, d->mValue );
00249       retval = Control;
00250     } else if ( !d->mAttr.isEmpty() && d->mValue.size() > 0 ) {
00251       d->mEntryType = Entry_Add;
00252       retval = Item;
00253     }
00254     break;
00255   case Entry_Add:
00256     if ( d->mAttr.isEmpty() && d->mValue.size() == 0 ) {
00257       retval = EndEntry;
00258     } else {
00259       retval = Item;
00260     }
00261     break;
00262   case Entry_Del:
00263     if ( d->mAttr.isEmpty() && d->mValue.size() == 0 ) {
00264       retval = EndEntry;
00265     } else {
00266       retval = Err;
00267     }
00268     break;
00269   case Entry_Mod:
00270     if ( d->mModType == Mod_None ) {
00271       kDebug() << "new modtype" << d->mAttr;
00272       if ( d->mAttr.isEmpty() && d->mValue.size() == 0 ) {
00273         retval = EndEntry;
00274       } else if ( attrLower == "add" ) {
00275         d->mModType = Mod_Add;
00276       } else if ( attrLower == "replace" ) {
00277         d->mModType = Mod_Replace;
00278         d->mAttr = QString::fromUtf8( d->mValue, d->mValue.size() );
00279         d->mValue = QByteArray();
00280         retval = Item;
00281       } else if ( attrLower == "delete" ) {
00282         d->mModType = Mod_Del;
00283         d->mAttr = QString::fromUtf8( d->mValue, d->mValue.size() );
00284         d->mValue = QByteArray();
00285         retval = Item;
00286       } else {
00287         retval = Err;
00288       }
00289     } else {
00290       if ( d->mAttr.isEmpty() ) {
00291         if ( QString::fromUtf8( d->mValue, d->mValue.size() ) == "-" ) {
00292           d->mModType = Mod_None;
00293         } else if ( d->mValue.size() == 0 ) {
00294           retval = EndEntry;
00295         } else {
00296           retval = Err;
00297         }
00298       } else {
00299         retval = Item;
00300       }
00301     }
00302     break;
00303   case Entry_Modrdn:
00304     if ( d->mAttr.isEmpty() && d->mValue.size() == 0 ) {
00305       retval = EndEntry;
00306     } else if ( attrLower == "newrdn" ) {
00307       d->mNewRdn = QString::fromUtf8( d->mValue, d->mValue.size() );
00308     } else if ( attrLower == "newsuperior" ) {
00309       d->mNewSuperior = QString::fromUtf8( d->mValue, d->mValue.size() );
00310     } else if ( attrLower == "deleteoldrdn" ) {
00311       if ( d->mValue.size() > 0 && d->mValue[0] == '0' ) {
00312         d->mDelOldRdn = false;
00313       } else if ( d->mValue.size() > 0 && d->mValue[0] == '1' ) {
00314         d->mDelOldRdn = true;
00315       } else {
00316         retval = Err;
00317       }
00318     } else {
00319       retval = Err;
00320     }
00321     break;
00322   }
00323   return retval;
00324 }
00325 
00326 Ldif::ParseValue Ldif::nextItem()
00327 {
00328   ParseValue retval = None;
00329   char c=0;
00330 
00331   while ( retval == None ) {
00332     if ( d->mPos < (uint)d->mLdif.size() ) {
00333       c = d->mLdif[d->mPos];
00334       d->mPos++;
00335       if ( d->mIsNewLine && c == '\r' ) {
00336         continue; //handle \n\r line end
00337       }
00338       if ( d->mIsNewLine && ( c == ' ' || c == '\t' ) ) { //line folding
00339         d->mIsNewLine = false;
00340         continue;
00341       }
00342       if ( d->mIsNewLine ) {
00343         d->mIsNewLine = false;
00344         retval = processLine();
00345         d->mLastParseValue = retval;
00346         d->mLine.resize( 0 );
00347         d->mIsComment = ( c == '#' );
00348       }
00349       if ( c == '\n' || c == '\r' ) {
00350         d->mLineNumber++;
00351         d->mIsNewLine = true;
00352         continue;
00353       }
00354     } else {
00355       retval = MoreData;
00356       break;
00357     }
00358 
00359     if ( !d->mIsComment ) {
00360       d->mLine += c;
00361     }
00362   }
00363   return retval;
00364 }
00365 
00366 void Ldif::endLdif()
00367 {
00368   QByteArray tmp( 3, '\n' );
00369   d->mLdif = tmp;
00370   d->mPos = 0;
00371 }
00372 
00373 void Ldif::startParsing()
00374 {
00375   d->mPos = d->mLineNumber = 0;
00376   d->mDelOldRdn = false;
00377   d->mEntryType = Entry_None;
00378   d->mModType = Mod_None;
00379   d->mDn = LdapDN();
00380   d->mNewRdn = d->mNewSuperior = QString();
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
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  • kabc
  • kblog
  • kcal
  • kimap
  • kioslave
  •   imap4
  •   mbox
  • kldap
  • kmime
  • kpimidentities
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.5.4
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