KLDAP Library
ldif.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00085 if ( value.size() > 0 && value[0] > 0 && value[0] != '\n' &&
00086 value[0] != '\r' && value[0] != ':' && value[0] != '<' ) safe = true;
00087
00088
00089 if ( safe ) {
00090 for ( i=1; i < value.size(); i++ ) {
00091
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
00135
00136 position = line.indexOf( ":" );
00137 if ( position == -1 ) {
00138
00139 fieldname = "";
00140 value = line.trimmed();
00141
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
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
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;
00337 }
00338 if ( d->mIsNewLine && ( c == ' ' || c == '\t' ) ) {
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 }