Merge fix

This commit is contained in:
Erik Zandvliet 2011-09-26 18:55:39 +02:00
commit 9fe909d034
4 changed files with 113 additions and 2 deletions

View file

@ -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 );
}

View file

@ -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

View file

@ -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;

View file

@ -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.