/*! * (C) Copyright 2003-2017 Awox SA. All rights reserved. * This work contains confidential trade secrets of Awox. * Use, examination, copying, transfer and disclosure to others * are prohibited, except with the express written agreement of Awox. * * @Author: Awox * @Date: 30/06/2017 */ /*------------------------------- INCLUDES ----------------------------------*/ extern "C" { #include } #include #include #include "core/uri-transform.h" #include "http-parameter.h" #define kIfNoneMatch "if-none-match" #define kPrefer "prefer" #define kOrigin "origin" /*! ---------------------------------------------------------------------------- * @fn HttpParameter * * @brief constructor of the http parameter. */ HttpParameter::HttpParameter (void) : m_request_timeout(-1) { } /*! ---------------------------------------------------------------------------- * @fn parse_from_uri * * @brief parse parameters from the uri. */ std::string HttpParameter::parse_from_uri (const std::string &a_parameters) { std::string the_result; std::vector the_list; std::vector::iterator the_it; std::string the_key, the_value, the_value_decoded; std::size_t the_pos; struct json_object *the_root_node = NULL; the_root_node = json_object_new_object(); the_list = split_params(a_parameters, '&'); for (the_it = the_list.begin(); the_it != the_list.end(); ++the_it) { // printf("--> %s\n", (*the_it).c_str()); the_pos = (*the_it).find_first_of("=", 0); if (the_pos != std::string::npos) { the_key = (*the_it).substr(0, the_pos); the_value = (*the_it).substr(the_pos + 1); the_value_decoded = UriTransform::decode(the_value); #if 0 printf(" - key = %s\n", the_key.c_str()); printf(" - value = %s\n", the_value.c_str()); printf(" - valuedecode = %s\n", the_value_decoded.c_str()); #endif if (is_number(the_value_decoded)) json_object_object_add(the_root_node, the_key.c_str(), json_object_new_int(std::stoi(the_value_decoded))); else if (the_value_decoded == "true") json_object_object_add(the_root_node, the_key.c_str(), json_object_new_boolean(true)); else if (the_value_decoded == "false") json_object_object_add(the_root_node, the_key.c_str(), json_object_new_boolean(false)); else json_object_object_add(the_root_node, the_key.c_str(), json_object_new_string(the_value_decoded.c_str())); } } the_result = json_object_to_json_string(the_root_node); // Clean the json object. json_object_put(the_root_node); return the_result; } /*! ---------------------------------------------------------------------------- * @fn parse * * @brief parse the http header and save only the wanted headers. */ bool HttpParameter::parse (client *a_client) { std::string the_prefer_string; char *the_string = blobmsg_format_json(a_client->hdr.head, true); struct json_object *the_root_node = NULL, *the_value_node; the_root_node = json_tokener_parse(the_string); // printf("HttpParameter::parse: <%s>\n", the_string); free(the_string); if (the_root_node == NULL) { return false; } // Get if-none-match if (json_object_object_get_ex(the_root_node, kIfNoneMatch, &the_value_node)) { m_etag = json_object_get_string(the_value_node); } // Get Prefer - wait RFC 7240 // Prefer: wait=120 if (json_object_object_get_ex(the_root_node, kPrefer, &the_value_node)) { std::vector the_list; the_prefer_string = json_object_get_string(the_value_node); the_list = split_params(the_prefer_string, '='); std::string the_token = the_list [1]; //printf("the_prefer_string: %s\n", the_prefer_string.c_str()); //printf("the_token: %s\n", the_token.c_str()); if (is_number(the_token)) { m_request_timeout = std::atoi(the_token.c_str()); } // printf("timeout = %d\n", m_request_timeout); } // Get Origin if (json_object_object_get_ex(the_root_node, kOrigin, &the_value_node)) { m_origin = json_object_get_string(the_value_node); } json_object_put(the_root_node); // printf("parse: E-tag: %s, timeout: %d, origin: %s\n", m_etag.c_str(), m_request_timeout, m_origin.c_str()); return true; } /*! ---------------------------------------------------------------------------- * @fn get_origin * * @brief get the etag from the header request. */ std::string HttpParameter::get_origin (void) { return m_origin; } /*! ---------------------------------------------------------------------------- * @fn get_etag * * @brief get the etag from the header request. */ std::string HttpParameter::get_etag (void) { return m_etag; } /*! ---------------------------------------------------------------------------- * @fn get_request_timeout * * @brief extract the the keep-alive timeout from the header (as second) * and return it as millisecond timeout. */ int16_t HttpParameter::get_request_timeout (void) { return m_request_timeout; } /*! ---------------------------------------------------------------------------- * @fn split_params * * @brief method to split a string into sub string from a separator. and return a * vector from all the substrings. */ std::vector HttpParameter::split_params (const std::string &a_string, char a_seperator) { std::vector the_output; std::string::size_type the_prev_pos = 0, the_pos = 0; while ((the_pos = a_string.find(a_seperator, the_pos)) != std::string::npos) { std::string substring(a_string.substr(the_prev_pos, the_pos - the_prev_pos)); the_output.push_back(substring); the_prev_pos = ++the_pos; } the_output.push_back(a_string.substr(the_prev_pos, the_pos - the_prev_pos)); // Last word return the_output; } /*! ---------------------------------------------------------------------------- * @fn is_number * * @brief return true if the string given has parameter is a number. */ bool HttpParameter::is_number (const std::string & a_string) { char* p; strtod (a_string.c_str(), &p); return *p == 0; }