~jk0/nova/xs-ipv6

« back to all changes in this revision

Viewing changes to vendor/Twisted-10.0.0/twisted/words/protocols/jabber/jid.py

  • Committer: Jesse Andrews
  • Date: 2010-05-28 06:05:26 UTC
  • Revision ID: git-v1:bf6e6e718cdc7488e2da87b21e258ccc065fe499
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- test-case-name: twisted.words.test.test_jabberjid -*-
 
2
#
 
3
# Copyright (c) 2001-2008 Twisted Matrix Laboratories.
 
4
# See LICENSE for details.
 
5
 
 
6
"""
 
7
Jabber Identifier support.
 
8
 
 
9
This module provides an object to represent Jabber Identifiers (JIDs) and
 
10
parse string representations into them with proper checking for illegal
 
11
characters, case folding and canonicalisation through L{stringprep<twisted.words.protocols.jabber.xmpp_stringprep>}.
 
12
"""
 
13
 
 
14
from twisted.words.protocols.jabber.xmpp_stringprep import nodeprep, resourceprep, nameprep
 
15
 
 
16
class InvalidFormat(Exception):
 
17
    """
 
18
    The given string could not be parsed into a valid Jabber Identifier (JID).
 
19
    """
 
20
 
 
21
def parse(jidstring):
 
22
    """
 
23
    Parse given JID string into its respective parts and apply stringprep.
 
24
 
 
25
    @param jidstring: string representation of a JID.
 
26
    @type jidstring: C{unicode}
 
27
    @return: tuple of (user, host, resource), each of type C{unicode} as
 
28
             the parsed and stringprep'd parts of the given JID. If the
 
29
             given string did not have a user or resource part, the respective
 
30
             field in the tuple will hold C{None}.
 
31
    @rtype: C{tuple}
 
32
    """
 
33
    user = None
 
34
    host = None
 
35
    resource = None
 
36
 
 
37
    # Search for delimiters
 
38
    user_sep = jidstring.find("@")
 
39
    res_sep  = jidstring.find("/")
 
40
 
 
41
    if user_sep == -1:
 
42
        if res_sep == -1:
 
43
            # host
 
44
            host = jidstring
 
45
        else:
 
46
            # host/resource
 
47
            host = jidstring[0:res_sep]
 
48
            resource = jidstring[res_sep + 1:] or None
 
49
    else:
 
50
        if res_sep == -1:
 
51
            # user@host
 
52
            user = jidstring[0:user_sep] or None
 
53
            host = jidstring[user_sep + 1:]
 
54
        else:
 
55
            if user_sep < res_sep:
 
56
                # user@host/resource
 
57
                user = jidstring[0:user_sep] or None
 
58
                host = jidstring[user_sep + 1:user_sep + (res_sep - user_sep)]
 
59
                resource = jidstring[res_sep + 1:] or None
 
60
            else:
 
61
                # host/resource (with an @ in resource)
 
62
                host = jidstring[0:res_sep]
 
63
                resource = jidstring[res_sep + 1:] or None
 
64
 
 
65
    return prep(user, host, resource)
 
66
 
 
67
def prep(user, host, resource):
 
68
    """
 
69
    Perform stringprep on all JID fragments.
 
70
 
 
71
    @param user: The user part of the JID.
 
72
    @type user: C{unicode}
 
73
    @param host: The host part of the JID.
 
74
    @type host: C{unicode}
 
75
    @param resource: The resource part of the JID.
 
76
    @type resource: C{unicode}
 
77
    @return: The given parts with stringprep applied.
 
78
    @rtype: C{tuple}
 
79
    """
 
80
 
 
81
    if user:
 
82
        try:
 
83
            user = nodeprep.prepare(unicode(user))
 
84
        except UnicodeError:
 
85
            raise InvalidFormat, "Invalid character in username"
 
86
    else:
 
87
        user = None
 
88
 
 
89
    if not host:
 
90
        raise InvalidFormat, "Server address required."
 
91
    else:
 
92
        try:
 
93
            host = nameprep.prepare(unicode(host))
 
94
        except UnicodeError:
 
95
            raise InvalidFormat, "Invalid character in hostname"
 
96
 
 
97
    if resource:
 
98
        try:
 
99
            resource = resourceprep.prepare(unicode(resource))
 
100
        except UnicodeError:
 
101
            raise InvalidFormat, "Invalid character in resource"
 
102
    else:
 
103
        resource = None
 
104
 
 
105
    return (user, host, resource)
 
106
 
 
107
__internJIDs = {}
 
108
 
 
109
def internJID(jidstring):
 
