201 lines
5.2 KiB
Ucode
201 lines
5.2 KiB
Ucode
#!/usr/bin/env ucode
|
|
|
|
let common = require("core.common");
|
|
|
|
let as_string = common.as_string;
|
|
|
|
function str_last_index(value, needle) {
|
|
value = as_string(value);
|
|
needle = as_string(needle);
|
|
if (needle == "")
|
|
return length(value);
|
|
|
|
for (let i = length(value) - length(needle); i >= 0; i--)
|
|
if (substr(value, i, length(needle)) == needle)
|
|
return i;
|
|
|
|
return -1;
|
|
}
|
|
|
|
function first_index_any(value, needles, start) {
|
|
value = as_string(value);
|
|
start = int(start || 0);
|
|
|
|
for (let i = start; i < length(value); i++) {
|
|
let c = substr(value, i, 1);
|
|
for (let needle in needles)
|
|
if (c == needle)
|
|
return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
function hex_digit_value(value) {
|
|
value = ord(lc(as_string(value)));
|
|
if (value >= 48 && value <= 57)
|
|
return value - 48;
|
|
if (value >= 97 && value <= 102)
|
|
return value - 87;
|
|
return -1;
|
|
}
|
|
|
|
function decode(value) {
|
|
value = as_string(value);
|
|
let result = "";
|
|
|
|
for (let i = 0; i < length(value); i++) {
|
|
let c = substr(value, i, 1);
|
|
if (c == "+") {
|
|
result += " ";
|
|
continue;
|
|
}
|
|
if (c == "%") {
|
|
let high = i + 1 < length(value) ? hex_digit_value(substr(value, i + 1, 1)) : -1;
|
|
let low = i + 2 < length(value) ? hex_digit_value(substr(value, i + 2, 1)) : -1;
|
|
if (high >= 0 && low >= 0) {
|
|
result += chr(high * 16 + low);
|
|
i += 2;
|
|
continue;
|
|
}
|
|
}
|
|
result += c;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
function scheme(value) {
|
|
value = as_string(value);
|
|
let marker = index(value, "://");
|
|
return marker >= 0 ? lc(substr(value, 0, marker)) : "";
|
|
}
|
|
|
|
function fragment(value) {
|
|
value = as_string(value);
|
|
let marker = index(value, "#");
|
|
return marker >= 0 ? decode(substr(value, marker + 1)) : "";
|
|
}
|
|
|
|
function strip_fragment(value) {
|
|
value = as_string(value);
|
|
let marker = index(value, "#");
|
|
return marker >= 0 ? substr(value, 0, marker) : value;
|
|
}
|
|
|
|
function strip_anchored_scheme(value) {
|
|
value = as_string(value);
|
|
let marker = index(value, "://");
|
|
if (marker < 0)
|
|
return value;
|
|
|
|
let prefix = substr(value, 0, marker);
|
|
if (index(prefix, "/") >= 0 || index(prefix, "?") >= 0)
|
|
return value;
|
|
|
|
return substr(value, marker + 3);
|
|
}
|
|
|
|
function strip_first_scheme_marker(value) {
|
|
value = as_string(value);
|
|
let marker = index(value, "://");
|
|
return marker >= 0 ? substr(value, marker + 3) : value;
|
|
}
|
|
|
|
function authority(value) {
|
|
value = strip_first_scheme_marker(value);
|
|
let at = str_last_index(value, "@");
|
|
if (at >= 0)
|
|
value = substr(value, at + 1);
|
|
|
|
let end = first_index_any(value, ["/", "?", "#"], 0);
|
|
return end >= 0 ? substr(value, 0, end) : value;
|
|
}
|
|
|
|
function host(value) {
|
|
let value_authority = authority(value);
|
|
if (substr(value_authority, 0, 1) == "[") {
|
|
let end = index(value_authority, "]");
|
|
return end > 0 ? substr(value_authority, 1, end - 1) : value_authority;
|
|
}
|
|
|
|
let colon = index(value_authority, ":");
|
|
if (colon < 0)
|
|
return value_authority;
|
|
|
|
return str_last_index(value_authority, ":") == colon ? substr(value_authority, 0, colon) : value_authority;
|
|
}
|
|
|
|
function port(value) {
|
|
let value_authority = authority(value);
|
|
if (substr(value_authority, 0, 1) == "[") {
|
|
let end = index(value_authority, "]");
|
|
if (end > 0 && substr(value_authority, end + 1, 1) == ":")
|
|
return substr(value_authority, end + 2);
|
|
return "";
|
|
}
|
|
|
|
let colon = index(value_authority, ":");
|
|
if (colon < 0 || str_last_index(value_authority, ":") != colon)
|
|
return "";
|
|
|
|
return substr(value_authority, colon + 1);
|
|
}
|
|
|
|
function userinfo(value) {
|
|
let value_authority = strip_first_scheme_marker(strip_fragment(value));
|
|
let end = first_index_any(value_authority, ["/", "?", "#"], 0);
|
|
value_authority = end >= 0 ? substr(value_authority, 0, end) : value_authority;
|
|
let at = str_last_index(value_authority, "@");
|
|
return at >= 0 ? decode(substr(value_authority, 0, at)) : "";
|
|
}
|
|
|
|
function path(value) {
|
|
value = strip_anchored_scheme(value);
|
|
let slash = index(value, "/");
|
|
value = slash >= 0 ? substr(value, slash) : "";
|
|
|
|
let query = index(value, "?");
|
|
if (query >= 0)
|
|
value = substr(value, 0, query);
|
|
|
|
return value;
|
|
}
|
|
|
|
function query_params(value) {
|
|
let result = {};
|
|
value = as_string(value);
|
|
let question = index(value, "?");
|
|
if (question < 0)
|
|
return result;
|
|
|
|
let query = substr(value, question + 1);
|
|
let hash = index(query, "#");
|
|
if (hash >= 0)
|
|
query = substr(query, 0, hash);
|
|
|
|
for (let pair in split(query, "&")) {
|
|
if (pair == "")
|
|
continue;
|
|
let equals = index(pair, "=");
|
|
let key = decode(equals >= 0 ? substr(pair, 0, equals) : pair);
|
|
let value = equals >= 0 ? decode(substr(pair, equals + 1)) : "";
|
|
if (key != "")
|
|
result[key] = value;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
return {
|
|
decode,
|
|
scheme,
|
|
fragment,
|
|
strip_fragment,
|
|
strip_anchored_scheme,
|
|
host,
|
|
port,
|
|
userinfo,
|
|
path,
|
|
query_params
|
|
};
|