/*
 * libjingle
 * Copyright 2004--2005, Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "talk/xmpp/jid.h"

#include <ctype.h>

#include <algorithm>
#include <string>

#include "talk/xmpp/constants.h"
#include "webrtc/base/common.h"
#include "webrtc/base/logging.h"

namespace buzz {

Jid::Jid() {
}

Jid::Jid(const std::string& jid_string) {
  if (jid_string.empty())
    return;

  // First find the slash and slice off that part
  size_t slash = jid_string.find('/');
  resource_name_ = (slash == std::string::npos ? STR_EMPTY :
                    jid_string.substr(slash + 1));

  // Now look for the node
  size_t at = jid_string.find('@');
  size_t domain_begin;
  if (at < slash && at != std::string::npos) {
    node_name_ = jid_string.substr(0, at);
    domain_begin = at + 1;
  } else {
    domain_begin = 0;
  }

  // Now take what is left as the domain
  size_t domain_length = (slash == std::string::npos) ?
      (jid_string.length() - domain_begin) : (slash - domain_begin);
  domain_name_ = jid_string.substr(domain_begin, domain_length);

  ValidateOrReset();
}

Jid::Jid(const std::string& node_name,
         const std::string& domain_name,
         const std::string& resource_name)
    :  node_name_(node_name),
       domain_name_(domain_name),
       resource_name_(resource_name) {
  ValidateOrReset();
}

void Jid::ValidateOrReset() {
  bool valid_node;
  bool valid_domain;
  bool valid_resource;

  node_name_ = PrepNode(node_name_, &valid_node);
  domain_name_ = PrepDomain(domain_name_, &valid_domain);
  resource_name_ = PrepResource(resource_name_, &valid_resource);

  if (!valid_node || !valid_domain || !valid_resource) {
    node_name_.clear();
    domain_name_.clear();
    resource_name_.clear();
  }
}

std::string Jid::Str() const {
  if (!IsValid())
    return STR_EMPTY;

  std::string ret;

  if (!node_name_.empty())
    ret = node_name_ + "@";

  ASSERT(domain_name_ != STR_EMPTY);
  ret += domain_name_;

  if (!resource_name_.empty())
    ret += "/" + resource_name_;

  return ret;
}

Jid::~Jid() {
}

bool Jid::IsEmpty() const {
  return (node_name_.empty() && domain_name_.empty() &&
          resource_name_.empty());
}

bool Jid::IsValid() const {
  return !domain_name_.empty();
}

bool Jid::IsBare() const {
  if (IsEmpty()) {
    LOG(LS_VERBOSE) << "Warning: Calling IsBare() on the empty jid.";
    return true;
  }
  return IsValid() && resource_name_.empty();
}

bool Jid::IsFull() const {
  return IsValid() && !resource_name_.empty();
}

Jid Jid::BareJid() const {
  if (!IsValid())
    return Jid();
  if (!IsFull())
    return *this;
  return Jid(node_name_, domain_name_, STR_EMPTY);
}

bool Jid::BareEquals(const Jid& other) const {
  return other.node_name_ == node_name_ &&
      other.domain_name_ == domain_name_;
}

void Jid::CopyFrom(const Jid& jid) {
  this->node_name_ = jid.node_name_;
  this->domain_name_ = jid.domain_name_;
  this->resource_name_ = jid.resource_name_;
}

bool Jid::operator==(const Jid& other) const {
  return other.node_name_ == node_name_ &&
      other.domain_name_ == domain_name_ &&
      other.resource_name_ == resource_name_;
}

int Jid::Compare(const Jid& other) const {
  int compare_result;
  compare_result = node_name_.compare(other.node_name_);
  if (0 != compare_result)
    return compare_result;
  compare_result = domain_name_.compare(other.domain_name_);
  if (0 != compare_result)
    return compare_result;
  compare_result = resource_name_.compare(other.resource_name_);
  return compare_result;
}

// --- JID parsing code: ---

// Checks and normalizes the node part of a JID.
std::string Jid::PrepNode(const std::string& node, bool* valid) {
  *valid = false;
  std::string result;

  for (std::string::const_iterator i = node.begin(); i < node.end(); ++i) {
    bool char_valid = true;
    unsigned char ch = *i;
    if (ch <= 0x7F) {
      result += PrepNodeAscii(ch, &char_valid);
    }
    else {
      // TODO: implement the correct stringprep protocol for these
      result += tolower(ch);
    }
    if (!char_valid) {
      return STR_EMPTY;
    }
  }

  if (result.length() > 1023) {
    return STR_EMPTY;
  }
  *valid = true;
  return result;
}


// Returns the appropriate mapping for an ASCII character in a node.
char Jid::PrepNodeAscii(char ch, bool* valid) {
  *valid = true;
  switch (ch) {
    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
    case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
    case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
    case 'V': case 'W': case 'X': case 'Y': case 'Z':
      return (char)(ch + ('a' - 'A'));

    case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05:
    case 0x06: case 0x07: case 0x08: case 0x09: case 0x0A: case 0x0B:
    case 0x0C: case 0x0D: case 0x0E: case 0x0F: case 0x10: case 0x11:
    case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
    case ' ': case '&': case '/': case ':': case '<': case '>': case '@':
    case '\"': case '\'':
    case 0x7F:
      *valid = false;
      return 0;

    default:
      return ch;
  }
}


// Checks and normalizes the resource part of a JID.
std::string Jid::PrepResource(const std::string& resource, bool* valid) {
  *valid = false;
  std::string result;

  for (std::string::const_iterator i = resource.begin();
       i < resource.end(); ++i) {
    bool char_valid = true;
    unsigned char ch = *i;
    if (ch <= 0x7F) {
      result += PrepResourceAscii(ch, &char_valid);
    }
    else {
      // TODO: implement the correct stringprep protocol for these
      result += ch;
    }
  }

  if (result.length() > 1023) {
    return STR_EMPTY;
  }
  *valid = true;
  return result;
}

// Returns the appropriate mapping for an ASCII character in a resource.
char Jid::PrepResourceAscii(char ch, bool* valid) {
  *valid = true;
  switch (ch) {
    case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05:
    case 0x06: case 0x07: case 0x08: case 0x09: case 0x0A: case 0x0B:
    case 0x0C: case 0x0D: case 0x0E: case 0x0F: case 0x10: case 0x11:
    case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
    case 0x7F:
      *valid = false;
      return 0;

    default:
      return ch;
  }
}

// Checks and normalizes the domain part of a JID.
std::string Jid::PrepDomain(const std::string& domain, bool* valid) {
  *valid = false;
  std::string result;

  // TODO: if the domain contains a ':', then we should parse it
  // as an IPv6 address rather than giving an error about illegal domain.
  PrepDomain(domain, &result, valid);
  if (!*valid) {
    return STR_EMPTY;
  }

  if (result.length() > 1023) {
    return STR_EMPTY;
  }
  *valid = true;
  return result;
}


// Checks and normalizes an IDNA domain.
void Jid::PrepDomain(const std::string& domain, std::string* buf, bool* valid) {
  *valid = false;
  std::string::const_iterator last = domain.begin();
  for (std::string::const_iterator i = domain.begin(); i < domain.end(); ++i) {
    bool label_valid = true;
    char ch = *i;
    switch (ch) {
      case 0x002E:
#if 0 // FIX: This isn't UTF-8-aware.
      case 0x3002:
      case 0xFF0E:
      case 0xFF61:
#endif
        PrepDomainLabel(last, i, buf, &label_valid);
        *buf += '.';
        last = i + 1;
        break;
    }
    if (!label_valid) {
      return;
    }
  }
  PrepDomainLabel(last, domain.end(), buf, valid);
}

// Checks and normalizes a domain label.
void Jid::PrepDomainLabel(
    std::string::const_iterator start, std::string::const_iterator end,
    std::string* buf, bool* valid) {
  *valid = false;

  int start_len = static_cast<int>(buf->length());
  for (std::string::const_iterator i = start; i < end; ++i) {
    bool char_valid = true;
    unsigned char ch = *i;
    if (ch <= 0x7F) {
      *buf += PrepDomainLabelAscii(ch, &char_valid);
    }
    else {
      // TODO: implement ToASCII for these
      *buf += ch;
    }
    if (!char_valid) {
      return;
    }
  }

  int count = static_cast<int>(buf->length() - start_len);
  if (count == 0) {
    return;
  }
  else if (count > 63) {
    return;
  }

  // Is this check needed? See comment in PrepDomainLabelAscii.
  if ((*buf)[start_len] == '-') {
    return;
  }
  if ((*buf)[buf->length() - 1] == '-') {
    return;
  }
  *valid = true;
}


// Returns the appropriate mapping for an ASCII character in a domain label.
char Jid::PrepDomainLabelAscii(char ch, bool* valid) {
  *valid = true;
  // TODO: A literal reading of the spec seems to say that we do
  // not need to check for these illegal characters (an "internationalized
  // domain label" runs ToASCII with UseSTD3... set to false).  But that
  // can't be right.  We should at least be checking that there are no '/'
  // or '@' characters in the domain.  Perhaps we should see what others
  // do in this case.

  switch (ch) {
    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
    case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
    case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
    case 'V': case 'W': case 'X': case 'Y': case 'Z':
      return (char)(ch + ('a' - 'A'));

    case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05:
    case 0x06: case 0x07: case 0x08: case 0x09: case 0x0A: case 0x0B:
    case 0x0C: case 0x0D: case 0x0E: case 0x0F: case 0x10: case 0x11:
    case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
    case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D:
    case 0x1E: case 0x1F: case 0x20: case 0x21: case 0x22: case 0x23:
    case 0x24: case 0x25: case 0x26: case 0x27: case 0x28: case 0x29:
    case 0x2A: case 0x2B: case 0x2C: case 0x2E: case 0x2F: case 0x3A:
    case 0x3B: case 0x3C: case 0x3D: case 0x3E: case 0x3F: case 0x40:
    case 0x5B: case 0x5C: case 0x5D: case 0x5E: case 0x5F: case 0x60:
    case 0x7B: case 0x7C: case 0x7D: case 0x7E: case 0x7F:
      *valid = false;
      return 0;

    default:
      return ch;
  }
}

}  // namespace buzz
