kabc
ldif.cpp
00001 /* 00002 A temporary copy to break dependency to KLDAP 00003 00004 This file is part of libkldap. 00005 Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu> 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License as published by the Free Software Foundation; either 00010 version 2 of the License, or (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Library General Public License for more details. 00016 00017 You should have received a copy of the GNU Library General Public License 00018 along with this library; see the file COPYING.LIB. If not, write to 00019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00020 Boston, MA 02110-1301, USA. 00021 */ 00022 00023 #include "ldif_p.h" 00024 00025 #include <kdebug.h> 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() == QLatin1String( "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 = QLatin1String( "" ); 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 == QLatin1String( "version" ) ) { 00217 if ( !d->mDn.isEmpty() ) { 00218 retval = Err; 00219 } 00220 } else if ( attrLower == QLatin1String( "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 == QLatin1String( "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 == QLatin1String( "add" ) ) { 00232 d->mEntryType = Entry_Add; 00233 } else if ( tmpval == QLatin1String( "delete" ) ) { 00234 d->mEntryType = Entry_Del; 00235 } else if ( tmpval == QLatin1String( "modrdn" ) || tmpval == QLatin1String( "moddn" ) ) { 00236 d->mNewRdn = QLatin1String( "" ); 00237 d->mNewSuperior = QLatin1String( "" ); 00238 d->mDelOldRdn = true; 00239 d->mEntryType = Entry_Modrdn; 00240 } else if ( tmpval == QLatin1String( "modify" ) ) { 00241 d->mEntryType = Entry_Mod; 00242 } else { 00243 retval = Err; 00244 } 00245 } 00246 } else if ( attrLower == QLatin1String( "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 == QLatin1String( "add" ) ) { 00274 d->mModType = Mod_Add; 00275 } else if ( attrLower == QLatin1String( "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 == QLatin1String( "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() ) == QLatin1String( "-" ) ) { 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 == QLatin1String( "newrdn" ) ) { 00306 d->mNewRdn = QString::fromUtf8( d->mValue, d->mValue.size() ); 00307 } else if ( attrLower == QLatin1String( "newsuperior" ) ) { 00308 d->mNewSuperior = QString::fromUtf8( d->mValue, d->mValue.size() ); 00309 } else if ( attrLower == QLatin1String( "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 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Tue May 8 2012 00:05:40 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Tue May 8 2012 00:05:40 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.