1f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/*
2f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * libjingle
3f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Copyright 2004--2005, Google Inc.
4f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
5f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Redistribution and use in source and binary forms, with or without
6f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * modification, are permitted provided that the following conditions are met:
7f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
8f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  1. Redistributions of source code must retain the above copyright notice,
9f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     this list of conditions and the following disclaimer.
10f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  2. Redistributions in binary form must reproduce the above copyright notice,
11f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     this list of conditions and the following disclaimer in the documentation
12f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     and/or other materials provided with the distribution.
13f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  3. The name of the author may not be used to endorse or promote products
14f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     derived from this software without specific prior written permission.
15f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
16f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch */
27f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
28f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/xmpp/jid.h"
29f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
30f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <ctype.h>
31f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
32f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <algorithm>
33f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <string>
34f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
35f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/common.h"
36f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/logging.h"
37f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/xmpp/constants.h"
38f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
39f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochnamespace buzz {
40f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
41f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochJid::Jid() : data_(NULL) {
42f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
43f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
44f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochJid::Jid(bool is_special, const std::string & special) {
45f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  data_ = is_special ? new Data(special, STR_EMPTY, STR_EMPTY) : NULL;
46f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
47f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
48f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochJid::Jid(const std::string & jid_string) {
49f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (jid_string == STR_EMPTY) {
50f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    data_ = NULL;
51f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
52f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
53f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
54f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // First find the slash and slice of that part
55f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  size_t slash = jid_string.find('/');
56f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::string resource_name = (slash == std::string::npos ? STR_EMPTY :
57f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                    jid_string.substr(slash + 1));
58f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
59f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Now look for the node
60f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::string node_name;
61f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  size_t at = jid_string.find('@');
62f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  size_t domain_begin;
63f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (at < slash && at != std::string::npos) {
64f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    node_name = jid_string.substr(0, at);
65f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    domain_begin = at + 1;
66f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else {
67f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    domain_begin = 0;
68f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
69f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
70f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Now take what is left as the domain
71f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  size_t domain_length =
72f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    (  slash == std::string::npos
73f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch     ? jid_string.length() - domain_begin
74f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch     : slash - domain_begin);
75f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
76f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // avoid allocating these constants repeatedly
77f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::string domain_name;
78f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
79f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (domain_length == 9  && jid_string.find("gmail.com", domain_begin) == domain_begin) {
80f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    domain_name = STR_GMAIL_COM;
81f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
82f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  else if (domain_length == 14 && jid_string.find("googlemail.com", domain_begin) == domain_begin) {
83f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    domain_name = STR_GOOGLEMAIL_COM;
84f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
85f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  else if (domain_length == 10 && jid_string.find("google.com", domain_begin) == domain_begin) {
86f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    domain_name = STR_GOOGLE_COM;
87f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
88f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  else {
89f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    domain_name = jid_string.substr(domain_begin, domain_length);
90f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
91f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
92f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // If the domain is empty we have a non-valid jid and we should empty
93f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // everything else out
94f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (domain_name.empty()) {
95f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    data_ = NULL;
96f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
97f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
98f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
99f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool valid_node;
100f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::string validated_node = prepNode(node_name,
101f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      node_name.begin(), node_name.end(), &valid_node);
102f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool valid_domain;
103f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::string validated_domain = prepDomain(domain_name,
104f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      domain_name.begin(), domain_name.end(), &valid_domain);
105f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool valid_resource;
106f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::string validated_resource = prepResource(resource_name,
107f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      resource_name.begin(), resource_name.end(), &valid_resource);
108f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
109f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!valid_node || !valid_domain || !valid_resource) {
110f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    data_ = NULL;
111f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
112f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
113f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
114f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  data_ = new Data(validated_node, validated_domain, validated_resource);
115f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
116f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
117f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochJid::Jid(const std::string & node_name,
118f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch         const std::string & domain_name,
119f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch         const std::string & resource_name) {
120f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (domain_name.empty()) {
121f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    data_ = NULL;
122f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
123f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
124f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
125f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool valid_node;
126f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::string validated_node = prepNode(node_name,
127f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      node_name.begin(), node_name.end(), &valid_node);
128f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool valid_domain;
129f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::string validated_domain = prepDomain(domain_name,
130f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      domain_name.begin(), domain_name.end(), &valid_domain);
131f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool valid_resource;
132f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::string validated_resource = prepResource(resource_name,
133f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      resource_name.begin(), resource_name.end(), &valid_resource);
134f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
135f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!valid_node || !valid_domain || !valid_resource) {
136f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    data_ = NULL;
137f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
138f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
139f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
140f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  data_ = new Data(validated_node, validated_domain, validated_resource);
141f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
142f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
143f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstd::string Jid::Str() const {
144f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!IsValid())
145f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return STR_EMPTY;
146f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
147f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::string ret;
148f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
149f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!data_->node_name_.empty())
150f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ret = data_->node_name_ + "@";
151f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
152f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(data_->domain_name_ != STR_EMPTY);
153f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ret += data_->domain_name_;
154f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
155f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!data_->resource_name_.empty())
156f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ret += "/" + data_->resource_name_;
157f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
158f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return ret;
159f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
160f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
161f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool
162f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochJid::IsValid() const {
163f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return data_ != NULL && !data_->domain_name_.empty();
164f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
165f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
166f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool
167f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochJid::IsBare() const {
168f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (Compare(JID_EMPTY) == 0) {
169f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_VERBOSE) << "Warning: Calling IsBare() on the empty jid";
170f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return true;
171f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
172f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return IsValid() &&
173f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch         data_->resource_name_.empty();
174f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
175f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
176f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool
177f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochJid::IsFull() const {
178f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return IsValid() &&
179f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch         !data_->resource_name_.empty();
180f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
181f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
182f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochJid
183f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochJid::BareJid() const {
184f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!IsValid())
185f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return Jid();
186f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!IsFull())
187f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return *this;
188f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return Jid(data_->node_name_, data_->domain_name_, STR_EMPTY);
189f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
190f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
191f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if 0
192f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid
193f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochJid::set_node(const std::string & node_name) {
194f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    data_->node_name_ = node_name;
195f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
196f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid
197f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochJid::set_domain(const std::string & domain_name) {
198f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    data_->domain_name_ = domain_name;
199f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
200f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid
201f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochJid::set_resource(const std::string & res_name) {
202f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    data_->resource_name_ = res_name;
203f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
204f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
205f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
206f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool
207f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochJid::BareEquals(const Jid & other) const {
208f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return (other.data_ == data_ ||
209f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          (data_ != NULL &&
210f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          other.data_ != NULL &&
211f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          other.data_->node_name_ == data_->node_name_ &&
212f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          other.data_->domain_name_ == data_->domain_name_));
213f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
214f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
215f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool
216f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochJid::operator==(const Jid & other) const {
217f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return (other.data_ == data_ ||
218f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          (data_ != NULL &&
219f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          other.data_ != NULL &&
220f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          other.data_->node_name_ == data_->node_name_ &&
221f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          other.data_->domain_name_ == data_->domain_name_ &&
222f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          other.data_->resource_name_ == data_->resource_name_));
223f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
224f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
225f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint
226f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochJid::Compare(const Jid & other) const {
227f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (other.data_ == data_)
228f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return 0;
229f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (data_ == NULL)
230f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return -1;
231f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (other.data_ == NULL)
232f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return 1;
233f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
234f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int compare_result;
235f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  compare_result = data_->node_name_.compare(other.data_->node_name_);
236f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (0 != compare_result)
237f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return compare_result;
238f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  compare_result = data_->domain_name_.compare(other.data_->domain_name_);
239f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (0 != compare_result)
240f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return compare_result;
241f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  compare_result = data_->resource_name_.compare(other.data_->resource_name_);
242f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return compare_result;
243f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
244f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
245f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochuint32 Jid::ComputeLameHash() const {
246f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  uint32 hash = 0;
247f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Hash the node portion
248f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  {
249f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    const std::string &str = node();
250f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    for (int i = 0; i < static_cast<int>(str.size()); ++i) {
251f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      hash = ((hash << 2) + hash) + str[i];
252f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
253f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
254f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
255f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Hash the domain portion
256f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  {
257f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    const std::string &str = domain();
258f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    for (int i = 0; i < static_cast<int>(str.size()); ++i)
259f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      hash = ((hash << 2) + hash) + str[i];
260f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
261f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
262f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Hash the resource portion
263f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  {
264f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    const std::string &str = resource();
265f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    for (int i = 0; i < static_cast<int>(str.size()); ++i)
266f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      hash = ((hash << 2) + hash) + str[i];
267f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
268f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
269f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return hash;
270f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
271f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
272f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// --- JID parsing code: ---
273f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
274f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Checks and normalizes the node part of a JID.
275f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstd::string
276f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochJid::prepNode(const std::string str, std::string::const_iterator start,
277f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    std::string::const_iterator end, bool *valid) {
278f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  *valid = false;
279f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::string result;
280f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
281f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  for (std::string::const_iterator i = start; i < end; i++) {
282f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    bool char_valid = true;
283f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    unsigned char ch = *i;
284f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (ch <= 0x7F) {
285f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      result += prepNodeAscii(ch, &char_valid);
286f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
287f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    else {
288f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // TODO: implement the correct stringprep protocol for these
289f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      result += tolower(ch);
290f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
291f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!char_valid) {
292f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return STR_EMPTY;
293f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
294f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
295f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
296f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (result.length() > 1023) {
297f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return STR_EMPTY;
298f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
299f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  *valid = true;
300f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return result;
301f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
302f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
303f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
304f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Returns the appropriate mapping for an ASCII character in a node.
305f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochchar
306f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochJid::prepNodeAscii(char ch, bool *valid) {
307f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  *valid = true;
308f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  switch (ch) {
309f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
310f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
311f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
312f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 'V': case 'W': case 'X': case 'Y': case 'Z':
313f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return (char)(ch + ('a' - 'A'));
314f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
315f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05:
316f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 0x06: case 0x07: case 0x08: case 0x09: case 0x0A: case 0x0B:
317f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 0x0C: case 0x0D: case 0x0E: case 0x0F: case 0x10: case 0x11:
318f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
319f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case ' ': case '&': case '/': case ':': case '<': case '>': case '@':
320f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case '\"': case '\'':
321f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 0x7F:
322f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      *valid = false;
323f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return 0;
324f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
325f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    default:
326f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return ch;
327f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
328f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
329f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
330f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
331f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Checks and normalizes the resource part of a JID.
332f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstd::string
333f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochJid::prepResource(const std::string str, std::string::const_iterator start,
334f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    std::string::const_iterator end, bool *valid) {
335f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  *valid = false;
336f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::string result;
337f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
338f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  for (std::string::const_iterator i = start; i < end; i++) {
339f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    bool char_valid = true;
340f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    unsigned char ch = *i;
341f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (ch <= 0x7F) {
342f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      result += prepResourceAscii(ch, &char_valid);
343f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
344f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    else {
345f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // TODO: implement the correct stringprep protocol for these
346f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      result += ch;
347f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
348f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
349f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
350f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (result.length() > 1023) {
351f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return STR_EMPTY;
352f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
353f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  *valid = true;
354f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return result;
355f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
356f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
357f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Returns the appropriate mapping for an ASCII character in a resource.
358f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochchar
359f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochJid::prepResourceAscii(char ch, bool *valid) {
360f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  *valid = true;
361f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  switch (ch) {
362f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05:
363f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 0x06: case 0x07: case 0x08: case 0x09: case 0x0A: case 0x0B:
364f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 0x0C: case 0x0D: case 0x0E: case 0x0F: case 0x10: case 0x11:
365f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
366f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 0x7F:
367f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      *valid = false;
368f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return 0;
369f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
370f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    default:
371f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return ch;
372f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
373f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
374f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
375f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Checks and normalizes the domain part of a JID.
376f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstd::string
377f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochJid::prepDomain(const std::string str, std::string::const_iterator start,
378f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    std::string::const_iterator end, bool *valid) {
379f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  *valid = false;
380f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::string result;
381f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
382f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // TODO: if the domain contains a ':', then we should parse it
383f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // as an IPv6 address rather than giving an error about illegal domain.
384f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  prepDomain(str, start, end, &result, valid);
385f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!*valid) {
386f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return STR_EMPTY;
387f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
388f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
389f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (result.length() > 1023) {
390f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return STR_EMPTY;
391f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
392f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  *valid = true;
393f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return result;
394f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
395f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
396f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
397f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Checks and normalizes an IDNA domain.
398f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid
399f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochJid::prepDomain(const std::string str, std::string::const_iterator start,
400f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    std::string::const_iterator end, std::string *buf, bool *valid) {
401f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  *valid = false;
402f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::string::const_iterator last = start;
403f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  for (std::string::const_iterator i = start; i < end; i++) {
404f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    bool label_valid = true;
405f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    char ch = *i;
406f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    switch (ch) {
407f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      case 0x002E:
408f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if 0 // FIX: This isn't UTF-8-aware.
409f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      case 0x3002:
410f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      case 0xFF0E:
411f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      case 0xFF61:
412f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
413f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        prepDomainLabel(str, last, i, buf, &label_valid);
414f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        *buf += '.';
415f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        last = i + 1;
416f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        break;
417f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
418f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!label_valid) {
419f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return;
420f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
421f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
422f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  prepDomainLabel(str, last, end, buf, valid);
423f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
424f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
425f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Checks and normalizes a domain label.
426f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid
427f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochJid::prepDomainLabel(const std::string str, std::string::const_iterator start,
428f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    std::string::const_iterator end, std::string *buf, bool *valid) {
429f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  *valid = false;
430f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
431f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int startLen = buf->length();
432f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  for (std::string::const_iterator i = start; i < end; i++) {
433f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    bool char_valid = true;
434f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    unsigned char ch = *i;
435f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (ch <= 0x7F) {
436f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      *buf += prepDomainLabelAscii(ch, &char_valid);
437f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
438f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    else {
439f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // TODO: implement ToASCII for these
440f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      *buf += ch;
441f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
442f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!char_valid) {
443f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return;
444f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
445f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
446f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
447f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int count = buf->length() - startLen;
448f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (count == 0) {
449f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
450f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
451f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  else if (count > 63) {
452f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
453f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
454f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
455f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Is this check needed? See comment in prepDomainLabelAscii.
456f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if ((*buf)[startLen] == '-') {
457f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
458f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
459f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if ((*buf)[buf->length() - 1] == '-') {
460f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
461f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
462f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  *valid = true;
463f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
464f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
465f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
466f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Returns the appropriate mapping for an ASCII character in a domain label.
467f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochchar
468f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochJid::prepDomainLabelAscii(char ch, bool *valid) {
469f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  *valid = true;
470f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // TODO: A literal reading of the spec seems to say that we do
471f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // not need to check for these illegal characters (an "internationalized
472f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // domain label" runs ToASCII with UseSTD3... set to false).  But that
473f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // can't be right.  We should at least be checking that there are no '/'
474f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // or '@' characters in the domain.  Perhaps we should see what others
475f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // do in this case.
476f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
477f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  switch (ch) {
478f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
479f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
480f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
481f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 'V': case 'W': case 'X': case 'Y': case 'Z':
482f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return (char)(ch + ('a' - 'A'));
483f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
484f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05:
485f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 0x06: case 0x07: case 0x08: case 0x09: case 0x0A: case 0x0B:
486f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 0x0C: case 0x0D: case 0x0E: case 0x0F: case 0x10: case 0x11:
487f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
488f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D:
489f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 0x1E: case 0x1F: case 0x20: case 0x21: case 0x22: case 0x23:
490f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 0x24: case 0x25: case 0x26: case 0x27: case 0x28: case 0x29:
491f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 0x2A: case 0x2B: case 0x2C: case 0x2E: case 0x2F: case 0x3A:
492f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 0x3B: case 0x3C: case 0x3D: case 0x3E: case 0x3F: case 0x40:
493f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 0x5B: case 0x5C: case 0x5D: case 0x5E: case 0x5F: case 0x60:
494f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case 0x7B: case 0x7C: case 0x7D: case 0x7E: case 0x7F:
495f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      *valid = false;
496f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return 0;
497f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
498f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    default:
499f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return ch;
500f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
501f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
502f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
503f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
504