Fixed some issues in HTTP, added GET param support, fixed a bug, etc... lots of maintenaince.
This commit is contained in:
		
							parent
							
								
									266196d731
								
							
						
					
					
						commit
						fdfe95e792
					
				
					 4 changed files with 72 additions and 33 deletions
				
			
		| 
						 | 
				
			
			@ -14,9 +14,9 @@ void HTTP::Parser::Clean(){
 | 
			
		|||
  method = "GET";
 | 
			
		||||
  url = "/";
 | 
			
		||||
  protocol = "HTTP/1.1";
 | 
			
		||||
  body = "";
 | 
			
		||||
  body.clear();
 | 
			
		||||
  length = 0;
 | 
			
		||||
  HTTPbuffer = "";
 | 
			
		||||
  HTTPbuffer.clear();
 | 
			
		||||
  headers.clear();
 | 
			
		||||
  vars.clear();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -172,7 +172,10 @@ bool HTTP::Parser::parse(){
 | 
			
		|||
        if (f != std::string::npos){url = tmpA.substr(0, f); tmpA.erase(0, f+1);}
 | 
			
		||||
        f = tmpA.find(' ');
 | 
			
		||||
        if (f != std::string::npos){protocol = tmpA.substr(0, f); tmpA.erase(0, f+1);}
 | 
			
		||||
        /// \todo Include GET variable parsing?
 | 
			
		||||
        if (url.find('?') != std::string::npos){
 | 
			
		||||
          std::string queryvars = url.substr(url.find('?')+1);
 | 
			
		||||
          parseVars(queryvars); //parse GET variables
 | 
			
		||||
        }
 | 
			
		||||
      }else{
 | 
			
		||||
        if (tmpA.size() == 0){
 | 
			
		||||
          seenHeaders = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -191,22 +194,7 @@ bool HTTP::Parser::parse(){
 | 
			
		|||
        if (HTTPbuffer.length() >= length){
 | 
			
		||||
          body = HTTPbuffer.substr(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);
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          parseVars(body); //parse POST variables
 | 
			
		||||
          return true;
 | 
			
		||||
        }else{
 | 
			
		||||
          return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -229,6 +217,26 @@ void HTTP::Parser::SendResponse(Socket::Connection & conn, std::string code, std
 | 
			
		|||
  conn.write(tmp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Parses GET or POST-style variable data.
 | 
			
		||||
/// Saves to internal variable structure using HTTP::Parser::SetVar.
 | 
			
		||||
void HTTP::Parser::parseVars(std::string & data){
 | 
			
		||||
  std::string varname;
 | 
			
		||||
  std::string varval;
 | 
			
		||||
  while (data.find('=') != std::string::npos){
 | 
			
		||||
    size_t found = data.find('=');
 | 
			
		||||
    varname = urlunescape(data.substr(0, found));
 | 
			
		||||
    data.erase(0, found+1);
 | 
			
		||||
    found = data.find('&');
 | 
			
		||||
    varval = urlunescape(data.substr(0, found));
 | 
			
		||||
    SetVar(varname, varval);
 | 
			
		||||
    if (found == std::string::npos){
 | 
			
		||||
      data.clear();
 | 
			
		||||
    }else{
 | 
			
		||||
      data.erase(0, found+1);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Sends data as HTTP/1.1 bodypart to conn.
 | 
			
		||||
/// HTTP/1.1 chunked encoding is automatically applied if needed.
 | 
			
		||||
/// \param conn The Socket::Connection to send the part over.
 | 
			
		||||
| 
						 | 
				
			
			@ -257,24 +265,26 @@ void HTTP::Parser::SendBodyPart(Socket::Connection & conn, std::string 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;
 | 
			
		||||
/// Unescapes URLencoded std::strings.
 | 
			
		||||
std::string HTTP::Parser::urlunescape(std::string in){
 | 
			
		||||
  std::string out;
 | 
			
		||||
  for (unsigned int i = 0; i < in.length(); ++i){
 | 
			
		||||
    if (in[i] == '%'){
 | 
			
		||||
      char tmp = 0;
 | 
			
		||||
      ++i;
 | 
			
		||||
      if (i < in.length()){
 | 
			
		||||
        tmp = unhex(in[i]) << 4;
 | 
			
		||||
      }
 | 
			
		||||
      if (*++s != '\0'){
 | 
			
		||||
        *p++ += unhex(*s);
 | 
			
		||||
      ++i;
 | 
			
		||||
      if (i < in.length()){
 | 
			
		||||
        tmp += unhex(in[i]);
 | 
			
		||||
      }
 | 
			
		||||
      out += tmp;
 | 
			
		||||
    } else {
 | 
			
		||||
      if (*s == '+'){*p++ = ' ';}else{*p++ = *s;}
 | 
			
		||||
      if (in[i] == '+'){out += ' ';}else{out += in[i];}
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  *p = '\0';
 | 
			
		||||
  return std::string(s);
 | 
			
		||||
  return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Helper function for urlunescape.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,7 +30,7 @@ namespace HTTP{
 | 
			
		|||
      void SendBodyPart(Socket::Connection & conn, std::string bodypart);
 | 
			
		||||
      void Clean();
 | 
			
		||||
      bool CleanForNext();
 | 
			
		||||
      std::string urlunescape(char *s); ///< Unescapes URLencoded C-strings to a std::string.
 | 
			
		||||
      std::string urlunescape(std::string in);
 | 
			
		||||
      std::string body;
 | 
			
		||||
      std::string method;
 | 
			
		||||
      std::string url;
 | 
			
		||||
| 
						 | 
				
			
			@ -40,6 +40,7 @@ namespace HTTP{
 | 
			
		|||
      bool seenHeaders;
 | 
			
		||||
      bool seenReq;
 | 
			
		||||
      bool parse();
 | 
			
		||||
      void parseVars(std::string & data);
 | 
			
		||||
      std::string HTTPbuffer;
 | 
			
		||||
      std::map<std::string, std::string> headers;
 | 
			
		||||
      std::map<std::string, std::string> vars;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,10 +10,35 @@
 | 
			
		|||
#if DEBUG >= 1
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#endif
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <pwd.h>
 | 
			
		||||
 | 
			
		||||
std::map<pid_t, std::string> Util::Procs::plist;
 | 
			
		||||
bool Util::Procs::handler_set = false;
 | 
			
		||||
 | 
			
		||||
/// Sets the current process' running user
 | 
			
		||||
void Util::setUser(std::string username){
 | 
			
		||||
  if (username != "root"){
 | 
			
		||||
    struct passwd * user_info = getpwnam(username.c_str());
 | 
			
		||||
    if (!user_info){
 | 
			
		||||
      #if DEBUG >= 1
 | 
			
		||||
      fprintf(stderr, "Error: could not setuid %s: could not get PID\n", username.c_str());
 | 
			
		||||
      #endif
 | 
			
		||||
      return 1;
 | 
			
		||||
    }else{
 | 
			
		||||
      if (setuid(user_info->pw_uid) != 0){
 | 
			
		||||
        #if DEBUG >= 1
 | 
			
		||||
        fprintf(stderr, "Error: could not setuid %s: not allowed\n", username.c_str());
 | 
			
		||||
        #endif
 | 
			
		||||
      }else{
 | 
			
		||||
        #if DEBUG >= 3
 | 
			
		||||
        fprintf(stderr, "Changed user to %s\n", username.c_str());
 | 
			
		||||
        #endif
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Used internally to capture child signals and update plist.
 | 
			
		||||
void Util::Procs::childsig_handler(int signum){
 | 
			
		||||
  if (signum != SIGCHLD){return;}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,4 +27,7 @@ namespace Util{
 | 
			
		|||
      static pid_t getPid(std::string name);
 | 
			
		||||
      static std::string getName(pid_t name);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  static setUser(std::string user);
 | 
			
		||||
  
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue