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 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
00052
if ( value.size() > 0 && value[0] > 0 && value[0] !=
'\n' &&
00053 value[0] !=
'\r' && value[0] !=
':' && value[0] !=
'<' ) safe =
true;
00054
00055
00056
if ( safe ) {
00057
for ( i=1; i < value.size(); i++ ) {
00058
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
00113
00114 position = line.find(
":" );
00115
if ( position == -1 ) {
00116
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
00125
return false;
00126 }
00127
00128 linelen = line.length();
00129
00130
if ( linelen > ( position + 1 ) && line[ position + 1 ] ==
':' ) {
00131
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
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;
00313
if ( mIsNewLine && ( c ==
' ' || c ==
'\t' ) ) {
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 }