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 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
const char *data = value.data();
00092
00093 tmp.setRawData( data, valuelen );
00094 ret =
assembleLine( fieldname, tmp, linelen, url );
00095 tmp.resetRawData( data, 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
const char *data;
00112
00113
00114
00115 position = line.find(
":" );
00116
if ( position == -1 ) {
00117
00118 fieldname =
"";
00119
QCString str;
00120 str = line.stripWhiteSpace();
00121 linelen = str.length();
00122 data = str.data();
00123 tmp.setRawData( data, linelen );
00124 value = tmp.copy();
00125 tmp.resetRawData( data, linelen );
00126
00127
return false;
00128 }
00129
00130 linelen = line.length();
00131
00132
if ( linelen > ( position + 1 ) && line[ position + 1 ] ==
':' ) {
00133
00134 fieldname = QString::fromUtf8(
00135 line.left( position ).stripWhiteSpace() );
00136
if ( linelen <= ( position + 3 ) ) {
00137 value.resize( 0 );
00138
return false;
00139 }
00140 data = &line.data()[ position + 3 ];
00141 tmp.setRawData( data, linelen - position - 3 );
00142 KCodecs::base64Decode( tmp, value );
00143 tmp.resetRawData( data, linelen - position - 3 );
00144
return false;
00145 }
00146
00147
if ( linelen > ( position + 1 ) && line[ position + 1 ] ==
'<' ) {
00148
00149 fieldname = QString::fromUtf8(
00150 line.left( position ).stripWhiteSpace() );
00151
if ( linelen <= ( position + 3 ) ) {
00152 value.resize( 0 );
00153
return false;
00154 }
00155 data = &line.data()[ position + 3];
00156 tmp.setRawData( data, linelen - position - 3 );
00157 value = tmp.copy();
00158 tmp.resetRawData( data, linelen - position - 3 );
00159
return true;
00160 }
00161
00162 fieldname = QString::fromUtf8(line.left( position ).stripWhiteSpace());
00163
if ( linelen <= ( position + 2 ) ) {
00164 value.resize( 0 );
00165
return false;
00166 }
00167 data = &line.data()[ position + 2 ];
00168 tmp.setRawData( data, linelen - position - 2 );
00169 value = tmp.copy();
00170 tmp.resetRawData( data, linelen - position - 2 );
00171
return false;
00172 }
00173
00174 bool LDIF::splitControl(
const QCString &line,
QString &oid,
bool &critical,
00175
QByteArray &value )
00176 {
00177
QString tmp;
00178 critical =
false;
00179
bool url =
splitLine( line, tmp, value );
00180
00181
kdDebug(5700) <<
"splitControl: value: " << QString::fromUtf8(value, value.size()) <<
endl;
00182
if ( tmp.isEmpty() ) {
00183 tmp = QString::fromUtf8( value, value.size() );
00184 value.resize( 0 );
00185 }
00186
if ( tmp.right( 4 ) ==
"true" ) {
00187 critical =
true;
00188 tmp.truncate( tmp.length() - 5 );
00189 }
else if ( tmp.right( 5 ) ==
"false" ) {
00190 critical =
false;
00191 tmp.truncate( tmp.length() - 6 );
00192 }
00193 oid = tmp;
00194
return url;
00195 }
00196
00197 LDIF::ParseVal
LDIF::processLine()
00198 {
00199
00200
if ( mIsComment )
return None;
00201
00202 ParseVal retval = None;
00203
if ( mLastParseVal == EndEntry ) mEntryType = Entry_None;
00204
00205 mUrl =
splitLine( line, mAttr, mVal );
00206
00207
QString attrLower = mAttr.lower();
00208
00209
switch ( mEntryType ) {
00210
case Entry_None:
00211
if ( attrLower ==
"version" ) {
00212
if ( !mDn.isEmpty() ) retval = Err;
00213 }
else if ( attrLower ==
"dn" ) {
00214
kdDebug(5700) <<
"ldapentry dn: " << QString::fromUtf8( mVal, mVal.size() ) <<
endl;
00215 mDn = QString::fromUtf8( mVal, mVal.size() );
00216 mModType = Mod_None;
00217 retval = NewEntry;
00218 }
else if ( attrLower ==
"changetype" ) {
00219
if ( mDn.isEmpty() )
00220 retval = Err;
00221
else {
00222
QString tmpval = QString::fromUtf8( mVal, mVal.size() );
00223
kdDebug(5700) <<
"changetype: " << tmpval <<
endl;
00224
if ( tmpval ==
"add" ) mEntryType = Entry_Add;
00225
else if ( tmpval ==
"delete" ) mEntryType = Entry_Del;
00226
else if ( tmpval ==
"modrdn" || tmpval ==
"moddn" ) {
00227 mNewRdn =
"";
00228 mNewSuperior =
"";
00229 mDelOldRdn =
true;
00230 mEntryType = Entry_Modrdn;
00231 }
00232
else if ( tmpval ==
"modify" ) mEntryType = Entry_Mod;
00233
else retval = Err;
00234 }
00235 }
else if ( attrLower ==
"control" ) {
00236 mUrl =
splitControl(
QCString( mVal, mVal.size() + 1 ), mOid, mCritical, mVal );
00237 retval = Control;
00238 }
else if ( !mAttr.isEmpty() && mVal.size() > 0 ) {
00239 mEntryType = Entry_Add;
00240 retval = Item;
00241 }
00242
break;
00243
case Entry_Add:
00244
if ( mAttr.isEmpty() && mVal.size() == 0 )
00245 retval = EndEntry;
00246
else
00247 retval = Item;
00248
break;
00249
case Entry_Del:
00250
if ( mAttr.isEmpty() && mVal.size() == 0 )
00251 retval = EndEntry;
00252
else
00253 retval = Err;
00254
break;
00255
case Entry_Mod:
00256
if ( mModType == Mod_None ) {
00257
kdDebug(5700) <<
"kio_ldap: new modtype " << mAttr <<
endl;
00258
if ( mAttr.isEmpty() && mVal.size() == 0 ) {
00259 retval = EndEntry;
00260 }
else if ( attrLower ==
"add" ) {
00261 mModType = Mod_Add;
00262 }
else if ( attrLower ==
"replace" ) {
00263 mModType = Mod_Replace;
00264 mAttr = QString::fromUtf8( mVal, mVal.size() );
00265 mVal.resize( 0 );
00266 retval = Item;
00267 }
else if ( attrLower ==
"delete" ) {
00268 mModType = Mod_Del;
00269 mAttr = QString::fromUtf8( mVal, mVal.size() );
00270 mVal.resize( 0 );
00271 retval = Item;
00272 }
else {
00273 retval = Err;
00274 }
00275 }
else {
00276
if ( mAttr.isEmpty() ) {
00277
if ( QString::fromUtf8( mVal, mVal.size() ) ==
"-" ) {
00278 mModType = Mod_None;
00279 }
else if ( mVal.size() == 0 ) {
00280 retval = EndEntry;
00281 }
else
00282 retval = Err;
00283 }
else
00284 retval = Item;
00285 }
00286
break;
00287
case Entry_Modrdn:
00288
if ( mAttr.isEmpty() && mVal.size() == 0 )
00289 retval = EndEntry;
00290
else if ( attrLower ==
"newrdn" )
00291 mNewRdn = QString::fromUtf8( mVal, mVal.size() );
00292
else if ( attrLower ==
"newsuperior" )
00293 mNewSuperior = QString::fromUtf8( mVal, mVal.size() );
00294
else if ( attrLower ==
"deleteoldrdn" ) {
00295
if ( mVal.size() > 0 && mVal[0] ==
'0' )
00296 mDelOldRdn =
false;
00297
else if ( mVal.size() > 0 && mVal[0] ==
'1' )
00298 mDelOldRdn =
true;
00299
else
00300 retval = Err;
00301 }
else
00302 retval = Err;
00303
break;
00304 }
00305
return retval;
00306 }
00307
00308 LDIF::ParseVal
LDIF::nextItem()
00309 {
00310 ParseVal retval = None;
00311
char c=0;
00312
00313
while( retval == None ) {
00314
if ( mPos < mLdif.size() ) {
00315 c = mLdif[mPos];
00316 mPos++;
00317
if ( mIsNewLine && c ==
'\r' )
continue;
00318
if ( mIsNewLine && ( c ==
' ' || c ==
'\t' ) ) {
00319 mIsNewLine =
false;
00320
continue;
00321 }
00322
if ( mIsNewLine ) {
00323 mIsNewLine =
false;
00324 retval =
processLine();
00325 mLastParseVal = retval;
00326 line.resize( 0 );
00327 mIsComment = ( c ==
'#' );
00328 }
00329
if ( c ==
'\n' || c ==
'\r' ) {
00330 mLineNo++;
00331 mIsNewLine =
true;
00332
continue;
00333 }
00334 }
else {
00335 retval = MoreData;
00336
break;
00337 }
00338
00339
if ( !mIsComment ) line += c;
00340 }
00341
return retval;
00342 }
00343
00344 void LDIF::endLDIF()
00345 {
00346
QByteArray tmp( 3 );
00347 tmp[ 0 ] =
'\n';
00348 tmp[ 1 ] =
'\n';
00349 tmp[ 2 ] =
'\n';
00350 mLdif = tmp;
00351 mPos = 0;
00352 }
00353
00354 void LDIF::startParsing()
00355 {
00356 mPos = mLineNo = 0;
00357 mDelOldRdn =
false;
00358 mEntryType = Entry_None;
00359 mModType = Mod_None;
00360 mDn = mNewRdn = mNewSuperior =
"";
00361 line =
"";
00362 mIsNewLine =
false;
00363 mIsComment =
false;
00364 mLastParseVal = None;
00365 }