kabc
ldapdn.cpp
00001 /* 00002 A temporary copy to break dependency to KLDAP 00003 00004 This file is part of libkldap. 00005 Copyright (c) 2006 Sean Harmer <sh@theharmers.co.uk> 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License as published by the Free Software Foundation; either 00010 version 2 of the License, or (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Library General Public License for more details. 00016 00017 You should have received a copy of the GNU Library General Public License 00018 along with this library; see the file COPYING.LIB. If not, write to 00019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00020 Boston, MA 02110-1301, USA. 00021 */ 00022 00023 #include "ldapdn_p.h" 00024 00025 #include <algorithm> 00026 00027 #include <kdebug.h> 00028 00029 class LdapDN::LdapDNPrivate 00030 { 00031 public: 00032 LdapDNPrivate() : m_dn() {} 00033 ~LdapDNPrivate() {} 00034 00035 bool isValidRDNString( const QString &rdn ) const; 00036 QStringList splitOnNonEscapedChar( const QString &rdn, const QChar &ch ) const; 00037 00038 QString m_dn; 00039 }; 00040 00041 bool LdapDN::LdapDNPrivate::isValidRDNString( const QString &rdn ) const 00042 { 00043 kDebug() << "Testing rdn:" << rdn; 00044 00045 // If it is a muli-valued rdn, split it into its constituent parts 00046 QStringList rdnParts = splitOnNonEscapedChar( rdn, QLatin1Char( '+' ) ); 00047 if ( rdnParts.size() > 1 ) { 00048 for ( int i = 0; i < rdnParts.size(); i++ ) { 00049 if ( !isValidRDNString( rdnParts.at( i ) ) ) { 00050 return false; 00051 } 00052 } 00053 return true; 00054 } 00055 00056 // Split the rdn into the attribute name and value parts 00057 QStringList components = rdn.split( QLatin1Char( '=' ) ); 00058 00059 // We should have exactly two parts 00060 if ( components.size() != 2 ) { 00061 return false; 00062 } 00063 00064 return true; 00065 } 00066 00067 QStringList LdapDN::LdapDNPrivate::splitOnNonEscapedChar( const QString &str, 00068 const QChar &ch ) const 00069 { 00070 QStringList strParts; 00071 int index = 0; 00072 int searchFrom = 0; 00073 int strPartStartIndex = 0; 00074 while ( ( index = str.indexOf( ch, searchFrom ) ) != -1 ) { 00075 const QChar prev = str[std::max( 0, index - 1 )]; 00076 if ( prev != QLatin1Char( '\\' ) ) { 00077 // Found a component of a multi-valued RDN 00078 //kDebug() << "Found" << ch << "at index" << index; 00079 QString tmp = str.mid( strPartStartIndex, index - strPartStartIndex ); 00080 //kDebug() << "Adding part:" << tmp; 00081 strParts.append( tmp ); 00082 strPartStartIndex = index + 1; 00083 } 00084 00085 searchFrom = index + 1; 00086 } 00087 00088 // Add on the part after the last found delimeter 00089 QString tmp = str.mid( strPartStartIndex ); 00090 //kDebug() << "Adding part:" << tmp; 00091 strParts.append( tmp ); 00092 00093 return strParts; 00094 } 00095 00096 LdapDN::LdapDN() 00097 : d( new LdapDNPrivate ) 00098 { 00099 00100 } 00101 00102 LdapDN::LdapDN( const QString &dn ) 00103 : d( new LdapDNPrivate ) 00104 { 00105 d->m_dn = dn; 00106 } 00107 00108 LdapDN::LdapDN( const LdapDN &that ) 00109 : d( new LdapDNPrivate ) 00110 { 00111 *d = *that.d; 00112 } 00113 00114 LdapDN &LdapDN::operator=( const LdapDN &that ) 00115 { 00116 if ( this == &that ) { 00117 return *this; 00118 } 00119 00120 *d = *that.d; 00121 return *this; 00122 } 00123 00124 LdapDN::~LdapDN() 00125 { 00126 delete d; 00127 } 00128 00129 void LdapDN::clear() 00130 { 00131 d->m_dn.clear(); 00132 } 00133 00134 bool LdapDN::isEmpty() const 00135 { 00136 return d->m_dn.isEmpty(); 00137 } 00138 00139 QString LdapDN::toString() const 00140 { 00141 return d->m_dn; 00142 } 00143 00144 QString LdapDN::toString( int depth ) const 00145 { 00146 QStringList rdns = d->splitOnNonEscapedChar( d->m_dn, QLatin1Char( ',' ) ); 00147 if ( depth >= rdns.size() ) { 00148 return QString(); 00149 } 00150 00151 // Construct a DN down to the requested depth 00152 QString dn; 00153 for ( int i = depth; i >= 0; i-- ) { 00154 dn += rdns.at( rdns.size() - 1 - i ) + QLatin1Char( ',' ); 00155 kDebug() << "dn =" << dn; 00156 } 00157 dn = dn.left( dn.length() - 1 ); // Strip off the extraneous comma 00158 00159 return dn; 00160 } 00161 00162 QString LdapDN::rdnString() const 00163 { 00165 QStringList rdns = d->splitOnNonEscapedChar( d->m_dn, QLatin1Char( ',' ) ); 00166 return rdns.at( 0 ); 00167 } 00168 00169 QString LdapDN::rdnString( int depth ) const 00170 { 00171 QStringList rdns = d->splitOnNonEscapedChar( d->m_dn, QLatin1Char( ',' ) ); 00172 if ( depth >= rdns.size() ) { 00173 return QString(); 00174 } 00175 return rdns.at( rdns.size() - 1 - depth ); 00176 } 00177 00178 bool LdapDN::isValid() const 00179 { 00180 kDebug() << "Testing dn:" << d->m_dn; 00181 00182 // Break the string into rdn's 00183 QStringList rdns = d->splitOnNonEscapedChar( d->m_dn, QLatin1Char( ',' ) ); 00184 00185 // Test to see if each rdn is valid 00186 for ( int i = 0; i < rdns.size(); i++ ) { 00187 if ( !d->isValidRDNString( rdns.at( i ) ) ) { 00188 return false; 00189 } 00190 } 00191 00192 return true; 00193 } 00194 00195 int LdapDN::depth() const 00196 { 00197 QStringList rdns = d->splitOnNonEscapedChar( d->m_dn, QLatin1Char( ',' ) ); 00198 return rdns.size(); 00199 } 00200 00201 bool LdapDN::operator == ( const LdapDN &rhs ) const 00202 { 00203 return d->m_dn == rhs.d->m_dn; 00204 } 00205 00206 bool LdapDN::operator != ( const LdapDN &rhs ) const 00207 { 00208 return d->m_dn != rhs.d->m_dn; 00209 }