TDE core libraries
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

366 lines
9.9KB

  1. /*
  2. This file is part of libtdeabc.
  3. Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu>
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public
  6. License as published by the Free Software Foundation; either
  7. version 2 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public License
  13. along with this library; see the file COPYING.LIB. If not, write to
  14. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  15. Boston, MA 02110-1301, USA.
  16. */
  17. #include <kdebug.h>
  18. #include <kmdcodec.h>
  19. #include "ldif.h"
  20. using namespace TDEABC;
  21. LDIF::LDIF()
  22. {
  23. startParsing();
  24. }
  25. LDIF::~LDIF()
  26. {
  27. }
  28. TQCString LDIF::assembleLine( const TQString &fieldname, const TQByteArray &value,
  29. uint linelen, bool url )
  30. {
  31. bool safe = false;
  32. bool isDn;
  33. TQCString result;
  34. uint i;
  35. if ( url ) {
  36. result = fieldname.utf8() + ":< " + TQCString( value.data(), value.size()+1 );
  37. } else {
  38. isDn = fieldname.lower() == "dn";
  39. //SAFE-INIT-CHAR
  40. if ( value.size() > 0 && value[0] > 0 && value[0] != '\n' &&
  41. value[0] != '\r' && value[0] != ':' && value[0] != '<' ) safe = true;
  42. //SAFE-CHAR
  43. if ( safe ) {
  44. for ( i=1; i < value.size(); i++ ) {
  45. //allow utf-8 in Distinguished Names
  46. if ( ( isDn && value[i] == 0 ) ||
  47. ( !isDn && value[i] <= 0 ) ||
  48. value[i] == '\r' || value[i] == '\n' ) {
  49. safe = false;
  50. break;
  51. }
  52. }
  53. }
  54. if ( value.size() == 0 ) safe = true;
  55. if( safe ) {
  56. result = fieldname.utf8() + ": " + TQCString( value.data(), value.size()+1 );
  57. } else {
  58. result = fieldname.utf8() + ":: " + KCodecs::base64Encode( value, false );
  59. }
  60. if ( linelen > 0 ) {
  61. i = (fieldname.length()+2) > linelen ? fieldname.length()+2 : linelen;
  62. while ( i < result.length() ) {
  63. result.insert( i, "\n " );
  64. i += linelen+2;
  65. }
  66. }
  67. }
  68. return result;
  69. }
  70. TQCString LDIF::assembleLine( const TQString &fieldname, const TQCString &value,
  71. uint linelen, bool url )
  72. {
  73. TQCString ret;
  74. TQByteArray tmp;
  75. uint valuelen = value.length();
  76. const char *data = value.data();
  77. tmp.setRawData( data, valuelen );
  78. ret = assembleLine( fieldname, tmp, linelen, url );
  79. tmp.resetRawData( data, valuelen );
  80. return ret;
  81. }
  82. TQCString LDIF::assembleLine( const TQString &fieldname, const TQString &value,
  83. uint linelen, bool url )
  84. {
  85. return assembleLine( fieldname, value.utf8(), linelen, url );
  86. }
  87. bool LDIF::splitLine( const TQCString &line, TQString &fieldname, TQByteArray &value )
  88. {
  89. int position;
  90. TQByteArray tmp;
  91. int linelen;
  92. const char *data;
  93. // kdDebug(5700) << "splitLine line: " << TQString::fromUtf8(line) << endl;
  94. position = line.find( ":" );
  95. if ( position == -1 ) {
  96. // strange: we did not find a fieldname
  97. fieldname = "";
  98. TQCString str;
  99. str = line.stripWhiteSpace();
  100. linelen = str.length();
  101. data = str.data();
  102. tmp.setRawData( data, linelen );
  103. value = tmp.copy();
  104. tmp.resetRawData( data, linelen );
  105. // kdDebug(5700) << "value : " << value[0] << endl;
  106. return false;
  107. }
  108. linelen = line.length();
  109. if ( linelen > ( position + 1 ) && line[ position + 1 ] == ':' ) {
  110. // String is BASE64 encoded -> decode it now.
  111. fieldname = TQString::fromUtf8(
  112. line.left( position ).stripWhiteSpace() );
  113. if ( linelen <= ( position + 3 ) ) {
  114. value.resize( 0 );
  115. return false;
  116. }
  117. data = &line.data()[ position + 3 ];
  118. tmp.setRawData( data, linelen - position - 3 );
  119. KCodecs::base64Decode( tmp, value );
  120. tmp.resetRawData( data, linelen - position - 3 );
  121. return false;
  122. }
  123. if ( linelen > ( position + 1 ) && line[ position + 1 ] == '<' ) {
  124. // String is an URL.
  125. fieldname = TQString::fromUtf8(
  126. line.left( position ).stripWhiteSpace() );
  127. if ( linelen <= ( position + 3 ) ) {
  128. value.resize( 0 );
  129. return false;
  130. }
  131. data = &line.data()[ position + 3];
  132. tmp.setRawData( data, linelen - position - 3 );
  133. value = tmp.copy();
  134. tmp.resetRawData( data, linelen - position - 3 );
  135. return true;
  136. }
  137. fieldname = TQString::fromUtf8(line.left( position ).stripWhiteSpace());
  138. if ( linelen <= ( position + 2 ) ) {
  139. value.resize( 0 );
  140. return false;
  141. }
  142. data = &line.data()[ position + 2 ];
  143. tmp.setRawData( data, linelen - position - 2 );
  144. value = tmp.copy();
  145. tmp.resetRawData( data, linelen - position - 2 );
  146. return false;
  147. }
  148. bool LDIF::splitControl( const TQCString &line, TQString &oid, bool &critical,
  149. TQByteArray &value )
  150. {
  151. TQString tmp;
  152. critical = false;
  153. bool url = splitLine( line, tmp, value );
  154. kdDebug(5700) << "splitControl: value: " << TQString(TQString::fromUtf8(value, value.size())) << endl;
  155. if ( tmp.isEmpty() ) {
  156. tmp = TQString::fromUtf8( value, value.size() );
  157. value.resize( 0 );
  158. }
  159. if ( tmp.right( 4 ) == "true" ) {
  160. critical = true;
  161. tmp.truncate( tmp.length() - 5 );
  162. } else if ( tmp.right( 5 ) == "false" ) {
  163. critical = false;
  164. tmp.truncate( tmp.length() - 6 );
  165. }
  166. oid = tmp;
  167. return url;
  168. }
  169. LDIF::ParseVal LDIF::processLine()
  170. {
  171. if ( mIsComment ) return None;
  172. ParseVal retval = None;
  173. if ( mLastParseVal == EndEntry ) mEntryType = Entry_None;
  174. mUrl = splitLine( line, mAttr, mVal );
  175. TQString attrLower = mAttr.lower();
  176. switch ( mEntryType ) {
  177. case Entry_None:
  178. if ( attrLower == "version" ) {
  179. if ( !mDn.isEmpty() ) retval = Err;
  180. } else if ( attrLower == "dn" ) {
  181. kdDebug(5700) << "ldapentry dn: " << TQString(TQString::fromUtf8( mVal, mVal.size() )) << endl;
  182. mDn = TQString::fromUtf8( mVal, mVal.size() );
  183. mModType = Mod_None;
  184. retval = NewEntry;
  185. } else if ( attrLower == "changetype" ) {
  186. if ( mDn.isEmpty() )
  187. retval = Err;
  188. else {
  189. TQString tmpval = TQString::fromUtf8( mVal, mVal.size() );
  190. kdDebug(5700) << "changetype: " << tmpval << endl;
  191. if ( tmpval == "add" ) mEntryType = Entry_Add;
  192. else if ( tmpval == "delete" ) mEntryType = Entry_Del;
  193. else if ( tmpval == "modrdn" || tmpval == "moddn" ) {
  194. mNewRdn = "";
  195. mNewSuperior = "";
  196. mDelOldRdn = true;
  197. mEntryType = Entry_Modrdn;
  198. }
  199. else if ( tmpval == "modify" ) mEntryType = Entry_Mod;
  200. else retval = Err;
  201. }
  202. } else if ( attrLower == "control" ) {
  203. mUrl = splitControl( TQCString( mVal, mVal.size() + 1 ), mOid, mCritical, mVal );
  204. retval = Control;
  205. } else if ( !mAttr.isEmpty() && mVal.size() > 0 ) {
  206. mEntryType = Entry_Add;
  207. retval = Item;
  208. }
  209. break;
  210. case Entry_Add:
  211. if ( mAttr.isEmpty() && mVal.size() == 0 )
  212. retval = EndEntry;
  213. else
  214. retval = Item;
  215. break;
  216. case Entry_Del:
  217. if ( mAttr.isEmpty() && mVal.size() == 0 )
  218. retval = EndEntry;
  219. else
  220. retval = Err;
  221. break;
  222. case Entry_Mod:
  223. if ( mModType == Mod_None ) {
  224. kdDebug(5700) << "tdeio_ldap: new modtype " << mAttr << endl;
  225. if ( mAttr.isEmpty() && mVal.size() == 0 ) {
  226. retval = EndEntry;
  227. } else if ( attrLower == "add" ) {
  228. mModType = Mod_Add;
  229. } else if ( attrLower == "replace" ) {
  230. mModType = Mod_Replace;
  231. mAttr = TQString::fromUtf8( mVal, mVal.size() );
  232. mVal.resize( 0 );
  233. retval = Item;
  234. } else if ( attrLower == "delete" ) {
  235. mModType = Mod_Del;
  236. mAttr = TQString::fromUtf8( mVal, mVal.size() );
  237. mVal.resize( 0 );
  238. retval = Item;
  239. } else {
  240. retval = Err;
  241. }
  242. } else {
  243. if ( mAttr.isEmpty() ) {
  244. if ( TQString::fromUtf8( mVal, mVal.size() ) == "-" ) {
  245. mModType = Mod_None;
  246. } else if ( mVal.size() == 0 ) {
  247. retval = EndEntry;
  248. } else
  249. retval = Err;
  250. } else
  251. retval = Item;
  252. }
  253. break;
  254. case Entry_Modrdn:
  255. if ( mAttr.isEmpty() && mVal.size() == 0 )
  256. retval = EndEntry;
  257. else if ( attrLower == "newrdn" )
  258. mNewRdn = TQString::fromUtf8( mVal, mVal.size() );
  259. else if ( attrLower == "newsuperior" )
  260. mNewSuperior = TQString::fromUtf8( mVal, mVal.size() );
  261. else if ( attrLower == "deleteoldrdn" ) {
  262. if ( mVal.size() > 0 && mVal[0] == '0' )
  263. mDelOldRdn = false;
  264. else if ( mVal.size() > 0 && mVal[0] == '1' )
  265. mDelOldRdn = true;
  266. else
  267. retval = Err;
  268. } else
  269. retval = Err;
  270. break;
  271. }
  272. return retval;
  273. }
  274. LDIF::ParseVal LDIF::nextItem()
  275. {
  276. ParseVal retval = None;
  277. char c=0;
  278. while( retval == None ) {
  279. if ( mPos < mLdif.size() ) {
  280. c = mLdif[mPos];
  281. mPos++;
  282. if ( mIsNewLine && c == '\r' ) continue; //handle \n\r line end
  283. if ( mIsNewLine && ( c == ' ' || c == '\t' ) ) { //line folding
  284. mIsNewLine = false;
  285. continue;
  286. }
  287. if ( mIsNewLine ) {
  288. mIsNewLine = false;
  289. retval = processLine();
  290. mLastParseVal = retval;
  291. line.resize( 0 );
  292. mIsComment = ( c == '#' );
  293. }
  294. if ( c == '\n' || c == '\r' ) {
  295. mLineNo++;
  296. mIsNewLine = true;
  297. continue;
  298. }
  299. } else {
  300. retval = MoreData;
  301. break;
  302. }
  303. if ( !mIsComment ) line += c;
  304. }
  305. return retval;
  306. }
  307. void LDIF::endLDIF()
  308. {
  309. TQByteArray tmp( 3 );
  310. tmp[ 0 ] = '\n';
  311. tmp[ 1 ] = '\n';
  312. tmp[ 2 ] = '\n';
  313. mLdif = tmp;
  314. mPos = 0;
  315. }
  316. void LDIF::startParsing()
  317. {
  318. mPos = mLineNo = 0;
  319. mDelOldRdn = false;
  320. mEntryType = Entry_None;
  321. mModType = Mod_None;
  322. mDn = mNewRdn = mNewSuperior = "";
  323. line = "";
  324. mIsNewLine = false;
  325. mIsComment = false;
  326. mLastParseVal = None;
  327. }