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.

210 lines
6.1 KiB

#include "UDPTCPNetwork.h"
#include <pthread.h>
#include <unistd.h>
#include <time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <list>
WebRequestBuffer::WebRequestBuffer () {
buffer_pos_data = -1;
buffer_size = 0;
buffer_ptr = NULL;
buffer_len = 0;
}
WebRequestBuffer::~WebRequestBuffer () {
if (buffer_ptr) {
free (buffer_ptr);
buffer_ptr = NULL;
buffer_size = 0;
buffer_len = 0;
buffer_pos_data = -1;
}
}
/// @brief add text to buffer
/// @param buffer
/// @param len
/// @return 0 on error, 1 on success
int WebRequestBuffer::AddBuffer (char *buffer, int len) {
//
// if needed allocate enought buffer, to the next kB
if (buffer_ptr == NULL || buffer_size <= buffer_len+len) {
buffer_size = 1024 * (1 + ((buffer_len + len) / 1024));
if (buffer_ptr == NULL) buffer_ptr = (char*) malloc (buffer_size);
else buffer_ptr = (char*) realloc (buffer_ptr, buffer_size);
}
if (buffer_ptr == NULL || buffer_size < buffer_len+len) {
fprintf (stderr, "%s:%d could not allocate enought memory. buffer_size:%d buffer_len+len:%d \n",
__FILE__, __LINE__, buffer_size, buffer_len + len);
return 0;
}
memcpy (buffer_ptr + buffer_len, buffer, len);
buffer_len += len;
buffer_ptr[buffer_len] = 0;
// debug("buffer:'%s'\n", buffer_ptr);
return 1;
};
/// @brief copy the current buffer to the destination, resize destination if needed
/// @param dstptr pointer to the destination pointer, in case of a reallocation
/// @param max pointer to current allocated size of the pointer
/// @return > 0 - len in bytes of the buffer, = -1 error occured
int WebRequestBuffer::GetBuffer (char **dstptr, int *max) {
// check: valid pointers
if (dstptr == NULL || max == NULL) {
fprintf (stderr, "%s:%d not pointer to buffer or not pointer to a lenght set\n",
__FILE__, __LINE__);
return -1;
}
// check: size and reallocate
if (*max < buffer_len || *max < 0) {
char *tb = (char*) realloc (*dstptr, buffer_len);
*dstptr = tb;
*max = buffer_size;
}
// check: could alloc memory
if (*dstptr == NULL) {
fprintf (stderr, "%s:%d no destination pointer set\n",
__FILE__, __LINE__);
return -1;
}
memcpy (*dstptr, buffer_ptr, buffer_len);
return buffer_len;
};
/// @brief Check if the Request is Complete. In this case the request_type and the request can
/// @brief be read with GetRequest and GetType(). For a new request Clear() must be called.
/// @return 0 . not complete, 1 . request complete
bool WebRequestBuffer::RequestComplete() {
int i = 0;
int element = 0; // 0. Parameter 1. Value 2. Value n
int line = 0;
WebHeaderLine hl;
request = "";
protocol_version = "HTTP/1.0";
request_type = WEB_REQUEST_UNSUPPORTED;
buffer_pos_data = -1;
if (buffer_ptr == NULL) return false;
hl.Clear();
for (i = 0, element = 0; i < buffer_len; i++) {
//
// check if line is complete
if (buffer_ptr[i] == '\n') {
if (hl.value.length() == 0 && hl.parameter.length() == 0) {
buffer_pos_data = i+1; // save position of first data byte
return true;
}
// the first line holds the request type and the location/path.
if (line == 0) {
hl.parameter = string_to_upper(hl.parameter);
if (hl.parameter.compare("GET") == 0) request_type = WEB_REQUEST_GET;
if (hl.parameter.compare("POST") == 0) request_type = WEB_REQUEST_POST;
request = string_to_lower(hl.value);
}
headerlines.push_back(hl);
hl.Clear();
element = 0;
line++;
continue;
}
// ignore some elements -> maybe it is not needed
else if (strchr ("\t ", buffer_ptr[i]) != NULL) {
element++;
if (element > 1) hl.value += buffer_ptr[i];
}
// ignore last CR
else if (buffer_ptr[i] != '\r') {
if (element == 0) hl.parameter += buffer_ptr[i];
// first line ignore protocol version
else if (line > 0 || element == 1) hl.value += buffer_ptr[i];
}
}
return false;
}
/// @brief get some information about the complete request
/// @param cmd propably get or set command
/// @param obj object related with this command
/// @param jp some json data
/// @return
int WebRequestBuffer::GetRequestCmdObj(std::string *cmd, std::string *obj, JSONParse *jp) {
std::string rq = GetRequest();
int secslash = 0;
if (cmd == NULL || obj == NULL || jp == NULL)
errorexit ("Fatal Error cmd:%p obj:%p jp:%p none of these should be NULL\n",
cmd, obj, jp);
secslash = rq.find ('/', 1);
*cmd = rq.substr(1, secslash-1);
*obj = rq.substr(secslash+1, std::string::npos);
if (buffer_pos_data > 0) (*jp).Set(buffer_ptr+buffer_pos_data);
else (*jp).Clear();
return 1;
}
std::string WebRequestBuffer::GetRequest() {
std::string rq = "";
char lastc = 0;
char c = 0;
//
// filter out /. .. ./
for (int i = 0; i < request.length(); i++) {
c = request[i];
if (((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') || c == '/' || c == '.' || c == '-' ) &&
(!((c == '.' || c == '/' ) && (lastc == '/' || lastc == '.')))) {
rq += c;
lastc = c;
}
}
return rq;
}
std::string WebRequestBuffer::GetCookie(std::string name) {
std::list<WebHeaderLine>::iterator il;
std::size_t i;
for (il = headerlines.begin(); il != headerlines.end(); il++) {
if (string_to_lower(il->parameter).compare("cookie:") == 0) {
i = il->value.find('=');
if (i == std::string::npos) continue;
if (il->value.substr(0, i).compare(name) == 0)
return il->value.substr(i+1, std::string::npos);
}
}
return "";
};