1269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org/*
2269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *
4269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
5269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
6269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
7269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
8269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org */
10269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
11269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/libjingle/xmpp/jid.h"
12269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
13269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include <ctype.h>
14269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
15269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include <algorithm>
16269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include <string>
17269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
18269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/libjingle/xmpp/constants.h"
19269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/common.h"
20269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/logging.h"
21269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
22269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgnamespace buzz {
23269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
24269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgJid::Jid() {
25269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
26269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
27269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgJid::Jid(const std::string& jid_string) {
28269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (jid_string.empty())
29269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return;
30269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
31269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // First find the slash and slice off that part
32269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  size_t slash = jid_string.find('/');
33269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  resource_name_ = (slash == std::string::npos ? STR_EMPTY :
34269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                    jid_string.substr(slash + 1));
35269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
36269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Now look for the node
37269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  size_t at = jid_string.find('@');
38269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  size_t domain_begin;
39269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (at < slash && at != std::string::npos) {
40269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    node_name_ = jid_string.substr(0, at);
41269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    domain_begin = at + 1;
42269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  } else {
43269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    domain_begin = 0;
44269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
45269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
46269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Now take what is left as the domain
47269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  size_t domain_length = (slash == std::string::npos) ?
48269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      (jid_string.length() - domain_begin) : (slash - domain_begin);
49269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  domain_name_ = jid_string.substr(domain_begin, domain_length);
50269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
51269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ValidateOrReset();
52269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
53269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
54269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgJid::Jid(const std::string& node_name,
55269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org         const std::string& domain_name,
56269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org         const std::string& resource_name)
57269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    :  node_name_(node_name),
58269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org       domain_name_(domain_name),
59269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org       resource_name_(resource_name) {
60269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ValidateOrReset();
61269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
62269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
63269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid Jid::ValidateOrReset() {
64269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  bool valid_node;
65269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  bool valid_domain;
66269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  bool valid_resource;
67269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
68269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  node_name_ = PrepNode(node_name_, &valid_node);
69269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  domain_name_ = PrepDomain(domain_name_, &valid_domain);
70269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  resource_name_ = PrepResource(resource_name_, &valid_resource);
71269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
72269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (!valid_node || !valid_domain || !valid_resource) {
73269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    node_name_.clear();
74269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    domain_name_.clear();
75269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    resource_name_.clear();
76269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
77269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
78269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
79269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstd::string Jid::Str() const {
80269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (!IsValid())
81269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return STR_EMPTY;
82269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
83269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::string ret;
84269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
85269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (!node_name_.empty())
86269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ret = node_name_ + "@";
87269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
88269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT(domain_name_ != STR_EMPTY);
89269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ret += domain_name_;
90269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
91269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (!resource_name_.empty())
92269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ret += "/" + resource_name_;
93269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
94269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return ret;
95269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
96269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
97269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgJid::~Jid() {
98269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
99269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
100269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgbool Jid::IsEmpty() const {
101269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return (node_name_.empty() && domain_name_.empty() &&
102269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org          resource_name_.empty());
103269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
104269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
105269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgbool Jid::IsValid() const {
106269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return !domain_name_.empty();
107269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
108269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
109269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgbool Jid::IsBare() const {
110269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (IsEmpty()) {
111269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    LOG(LS_VERBOSE) << "Warning: Calling IsBare() on the empty jid.";
112269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return true;
113269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
114269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return IsValid() && resource_name_.empty();
115269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
116269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
117269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgbool Jid::IsFull() const {
118269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return IsValid() && !resource_name_.empty();
119269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
120269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
121269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgJid Jid::BareJid() const {
122269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (!IsValid())
123269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return Jid();
124269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (!IsFull())
125269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return *this;
126269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return Jid(node_name_, domain_name_, STR_EMPTY);
127269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
128269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
129269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgbool Jid::BareEquals(const Jid& other) const {
130269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return other.node_name_ == node_name_ &&
131269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      other.domain_name_ == domain_name_;
132269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
133269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
134269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid Jid::CopyFrom(const Jid& jid) {
135269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  this->node_name_ = jid.node_name_;
136269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  this->domain_name_ = jid.domain_name_;
137269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  this->resource_name_ = jid.resource_name_;
138269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
139269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
140269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgbool Jid::operator==(const Jid& other) const {
141269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return other.node_name_ == node_name_ &&
142269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      other.domain_name_ == domain_name_ &&
143269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      other.resource_name_ == resource_name_;
144269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
145269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
146269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgint Jid::Compare(const Jid& other) const {
147269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  int compare_result;
148269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  compare_result = node_name_.compare(other.node_name_);
149269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (0 != compare_result)
150269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return compare_result;
151269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  compare_result = domain_name_.compare(other.domain_name_);
152269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (0 != compare_result)
153269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return compare_result;
154269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  compare_result = resource_name_.compare(other.resource_name_);
155269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return compare_result;
156269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
157269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
158269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// --- JID parsing code: ---
159269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
160269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Checks and normalizes the node part of a JID.
161269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstd::string Jid::PrepNode(const std::string& node, bool* valid) {
162269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  *valid = false;
163269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::string result;
164269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
165269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  for (std::string::const_iterator i = node.begin(); i < node.end(); ++i) {
166269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    bool char_valid = true;
167269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    unsigned char ch = *i;
168269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (ch <= 0x7F) {
169269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      result += PrepNodeAscii(ch, &char_valid);
170269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
171269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    else {
172269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      // TODO: implement the correct stringprep protocol for these
173269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      result += tolower(ch);
174269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
175269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (!char_valid) {
176269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      return STR_EMPTY;
177269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
178269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
179269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
180269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (result.length() > 1023) {
181269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return STR_EMPTY;
182269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
183269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  *valid = true;
184269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return result;
185269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
186269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
187269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
188269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Returns the appropriate mapping for an ASCII character in a node.
189269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgchar Jid::PrepNodeAscii(char ch, bool* valid) {
190269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  *valid = true;
191269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  switch (ch) {
192269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
193269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
194269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
195269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 'V': case 'W': case 'X': case 'Y': case 'Z':
196269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      return (char)(ch + ('a' - 'A'));
197269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
198269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05:
199269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 0x06: case 0x07: case 0x08: case 0x09: case 0x0A: case 0x0B:
200269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 0x0C: case 0x0D: case 0x0E: case 0x0F: case 0x10: case 0x11:
201269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
202269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case ' ': case '&': case '/': case ':': case '<': case '>': case '@':
203269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case '\"': case '\'':
204269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 0x7F:
205269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      *valid = false;
206269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      return 0;
207269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
208269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    default:
209269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      return ch;
210269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
211269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
212269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
213269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
214269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Checks and normalizes the resource part of a JID.
215269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstd::string Jid::PrepResource(const std::string& resource, bool* valid) {
216269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  *valid = false;
217269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::string result;
218269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
219269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  for (std::string::const_iterator i = resource.begin();
220269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org       i < resource.end(); ++i) {
221269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    bool char_valid = true;
222269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    unsigned char ch = *i;
223269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (ch <= 0x7F) {
224269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      result += PrepResourceAscii(ch, &char_valid);
225269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
226269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    else {
227269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      // TODO: implement the correct stringprep protocol for these
228269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      result += ch;
229269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
230269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
231269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
232269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (result.length() > 1023) {
233269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return STR_EMPTY;
234269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
235269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  *valid = true;
236269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return result;
237269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
238269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
239269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Returns the appropriate mapping for an ASCII character in a resource.
240269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgchar Jid::PrepResourceAscii(char ch, bool* valid) {
241269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  *valid = true;
242269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  switch (ch) {
243269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05:
244269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 0x06: case 0x07: case 0x08: case 0x09: case 0x0A: case 0x0B:
245269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 0x0C: case 0x0D: case 0x0E: case 0x0F: case 0x10: case 0x11:
246269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
247269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 0x7F:
248269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      *valid = false;
249269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      return 0;
250269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
251269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    default:
252269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      return ch;
253269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
254269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
255269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
256269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Checks and normalizes the domain part of a JID.
257269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstd::string Jid::PrepDomain(const std::string& domain, bool* valid) {
258269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  *valid = false;
259269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::string result;
260269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
261269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // TODO: if the domain contains a ':', then we should parse it
262269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // as an IPv6 address rather than giving an error about illegal domain.
263269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  PrepDomain(domain, &result, valid);
264269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (!*valid) {
265269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return STR_EMPTY;
266269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
267269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
268269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (result.length() > 1023) {
269269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return STR_EMPTY;
270269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
271269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  *valid = true;
272269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return result;
273269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
274269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
275269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
276269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Checks and normalizes an IDNA domain.
277269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid Jid::PrepDomain(const std::string& domain, std::string* buf, bool* valid) {
278269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  *valid = false;
279269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::string::const_iterator last = domain.begin();
280269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  for (std::string::const_iterator i = domain.begin(); i < domain.end(); ++i) {
281269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    bool label_valid = true;
282269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    char ch = *i;
283269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    switch (ch) {
284269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      case 0x002E:
285269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#if 0 // FIX: This isn't UTF-8-aware.
286269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      case 0x3002:
287269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      case 0xFF0E:
288269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      case 0xFF61:
289269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#endif
290269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        PrepDomainLabel(last, i, buf, &label_valid);
291269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        *buf += '.';
292269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        last = i + 1;
293269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        break;
294269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
295269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (!label_valid) {
296269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      return;
297269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
298269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
299269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  PrepDomainLabel(last, domain.end(), buf, valid);
300269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
301269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
302269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Checks and normalizes a domain label.
303269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid Jid::PrepDomainLabel(
304269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    std::string::const_iterator start, std::string::const_iterator end,
305269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    std::string* buf, bool* valid) {
306269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  *valid = false;
307269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
308269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  int start_len = static_cast<int>(buf->length());
309269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  for (std::string::const_iterator i = start; i < end; ++i) {
310269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    bool char_valid = true;
311269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    unsigned char ch = *i;
312269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (ch <= 0x7F) {
313269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      *buf += PrepDomainLabelAscii(ch, &char_valid);
314269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
315269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    else {
316269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      // TODO: implement ToASCII for these
317269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      *buf += ch;
318269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
319269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (!char_valid) {
320269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      return;
321269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
322269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
323269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
324269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  int count = static_cast<int>(buf->length() - start_len);
325269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (count == 0) {
326269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return;
327269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
328269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  else if (count > 63) {
329269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return;
330269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
331269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
332269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Is this check needed? See comment in PrepDomainLabelAscii.
333269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if ((*buf)[start_len] == '-') {
334269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return;
335269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
336269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if ((*buf)[buf->length() - 1] == '-') {
337269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return;
338269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
339269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  *valid = true;
340269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
341269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
342269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
343269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Returns the appropriate mapping for an ASCII character in a domain label.
344269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgchar Jid::PrepDomainLabelAscii(char ch, bool* valid) {
345269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  *valid = true;
346269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // TODO: A literal reading of the spec seems to say that we do
347269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // not need to check for these illegal characters (an "internationalized
348269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // domain label" runs ToASCII with UseSTD3... set to false).  But that
349269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // can't be right.  We should at least be checking that there are no '/'
350269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // or '@' characters in the domain.  Perhaps we should see what others
351269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // do in this case.
352269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
353269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  switch (ch) {
354269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
355269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
356269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
357269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 'V': case 'W': case 'X': case 'Y': case 'Z':
358269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      return (char)(ch + ('a' - 'A'));
359269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
360269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05:
361269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 0x06: case 0x07: case 0x08: case 0x09: case 0x0A: case 0x0B:
362269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 0x0C: case 0x0D: case 0x0E: case 0x0F: case 0x10: case 0x11:
363269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
364269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D:
365269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 0x1E: case 0x1F: case 0x20: case 0x21: case 0x22: case 0x23:
366269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 0x24: case 0x25: case 0x26: case 0x27: case 0x28: case 0x29:
367269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 0x2A: case 0x2B: case 0x2C: case 0x2E: case 0x2F: case 0x3A:
368269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 0x3B: case 0x3C: case 0x3D: case 0x3E: case 0x3F: case 0x40:
369269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 0x5B: case 0x5C: case 0x5D: case 0x5E: case 0x5F: case 0x60:
370269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case 0x7B: case 0x7C: case 0x7D: case 0x7E: case 0x7F:
371269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      *valid = false;
372269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      return 0;
373269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
374269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    default:
375269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      return ch;
376269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
377269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
378269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
379269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}  // namespace buzz
380