1
0

Changed how Lua handles the (Post)Params in the HTTPRequest of a WebPlugin

It should now be theoretically possible to upload files through WebAdmin

git-svn-id: http://mc-server.googlecode.com/svn/trunk@203 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
faketruth
2012-01-31 20:56:42 +00:00
parent 59e740035e
commit 968f41ba51
12 changed files with 444 additions and 117 deletions

View File

@@ -49,6 +49,206 @@
webserver::request_func webserver::request_func_=0;
static std::vector< std::string > StringSplit(std::string str, std::string delim)
{
std::vector< std::string > results;
size_t cutAt;
while( (cutAt = str.find_first_of(delim)) != str.npos )
{
if(cutAt > 0)
{
results.push_back(str.substr(0,cutAt));
}
str = str.substr(cutAt+1);
}
if(str.length() > 0)
{
results.push_back(str);
}
return results;
}
static std::string EatLine( std::string& a_String )
{
std::string RetVal = "";
unsigned int StringSize = a_String.size();
const char* c = a_String.c_str();
for( unsigned int i = 0; i < StringSize; ++i, ++c)
{
if( *c == '\n' )
{
RetVal += *c;
// ++i; ++c;
// if( i < StringSize )
// {
// if( *c == '\r' )
// {
// RetVal += *c;
// }
// }
break;
}
RetVal += *c;
}
a_String = a_String.substr( RetVal.size() );
return RetVal;
}
// Turns
// "blabla my string with \"quotes\"!"
// into
// blabla my string with "quotes"!
static std::string GetQuotedString( const std::string& a_String )
{
std::string RetVal;
bool bGotFirstQuote = false;
bool bIgnoreNext = false;
unsigned int StrLen = a_String.size();
for( unsigned int i = 0; i < StrLen; ++i )
{
if( bIgnoreNext == false )
{
if( a_String[i] == '\"' )
{
if( bGotFirstQuote == false )
{
bGotFirstQuote = true;
}
else
{
break;
}
continue;
}
else if( a_String[i] == '\\' ) // Escape character
{
bIgnoreNext = true;
continue;
}
}
RetVal.push_back( a_String[i] );
bIgnoreNext = false;
}
return RetVal;
}
void ParseMultipartFormData( webserver::http_request& req, Socket* s)
{
static const std::string multipart_form_data = "multipart/form-data";
if(req.content_type_.substr(0, multipart_form_data.size()) == multipart_form_data) // Difficult data... :(
{
typedef std::vector< std::string > StringVector;
StringVector ContentTypeData = StringSplit( req.content_type_, "; " );
std::string boundary;
// Find boundary
for( unsigned int i = 0; i < ContentTypeData.size(); ++i )
{
static const std::string boundary_ = "boundary=";
if( ContentTypeData[i].substr(0, boundary_.size()) == boundary_ ) // Found boundary
{
boundary = ContentTypeData[i].substr( boundary_.size() );
}
}
//LOGINFO("Boundary: %s", boundary.c_str() );
std::string boundary_start = "--" + boundary;
std::string boundary_end = boundary_start + "--";
std::string Content = s->ReceiveBytes( req.content_length_ );
//printf("Total content: \n%s\n", Content.c_str() );
// Should start with boundary!
std::string line = EatLine( Content );
if( line.substr(0, boundary_start.size() ) != boundary_start )
{
// Something was wrong! :(
Content.clear();
}
while( !Content.empty() )
{
webserver::formdata FormData;
static const std::string content_disposition = "Content-Disposition: ";
static const std::string content_type = "Content-Type: ";
std::string f_disposition;
while( 1 )
{
std::string line = EatLine( Content );
if( line.empty() )
break;
unsigned int pos_cr_lf = line.find_first_of("\x0a\x0d");
if (pos_cr_lf == 0) break; // Empty line, indicates end of mime thingy
if( line.substr(0, content_disposition.size() ) == content_disposition )
{
f_disposition = line.substr(content_disposition.size());
LOGINFO("Disposition: %s", f_disposition.c_str() );
}
else if( line.substr(0, content_type.size() ) == content_type )
{
FormData.content_type_ = line.substr(content_type.size());
}
//LOGINFO("Got line: '%s'", line.c_str() );
}
// Check if we got the proper headers
if( !f_disposition.empty() )
{
static const std::string disp_name = "name=";
static const std::string disp_filename = "filename=";
// Parse the disposition
StringVector DispositionData = StringSplit( f_disposition, "; " );
for( unsigned int i = 0; i < DispositionData.size(); ++i )
{
if( DispositionData[i].substr(0, disp_name.size()) == disp_name )
{
FormData.name_ = GetQuotedString( DispositionData[i].substr(disp_name.size()) );
}
else if( DispositionData[i].substr(0, disp_filename.size()) == disp_filename )
{
FormData.filename_ = GetQuotedString( DispositionData[i].substr(disp_filename.size()) );
}
}
std::string ContentValue;
// Parse until boundary_end is found
while( 1 )
{
std::string line = EatLine( Content );
if( line.empty() )
break;
if( line.substr(0, boundary_end.size() ) == boundary_end )
{
break;
}
else if( line.substr(0, boundary_start.size() ) == boundary_start )
{
break;
}
ContentValue.append( line.c_str(), line.size() );
}
FormData.value_ = ContentValue;
}
req.multipart_formdata_.push_back( FormData );
}
}
}
#ifdef _WIN32
unsigned webserver::Request(void* ptr_s)
#else
@@ -99,7 +299,10 @@ void* webserver::Request(void* ptr_s)
while(1)
{
line=s->ReceiveLine();
if (line.empty()) break;
if (line.empty())
{
break;
}
unsigned int pos_cr_lf = line.find_first_of("\x0a\x0d");
if (pos_cr_lf == 0) break;
@@ -143,22 +346,23 @@ void* webserver::Request(void* ptr_s)
}
}
if( req.method_.compare("POST") == 0 )
if( (req.method_.compare("POST") == 0) && (req.content_length_ > 0) )
{
if( req.content_length_ > 0 )
// The only content type we can parse at the moment, the default HTML post data
if( req.content_type_.compare( "application/x-www-form-urlencoded" ) == 0 )
{
// The only content type we can parse at the moment, the default HTML post data
if( req.content_type_.compare( "application/x-www-form-urlencoded" ) == 0 )
{
std::string Content = s->ReceiveBytes( req.content_length_ );
Content.insert( 0, "/ ?" ); // Little hack, inserts dummy URL so that SplitGetReq() can work with this content
std::string Content = s->ReceiveBytes( req.content_length_ );
Content.insert( 0, "/ ?" ); // Little hack, inserts dummy URL so that SplitGetReq() can work with this content
std::string dummy;
std::map<std::string, std::string> post_params;
SplitGetReq(Content, dummy, post_params);
std::string dummy;
std::map<std::string, std::string> post_params;
SplitGetReq(Content, dummy, post_params);
req.params_post_ = post_params;
}
req.params_post_ = post_params;
}
else
{
ParseMultipartFormData( req, s );
}
}