Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

# Copyright (C) 2007  Red Hat 

# see file 'COPYING' for use and warranty information 

# 

# This program is free software; you can redistribute it and/or modify 

# it under the terms of the GNU General Public License as published by 

# the Free Software Foundation, either version 3 of the License, or 

# (at your option) any later version. 

# 

# This program is distributed in the hope that it will be useful, 

# but WITHOUT ANY WARRANTY; without even the implied warranty of 

# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 

# GNU General Public License for more details. 

# 

# You should have received a copy of the GNU General Public License 

# along with this program.  If not, see <http://www.gnu.org/licenses/>. 

# 

 

import copy 

 

import ipapython.ipautil 

 

def utf8_encode_value(value): 

    if isinstance(value,unicode): 

        return value.encode('utf-8') 

    return value 

 

def utf8_encode_values(values): 

    if isinstance(values,list) or isinstance(values,tuple): 

        return map(utf8_encode_value, values) 

    else: 

        return utf8_encode_value(values) 

 

def copy_CIDict(x): 

    """Do a deep copy of a CIDict""" 

    y = {} 

    for key, value in x.iteritems(): 

        y[copy.deepcopy(key)] = copy.deepcopy(value) 

    return y 

 

class Entity: 

    """This class represents an IPA user.  An LDAP entry consists of a DN 

    and a list of attributes.  Each attribute consists of a name and a list of 

    values. For the time being I will maintain this. 

 

    In python-ldap, entries are returned as a list of 2-tuples. 

    Instance variables: 

    dn - string - the string DN of the entry 

    data - CIDict - case insensitive dict of the attributes and values 

    orig_data - CIDict - case insentiive dict of the original attributes and values""" 

 

    def __init__(self,entrydata=None): 

        """data is the raw data returned from the python-ldap result method, 

        which is a search result entry or a reference or None. 

        If creating a new empty entry, data is the string DN.""" 

        if entrydata: 

            if isinstance(entrydata,tuple): 

                self.dn = entrydata[0] 

                self.data = ipapython.ipautil.CIDict(entrydata[1]) 

            elif isinstance(entrydata,str) or isinstance(entrydata,unicode): 

                self.dn = entrydata 

                self.data = ipapython.ipautil.CIDict() 

            elif isinstance(entrydata,dict): 

                self.dn = entrydata['dn'] 

                del entrydata['dn'] 

                self.data = ipapython.ipautil.CIDict(entrydata) 

        else: 

            self.dn = '' 

            self.data = ipapython.ipautil.CIDict() 

 

        self.orig_data = ipapython.ipautil.CIDict(copy_CIDict(self.data)) 

 

    def __nonzero__(self): 

        """This allows us to do tests like if entry: returns false if there is no data, 

        true otherwise""" 

        return self.data != None and len(self.data) > 0 

 

    def hasAttr(self,name): 

        """Return True if this entry has an attribute named name, False otherwise""" 

        return self.data and self.data.has_key(name) 

 

    def __setattr__(self,name,value): 

        """One should use setValue() or setValues() to set values except for 

           dn and data which are special.""" 

        if name != 'dn' and name != 'data' and name != 'orig_data': 

            raise KeyError, 'use setValue() or setValues()' 

        else: 

            self.__dict__[name] = value 

 

    def __getattr__(self,name): 

        """If name is the name of an LDAP attribute, return the first value for that 

        attribute - equivalent to getValue - this allows the use of 

        entry.cn 

        instead of 

        entry.getValue('cn') 

        This also allows us to return None if an attribute is not found rather than 

        throwing an exception""" 

        return self.getValue(name) 

 

    def getValues(self,name): 

        """Get the list (array) of values for the attribute named name""" 

        return self.data.get(name) 

 

    def getValue(self,name,default=None): 

        """Get the first value for the attribute named name""" 

        value =  self.data.get(name,default) 

        if isinstance(value,list) or isinstance(value,tuple): 

            return value[0] 

        else: 

            return value 

 

    def setValue(self,name,*value): 

        """Value passed in may be a single value, several values, or a single sequence. 

        For example: 

           ent.setValue('name', 'value') 

           ent.setValue('name', 'value1', 'value2', ..., 'valueN') 

           ent.setValue('name', ['value1', 'value2', ..., 'valueN']) 

           ent.setValue('name', ('value1', 'value2', ..., 'valueN')) 

        Since *value is a tuple, we may have to extract a list or tuple from that 

        tuple as in the last two examples above""" 

        if (len(value) < 1): 

            return 

        if (len(value) == 1): 

            self.data[name] = utf8_encode_values(value[0]) 

        else: 

            self.data[name] = utf8_encode_values(value) 

 

    setValues = setValue 

 

    def setValueNotEmpty(self,name,*value): 

        """Similar to setValue() but will not set an empty field. This 

           is an attempt to avoid adding empty attributes.""" 

        if (len(value) >= 1) and value[0] and len(value[0]) > 0: 

            if isinstance(value[0], list): 

                if len(value[0][0]) > 0: 

                    self.setValue(name, *value) 

                    return 

            else: 

                self.setValue(name, *value) 

                return 

 

        # At this point we have an empty incoming value. See if they are 

        # trying to erase the current value. If so we'll delete it so 

        # it gets marked as removed in the modlist. 

        v = self.getValues(name) 

        if v: 

            self.delValue(name) 

 

        return 

 

    def delValue(self,name): 

        """Remove the attribute named name.""" 

        if self.data.get(name,None): 

            del self.data[name] 

 

    def toTupleList(self): 

        """Convert the attrs and values to a list of 2-tuples.  The first element 

        of the tuple is the attribute name.  The second element is either a 

        single value or a list of values.""" 

        return self.data.items() 

 

    def toDict(self): 

        """Convert the attrs and values to a dict. The dict is keyed on the 

        attribute name.  The value is either single value or a list of values.""" 

        result = ipapython.ipautil.CIDict(self.data) 

        result['dn'] = self.dn 

        return result 

 

    def attrList(self): 

        """Return a list of all attributes in the entry""" 

        return self.data.keys() 

 

    def origDataDict(self): 

        """Returns a dict of the original values of the user.  Used for updates.""" 

        result = ipapython.ipautil.CIDict(self.orig_data) 

        result['dn'] = self.dn 

        return result 

 

#    def __str__(self): 

#        """Convert the Entry to its LDIF representation""" 

#        return self.__repr__() 

# 

#    # the ldif class base64 encodes some attrs which I would rather see in raw form - to 

#    # encode specific attrs as base64, add them to the list below 

#    ldif.safe_string_re = re.compile('^$') 

#    base64_attrs = ['nsstate', 'krbprincipalkey', 'krbExtraData'] 

# 

#    def __repr__(self): 

#        """Convert the Entry to its LDIF representation""" 

#        sio = cStringIO.StringIO() 

#        # what's all this then?  the unparse method will currently only accept 

#        # a list or a dict, not a class derived from them.  self.data is a 

#        # cidict, so unparse barfs on it.  I've filed a bug against python-ldap, 

#        # but in the meantime, we have to convert to a plain old dict for printing 

#        # I also don't want to see wrapping, so set the line width really high (1000) 

#        newdata = {} 

#        newdata.update(self.data) 

#        ldif.LDIFWriter(sio,User.base64_attrs,1000).unparse(self.dn,newdata) 

#        return sio.getvalue()