1// OpenLDAP: pkg/ldap/contrib/ldapc++/src/LDAPAttributeList.cpp,v 1.7.6.4 2008/07/08 19:31:00 quanah Exp
2/*
3 * Copyright 2000-2007, OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5 */
6
7
8#include "debug.h"
9
10#include "LDAPAttributeList.h"
11
12#include "LDAPException.h"
13#include "LDAPAttribute.h"
14#include "LDAPAsynConnection.h"
15#include "LDAPMessage.h"
16
17#include <cstdlib>
18
19using namespace std;
20
21// little helper function for doing case insensitve string comparison
22bool nocase_compare(char c1, char c2);
23
24LDAPAttributeList::LDAPAttributeList(){
25    DEBUG(LDAP_DEBUG_CONSTRUCT,
26            "LDAPAttributeList::LDAPAttributList( )" << endl);
27}
28
29LDAPAttributeList::LDAPAttributeList(const LDAPAttributeList& al){
30    DEBUG(LDAP_DEBUG_CONSTRUCT,
31            "LDAPAttributeList::LDAPAttributList(&)" << endl);
32    m_attrs=al.m_attrs;
33}
34
35LDAPAttributeList::LDAPAttributeList(const LDAPAsynConnection *ld,
36        LDAPMessage *msg){
37    DEBUG(LDAP_DEBUG_CONSTRUCT,
38            "LDAPAttributeList::LDAPAttributList()" << endl);
39    BerElement *ptr=0;
40    char *name=ldap_first_attribute(ld->getSessionHandle(), msg, &ptr);
41/*
42   This code was making problems if no attribute were returned
43   How am I supposed to find decoding errors? ldap_first/next_attribute
44   return 0 in case of error or if there are no more attributes. In either
45   case they set the LDAP* error code to 0x54 (Decoding error) ??? Strange..
46
47   There will be some changes in the new version of the C-API so that this
48   code should work in the future.
49   if(name == 0){
50        ber_free(ptr,0);
51        ldap_memfree(name);
52        throw LDAPException(ld);
53    }else{
54*/        BerValue **values;
55        for (;name !=0;
56                name=ldap_next_attribute(ld->getSessionHandle(),msg,ptr) ){
57            values=ldap_get_values_len(ld->getSessionHandle(),
58                    msg, name);
59            this->addAttribute(LDAPAttribute(name, values));
60            ldap_memfree(name);
61            ldap_value_free_len(values);
62        }
63        ber_free(ptr,0);
64//    }
65}
66
67LDAPAttributeList::~LDAPAttributeList(){
68    DEBUG(LDAP_DEBUG_DESTROY,"LDAPAttributeList::~LDAPAttributList()" << endl);
69}
70
71size_t LDAPAttributeList::size() const{
72    DEBUG(LDAP_DEBUG_TRACE,"LDAPAttribute::size()" << endl);
73    return m_attrs.size();
74}
75
76bool LDAPAttributeList::empty() const{
77    DEBUG(LDAP_DEBUG_TRACE,"LDAPAttribute::empty()" << endl);
78    return m_attrs.empty();
79}
80
81LDAPAttributeList::const_iterator LDAPAttributeList::begin() const{
82    DEBUG(LDAP_DEBUG_TRACE,"LDAPAttribute::begin()" << endl);
83    return m_attrs.begin();
84}
85
86LDAPAttributeList::const_iterator LDAPAttributeList::end() const{
87    DEBUG(LDAP_DEBUG_TRACE,"LDAPAttribute::end()" << endl);
88    return m_attrs.end();
89}
90
91const LDAPAttribute* LDAPAttributeList::getAttributeByName(
92	const string& name) const {
93    DEBUG(LDAP_DEBUG_TRACE,"LDAPAttribute::getAttributeByName()" << endl);
94    DEBUG(LDAP_DEBUG_TRACE | LDAP_DEBUG_PARAMETER,
95            "   name:" << name << endl);
96    LDAPAttributeList::const_iterator i;
97    for( i = m_attrs.begin(); i != m_attrs.end(); i++){
98	const std::string& tmpType = i->getName();
99	if(name.size() == tmpType.size()){
100	    if(equal(name.begin(), name.end(), tmpType.begin(),
101		    nocase_compare)){
102		return &(*i);
103		DEBUG(LDAP_DEBUG_TRACE,"    found:" << name << endl);
104	    }
105	}
106    }
107    return 0;
108}
109
110void LDAPAttributeList::addAttribute(const LDAPAttribute& attr){
111    DEBUG(LDAP_DEBUG_TRACE,"LDAPAttribute::addAttribute()" << endl);
112    DEBUG(LDAP_DEBUG_TRACE | LDAP_DEBUG_PARAMETER,
113            "   attr:" << attr << endl);
114    const std::string attrType = attr.getName();
115    const std::string::size_type attrLen = attrType.size();
116    std::string::size_type tmpAttrLen = 0;
117    bool done=false;
118    LDAPAttributeList::iterator i;
119    for( i=m_attrs.begin(); i != m_attrs.end(); i++ ){
120	const std::string tmpAttrType = i->getName();
121	tmpAttrLen = tmpAttrType.size();
122	if(tmpAttrLen == attrLen){
123	    if(equal(tmpAttrType.begin(), tmpAttrType.end(), attrType.begin(),
124		    nocase_compare)){
125		const StringList& values = attr.getValues();
126		StringList::const_iterator j;
127		for(j = values.begin(); j != values.end(); j++){
128		    i->addValue(*j);
129		}
130		DEBUG(LDAP_DEBUG_TRACE,"Attribute" << i->getName()
131			<< "already present" << endl);
132		done=true;
133		break; // The AttributeType was already present,
134		       // we are done here
135	    }
136	}
137    }
138    if(! done){
139	m_attrs.push_back(attr);
140    }
141}
142
143void LDAPAttributeList::delAttribute(const std::string& type)
144{
145    DEBUG(LDAP_DEBUG_TRACE,"LDAPAttribute::replaceAttribute()" << endl);
146    DEBUG(LDAP_DEBUG_TRACE | LDAP_DEBUG_PARAMETER, "   type: " << type << endl);
147    LDAPAttributeList::iterator i;
148    for( i = m_attrs.begin(); i != m_attrs.end(); i++){
149	if(type.size() == i->getName().size()){
150	    if(equal(type.begin(), type.end(), i->getName().begin(),
151		    nocase_compare)){
152                m_attrs.erase(i);
153                break;
154            }
155        }
156    }
157}
158
159void LDAPAttributeList::replaceAttribute(const LDAPAttribute& attr)
160{
161    DEBUG(LDAP_DEBUG_TRACE,"LDAPAttribute::replaceAttribute()" << endl);
162    DEBUG(LDAP_DEBUG_TRACE | LDAP_DEBUG_PARAMETER,
163            "   attr:" << attr << endl);
164
165    LDAPAttributeList::iterator i;
166    this->delAttribute( attr.getName() );
167    m_attrs.push_back(attr);
168}
169
170LDAPMod** LDAPAttributeList::toLDAPModArray() const{
171    DEBUG(LDAP_DEBUG_TRACE,"LDAPAttribute::toLDAPModArray()" << endl);
172    LDAPMod **ret = (LDAPMod**) malloc((m_attrs.size()+1) * sizeof(LDAPMod*));
173    LDAPAttributeList::const_iterator i;
174    int j=0;
175    for (i=m_attrs.begin(); i!= m_attrs.end(); i++, j++){
176        ret[j]=i->toLDAPMod();
177    }
178    ret[m_attrs.size()]=0;
179    return ret;
180}
181
182ostream& operator << (ostream& s, const LDAPAttributeList& al){
183    LDAPAttributeList::const_iterator i;
184    for(i=al.m_attrs.begin(); i!=al.m_attrs.end(); i++){
185        s << *i << "; ";
186    }
187    return s;
188}
189
190bool nocase_compare( char c1, char c2){
191    return toupper(c1) == toupper(c2);
192}
193
194