summaryrefslogtreecommitdiff
path: root/indra/llcommon/lluri.cpp
diff options
context:
space:
mode:
authorJames Cook <james@lindenlab.com>2007-01-02 08:33:20 +0000
committerJames Cook <james@lindenlab.com>2007-01-02 08:33:20 +0000
commit420b91db29485df39fd6e724e782c449158811cb (patch)
treeb471a94563af914d3ed3edd3e856d21cb1b69945 /indra/llcommon/lluri.cpp
Print done when done.
Diffstat (limited to 'indra/llcommon/lluri.cpp')
-rw-r--r--indra/llcommon/lluri.cpp579
1 files changed, 579 insertions, 0 deletions
diff --git a/indra/llcommon/lluri.cpp b/indra/llcommon/lluri.cpp
new file mode 100644
index 0000000000..1b66173399
--- /dev/null
+++ b/indra/llcommon/lluri.cpp
@@ -0,0 +1,579 @@
+/**
+ * @file lluri.cpp
+ * @author Phoenix
+ * @date 2006-02-08
+ * @brief Implementation of the LLURI class.
+ *
+ * Copyright (c) 2006-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "linden_common.h"
+#include "lluri.h"
+#include "llsd.h"
+
+// uric = reserved | unreserved | escaped
+// reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
+// unreserved = alphanum | mark
+// mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
+// escaped = "%" hex hex
+static const char* ESCAPED_CHARACTERS[256] =
+{
+ "%00", // 0
+ "%01", // 1
+ "%02", // 2
+ "%03", // 3
+ "%04", // 4
+ "%05", // 5
+ "%06", // 6
+ "%07", // 7
+ "%08", // 8
+ "%09", // 9
+ "%0a", // 10
+ "%0b", // 11
+ "%0c", // 12
+ "%0d", // 13
+ "%0e", // 14
+ "%0f", // 15
+ "%10", // 16
+ "%11", // 17
+ "%12", // 18
+ "%13", // 19
+ "%14", // 20
+ "%15", // 21
+ "%16", // 22
+ "%17", // 23
+ "%18", // 24
+ "%19", // 25
+ "%1a", // 26
+ "%1b", // 27
+ "%1c", // 28
+ "%1d", // 29
+ "%1e", // 30
+ "%1f", // 31
+ "%20", // 32
+ "!", // 33
+ "%22", // 34
+ "%23", // 35
+ "$", // 36
+ "%25", // 37
+ "&", // 38
+ "'", // 39
+ "(", // 40
+ ")", // 41
+ "*", // 42
+ "+", // 43
+ ",", // 44
+ "-", // 45
+ ".", // 46
+ "/", // 47
+ "0", // 48
+ "1", // 49
+ "2", // 50
+ "3", // 51
+ "4", // 52
+ "5", // 53
+ "6", // 54
+ "7", // 55
+ "8", // 56
+ "9", // 57
+ ":", // 58
+ ";", // 59
+ "%3c", // 60
+ "=", // 61
+ "%3e", // 62
+ "?", // 63
+ "@", // 64
+ "A", // 65
+ "B", // 66
+ "C", // 67
+ "D", // 68
+ "E", // 69
+ "F", // 70
+ "G", // 71
+ "H", // 72
+ "I", // 73
+ "J", // 74
+ "K", // 75
+ "L", // 76
+ "M", // 77
+ "N", // 78
+ "O", // 79
+ "P", // 80
+ "Q", // 81
+ "R", // 82
+ "S", // 83
+ "T", // 84
+ "U", // 85
+ "V", // 86
+ "W", // 87
+ "X", // 88
+ "Y", // 89
+ "Z", // 90
+ "%5b", // 91
+ "%5c", // 92
+ "%5d", // 93
+ "%5e", // 94
+ "_", // 95
+ "%60", // 96
+ "a", // 97
+ "b", // 98
+ "c", // 99
+ "d", // 100
+ "e", // 101
+ "f", // 102
+ "g", // 103
+ "h", // 104
+ "i", // 105
+ "j", // 106
+ "k", // 107
+ "l", // 108
+ "m", // 109
+ "n", // 110
+ "o", // 111
+ "p", // 112
+ "q", // 113
+ "r", // 114
+ "s", // 115
+ "t", // 116
+ "u", // 117
+ "v", // 118
+ "w", // 119
+ "x", // 120
+ "y", // 121
+ "z", // 122
+ "%7b", // 123
+ "%7c", // 124
+ "%7d", // 125
+ "~", // 126
+ "%7f", // 127
+ "%80", // 128
+ "%81", // 129
+ "%82", // 130
+ "%83", // 131
+ "%84", // 132
+ "%85", // 133
+ "%86", // 134
+ "%87", // 135
+ "%88", // 136
+ "%89", // 137
+ "%8a", // 138
+ "%8b", // 139
+ "%8c", // 140
+ "%8d", // 141
+ "%8e", // 142
+ "%8f", // 143
+ "%90", // 144
+ "%91", // 145
+ "%92", // 146
+ "%93", // 147
+ "%94", // 148
+ "%95", // 149
+ "%96", // 150
+ "%97", // 151
+ "%98", // 152
+ "%99", // 153
+ "%9a", // 154
+ "%9b", // 155
+ "%9c", // 156
+ "%9d", // 157
+ "%9e", // 158
+ "%9f", // 159
+ "%a0", // 160
+ "%a1", // 161
+ "%a2", // 162
+ "%a3", // 163
+ "%a4", // 164
+ "%a5", // 165
+ "%a6", // 166
+ "%a7", // 167
+ "%a8", // 168
+ "%a9", // 169
+ "%aa", // 170
+ "%ab", // 171
+ "%ac", // 172
+ "%ad", // 173
+ "%ae", // 174
+ "%af", // 175
+ "%b0", // 176
+ "%b1", // 177
+ "%b2", // 178
+ "%b3", // 179
+ "%b4", // 180
+ "%b5", // 181
+ "%b6", // 182
+ "%b7", // 183
+ "%b8", // 184
+ "%b9", // 185
+ "%ba", // 186
+ "%bb", // 187
+ "%bc", // 188
+ "%bd", // 189
+ "%be", // 190
+ "%bf", // 191
+ "%c0", // 192
+ "%c1", // 193
+ "%c2", // 194
+ "%c3", // 195
+ "%c4", // 196
+ "%c5", // 197
+ "%c6", // 198
+ "%c7", // 199
+ "%c8", // 200
+ "%c9", // 201
+ "%ca", // 202
+ "%cb", // 203
+ "%cc", // 204
+ "%cd", // 205
+ "%ce", // 206
+ "%cf", // 207
+ "%d0", // 208
+ "%d1", // 209
+ "%d2", // 210
+ "%d3", // 211
+ "%d4", // 212
+ "%d5", // 213
+ "%d6", // 214
+ "%d7", // 215
+ "%d8", // 216
+ "%d9", // 217
+ "%da", // 218
+ "%db", // 219
+ "%dc", // 220
+ "%dd", // 221
+ "%de", // 222
+ "%df", // 223
+ "%e0", // 224
+ "%e1", // 225
+ "%e2", // 226
+ "%e3", // 227
+ "%e4", // 228
+ "%e5", // 229
+ "%e6", // 230
+ "%e7", // 231
+ "%e8", // 232
+ "%e9", // 233
+ "%ea", // 234
+ "%eb", // 235
+ "%ec", // 236
+ "%ed", // 237
+ "%ee", // 238
+ "%ef", // 239
+ "%f0", // 240
+ "%f1", // 241
+ "%f2", // 242
+ "%f3", // 243
+ "%f4", // 244
+ "%f5", // 245
+ "%f6", // 246
+ "%f7", // 247
+ "%f8", // 248
+ "%f9", // 249
+ "%fa", // 250
+ "%fb", // 251
+ "%fc", // 252
+ "%fd", // 253
+ "%fe", // 254
+ "%ff" // 255
+};
+
+LLURI::LLURI()
+{
+}
+
+LLURI::LLURI(const std::string& escaped_str)
+{
+ std::string::size_type delim_pos, delim_pos2;
+ delim_pos = escaped_str.find(':');
+ std::string temp;
+ if (delim_pos == std::string::npos)
+ {
+ mScheme = "";
+ mEscapedOpaque = escaped_str;
+ }
+ else
+ {
+ mScheme = escaped_str.substr(0, delim_pos);
+ mEscapedOpaque = escaped_str.substr(delim_pos+1);
+ }
+
+ if (mScheme == "http" || mScheme == "https" || mScheme == "ftp")
+ {
+ if (mEscapedOpaque.substr(0,2) != "//")
+ {
+ return;
+ }
+
+ delim_pos = mEscapedOpaque.find('/', 2);
+ delim_pos2 = mEscapedOpaque.find('?', 2);
+ // no path, no query
+ if (delim_pos == std::string::npos &&
+ delim_pos2 == std::string::npos)
+ {
+ mEscapedAuthority = mEscapedOpaque.substr(2);
+ mEscapedPath = "";
+ }
+ // path exist, no query
+ else if (delim_pos2 == std::string::npos)
+ {
+ mEscapedAuthority = mEscapedOpaque.substr(2,delim_pos-2);
+ mEscapedPath = mEscapedOpaque.substr(delim_pos);
+ }
+ // no path, only query
+ else if (delim_pos == std::string::npos ||
+ delim_pos2 < delim_pos)
+ {
+ mEscapedAuthority = mEscapedOpaque.substr(2,delim_pos2-2);
+ // query part will be broken out later
+ mEscapedPath = mEscapedOpaque.substr(delim_pos2);
+ }
+ // path and query
+ else
+ {
+ mEscapedAuthority = mEscapedOpaque.substr(2,delim_pos-2);
+ // query part will be broken out later
+ mEscapedPath = mEscapedOpaque.substr(delim_pos);
+ }
+ }
+
+ delim_pos = mEscapedPath.find('?');
+ if (delim_pos != std::string::npos)
+ {
+ mEscapedQuery = mEscapedPath.substr(delim_pos+1);
+ mEscapedPath = mEscapedPath.substr(0,delim_pos);
+ }
+}
+
+LLURI::~LLURI()
+{
+}
+
+
+LLURI LLURI::buildHTTP(const std::string& host_port,
+ const LLSD& path)
+{
+ LLURI result;
+ result.mScheme = "HTTP";
+ // TODO: deal with '/' '?' '#' in host_port
+ result.mEscapedAuthority = "//" + escape(host_port);
+ if (path.isArray())
+ {
+ // break out and escape each path component
+ for (LLSD::array_const_iterator it = path.beginArray();
+ it != path.endArray();
+ ++it)
+ {
+ lldebugs << "PATH: inserting " << it->asString() << llendl;
+ result.mEscapedPath += "/" + escape(it->asString());
+ }
+ }
+ result.mEscapedOpaque = result.mEscapedAuthority +
+ result.mEscapedPath;
+ return result;
+}
+
+// static
+LLURI LLURI::buildHTTP(const std::string& host_port,
+ const LLSD& path,
+ const LLSD& query)
+{
+ LLURI result = buildHTTP(host_port, path);
+ // break out and escape each query component
+ if (query.isMap())
+ {
+ for (LLSD::map_const_iterator it = query.beginMap();
+ it != query.endMap();
+ it++)
+ {
+ result.mEscapedQuery += escape(it->first) +
+ (it->second.isUndefined() ? "" : "=" + it->second.asString()) +
+ "&";
+ }
+ if (query.size() > 0)
+ {
+ result.mEscapedOpaque += "?" + result.mEscapedQuery;
+ }
+ }
+ return result;
+}
+
+std::string LLURI::asString() const
+{
+ if (mScheme.empty())
+ {
+ return mEscapedOpaque;
+ }
+ else
+ {
+ return mScheme + ":" + mEscapedOpaque;
+ }
+}
+
+std::string LLURI::scheme() const
+{
+ return mScheme;
+}
+
+std::string LLURI::opaque() const
+{
+ return unescape(mEscapedOpaque);
+}
+
+std::string LLURI::authority() const
+{
+ return unescape(mEscapedAuthority);
+}
+
+
+namespace {
+ void findAuthorityParts(const std::string& authority,
+ std::string& user,
+ std::string& host,
+ std::string& port)
+ {
+ std::string::size_type start_pos = authority.find('@');
+ if (start_pos == std::string::npos)
+ {
+ user = "";
+ start_pos = 0;
+ }
+ else
+ {
+ user = authority.substr(0, start_pos);
+ start_pos += 1;
+ }
+
+ std::string::size_type end_pos = authority.find(':', start_pos);
+ if (end_pos == std::string::npos)
+ {
+ host = authority.substr(start_pos);
+ port = "";
+ }
+ else
+ {
+ host = authority.substr(start_pos, end_pos - start_pos);
+ port = authority.substr(end_pos + 1);
+ }
+ }
+}
+
+std::string LLURI::hostName() const
+{
+ std::string user, host, port;
+ findAuthorityParts(mEscapedAuthority, user, host, port);
+ return unescape(host);
+}
+
+U16 LLURI::hostPort() const
+{
+ std::string user, host, port;
+ findAuthorityParts(mEscapedAuthority, user, host, port);
+ if (port.empty())
+ {
+ if (mScheme == "http")
+ return 80;
+ if (mScheme == "https")
+ return 443;
+ if (mScheme == "ftp")
+ return 21;
+ return 0;
+ }
+ return atoi(port.c_str());
+}
+
+std::string LLURI::path() const
+{
+ return unescape(mEscapedPath);
+}
+
+std::string LLURI::query() const
+{
+ return unescape(mEscapedQuery);
+}
+
+LLSD LLURI::queryMap() const
+{
+ return queryMap(mEscapedQuery);
+}
+
+// static
+LLSD LLURI::queryMap(std::string escaped_query_string)
+{
+ lldebugs << "LLURI::queryMap query params: " << escaped_query_string << llendl;
+
+ LLSD result = LLSD::emptyArray();
+ while(!escaped_query_string.empty())
+ {
+ // get tuple first
+ std::string tuple;
+ std::string::size_type tuple_begin = escaped_query_string.find('&');
+ if (tuple_begin != std::string::npos)
+ {
+ tuple = escaped_query_string.substr(0, tuple_begin);
+ escaped_query_string = escaped_query_string.substr(tuple_begin+1);
+ }
+ else
+ {
+ tuple = escaped_query_string;
+ escaped_query_string = "";
+ }
+ if (tuple.empty()) continue;
+
+ // parse tuple
+ std::string::size_type key_end = tuple.find('=');
+ if (key_end != std::string::npos)
+ {
+ std::string key = unescape(tuple.substr(0,key_end));
+ std::string value = unescape(tuple.substr(key_end+1));
+ lldebugs << "inserting key " << key << " value " << value << llendl;
+ result[key] = value;
+ }
+ else
+ {
+ lldebugs << "inserting key " << unescape(tuple) << " value true" << llendl;
+ result[unescape(tuple)] = true;
+ }
+ }
+ return result;
+}
+
+// static
+std::string LLURI::escape(const std::string& str)
+{
+ std::ostringstream ostr;
+ std::string::const_iterator it = str.begin();
+ std::string::const_iterator end = str.end();
+ S32 c;
+ for(; it != end; ++it)
+ {
+ c = (S32)(*it);
+ ostr << ESCAPED_CHARACTERS[c];
+ }
+ return ostr.str();
+}
+
+// static
+std::string LLURI::unescape(const std::string& str)
+{
+ std::ostringstream ostr;
+ std::string::const_iterator it = str.begin();
+ std::string::const_iterator end = str.end();
+ for(; it != end; ++it)
+ {
+ if((*it) == '%')
+ {
+ ++it;
+ if(it == end) break;
+ U8 c = hex_as_nybble(*it++);
+ c = c << 4;
+ if (it == end) break;
+ c |= hex_as_nybble(*it);
+ ostr.put((char)c);
+ }
+ else
+ {
+ ostr.put(*it);
+ }
+ }
+ return ostr.str();
+}