added: parser for multipart forms, files: postmultiparser.h postmultiparser.cpp
added: function: upload git-svn-id: svn://ttmath.org/publicrep/cmslu/trunk@543 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
@@ -7,7 +7,7 @@ config.o: dircontainer.h users.h user.h ugcontainer.h groups.h group.h
|
||||
config.o: functions.h function.h lastcontainer.h mounts.h mount.h rebus.h
|
||||
config.o: plugin.h request.h requesttypes.h session.h done.h error.h thread.h
|
||||
config.o: compress.h acceptencodingparser.h acceptbaseparser.h htmlfilter.h
|
||||
config.o: pluginmsg.h misc.h
|
||||
config.o: postmultiparser.h pluginmsg.h misc.h
|
||||
data.o: data.h dirs.h item.h dircontainer.h users.h user.h ugcontainer.h
|
||||
data.o: log.h groups.h group.h functions.h function.h lastcontainer.h
|
||||
data.o: mounts.h mount.h rebus.h
|
||||
@@ -28,7 +28,7 @@ functionparser.o: dirs.h dircontainer.h users.h user.h ugcontainer.h groups.h
|
||||
functionparser.o: group.h functions.h function.h lastcontainer.h mounts.h
|
||||
functionparser.o: mount.h rebus.h db.h thread.h request.h session.h done.h
|
||||
functionparser.o: compress.h acceptencodingparser.h acceptbaseparser.h
|
||||
functionparser.o: htmlfilter.h
|
||||
functionparser.o: htmlfilter.h postmultiparser.h
|
||||
functions.o: functions.h function.h item.h
|
||||
groups.o: groups.h group.h ugcontainer.h log.h db.h item.h user.h thread.h
|
||||
groups.o: error.h dircontainer.h
|
||||
@@ -47,25 +47,32 @@ mounts.o: mounts.h mount.h data.h dirs.h item.h dircontainer.h users.h user.h
|
||||
mounts.o: ugcontainer.h log.h groups.h group.h functions.h function.h
|
||||
mounts.o: lastcontainer.h rebus.h request.h requesttypes.h session.h done.h
|
||||
mounts.o: error.h thread.h compress.h acceptencodingparser.h
|
||||
mounts.o: acceptbaseparser.h htmlfilter.h mountparser.h db.h
|
||||
mounts.o: acceptbaseparser.h htmlfilter.h postmultiparser.h mountparser.h
|
||||
mounts.o: db.h
|
||||
notify.o: log.h notify.h ../templatesnotify/templatesnotify.h ../core/mount.h
|
||||
notify.o: data.h dirs.h item.h dircontainer.h users.h user.h ugcontainer.h
|
||||
notify.o: groups.h group.h functions.h function.h lastcontainer.h mounts.h
|
||||
notify.o: mount.h rebus.h misc.h request.h requesttypes.h session.h done.h
|
||||
notify.o: error.h thread.h compress.h acceptencodingparser.h
|
||||
notify.o: acceptbaseparser.h htmlfilter.h
|
||||
notify.o: acceptbaseparser.h htmlfilter.h postmultiparser.h
|
||||
plugin.o: plugin.h request.h requesttypes.h session.h done.h item.h error.h
|
||||
plugin.o: log.h user.h rebus.h function.h thread.h compress.h
|
||||
plugin.o: acceptencodingparser.h acceptbaseparser.h htmlfilter.h data.h
|
||||
plugin.o: dirs.h dircontainer.h users.h ugcontainer.h groups.h group.h
|
||||
plugin.o: functions.h lastcontainer.h mounts.h mount.h pluginmsg.h
|
||||
plugin.o: acceptencodingparser.h acceptbaseparser.h htmlfilter.h
|
||||
plugin.o: postmultiparser.h data.h dirs.h dircontainer.h users.h
|
||||
plugin.o: ugcontainer.h groups.h group.h functions.h lastcontainer.h mounts.h
|
||||
plugin.o: mount.h pluginmsg.h
|
||||
postmultiparser.o: postmultiparser.h error.h log.h requesttypes.h data.h
|
||||
postmultiparser.o: dirs.h item.h dircontainer.h users.h user.h ugcontainer.h
|
||||
postmultiparser.o: groups.h group.h functions.h function.h lastcontainer.h
|
||||
postmultiparser.o: mounts.h mount.h rebus.h
|
||||
rebus.o: log.h rebus.h misc.h item.h
|
||||
request.o: request.h requesttypes.h session.h done.h item.h error.h log.h
|
||||
request.o: user.h rebus.h function.h thread.h compress.h
|
||||
request.o: acceptencodingparser.h acceptbaseparser.h htmlfilter.h getparser.h
|
||||
request.o: httpsimpleparser.h postparser.h cookieparser.h data.h dirs.h
|
||||
request.o: dircontainer.h users.h ugcontainer.h groups.h group.h functions.h
|
||||
request.o: lastcontainer.h mounts.h mount.h plugin.h pluginmsg.h misc.h
|
||||
request.o: acceptencodingparser.h acceptbaseparser.h htmlfilter.h
|
||||
request.o: postmultiparser.h getparser.h httpsimpleparser.h postparser.h
|
||||
request.o: cookieparser.h data.h dirs.h dircontainer.h users.h ugcontainer.h
|
||||
request.o: groups.h group.h functions.h lastcontainer.h mounts.h mount.h
|
||||
request.o: plugin.h pluginmsg.h misc.h
|
||||
requestcontroller.o: requestcontroller.h ../content/content.h ../core/item.h
|
||||
requestcontroller.o: ../templates/templates.h ../templates/patterncacher.h
|
||||
requestcontroller.o: ../core/thread.h sessionmanager.h sessioncontainer.h
|
||||
@@ -74,8 +81,8 @@ requestcontroller.o: functionparser.h requesttypes.h data.h dirs.h
|
||||
requestcontroller.o: dircontainer.h users.h ugcontainer.h groups.h group.h
|
||||
requestcontroller.o: functions.h function.h lastcontainer.h mounts.h mount.h
|
||||
requestcontroller.o: request.h thread.h compress.h acceptencodingparser.h
|
||||
requestcontroller.o: acceptbaseparser.h htmlfilter.h postparser.h
|
||||
requestcontroller.o: httpsimpleparser.h cookieparser.h notify.h
|
||||
requestcontroller.o: acceptbaseparser.h htmlfilter.h postmultiparser.h
|
||||
requestcontroller.o: postparser.h httpsimpleparser.h cookieparser.h notify.h
|
||||
requestcontroller.o: ../templatesnotify/templatesnotify.h ../core/mount.h
|
||||
session.o: session.h done.h item.h error.h log.h user.h rebus.h
|
||||
sessioncontainer.o: sessioncontainer.h session.h done.h item.h error.h log.h
|
||||
@@ -85,9 +92,9 @@ sessioncontainer.o: lastcontainer.h mounts.h mount.h
|
||||
sessionmanager.o: sessionmanager.h sessioncontainer.h session.h done.h item.h
|
||||
sessionmanager.o: error.h log.h user.h rebus.h request.h requesttypes.h
|
||||
sessionmanager.o: function.h thread.h compress.h acceptencodingparser.h
|
||||
sessionmanager.o: acceptbaseparser.h htmlfilter.h data.h dirs.h
|
||||
sessionmanager.o: dircontainer.h users.h ugcontainer.h groups.h group.h
|
||||
sessionmanager.o: functions.h lastcontainer.h mounts.h mount.h
|
||||
sessionmanager.o: acceptbaseparser.h htmlfilter.h postmultiparser.h data.h
|
||||
sessionmanager.o: dirs.h dircontainer.h users.h ugcontainer.h groups.h
|
||||
sessionmanager.o: group.h functions.h lastcontainer.h mounts.h mount.h
|
||||
sessionmanager.o: sessionparser.h
|
||||
sessionparser.o: sessionparser.h session.h done.h item.h error.h log.h user.h
|
||||
sessionparser.o: rebus.h sessioncontainer.h data.h dirs.h dircontainer.h
|
||||
|
@@ -1 +1 @@
|
||||
o = acceptbaseparser.o compress.o config.o data.o db.o db_itemcolumns.o dircontainer.o dirs.o done.o error.o function.o functioncodeparser.o functionparser.o functions.o groups.o htmlfilter.o httpsimpleparser.o lastcontainer.o log.o misc.o mount.o mountparser.o mounts.o notify.o plugin.o rebus.o request.o requestcontroller.o session.o sessioncontainer.o sessionmanager.o sessionparser.o users.o
|
||||
o = acceptbaseparser.o compress.o config.o data.o db.o db_itemcolumns.o dircontainer.o dirs.o done.o error.o function.o functioncodeparser.o functionparser.o functions.o groups.o htmlfilter.o httpsimpleparser.o lastcontainer.o log.o misc.o mount.o mountparser.o mounts.o notify.o plugin.o postmultiparser.o rebus.o request.o requestcontroller.o session.o sessioncontainer.o sessionmanager.o sessionparser.o users.o
|
||||
|
@@ -104,6 +104,8 @@ void Config::AssignValues()
|
||||
else
|
||||
data.log_stdout = false;
|
||||
|
||||
data.post_file_max = Int("post_file_max");
|
||||
|
||||
data.templates = Text("templates");
|
||||
data.default_index = Text("default_index");
|
||||
data.http_session_id_name = Text("http_session_id_name");
|
||||
|
@@ -109,6 +109,11 @@ public:
|
||||
// the url of a new empty item (if there is not the subject too)
|
||||
std::string item_url_empty;
|
||||
|
||||
// maximum length of a file send by post multipart form
|
||||
// 0 - not used
|
||||
int post_file_max;
|
||||
|
||||
|
||||
// below variables are based on the other config variables
|
||||
|
||||
// base_url_prefix + base_server
|
||||
|
@@ -54,6 +54,11 @@ public:
|
||||
spam,
|
||||
incorrect_rebus,
|
||||
|
||||
no_boundary,
|
||||
broken_input,
|
||||
input_too_large,
|
||||
cant_create_file,
|
||||
|
||||
unknown = 1000
|
||||
|
||||
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#define FUN_CREATETHREAD 14
|
||||
#define FUN_THREAD 15
|
||||
#define FUN_RELOAD 16
|
||||
#define FUN_UPLOAD 17
|
||||
|
||||
|
||||
|
||||
@@ -40,31 +41,6 @@ class Function
|
||||
|
||||
public:
|
||||
|
||||
/*
|
||||
enum Code
|
||||
{
|
||||
none,
|
||||
ls,
|
||||
cat,
|
||||
node,
|
||||
emacs,
|
||||
mkdir,
|
||||
default,
|
||||
priv,
|
||||
rm,
|
||||
login,
|
||||
logout,
|
||||
run,
|
||||
who
|
||||
};
|
||||
|
||||
|
||||
Code code;
|
||||
*/
|
||||
/*
|
||||
we do not use enum etc. because the code will be used with an application too
|
||||
(application can set others values)
|
||||
*/
|
||||
int code;
|
||||
Item item;
|
||||
|
||||
|
@@ -96,6 +96,9 @@ void Functions::ReadFunctions()
|
||||
f.item.url = "thread";
|
||||
table.insert( std::make_pair(f.item.url, f) );
|
||||
|
||||
f.code = FUN_UPLOAD;
|
||||
f.item.url = "upload";
|
||||
table.insert( std::make_pair(f.item.url, f) );
|
||||
|
||||
// functions which need more privileges
|
||||
|
||||
|
550
core/postmultiparser.cpp
Executable file
550
core/postmultiparser.cpp
Executable file
@@ -0,0 +1,550 @@
|
||||
/*
|
||||
* This file is a part of CMSLU -- Content Management System like Unix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2009, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "postmultiparser.h"
|
||||
#include "log.h"
|
||||
#include "data.h"
|
||||
|
||||
|
||||
PostMultiParser::PostMultiParser()
|
||||
{
|
||||
in_buffer = new unsigned char[CMSLU_POSTMULTI_INPUT_BUFFER];
|
||||
}
|
||||
|
||||
|
||||
PostMultiParser::PostMultiParser(const PostMultiParser &)
|
||||
{
|
||||
in_buffer = new unsigned char[CMSLU_POSTMULTI_INPUT_BUFFER];
|
||||
}
|
||||
|
||||
|
||||
|
||||
PostMultiParser & PostMultiParser::operator=(const PostMultiParser &)
|
||||
{
|
||||
in_buffer = new unsigned char[CMSLU_POSTMULTI_INPUT_BUFFER];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PostMultiParser::~PostMultiParser()
|
||||
{
|
||||
delete [] in_buffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PostMultiParser::ReadBoundary()
|
||||
{
|
||||
boundary.clear();
|
||||
|
||||
while( last != -1 && last != 10 && last != 13 )
|
||||
{
|
||||
boundary += last;
|
||||
ReadChar();
|
||||
}
|
||||
|
||||
if( last == 13 )
|
||||
{
|
||||
ReadChar();
|
||||
line_end_dos = true;
|
||||
}
|
||||
|
||||
if( last == 10 )
|
||||
ReadChar();
|
||||
}
|
||||
|
||||
|
||||
bool PostMultiParser::IsWhite(int c)
|
||||
{
|
||||
if( c==' ' || c=='\t' || c==13 )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void PostMultiParser::SkipWhite()
|
||||
{
|
||||
while( IsWhite(last) )
|
||||
ReadChar();
|
||||
}
|
||||
|
||||
|
||||
bool PostMultiParser::IsHeader()
|
||||
{
|
||||
SkipWhite();
|
||||
|
||||
if( last == 10 )
|
||||
{
|
||||
ReadChar();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PostMultiParser::ReadHeaderName()
|
||||
{
|
||||
SkipWhite();
|
||||
|
||||
while( last!=-1 && last!=':' && last!='=' && !IsWhite(last) && last!=10 )
|
||||
{
|
||||
header_name += last;
|
||||
ReadChar();
|
||||
}
|
||||
|
||||
SkipWhite();
|
||||
|
||||
if( last != ':' && last != '=' )
|
||||
{
|
||||
err = Error::broken_input;
|
||||
return;
|
||||
}
|
||||
|
||||
ReadChar();
|
||||
}
|
||||
|
||||
|
||||
void PostMultiParser::ReadHeaderValue()
|
||||
{
|
||||
bool was_apost = false;
|
||||
|
||||
SkipWhite();
|
||||
|
||||
if( last == '"' )
|
||||
{
|
||||
was_apost = true;
|
||||
ReadChar();
|
||||
}
|
||||
|
||||
while( last!=-1 && last!=10 &&
|
||||
((!was_apost && last!=';' && !IsWhite(last)) || (was_apost && last!='"')))
|
||||
{
|
||||
header_value += last;
|
||||
ReadChar();
|
||||
}
|
||||
|
||||
if( was_apost )
|
||||
{
|
||||
if( last != '"' )
|
||||
{
|
||||
err = Error::broken_input;
|
||||
return;
|
||||
}
|
||||
|
||||
ReadChar();
|
||||
}
|
||||
|
||||
SkipWhite();
|
||||
|
||||
if( last != ';' && last != 10 )
|
||||
{
|
||||
err = Error::broken_input;
|
||||
return;
|
||||
}
|
||||
|
||||
ReadChar();
|
||||
}
|
||||
|
||||
|
||||
void PostMultiParser::ReadPartHeader()
|
||||
{
|
||||
header_name.clear();
|
||||
header_value.clear();
|
||||
|
||||
ReadHeaderName();
|
||||
|
||||
if( err != Error::ok )
|
||||
return;
|
||||
|
||||
ReadHeaderValue();
|
||||
|
||||
if( err != Error::ok )
|
||||
return;
|
||||
|
||||
log << "PMP: " << header_name << ": " << header_value << logend;
|
||||
|
||||
if( header_name == "name" )
|
||||
name = header_value;
|
||||
|
||||
if( header_name == "filename" )
|
||||
filename = header_value;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool PostMultiParser::HasBoundary()
|
||||
{
|
||||
if( content.size() < boundary.size() )
|
||||
return false;
|
||||
|
||||
size_t c = content.size() - boundary.size();
|
||||
size_t b = 0;
|
||||
|
||||
for( ; c<content.size() ; ++c, ++b)
|
||||
{
|
||||
if( content[c] != boundary[b] )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PostMultiParser::LogFirst(const std::string & to_log, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if( len > to_log.size() )
|
||||
len = to_log.size();
|
||||
|
||||
log << log3 << "PMP: Content (";
|
||||
|
||||
if( len > 0 )
|
||||
log << "len: " << to_log.size() << ", first " << len << " bytes";
|
||||
else
|
||||
log << "empty";
|
||||
|
||||
log << "): \"";
|
||||
|
||||
for(i=0 ; i<len ; ++i)
|
||||
{
|
||||
if( to_log[i] < 32 )
|
||||
log << '.';
|
||||
else
|
||||
log << to_log[i];
|
||||
}
|
||||
|
||||
log << "\"" << logend;
|
||||
}
|
||||
|
||||
|
||||
void PostMultiParser::ReadContentSkipBoundary(bool has_boundary)
|
||||
{
|
||||
if( has_boundary )
|
||||
content.erase(content.size()-boundary.size());
|
||||
|
||||
// the last new line character doesn't belong to the content
|
||||
if( !content.empty() && content[content.size()-1] == 10 )
|
||||
{
|
||||
content.erase(content.size()-1);
|
||||
|
||||
if( line_end_dos && !content.empty() && content[content.size()-1] == 13 )
|
||||
content.erase(content.size()-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PostMultiParser::ReadContentToFileLoop()
|
||||
{
|
||||
bool has_boundary = false;
|
||||
|
||||
|
||||
while( last!=-1 && !(has_boundary=HasBoundary()) )
|
||||
{
|
||||
content += last;
|
||||
ReadChar();
|
||||
|
||||
if( content.size() > CMSLU_POSTMULTI_OUTPUT_BUFFER + boundary.size() + 2 ) // +2 for the new line character
|
||||
{
|
||||
tmp_file.write(content.c_str(), CMSLU_POSTMULTI_OUTPUT_BUFFER);
|
||||
content_len += CMSLU_POSTMULTI_OUTPUT_BUFFER;
|
||||
content.erase(0, CMSLU_POSTMULTI_OUTPUT_BUFFER);
|
||||
}
|
||||
|
||||
if( data.post_file_max != 0 && content_len > (size_t)data.post_file_max )
|
||||
{
|
||||
err = Error::input_too_large;
|
||||
log << log1 << "PMP: content greater than " << data.post_file_max << " (skipping)" << logend;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ReadContentSkipBoundary(has_boundary);
|
||||
|
||||
// saving the rest
|
||||
if( !content.empty() )
|
||||
{
|
||||
tmp_file.write(content.c_str(), content.size());
|
||||
content_len += content.size();
|
||||
content.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void PostMultiParser::ReadContentToFile()
|
||||
{
|
||||
time_t t1, t2;
|
||||
|
||||
content.clear();
|
||||
content.reserve(CMSLU_POSTMULTI_OUTPUT_BUFFER + boundary.size());
|
||||
content_len = 0;
|
||||
t1 = time(0);
|
||||
|
||||
ReadContentToFileLoop();
|
||||
|
||||
tmp_file.close();
|
||||
log << log2 << "PMP: content size: " << content_len << " bytes" << logend;
|
||||
|
||||
t2 = time(0);
|
||||
|
||||
if( t2 - t1 > 1 )
|
||||
log << log2 << "PMP: content read in " << (t2-t1) << " sec" << logend;
|
||||
}
|
||||
|
||||
|
||||
void PostMultiParser::ReadContentLoop()
|
||||
{
|
||||
bool has_boundary = false;
|
||||
|
||||
|
||||
while( last!=-1 && !(has_boundary=HasBoundary()) )
|
||||
{
|
||||
content += last;
|
||||
content_len += 1;
|
||||
ReadChar();
|
||||
|
||||
if( data.post_file_max != 0 && content_len > (size_t)data.post_file_max )
|
||||
{
|
||||
err = Error::input_too_large;
|
||||
log << log1 << "PMP: content greater than " << data.post_file_max << " (skipping)" << logend;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ReadContentSkipBoundary(has_boundary);
|
||||
}
|
||||
|
||||
|
||||
void PostMultiParser::ReadContent()
|
||||
{
|
||||
content.clear();
|
||||
content_len = 0;
|
||||
|
||||
ReadContentLoop();
|
||||
|
||||
log << log2 << "PMP: content size: " << content_len << " bytes" << logend;
|
||||
LogFirst(content, 200);
|
||||
}
|
||||
|
||||
|
||||
void PostMultiParser::AddNormalPostVar()
|
||||
{
|
||||
if( post_table->size() >= CMSLU_POSTTABLE_MAXSIZE )
|
||||
{
|
||||
err = Error::input_too_large;
|
||||
log << log1 << "PMP: more than " << CMSLU_POSTTABLE_MAXSIZE << " post variables (skipping)" << logend;
|
||||
return;
|
||||
}
|
||||
|
||||
std::pair<PostTable::iterator, bool> res = post_table->insert( std::make_pair(name, content) );
|
||||
bool added = res.second;
|
||||
|
||||
log << log2 << "PMP: POST var, name: \"" << name << "\"";
|
||||
|
||||
if( !added )
|
||||
log << log2 << " (skipped)";
|
||||
|
||||
log << logend;
|
||||
}
|
||||
|
||||
|
||||
void PostMultiParser::AddFilePostVar()
|
||||
{
|
||||
if( post_file_table->size() >= CMSLU_POSTTABLE_MAXSIZE )
|
||||
{
|
||||
err = Error::input_too_large;
|
||||
log << log1 << "PMP: more than " << CMSLU_POSTTABLE_MAXSIZE << " post file variables (skipping)" << logend;
|
||||
return;
|
||||
}
|
||||
|
||||
post_file_temp.filename = filename;
|
||||
post_file_temp.tmp_filename = tmp_filename;
|
||||
std::pair<PostFileTable::iterator, bool> res = post_file_table->insert( std::make_pair(name, post_file_temp) );
|
||||
bool added = res.second;
|
||||
|
||||
log << log2 << "PMP: POST FILE var, name: \"" << name << "\"";
|
||||
|
||||
if( !added )
|
||||
log << log2 << " (skipped)";
|
||||
|
||||
log << logend;
|
||||
}
|
||||
|
||||
|
||||
void PostMultiParser::AddPostVar()
|
||||
{
|
||||
if( name.empty() )
|
||||
return;
|
||||
|
||||
|
||||
if( filename.empty() )
|
||||
{
|
||||
AddNormalPostVar();
|
||||
}
|
||||
else
|
||||
{
|
||||
AddFilePostVar();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PostMultiParser::CheckBoundaryEnd()
|
||||
{
|
||||
if( last == '-' )
|
||||
{
|
||||
ReadChar();
|
||||
|
||||
if( last != '-' )
|
||||
{
|
||||
err = Error::broken_input;
|
||||
return;
|
||||
}
|
||||
|
||||
// end of parsing
|
||||
// the rest input (if exists) is ignored
|
||||
last = -1;
|
||||
}
|
||||
|
||||
// skipping a new line after the boundary
|
||||
if( last == 13 )
|
||||
ReadChar();
|
||||
|
||||
if( last == 10 )
|
||||
ReadChar();
|
||||
}
|
||||
|
||||
|
||||
void PostMultiParser::CreateTmpFile()
|
||||
{
|
||||
char buf[100];
|
||||
|
||||
sprintf(buf, "/tmp/cmslu_%u_%d_%u", (unsigned)getpid(), tmp_filename_postfix, rand());
|
||||
tmp_filename_postfix += 1;
|
||||
|
||||
tmp_file.open(buf, std::ios_base::binary | std::ios_base::out);
|
||||
tmp_filename = buf;
|
||||
|
||||
if( !tmp_file )
|
||||
{
|
||||
log << log1 << "PMP: can't create a temporary file: " << tmp_filename << logend;
|
||||
err = Error::cant_create_file;
|
||||
return;
|
||||
}
|
||||
|
||||
log << log3 << "PMP: using temporary file for the content: " << tmp_filename << logend;
|
||||
}
|
||||
|
||||
|
||||
void PostMultiParser::ReadPart()
|
||||
{
|
||||
name.clear();
|
||||
filename.clear();
|
||||
|
||||
while( IsHeader() )
|
||||
ReadPartHeader();
|
||||
|
||||
if( err != Error::ok )
|
||||
return;
|
||||
|
||||
if( !filename.empty() )
|
||||
CreateTmpFile();
|
||||
|
||||
if( err != Error::ok )
|
||||
return;
|
||||
|
||||
if( !filename.empty() )
|
||||
ReadContentToFile();
|
||||
else
|
||||
ReadContent();
|
||||
|
||||
if( err == Error::ok )
|
||||
{
|
||||
AddPostVar();
|
||||
CheckBoundaryEnd();
|
||||
}
|
||||
|
||||
if( err != Error::ok && !filename.empty() )
|
||||
{
|
||||
log << log1 << "PMP: deleting the tmp file: " << tmp_filename << logend;
|
||||
unlink(tmp_filename.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PostMultiParser::ReadChar()
|
||||
{
|
||||
if( last == -1 )
|
||||
return;
|
||||
|
||||
if( in_buffer_ind >= in_buffer_len )
|
||||
{
|
||||
if( in_buffer_len < CMSLU_POSTMULTI_INPUT_BUFFER )
|
||||
{
|
||||
last = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
in_buffer_len = FCGX_GetStr((char*)in_buffer, CMSLU_POSTMULTI_INPUT_BUFFER, in);
|
||||
in_buffer_ind = 0;
|
||||
}
|
||||
|
||||
if( in_buffer_len == 0 )
|
||||
{
|
||||
last = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
last = in_buffer[in_buffer_ind];
|
||||
in_buffer_ind += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Error PostMultiParser::Parse(FCGX_Stream * in_, PostTable & post_table_, PostFileTable & post_file_table_)
|
||||
{
|
||||
in = in_;
|
||||
last = 0;
|
||||
err = Error::ok;
|
||||
line_end_dos = false;
|
||||
in_buffer_ind = CMSLU_POSTMULTI_INPUT_BUFFER;
|
||||
in_buffer_len = CMSLU_POSTMULTI_INPUT_BUFFER;
|
||||
post_table = &post_table_;
|
||||
post_file_table = &post_file_table_;
|
||||
tmp_filename_postfix = 1;
|
||||
|
||||
ReadChar();
|
||||
ReadBoundary();
|
||||
|
||||
if( boundary.empty() )
|
||||
return Error::no_boundary;
|
||||
|
||||
while( last!=-1 && err == Error::ok )
|
||||
ReadPart();
|
||||
|
||||
if( err != Error::ok )
|
||||
{
|
||||
post_table->clear();
|
||||
post_file_table->clear();
|
||||
|
||||
if( err != Error::input_too_large )
|
||||
log << log1 << "PMP: syntax error" << logend;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
93
core/postmultiparser.h
Executable file
93
core/postmultiparser.h
Executable file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* This file is a part of CMSLU -- Content Management System like Unix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2008-2009, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef headerfilecmslucorepostmultiparser
|
||||
#define headerfilecmslucorepostmultiparser
|
||||
|
||||
#include <string>
|
||||
#include <fcgiapp.h>
|
||||
#include <fstream>
|
||||
#include "error.h"
|
||||
#include "requesttypes.h"
|
||||
|
||||
// 2 MB
|
||||
#define CMSLU_POSTMULTI_INPUT_BUFFER 2097152
|
||||
#define CMSLU_POSTMULTI_OUTPUT_BUFFER 2097152
|
||||
|
||||
|
||||
class PostMultiParser
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
PostMultiParser();
|
||||
PostMultiParser(const PostMultiParser &);
|
||||
PostMultiParser & operator=(const PostMultiParser &);
|
||||
~PostMultiParser();
|
||||
|
||||
Error Parse(FCGX_Stream * in_, PostTable & post_table_, PostFileTable & post_file_table_);
|
||||
|
||||
private:
|
||||
|
||||
FCGX_Stream * in;
|
||||
unsigned char * in_buffer;
|
||||
std::ofstream tmp_file;
|
||||
std::string tmp_filename;
|
||||
int tmp_filename_postfix;
|
||||
size_t in_buffer_ind;
|
||||
size_t in_buffer_len;
|
||||
|
||||
PostTable * post_table;
|
||||
PostFileTable * post_file_table;
|
||||
|
||||
int last; // last read character
|
||||
|
||||
bool line_end_dos;
|
||||
std::string boundary;
|
||||
std::string content;
|
||||
size_t content_len;
|
||||
|
||||
std::string header_name, header_value;
|
||||
Error err;
|
||||
|
||||
std::string name, filename;
|
||||
PostFile post_file_temp;
|
||||
|
||||
void LogFirst(const std::string & to_log, size_t len);
|
||||
|
||||
bool IsWhite(int c);
|
||||
void SkipWhite();
|
||||
|
||||
void AddNormalPostVar();
|
||||
void AddFilePostVar();
|
||||
void AddPostVar();
|
||||
|
||||
void ReadBoundary();
|
||||
|
||||
bool IsHeader();
|
||||
void ReadHeaderName();
|
||||
void ReadHeaderValue();
|
||||
void ReadPartHeader();
|
||||
|
||||
void CreateTmpFile();
|
||||
bool HasBoundary();
|
||||
void ReadContentSkipBoundary(bool has_boundary);
|
||||
void ReadContentToFileLoop();
|
||||
void ReadContentToFile();
|
||||
void ReadContentLoop();
|
||||
void ReadContent();
|
||||
void CheckBoundaryEnd();
|
||||
void ReadPart();
|
||||
|
||||
void ReadChar();
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
@@ -8,6 +8,8 @@
|
||||
*/
|
||||
|
||||
#include <ctime>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include "request.h"
|
||||
#include "getparser.h"
|
||||
#include "postparser.h"
|
||||
@@ -31,6 +33,21 @@ void Request::Init()
|
||||
}
|
||||
|
||||
|
||||
void Request::ClearPostFileTmp()
|
||||
{
|
||||
// deleting temporary files (if exists)
|
||||
|
||||
while( !post_file_table.empty() )
|
||||
{
|
||||
const std::string & tmp_filename = post_file_table.begin()->second.tmp_filename;
|
||||
|
||||
if( unlink(tmp_filename.c_str()) == 0 )
|
||||
log << log3 << "Request: deleted tmp file: " << tmp_filename << logend;
|
||||
|
||||
post_file_table.erase(post_file_table.begin());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Request::Clear()
|
||||
{
|
||||
@@ -39,9 +56,10 @@ void Request::Clear()
|
||||
// id is never 0
|
||||
if( ++id == 0 )
|
||||
++id;
|
||||
|
||||
|
||||
get_table.clear();
|
||||
post_table.clear();
|
||||
post_file_table.clear();
|
||||
cookie_table.clear();
|
||||
|
||||
method = none;
|
||||
@@ -60,7 +78,9 @@ void Request::Clear()
|
||||
env_http_user_agent = &char_empty;
|
||||
env_http_accept_encoding = &char_empty;
|
||||
env_fcgi_role = &char_empty;
|
||||
|
||||
env_content_type = &char_empty;
|
||||
|
||||
|
||||
session = 0;
|
||||
|
||||
item_table.clear();
|
||||
@@ -241,6 +261,7 @@ void Request::ReadEnvVariables()
|
||||
env_http_user_agent = SetEnvVar("HTTP_USER_AGENT");
|
||||
env_http_accept_encoding = SetEnvVar("HTTP_ACCEPT_ENCODING");
|
||||
env_fcgi_role = SetEnvVar("FCGI_ROLE");
|
||||
env_content_type = SetEnvVar("CONTENT_TYPE");
|
||||
}
|
||||
|
||||
|
||||
@@ -255,6 +276,8 @@ void Request::CheckIE()
|
||||
browser_msie = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Request::CheckKonqueror()
|
||||
{
|
||||
char * kon = strstr(env_http_user_agent, "Konqueror");
|
||||
@@ -300,13 +323,24 @@ return true;
|
||||
|
||||
void Request::ReadParameters()
|
||||
{
|
||||
// !! wrzucic jako skladowa klasy
|
||||
GetParser get_parser(env_request_uri, get_table);
|
||||
get_parser.Parse();
|
||||
|
||||
if( method == post )
|
||||
{
|
||||
PostParser post_parser(in, post_table);
|
||||
post_parser.Parse();
|
||||
if( IsSubStringNoCase("multipart/form-data", env_content_type) )
|
||||
{
|
||||
log << log3 << "Request: post content type: multipart/form-data" << logend;
|
||||
|
||||
post_multi_parser.Parse(in, post_table, post_file_table);
|
||||
}
|
||||
else
|
||||
{
|
||||
// !! wrzucic jako skladowa klasy
|
||||
PostParser post_parser(in, post_table);
|
||||
post_parser.Parse();
|
||||
}
|
||||
}
|
||||
|
||||
CookieParser cookie_parser(env_http_cookie, cookie_table);
|
||||
@@ -739,6 +773,23 @@ return true;
|
||||
}
|
||||
|
||||
|
||||
bool Request::CanUseUpload(const Item & item, bool check_root)
|
||||
{
|
||||
// you can use 'upload' only in a directory
|
||||
if( item.type != Item::dir )
|
||||
return false;
|
||||
|
||||
if( !check_root && request.session->puser && request.session->puser->super_user )
|
||||
// super user can use mkdir everywhere
|
||||
return true;
|
||||
|
||||
if( !request.HasWriteAccess(item) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Request::CanUseHtml(long user_id)
|
||||
{
|
||||
User * puser = data.users.GetUser(user_id);
|
||||
@@ -787,3 +838,24 @@ return false;
|
||||
}
|
||||
|
||||
|
||||
bool Request::MakeDirsOnFS(std::string & path)
|
||||
{
|
||||
size_t i;
|
||||
path = "/home/tomek/roboczy/slimaczek.pl/static_auth"; // !! dodac do konfiga
|
||||
|
||||
// skipping the first - the first is root
|
||||
for(i=1 ; i<dir_table.size() ; ++i)
|
||||
{
|
||||
path += '/';
|
||||
path += dir_table[i]->url;
|
||||
|
||||
if( mkdir(path.c_str(), 0750) < 0 )
|
||||
{
|
||||
// oops
|
||||
log << log1 << "Request: can't create the directory on fs: " << path << logend;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@
|
||||
#include "compress.h"
|
||||
#include "acceptencodingparser.h"
|
||||
#include "htmlfilter.h"
|
||||
|
||||
#include "postmultiparser.h"
|
||||
|
||||
|
||||
struct Request
|
||||
@@ -48,9 +48,10 @@ struct Request
|
||||
std::ostringstream headers, page, debug, notify;
|
||||
|
||||
|
||||
GetTable get_table;
|
||||
PostTable post_table;
|
||||
CookieTable cookie_table;
|
||||
GetTable get_table;
|
||||
PostTable post_table;
|
||||
PostFileTable post_file_table;
|
||||
CookieTable cookie_table;
|
||||
|
||||
// environment variables
|
||||
// they are not null -- when the server doesn't have such a variable
|
||||
@@ -63,6 +64,7 @@ struct Request
|
||||
const char * env_http_user_agent;
|
||||
const char * env_http_accept_encoding;
|
||||
const char * env_fcgi_role;
|
||||
const char * env_content_type;
|
||||
|
||||
// true if the browser is Microsoft Internet Explorer
|
||||
bool browser_msie;
|
||||
@@ -111,6 +113,7 @@ struct Request
|
||||
void PrintIn();
|
||||
|
||||
Request();
|
||||
void ClearPostFileTmp();
|
||||
void Clear();
|
||||
|
||||
void Init();
|
||||
@@ -146,10 +149,13 @@ struct Request
|
||||
bool CanRemove(const Item & item);
|
||||
bool CanUseEmacs(const Item & item, bool check_root = false);
|
||||
bool CanUseMkdir(const Item & item, bool check_root = false);
|
||||
|
||||
bool CanUseUpload(const Item & item, bool check_root = false);
|
||||
|
||||
bool CanUseHtml(long user_id);
|
||||
bool CanUseBBCode(long user_id);
|
||||
|
||||
bool MakeDirsOnFS(std::string & path);
|
||||
|
||||
private:
|
||||
|
||||
enum Header
|
||||
@@ -171,6 +177,9 @@ private:
|
||||
// it contains '\0'
|
||||
const char char_empty;
|
||||
|
||||
|
||||
PostMultiParser post_multi_parser;
|
||||
|
||||
const char * SetEnvVar(const char * var);
|
||||
void StandardLog();
|
||||
|
||||
@@ -178,6 +187,7 @@ private:
|
||||
AcceptEncodingParser accept_encoding_parser;
|
||||
HTMLFilter html_filter;
|
||||
|
||||
|
||||
// html after filtering
|
||||
std::string clean_html;
|
||||
|
||||
|
@@ -229,6 +229,8 @@ void RequestController::Loop()
|
||||
FCGX_Finish();
|
||||
return;
|
||||
}
|
||||
|
||||
request.ClearPostFileTmp();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -15,9 +15,19 @@
|
||||
#include <map>
|
||||
|
||||
|
||||
#define CMSLU_POSTTABLE_MAXSIZE 20
|
||||
|
||||
|
||||
struct PostFile
|
||||
{
|
||||
std::string filename; // original file name
|
||||
std::string tmp_filename; // file with content (in /tmp)
|
||||
};
|
||||
|
||||
// some global types used by Request class
|
||||
typedef std::vector<std::string> GetTable;
|
||||
typedef std::vector<std::string> GetTable;
|
||||
typedef std::map<std::string, std::string> PostTable;
|
||||
typedef std::map<std::string, PostFile> PostFileTable;
|
||||
typedef std::map<std::string, std::string> CookieTable;
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user