kabc 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 KABC; 00027 00028 static const char delimiter[ 3 ] = { '\n', '\n', '\n' }; 00029 00030 LDIF::LDIF() 00031 { 00032 startParsing(); 00033 } 00034 00035 LDIF::~LDIF() 00036 { 00037 } 00038 00039 QCString LDIF::assembleLine( const QString &fieldname, const QByteArray &value, 00040 uint linelen, bool url ) 00041 { 00042 bool safe = false; 00043 bool isDn; 00044 QCString result; 00045 uint i; 00046 00047 if ( url ) { 00048 result = fieldname.utf8() + ":< " + QCString( value.data(), value.size()+1 ); 00049 } else { 00050 isDn = fieldname.lower() == "dn"; 00051 //SAFE-INIT-CHAR 00052 if ( value.size() > 0 && value[0] > 0 && value[0] != '\n' && 00053 value[0] != '\r' && value[0] != ':' && value[0] != '<' ) safe = true; 00054 00055 //SAFE-CHAR 00056 if ( safe ) { 00057 for ( i=1; i < value.size(); i++ ) { 00058 //allow utf-8 in Distinguished Names 00059 if ( ( isDn && value[i] == 0 ) || 00060 ( !isDn && value[i] <= 0 ) || 00061 value[i] == '\r' || value[i] == '\n' ) { 00062 safe = false; 00063 break; 00064 } 00065 } 00066 } 00067 00068 if ( value.size() == 0 ) safe = true; 00069 00070 if( safe ) { 00071 result = fieldname.utf8() + ": " + QCString( value.data(), value.size()+1 ); 00072 } else { 00073 result = fieldname.utf8() + ":: " + KCodecs::base64Encode( value, false ); 00074 } 00075 00076 if ( linelen > 0 ) { 00077 i = (fieldname.length()+2) > linelen ? fieldname.length()+2 : linelen; 00078 while ( i < result.length() ) { 00079 result.insert( i, "\n " ); 00080 i += linelen+2; 00081 } 00082 } 00083 } 00084 return result; 00085 } 00086 00087 QCString LDIF::assembleLine( const QString &fieldname, const QCString &value, 00088 uint linelen, bool url ) 00089 { 00090 QCString ret; 00091 QByteArray tmp; 00092 uint valuelen = value.length(); 00093 tmp.setRawData( value, valuelen ); 00094 ret = assembleLine( fieldname, tmp, linelen, url ); 00095 tmp.resetRawData( value, valuelen ); 00096 return ret; 00097 00098 } 00099 00100 QCString LDIF::assembleLine( const QString &fieldname, const QString &value, 00101 uint linelen, bool url ) 00102 { 00103 return assembleLine( fieldname, value.utf8(), linelen, url ); 00104 } 00105 00106 bool LDIF::splitLine( const QCString &line, QString &fieldname, QByteArray &value ) 00107 { 00108 int position; 00109 QByteArray tmp; 00110 int linelen; 00111 00112 // kdDebug(5700) << "splitLine line: " << QString::fromUtf8(line) << endl; 00113 00114 position = line.find( ":" ); 00115 if ( position == -1 ) { 00116 // strange: we did not find a fieldname 00117 fieldname = ""; 00118 QCString str; 00119 str = line.stripWhiteSpace(); 00120 linelen = str.length(); 00121 tmp.setRawData( str.data(), linelen ); 00122 value = tmp.copy(); 00123 tmp.resetRawData( str.data(), linelen ); 00124 // kdDebug(5700) << "value : " << value[0] << endl; 00125 return false; 00126 } 00127 00128 linelen = line.length(); 00129 00130 if ( linelen > ( position + 1 ) && line[ position + 1 ] == ':' ) { 00131 // String is BASE64 encoded -> decode it now. 00132 fieldname = QString::fromUtf8( 00133 line.left( position ).stripWhiteSpace() ); 00134 if ( linelen <= ( position + 3 ) ) { 00135 value.resize( 0 ); 00136 return false; 00137 } 00138 tmp.setRawData( &line.data()[ position + 3 ], linelen - position - 3 ); 00139 KCodecs::base64Decode( tmp, value ); 00140 tmp.resetRawData( &line.data()[ position + 3 ], linelen - position - 3 ); 00141 return false; 00142 } 00143 00144 if ( linelen > ( position + 1 ) && line[ position + 1 ] == '<' ) { 00145 // String is an URL. 00146 fieldname = QString::fromUtf8( 00147 line.left( position ).stripWhiteSpace() ); 00148 if ( linelen <= ( position + 3 ) ) { 00149 value.resize( 0 ); 00150 return false; 00151 } 00152 tmp.setRawData( &line.data()[ position + 3 ], linelen - position - 3 ); 00153 value = tmp.copy(); 00154 tmp.resetRawData( &line.data()[ position + 3 ], linelen - position - 3 ); 00155 return true; 00156 } 00157 00158 fieldname = QString::fromUtf8(line.left( position ).stripWhiteSpace()); 00159 if ( linelen <= ( position + 2 ) ) { 00160 value.resize( 0 ); 00161 return false; 00162 } 00163 tmp.setRawData( &line.data()[ position + 2 ], linelen - position - 2 ); 00164 value = tmp.copy(); 00165 tmp.resetRawData( &line.data()[ position + 2 ], linelen - position - 2 ); 00166 return false; 00167 } 00168 00169 bool LDIF::splitControl( const QCString &line, QString &oid, bool &critical, 00170 QByteArray &value ) 00171 { 00172 QString tmp; 00173 critical = false; 00174 bool url = splitLine( line, tmp, value ); 00175 00176 kdDebug(5700) << "splitControl: value: " << QString::fromUtf8(value, value.size()) << endl; 00177 if ( tmp.isEmpty() ) { 00178 tmp = QString::fromUtf8( value, value.size() ); 00179 value.resize( 0 ); 00180 } 00181 if ( tmp.right( 4 ) == "true" ) { 00182 critical = true; 00183 tmp.truncate( tmp.length() - 5 ); 00184 } else if ( tmp.right( 5 ) == "false" ) { 00185 critical = false; 00186 tmp.truncate( tmp.length() - 6 ); 00187 } 00188 oid = tmp; 00189 return url; 00190 } 00191 00192 LDIF::ParseVal LDIF::processLine() 00193 { 00194 00195 if ( mIsComment ) return None; 00196 00197 ParseVal retval = None; 00198 if ( mLastParseVal == EndEntry ) mEntryType = Entry_None; 00199 00200 mUrl = splitLine( line, mAttr, mVal ); 00201 00202 QString attrLower = mAttr.lower(); 00203 00204 switch ( mEntryType ) { 00205 case Entry_None: 00206 if ( attrLower == "version" ) { 00207 if ( !mDn.isEmpty() ) retval = Err; 00208 } else if ( attrLower == "dn" ) { 00209 kdDebug(5700) << "ldapentry dn: " << QString::fromUtf8( mVal, mVal.size() ) << endl; 00210 mDn = QString::fromUtf8( mVal, mVal.size() ); 00211 mModType = Mod_None; 00212 retval = NewEntry; 00213 } else if ( attrLower == "changetype" ) { 00214 if ( mDn.isEmpty() ) 00215 retval = Err; 00216 else { 00217 QString tmpval = QString::fromUtf8( mVal, mVal.size() ); 00218 kdDebug(5700) << "changetype: " << tmpval << endl; 00219 if ( tmpval == "add" ) mEntryType = Entry_Add; 00220 else if ( tmpval == "delete" ) mEntryType = Entry_Del; 00221 else if ( tmpval == "modrdn" || tmpval == "moddn" ) { 00222 mNewRdn = ""; 00223 mNewSuperior = ""; 00224 mDelOldRdn = true; 00225 mEntryType = Entry_Modrdn; 00226 } 00227 else if ( tmpval == "modify" ) mEntryType = Entry_Mod; 00228 else retval = Err; 00229 } 00230 } else if ( attrLower == "control" ) { 00231 mUrl = splitControl( QCString( mVal, mVal.size() + 1 ), mOid, mCritical, mVal ); 00232 retval = Control; 00233 } else if ( !mAttr.isEmpty() && mVal.size() > 0 ) { 00234 mEntryType = Entry_Add; 00235 retval = Item; 00236 } 00237 break; 00238 case Entry_Add: 00239 if ( mAttr.isEmpty() && mVal.size() == 0 ) 00240 retval = EndEntry; 00241 else 00242 retval = Item; 00243 break; 00244 case Entry_Del: 00245 if ( mAttr.isEmpty() && mVal.size() == 0 ) 00246 retval = EndEntry; 00247 else 00248 retval = Err; 00249 break; 00250 case Entry_Mod: 00251 if ( mModType == Mod_None ) { 00252 kdDebug(5700) << "kio_ldap: new modtype " << mAttr << endl; 00253 if ( mAttr.isEmpty() && mVal.size() == 0 ) { 00254 retval = EndEntry; 00255 } else if ( attrLower == "add" ) { 00256 mModType = Mod_Add; 00257 } else if ( attrLower == "replace" ) { 00258 mModType = Mod_Replace; 00259 mAttr = QString::fromUtf8( mVal, mVal.size() ); 00260 mVal.resize( 0 ); 00261 retval = Item; 00262 } else if ( attrLower == "delete" ) { 00263 mModType = Mod_Del; 00264 mAttr = QString::fromUtf8( mVal, mVal.size() ); 00265 mVal.resize( 0 ); 00266 retval = Item; 00267 } else { 00268 retval = Err; 00269 } 00270 } else { 00271 if ( mAttr.isEmpty() ) { 00272 if ( QString::fromUtf8( mVal, mVal.size() ) == "-" ) { 00273 mModType = Mod_None; 00274 } else if ( mVal.size() == 0 ) { 00275 retval = EndEntry; 00276 } else 00277 retval = Err; 00278 } else 00279 retval = Item; 00280 } 00281 break; 00282 case Entry_Modrdn: 00283 if ( mAttr.isEmpty() && mVal.size() == 0 ) 00284 retval = EndEntry; 00285 else if ( attrLower == "newrdn" ) 00286 mNewRdn = QString::fromUtf8( mVal, mVal.size() ); 00287 else if ( attrLower == "newsuperior" ) 00288 mNewSuperior = QString::fromUtf8( mVal, mVal.size() ); 00289 else if ( attrLower == "deleteoldrdn" ) { 00290 if ( mVal.size() > 0 && mVal[0] == '0' ) 00291 mDelOldRdn = false; 00292 else if ( mVal.size() > 0 && mVal[0] == '1' ) 00293 mDelOldRdn = true; 00294 else 00295 retval = Err; 00296 } else 00297 retval = Err; 00298 break; 00299 } 00300 return retval; 00301 } 00302 00303 LDIF::ParseVal LDIF::nextItem() 00304 { 00305 ParseVal retval = None; 00306 char c=0; 00307 00308 while( retval == None ) { 00309 if ( mPos < mLdif.size() ) { 00310 c = mLdif[mPos]; 00311 mPos++; 00312 if ( mIsNewLine && c == '\r' ) continue; //handle \n\r line end 00313 if ( mIsNewLine && ( c == ' ' || c == '\t' ) ) { //line folding 00314 mIsNewLine = false; 00315 continue; 00316 } 00317 if ( mIsNewLine ) { 00318 mIsNewLine = false; 00319 retval = processLine(); 00320 mLastParseVal = retval; 00321 line.resize( 0 ); 00322 mIsComment = ( c == '#' ); 00323 } 00324 if ( c == '\n' || c == '\r' ) { 00325 mLineNo++; 00326 mIsNewLine = true; 00327 continue; 00328 } 00329 } else { 00330 retval = MoreData; 00331 break; 00332 } 00333 00334 if ( !mIsComment ) line += c; 00335 } 00336 return retval; 00337 } 00338 00339 void LDIF::endLDIF() 00340 { 00341 mLdif.resetRawData( delimiter, 3 ); 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 kabc Library Version 3.3.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun Oct 17 11:33:00 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003