mirror of https://github.com/sipwise/sems.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
180 lines
4.0 KiB
180 lines
4.0 KiB
#include "arg_conversion.h"
|
|
#include "jsonArg.h"
|
|
#include "AmUtils.h"
|
|
|
|
using namespace std;
|
|
|
|
#define CSTR_LABEL 's'
|
|
#define ARRAY_LABEL 'a'
|
|
#define STRUCT_LABEL 'x'
|
|
|
|
static string arg2string(const AmArg &a)
|
|
{
|
|
string s;
|
|
char tmp[32];
|
|
const char *p;
|
|
|
|
switch (a.getType()) {
|
|
case AmArg::CStr:
|
|
p = a.asCStr();
|
|
sprintf(tmp, "%c%zd/", CSTR_LABEL, strlen(p));
|
|
s = tmp;
|
|
s += p;
|
|
return s;
|
|
|
|
case AmArg::Array:
|
|
sprintf(tmp, "%c%zd/", ARRAY_LABEL, a.size());
|
|
s = tmp;
|
|
for (size_t i = 0; i < a.size(); i ++) s += arg2string(a[i]);
|
|
return s;
|
|
|
|
case AmArg::Struct:
|
|
sprintf(tmp, "%c%zd/", STRUCT_LABEL, a.size());
|
|
s = tmp;
|
|
for (AmArg::ValueStruct::const_iterator it = a.asStruct()->begin();
|
|
it != a.asStruct()->end(); ++it) {
|
|
sprintf(tmp, "%zd/", it->first.size());
|
|
s += tmp;
|
|
s += it->first;
|
|
s += arg2string(it->second);
|
|
}
|
|
return s;
|
|
|
|
default:
|
|
throw string("arg2string not fully implenmented!");
|
|
}
|
|
|
|
return "???";
|
|
}
|
|
|
|
static bool read_len(const char *&src, int &len, int &dst)
|
|
{
|
|
int i;
|
|
dst = 0;
|
|
for (i = 0; i < len; i++) {
|
|
if ((src[i] >= '0') && (src[i] <= '9')) {
|
|
dst = 10 * dst + (src[i] - '0');
|
|
continue;
|
|
}
|
|
if (src[i] == '/') break;
|
|
return false; // not our length separator
|
|
}
|
|
if (i == len) return false; // separator is missing
|
|
if (i == 0) return false; // no number there
|
|
len -= i + 1;
|
|
src += i + 1;
|
|
return true;
|
|
}
|
|
|
|
static bool read_string(const char *&src, int &len, string &dst)
|
|
{
|
|
int l;
|
|
if (!read_len(src, len, l)) return false;
|
|
if (l <= len) {
|
|
dst.assign(src, l);
|
|
len -= l;
|
|
src += l;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static bool string2arg(const char *&src, int &len, AmArg &dst)
|
|
{
|
|
string s;
|
|
int cnt;
|
|
|
|
if (len < 1) return false;
|
|
|
|
switch (src[0]) {
|
|
|
|
case CSTR_LABEL:
|
|
if (!read_string(++src, --len, s)) return false;
|
|
dst = s;
|
|
return true;
|
|
|
|
case ARRAY_LABEL:
|
|
dst.assertArray();
|
|
if (!read_len(++src, --len, cnt)) return false;
|
|
for (int i = 0; i < cnt; i++) {
|
|
dst.push(AmArg());
|
|
if (!string2arg(src, len, dst.get(dst.size() - 1))) return false;
|
|
}
|
|
return true;
|
|
|
|
case STRUCT_LABEL:
|
|
dst.assertStruct();
|
|
if (!read_len(++src, --len, cnt)) return false;
|
|
for (int i = 0; i < cnt; i++) {
|
|
if (!read_string(src, len, s)) return false;
|
|
dst[s] = AmArg();
|
|
if (!string2arg(src, len, dst[s])) return false;
|
|
}
|
|
return true;
|
|
|
|
default:
|
|
DBG("unknown label '%c'\n", src[0]);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
#define ESCAPE_CHAR '?' // use % instead?
|
|
|
|
string arg2username(const AmArg &a)
|
|
{
|
|
string encoded = arg2string(a);
|
|
|
|
// encode the string using characters allowed in username
|
|
static const char *allowed =
|
|
"abcdefghijklmnopqrstuvwxyz"
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
"0123456789"
|
|
"-_.!~*'"
|
|
"&=+$,;/";
|
|
|
|
string res;
|
|
for (size_t i = 0; i < encoded.size(); i++) {
|
|
if (strchr(allowed, encoded[i])) res += encoded[i];
|
|
else {
|
|
res += ESCAPE_CHAR;
|
|
res += char2hex(encoded[i], true);
|
|
}
|
|
}
|
|
|
|
string json_vars = arg2json(a);
|
|
DBG("encoding variables: '%s'\n", json_vars.c_str());
|
|
DBG("encoded variables: '%s'\n", res.c_str());
|
|
|
|
return res;
|
|
}
|
|
|
|
bool username2arg(const string &src, AmArg &dst)
|
|
{
|
|
string encoded(src);
|
|
|
|
size_t pos = encoded.find(ESCAPE_CHAR);
|
|
while (pos != string::npos) {
|
|
if (pos + 2 >= encoded.size()) return false;
|
|
unsigned int c;
|
|
if (reverse_hex2int(string() + encoded[pos + 2] + encoded[pos + 1], c)) {
|
|
DBG("%c%c does not convert from hex\n", encoded[pos + 1], encoded[pos + 2]);
|
|
return false;
|
|
}
|
|
encoded.replace(pos, 3, 1, c);
|
|
pos = encoded.find(ESCAPE_CHAR, pos + 1);
|
|
}
|
|
|
|
DBG("encoded variables: '%s'\n", encoded.c_str());
|
|
|
|
const char *s = encoded.c_str();
|
|
int len = encoded.size();
|
|
bool res = string2arg(s, len, dst);
|
|
if (res) {
|
|
string json_vars = arg2json(dst);
|
|
DBG("decoded variables: '%s'\n", json_vars.c_str());
|
|
}
|
|
else DBG("decoding failed\n");
|
|
return res;
|
|
}
|