1 # -*- test-case-name: twisted.words.test.test_jabberjid -*-
3 # Copyright (c) Twisted Matrix Laboratories.
4 # See LICENSE for details.
7 Jabber Identifier support.
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>}.
14 from twisted.words.protocols.jabber.xmpp_stringprep import nodeprep, resourceprep, nameprep
16 class InvalidFormat(Exception):
18 The given string could not be parsed into a valid Jabber Identifier (JID).
23 Parse given JID string into its respective parts and apply stringprep.
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}.
37 # Search for delimiters
38 user_sep = jidstring.find("@")
39 res_sep = jidstring.find("/")
47 host = jidstring[0:res_sep]
48 resource = jidstring[res_sep + 1:] or None
52 user = jidstring[0:user_sep] or None
53 host = jidstring[user_sep + 1:]
55 if user_sep < res_sep:
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
61 # host/resource (with an @ in resource)
62 host = jidstring[0:res_sep]
63 resource = jidstring[res_sep + 1:] or None
65 return prep(user, host, resource)
67 def prep(user, host, resource):
69 Perform stringprep on all JID fragments.
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.
83 user = nodeprep.prepare(unicode(user))
85 raise InvalidFormat, "Invalid character in username"
90 raise InvalidFormat, "Server address required."
93 host = nameprep.prepare(unicode(host))
95 raise InvalidFormat, "Invalid character in hostname"
99 resource = resourceprep.prepare(unicode(resource))
101 raise InvalidFormat, "Invalid character in resource"
105 return (user, host, resource)
109 def internJID(jidstring):
116 if jidstring in __internJIDs:
117 return __internJIDs[jidstring]
120 __internJIDs[jidstring] = j
125 Represents a stringprep'd Jabber ID.
127 JID objects are hashable so they can be used in sets and as keys in
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.")
137 user, host, res = parse(str)
139 user, host, res = prep(*tuple)
147 Extract the bare JID as a unicode string.
149 A bare JID does not have a resource part, so this returns either
150 C{user@host} or just C{host}.
155 return u"%s@%s" % (self.user, self.host)
159 def userhostJID(self):
161 Extract the bare JID.
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}.
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}.
173 return internJID(self.userhost())
179 Return the string representation of this JID.
185 return u"%s@%s/%s" % (self.user, self.host, self.resource)
187 return u"%s@%s" % (self.user, self.host)
190 return u"%s/%s" % (self.host, self.resource)
194 def __eq__(self, other):
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.
202 if isinstance(other, JID):
203 return (self.user == other.user and
204 self.host == other.host and
205 self.resource == other.resource)
207 return NotImplemented
209 def __ne__(self, other):
211 Inequality comparison.
213 This negates L{__eq__} for comparison with JIDs and uses the default
214 comparison for other types.
216 result = self.__eq__(other)
217 if result is NotImplemented:
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.
230 return hash((self.user, self.host, self.resource))
232 def __unicode__(self):
234 Get unicode representation.
236 Return the string representation of this JID as a unicode string.
244 Get object representation.
246 Returns a string that would create a new JID object that compares equal
249 return 'JID(%r)' % self.full()