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