~singpolyma/biboumi

ref: d600a2843f1dbe3b1ba2dead9a020cc73d7d10ae biboumi/src/xmpp/jid.cpp -rw-r--r-- 2.6 KiB
d600a284 — Florent Le Coz Remove all the libs that are now in louloulibs 8 years ago
                                                                                
bf7b05ef Florent Le Coz
b11126a1 Florent Le Coz
0ab5ecea Florent Le Coz
b11126a1 Florent Le Coz
d600a284 Florent Le Coz
b11126a1 Florent Le Coz
bf7b05ef Florent Le Coz
83219052 Emmanuel Gil Peyrot
bf7b05ef Florent Le Coz
83219052 Emmanuel Gil Peyrot
bf7b05ef Florent Le Coz
b11126a1 Florent Le Coz
0ab5ecea Florent Le Coz
b11126a1 Florent Le Coz
de7b3503 Florent Le Coz
0ab5ecea Florent Le Coz
de7b3503 Florent Le Coz
0ab5ecea Florent Le Coz
de7b3503 Florent Le Coz
b11126a1 Florent Le Coz
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include <xmpp/jid.hpp>
#include <cstring>
#include <map>

#include <louloulibs.h>
#ifdef LIBIDN_FOUND
 #include <stringprep.h>
#endif

#include <logger/logger.hpp>

Jid::Jid(const std::string& jid)
{
  std::string::size_type slash = jid.find('/');
  if (slash != std::string::npos)
    {
      this->resource = jid.substr(slash + 1);
    }

  std::string::size_type at = jid.find('@');
  if (at != std::string::npos && at < slash)
    {
      this->local = jid.substr(0, at);
      at++;
    }
  else
    at = 0;

  this->domain = jid.substr(at, slash - at);
}

#include <iostream>

static constexpr size_t max_jid_part_len = 1023;

std::string jidprep(const std::string& original)
{
#ifdef LIBIDN_FOUND
  using CacheType = std::map<std::string, std::string>;
  static CacheType cache;
  std::pair<CacheType::iterator, bool> cached = cache.insert({original, {}});
  if (std::get<1>(cached) == false)
    { // Insertion failed: the result is already in the cache, return it
      return std::get<0>(cached)->second;
    }

  const std::string error_msg("Failed to convert " + original + " into a valid JID:");
  Jid jid(original);

  char local[max_jid_part_len] = {};
  memcpy(local, jid.local.data(), jid.local.size());
  Stringprep_rc rc = static_cast<Stringprep_rc>(::stringprep(local, max_jid_part_len,
                     static_cast<Stringprep_profile_flags>(0), stringprep_xmpp_nodeprep));
  if (rc != STRINGPREP_OK)
  {
    log_error(error_msg + stringprep_strerror(rc));
    return "";
  }

  char domain[max_jid_part_len] = {};
  memcpy(domain, jid.domain.data(), jid.domain.size());
  rc = static_cast<Stringprep_rc>(::stringprep(domain, max_jid_part_len,
       static_cast<Stringprep_profile_flags>(0), stringprep_nameprep));
  if (rc != STRINGPREP_OK)
  {
    log_error(error_msg + stringprep_strerror(rc));
    return "";
  }

  // If there is no resource, stop here
  if (jid.resource.empty())
    {
      std::get<0>(cached)->second = std::string(local) + "@" + domain;
      return std::get<0>(cached)->second;
    }

  // Otherwise, also process the resource part
  char resource[max_jid_part_len] = {};
  memcpy(resource, jid.resource.data(), jid.resource.size());
  rc = static_cast<Stringprep_rc>(::stringprep(resource, max_jid_part_len,
       static_cast<Stringprep_profile_flags>(0), stringprep_xmpp_resourceprep));
  if (rc != STRINGPREP_OK)
    {
      log_error(error_msg + stringprep_strerror(rc));
      return "";
    }
  std::get<0>(cached)->second = std::string(local) + "@" + domain + "/" + resource;
  return std::get<0>(cached)->second;

#else
  (void)original;
  return "";
#endif
}