Merge fix
This commit is contained in:
commit
9fe909d034
4 changed files with 113 additions and 2 deletions
|
@ -188,10 +188,25 @@ bool HTTP::Parser::parse(){
|
||||||
}
|
}
|
||||||
if (seenHeaders){
|
if (seenHeaders){
|
||||||
if (length > 0){
|
if (length > 0){
|
||||||
/// \todo Include POST variable parsing?
|
|
||||||
if (HTTPbuffer.length() >= length){
|
if (HTTPbuffer.length() >= length){
|
||||||
body = HTTPbuffer.substr(0, length);
|
body = HTTPbuffer.substr(0, length);
|
||||||
HTTPbuffer.erase(0, length);
|
HTTPbuffer.erase(0, length);
|
||||||
|
std::string tmppost = body;
|
||||||
|
std::string varname;
|
||||||
|
std::string varval;
|
||||||
|
while (tmppost.find('=') != std::string::npos){
|
||||||
|
size_t found = tmppost.find('=');
|
||||||
|
varname = urlunescape((char*)tmppost.substr(0, found).c_str());
|
||||||
|
tmppost.erase(0, found+1);
|
||||||
|
found = tmppost.find('&');
|
||||||
|
varval = urlunescape((char*)tmppost.substr(0, found).c_str());
|
||||||
|
SetVar(varname, varval);
|
||||||
|
if (found == std::string::npos){
|
||||||
|
tmppost.clear();
|
||||||
|
}else{
|
||||||
|
tmppost.erase(0, found+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}else{
|
}else{
|
||||||
return false;
|
return false;
|
||||||
|
@ -241,3 +256,29 @@ void HTTP::Parser::SendBodyPart(Socket::Connection & conn, std::string bodypart)
|
||||||
conn.write(bodypart);
|
conn.write(bodypart);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Unescapes URLencoded C-strings to a std::string.
|
||||||
|
/// This function *will* destroy the input data!
|
||||||
|
std::string HTTP::Parser::urlunescape(char *s){
|
||||||
|
char *p;
|
||||||
|
for (p = s; *s != '\0'; ++s){
|
||||||
|
if (*s == '%'){
|
||||||
|
if (*++s != '\0'){
|
||||||
|
*p = unhex(*s) << 4;
|
||||||
|
}
|
||||||
|
if (*++s != '\0'){
|
||||||
|
*p++ += unhex(*s);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (*s == '+'){*p++ = ' ';}else{*p++ = *s;}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*p = '\0';
|
||||||
|
return std::string(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper function for urlunescape.
|
||||||
|
/// Takes a single char input and outputs its integer hex value.
|
||||||
|
int HTTP::Parser::unhex(char c){
|
||||||
|
return( c >= '0' && c <= '9' ? c - '0' : c >= 'A' && c <= 'F' ? c - 'A' + 10 : c - 'a' + 10 );
|
||||||
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ namespace HTTP{
|
||||||
void SendBodyPart(Socket::Connection & conn, std::string bodypart);
|
void SendBodyPart(Socket::Connection & conn, std::string bodypart);
|
||||||
void Clean();
|
void Clean();
|
||||||
bool CleanForNext();
|
bool CleanForNext();
|
||||||
|
std::string urlunescape(char *s); ///< Unescapes URLencoded C-strings to a std::string.
|
||||||
std::string body;
|
std::string body;
|
||||||
std::string method;
|
std::string method;
|
||||||
std::string url;
|
std::string url;
|
||||||
|
@ -43,5 +44,6 @@ namespace HTTP{
|
||||||
std::map<std::string, std::string> headers;
|
std::map<std::string, std::string> headers;
|
||||||
std::map<std::string, std::string> vars;
|
std::map<std::string, std::string> vars;
|
||||||
void Trim(std::string & s);
|
void Trim(std::string & s);
|
||||||
|
int unhex(char c); ///< Helper function for urlunescape.
|
||||||
};//HTTP::Parser class
|
};//HTTP::Parser class
|
||||||
};//HTTP namespace
|
};//HTTP namespace
|
||||||
|
|
|
@ -3,6 +3,11 @@
|
||||||
/// Written by Jaron Vietor in 2010 for DDVTech
|
/// Written by Jaron Vietor in 2010 for DDVTech
|
||||||
|
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
|
#include <poll.h>
|
||||||
|
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Create a new base socket. This is a basic constructor for converting any valid socket to a Socket::Connection.
|
/// Create a new base socket. This is a basic constructor for converting any valid socket to a Socket::Connection.
|
||||||
/// \param sockNo Integer representing the socket to convert.
|
/// \param sockNo Integer representing the socket to convert.
|
||||||
|
@ -69,6 +74,27 @@ Socket::Connection::Connection(std::string address, bool nonblock){
|
||||||
}
|
}
|
||||||
}//Socket::Connection Unix Contructor
|
}//Socket::Connection Unix Contructor
|
||||||
|
|
||||||
|
/// Calls poll() on the socket, checking if data is available.
|
||||||
|
/// This function may return true even if there is no data, but never returns false when there is.
|
||||||
|
bool Socket::Connection::canRead(){
|
||||||
|
struct pollfd PFD;
|
||||||
|
PFD.fd = sock;
|
||||||
|
PFD.events = POLLIN;
|
||||||
|
PFD.revents = 0;
|
||||||
|
poll(&PFD, 1, 5);
|
||||||
|
return (PFD.revents & POLLIN) == POLLIN;
|
||||||
|
}
|
||||||
|
/// Calls poll() on the socket, checking if data can be written.
|
||||||
|
bool Socket::Connection::canWrite(){
|
||||||
|
struct pollfd PFD;
|
||||||
|
PFD.fd = sock;
|
||||||
|
PFD.events = POLLOUT;
|
||||||
|
PFD.revents = 0;
|
||||||
|
poll(&PFD, 1, 5);
|
||||||
|
return (PFD.revents & POLLOUT) == POLLOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Returns the ready-state for this socket.
|
/// Returns the ready-state for this socket.
|
||||||
/// \returns 1 if data is waiting to be read, -1 if not connected, 0 otherwise.
|
/// \returns 1 if data is waiting to be read, -1 if not connected, 0 otherwise.
|
||||||
signed int Socket::Connection::ready(){
|
signed int Socket::Connection::ready(){
|
||||||
|
@ -348,7 +374,47 @@ Socket::Server::Server(int port, std::string hostname, bool nonblock){
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
#if DEBUG >= 1
|
#if DEBUG >= 1
|
||||||
fprintf(stderr, "Binding failed! Error: %s\n", strerror(errno));
|
fprintf(stderr, "Binding failed, retrying as IPv4... (%s)\n", strerror(errno));
|
||||||
|
#endif
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if (sock < 0){
|
||||||
|
#if DEBUG >= 1
|
||||||
|
fprintf(stderr, "Could not create socket! Error: %s\n", strerror(errno));
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
on = 1;
|
||||||
|
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
||||||
|
if (nonblock){
|
||||||
|
int flags = fcntl(sock, F_GETFL, 0);
|
||||||
|
flags |= O_NONBLOCK;
|
||||||
|
fcntl(sock, F_SETFL, flags);
|
||||||
|
}
|
||||||
|
struct sockaddr_in addr4;
|
||||||
|
addr4.sin_family = AF_INET;
|
||||||
|
addr4.sin_port = htons(port);//set port
|
||||||
|
if (hostname == "0.0.0.0"){
|
||||||
|
addr4.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
}else{
|
||||||
|
inet_pton(AF_INET, hostname.c_str(), &addr4.sin_addr);//set interface, 0.0.0.0 (default) is all
|
||||||
|
}
|
||||||
|
ret = bind(sock, (sockaddr*)&addr4, sizeof(addr4));//do the actual bind
|
||||||
|
if (ret == 0){
|
||||||
|
ret = listen(sock, 100);//start listening, backlog of 100 allowed
|
||||||
|
if (ret == 0){
|
||||||
|
return;
|
||||||
|
}else{
|
||||||
|
#if DEBUG >= 1
|
||||||
|
fprintf(stderr, "Listen failed! Error: %s\n", strerror(errno));
|
||||||
|
#endif
|
||||||
|
close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
#if DEBUG >= 1
|
||||||
|
fprintf(stderr, "IPv4 binding also failed, giving up. (%s)\n", strerror(errno));
|
||||||
#endif
|
#endif
|
||||||
close();
|
close();
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -27,6 +27,8 @@ namespace Socket{
|
||||||
Connection(); ///< Create a new disconnected base socket.
|
Connection(); ///< Create a new disconnected base socket.
|
||||||
Connection(int sockNo); ///< Create a new base socket.
|
Connection(int sockNo); ///< Create a new base socket.
|
||||||
Connection(std::string adres, bool nonblock = false); ///< Create a new Unix Socket.
|
Connection(std::string adres, bool nonblock = false); ///< Create a new Unix Socket.
|
||||||
|
bool canRead(); ///< Calls poll() on the socket, checking if data is available.
|
||||||
|
bool canWrite(); ///< Calls poll() on the socket, checking if data can be written.
|
||||||
bool Error; ///< Set to true if a socket error happened.
|
bool Error; ///< Set to true if a socket error happened.
|
||||||
bool Blocking; ///< Set to true if a socket is currently or wants to be blocking.
|
bool Blocking; ///< Set to true if a socket is currently or wants to be blocking.
|
||||||
signed int ready(); ///< Returns the ready-state for this socket.
|
signed int ready(); ///< Returns the ready-state for this socket.
|
||||||
|
|
Loading…
Add table
Reference in a new issue