110
    """
 
111
    Return interned JID.
 
112
 
 
113
    @rtype: L{JID}
 
114
    """
 
115
 
 
116
    if jidstring in __internJIDs:
 
117
        return __internJIDs[jidstring]
 
118
    else:
 
119
        j = JID(jidstring)
 
120
        __internJIDs[jidstring] = j
 
121
        return j
 
122
 
 
123
class JID(object):
 
124
    """
 
125
    Represents a stringprep'd Jabber ID.
 
126
 
 
127
    JID objects are hashable so they can be used in sets and as keys in
 
128
    dictionaries.
 
129
    """
 
130
 
 
131
    def __init__(self, str=None, tuple=None):
 
132
        if not (str or tuple):
 
133
            raise RuntimeError("You must provide a value for either 'str' or "
 
134
                               "'tuple' arguments.")
 
135
 
 
136
        if str:
 
137
            user, host, res = parse(str)
 
138
        else:
 
139
            user, host, res = prep(*tuple)
 
140
 
 
141
        self.user = user
 
142
        self.host = host
 
143
        self.resource = res
 
144
 
 
145
    def userhost(self):
 
146
        """
 
147
        Extract the bare JID as a unicode string.
 
148
 
 
149
        A bare JID does not have a resource part, so this returns either
 
150
        C{user@host} or just C{host}.
 
151
 
 
152
        @rtype: C{unicode}
 
153
        """
 
154
        if self.user:
 
155
            return u"%s@%s" % (self.user, self.host)
 
156
        else:
 
157
            return self.host
 
158
 
 
159
    def userhostJID(self):
 
160
        """
 
161
        Extract the bare JID.
 
162
 
 
163
        A bare JID does not have a resource part, so this returns a
 
164
        L{JID} object representing either C{user@host} or just C{host}.
 
165
 
 
166
        If the object this method is called upon doesn't have a resource
 
167
        set, it will return itself. Otherwise, the bare JID object will
 
168
        be created, interned using L{internJID}.
 
169
 
 
170
        @rtype: L{JID}
 
171
        """
 
172
        if self.resource:
 
173
            return internJID(self.userhost())
 
174
        else:
 
175
            return self
 
176
 
 
177
    def full(self):
 
178
        """
 
179
        Return the string representation of this JID.
 
180
 
 
181
        @rtype: C{unicode}
 
182
        """
 
183
        if self.user:
 
184
            if self.resource:
 
185
                return u"%s@%s/%s" % (self.user, self.host, self.resource)
 
186
            else:
 
187
                return u"%s@%s" % (self.user, self.host)
 
188
        else:
 
189
            if self.resource:
 
190
                return u"%s/%s" % (self.host, self.resource)
 
191
            else:
 
192
                return self.host
 
193
 
 
194
    def __eq__(self, other):
 
195
        """
 
196
        Equality comparison.
 
197
 
 
198
        L{JID}s compare equal if their user, host and resource parts all
 
199
        compare equal.  When comparing against instances of other types, it
 
200
        uses the default comparison.
 
201
        """
 
202
        if isinstance(other, JID):
 
203
            return (self.user == other.user and
 
204
                    self.host == other.host and
 
205
                    self.resource == other.resource)
 
206
        else:
 
207
            return NotImplemented
 
208
 
 
209
    def __ne__(self, other):
 
210
        """
 
211
        Inequality comparison.
 
212
 
 
213
        This negates L{__eq__} for comparison with JIDs and uses the default
 
214
        comparison for other types.
 
215
        """
 
216
        result = self.__eq__(other)
 
217
        if result is NotImplemented:
 
218
            return result
 
219
        else:
 
220
            return not result
 
221
 
 
222
    def __hash__(self):
 
223
        """
 
224
        Calculate hash.
 
225
 
 
226
        L{JID}s with identical constituent user, host and resource parts have
 
227
        equal hash values.  In combination with the comparison defined on JIDs,
 
228
        this allows for using L{JID}s in sets and as dictionary keys.
 
229
        """
 
230
        return hash((self.user, self.host, self.resource))
 
231
 
 
232
    def __unicode__(self):
 
233
        """
 
234
        Get unicode representation.
 
235
 
 
236
        Return the string representation of this JID as a unicode string.
 
237
        @see: L{full}
 
238
        """
 
239
 
 
240
        return self.full()
 
241
 
 
242
    def __repr__(self):
 
243
        """
 
244
        Get object representation.
 
245
 
 
246
        Returns a string that would create a new JID object that compares equal
 
247
        to this one.
 
248
        """
 
249
        return 'JID(%r)' % self.full()