| 1 |
/* |
| 2 |
* Copyright (C) 2010-2012 TSUBAKIMOTO Hiroya <z0rac@users.sourceforge.jp> |
| 3 |
* |
| 4 |
* This software comes with ABSOLUTELY NO WARRANTY; for details of |
| 5 |
* the license terms, see the LICENSE.txt file included with the program. |
| 6 |
*/ |
| 7 |
#include "mailbox.h" |
| 8 |
#include "win32.h" |
| 9 |
#include <cassert> |
| 10 |
#include <cstdlib> |
| 11 |
#include <cstring> |
| 12 |
|
| 13 |
#ifdef _DEBUG |
| 14 |
#include <iostream> |
| 15 |
#define DBG(s) s |
| 16 |
#define LOG(s) (cout << s) |
| 17 |
#else |
| 18 |
#define DBG(s) |
| 19 |
#define LOG(s) |
| 20 |
#endif |
| 21 |
|
| 22 |
/* |
| 23 |
* Functions of the class uri |
| 24 |
*/ |
| 25 |
namespace { |
| 26 |
string::size_type find(const string& s, |
| 27 |
string::value_type c, string::size_type i = 0) |
| 28 |
{ |
| 29 |
while (i < s.size()) { |
| 30 |
if (s[i] == c) return i; |
| 31 |
i += (i + 1 < s.size() && IsDBCSLeadByte(BYTE(s[i]))) + 1; |
| 32 |
} |
| 33 |
return string::npos; |
| 34 |
} |
| 35 |
|
| 36 |
string decode(const string& s) |
| 37 |
{ |
| 38 |
string result; |
| 39 |
string::size_type i = 0; |
| 40 |
while (i < s.size()) { |
| 41 |
string::size_type n = find(s, '%', i); |
| 42 |
if (n == string::npos || s.size() - n < 3) break; |
| 43 |
result.append(s, i, n - i); |
| 44 |
char hex[3] = { s[n + 1], s[n + 2] }; |
| 45 |
char* e; |
| 46 |
char c = char(strtoul(hex, &e, 16)); |
| 47 |
i = n + (*e ? (c = '%', 1) : 3); |
| 48 |
result.push_back(c); |
| 49 |
} |
| 50 |
if (i < s.size()) result.append(s.c_str() + i); |
| 51 |
return result; |
| 52 |
} |
| 53 |
|
| 54 |
string encode(const string& s, const char* chs) |
| 55 |
{ |
| 56 |
string result; |
| 57 |
string::size_type i = 0; |
| 58 |
while (i < s.size()) { |
| 59 |
const char* const t = s.c_str(); |
| 60 |
const char* p = t + i; |
| 61 |
while (BYTE(*p) > 32) { |
| 62 |
string::size_type n = |
| 63 |
IsDBCSLeadByte(BYTE(*p)) ? (p[1] != 0) * 2 : !strchr(chs, *p); |
| 64 |
p += n; |
| 65 |
if (n == 0) break; |
| 66 |
} |
| 67 |
if (!*p) break; |
| 68 |
string::size_type n = p - t; |
| 69 |
result.append(s, i, n - i); |
| 70 |
char hex[4] = { '%' }; |
| 71 |
_ltoa(s[n] & 255, hex + 1, 16); |
| 72 |
result.append(hex); |
| 73 |
i = n + 1; |
| 74 |
} |
| 75 |
if (i < s.size()) result.append(s.c_str() + i); |
| 76 |
return result; |
| 77 |
} |
| 78 |
} |
| 79 |
|
| 80 |
uri::uri(const string& uri) |
| 81 |
{ |
| 82 |
string::size_type i = find(uri, '#'); |
| 83 |
if (i != string::npos) _part[fragment] = decode(uri.substr(i + 1)); |
| 84 |
|
| 85 |
string t(uri, 0, min(find(uri, '?'), i)); |
| 86 |
i = find(t, ':'); |
| 87 |
for (; i != string::npos; i = find(t, ':', i)) { |
| 88 |
if (++i == t.size() || t[i] != '/') continue; |
| 89 |
if (++i == t.size() || t[i] != '/') continue; |
| 90 |
_part[scheme] = decode(t.substr(0, i - 2)); |
| 91 |
t.erase(0, i + 1); |
| 92 |
break; |
| 93 |
} |
| 94 |
i = find(t, '/'); |
| 95 |
if (i != string::npos) { |
| 96 |
_part[path] = decode(t.substr(i + 1)); |
| 97 |
t.erase(i); |
| 98 |
} |
| 99 |
i = find(t, '@'); |
| 100 |
if (i != string::npos) { |
| 101 |
_part[user] = decode(t.substr(0, min(find(t, ';'), i))); |
| 102 |
t.erase(0, i + 1); |
| 103 |
} |
| 104 |
i = find(t, ':'); |
| 105 |
for (; i != string::npos; i = find(t, ':', i)) { |
| 106 |
string::size_type n = i; |
| 107 |
while (++i < t.size() && strchr("0123456789", t[i])) continue; |
| 108 |
if (i < t.size()) continue; |
| 109 |
_part[port] = t.substr(n + 1); |
| 110 |
t.erase(n); |
| 111 |
} |
| 112 |
_part[host] = decode(t); |
| 113 |
} |
| 114 |
|
| 115 |
uri::operator string() const |
| 116 |
{ |
| 117 |
string uri = encode(_part[scheme], "#%") + "://"; |
| 118 |
if (!_part[host].empty()) { |
| 119 |
if (!_part[user].empty()) uri += encode(_part[user], "@/#%") + '@'; |
| 120 |
const string& h = _part[host]; |
| 121 |
uri += encode(h, *h.begin() == '[' && *h.rbegin() == ']' ? "/#%" : ":/#%"); |
| 122 |
if (!_part[port].empty()) uri += ':' + _part[port]; |
| 123 |
} |
| 124 |
uri += '/' + encode(_part[path], "#%"); |
| 125 |
if (!_part[fragment].empty()) uri += '#' + encode(_part[fragment], "%"); |
| 126 |
return uri; |
| 127 |
} |