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.
sems/apps/sbc/call_control/rest/RestParams.cpp

169 lines
3.9 KiB

#include "RestParams.h"
#include "log.h"
#include <curl/curl.h>
#include <map>
#include "jsonArg.h"
using namespace std;
static void trim_spaces(string &s)
{
size_t pos = s.find_last_not_of(" \t\r\n");
if (pos != string::npos) {
s.erase(pos + 1);
pos = s.find_first_not_of(' ');
if (pos != string::npos) s.erase(0, pos);
}
else s.erase(s.begin(), s.end());
}
static bool str2bool(const char *s)
{
if ((!s) || (!*s)) return true; // understand as just bool option which should be true
if (strcasecmp(s, "yes") == 0) return true;
if (strcasecmp(s, "true") == 0) return true;
if (strcmp(s, "1") == 0) return true;
return false;
}
////////////////////////////////////////////////////////////////////////////////
void RestParams::getIfSet(const char *param_name, string &dst)
{
if (params.hasMember(param_name)) {
const AmArg &a = params[param_name];
if (isArgCStr(a)) dst = a.asCStr();
}
}
void RestParams::getIfSet(const char *param_name, bool &dst)
{
if (params.hasMember(param_name)) {
const AmArg &a = params[param_name];
if (isArgCStr(a)) dst = str2bool(a.asCStr());
if (isArgBool(a)) dst = a.asBool();
}
}
void RestParams::handleParamLine(const string &line, size_t begin, size_t end)
{
size_t pos;
pos = line.find('=', begin);
if (pos == string::npos) return; // "=" not found, ignore this param
if (pos >= end) return; // "=" found on another line, ignore this param
string name(line.substr(begin, pos - begin));
string value(line.substr(pos + 1, end - pos));
trim_spaces(name);
trim_spaces(value);
if (name.size() > 0) {
DBG("REST: param %s='%s'\n", name.c_str(), value.c_str());
params.push(name, AmArg(value));
}
}
bool RestParams::readFromText(const string &data)
{
size_t first = 0;
size_t last;
params.assertStruct();
while (true) {
last = data.find('\n', first);
if (last == string::npos) {
handleParamLine(data, first, data.size());
break;
}
else handleParamLine(data, first, last);
first = last + 1;
}
string dbg = arg2json(params);
return true;
}
bool RestParams::readFromJson(const string &data)
{
return json2arg(data, params);
}
bool RestParams::readFromXML(const string &data)
{
// TODO
ERROR("REST: trying to decode XML data - not implemented yet!\n");
return false;
}
bool RestParams::retrieve(const string &url, Format fmt)
{
string data;
DBG("REST: reading from url %s\n", url.c_str());
if (!get(url, data)) return false;
switch (fmt) {
case TEXT: return readFromText(data);
case JSON: return readFromJson(data);
case XML: return readFromXML(data);
}
return false;
}
static size_t store_data_cb(void *contents, size_t size, size_t nmemb, void *userp)
{
size_t realsize = size * nmemb;
string &mem = *((string *)userp);
try {
if (realsize > 0) mem.append((char *)contents, realsize);
}
catch (...) {
ERROR("error while reading data from an URL\n");
return 0;
}
return realsize;
}
bool RestParams::get(const string &url, string &data)
{
// based on http://curl.haxx.se/libcurl/c/getinmemory.html
CURL *curl_handle = curl_easy_init();
data.clear();
if (!curl_handle) {
// this can't be ignored
throw string("curl_easy_init() failed\n");
}
curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, store_data_cb);
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&data);
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "REST-in-peace/0.1");
CURLcode res = curl_easy_perform(curl_handle);
long code = 0;
curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &code);
curl_easy_cleanup(curl_handle);
if (res != 0) {
// really ignore these errors?
DBG("libcurl returned error %d\n", res);
return false;
}
if ((code < 200) || (code > 299)) {
DBG("non-ok response code when downloading data: %ld\n", code);
return false;
}
return true;
}