removed: Request::debug all stream used for debugging info
some environment variables were put there removed: config variable: debug_info removed: Request::role (responder, authorizer) now we have only one role: responder added: new config variables: log_env_variables (default false) - when true then fastcgi environment variables are logged to the log file log_http_answer_headers (default false) - when true all http headers created by winix ale logged (note that the www server can add/adjust other headers) changed: some refactoring in Request struct changed: CookieTab to std::map<std::wstring, std::wstring> beforehand std::string was used (changed CookieParser as well) changed: Request::SetCookie() to AddCookie() added: Request::out_headers (a PT::Space struct) http headers (without cookies) send back to the client added: Request::out_cookies (a PT::Space struct) cookies send to the client changed: App class to use Request::out_headers and Request::out_cookies some SendHeaders...() methods were renamed to PrepareHeaders...() and they create output in Request::out_headers first (and out_cookies) and later it is sent added: two plugin messages: // http headers (without cookies) were created and are ready to send // here you can make some changes to them // in p1 you have a pointer to the PT::Space (Request::out_headers) #define WINIX_PREPARE_TO_SEND_HTTP_HEADERS 31070 // http cookies were created and are ready to send // here you can make some changes to them // in p1 you have a pointer to the PT::Space (Request::out_cookies) #define WINIX_PREPARE_TO_SEND_HTTP_COOKIES 31080 added: config variable: // how many output streams do we have in Request class // default: 16 (64 maximum) size_t ezc_out_streams_size; git-svn-id: svn://ttmath.org/publicrep/winix/trunk@940 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
236
core/app.cpp
236
core/app.cpp
@@ -162,6 +162,8 @@ bool App::Init()
|
||||
post_parser.LogValueSize(config.log_post_value_size);
|
||||
// post_multi_parser has a pointer to the config
|
||||
|
||||
cookie_parser.UTF8(config.utf8);
|
||||
|
||||
plugin.Call((Session*)0, WINIX_PLUGIN_INIT);
|
||||
|
||||
return true;
|
||||
@@ -572,26 +574,13 @@ void App::Make()
|
||||
|
||||
plugin.Call(WINIX_CONTENT_MAKE);
|
||||
MakePage();
|
||||
|
||||
if( config.debug_info )
|
||||
{
|
||||
// !! dodac inne informacje (get, post, itp)
|
||||
// jesli jest debug_info wlaczone to nie robic przekierowan
|
||||
PrintEnv();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void App::PrintEnv()
|
||||
void App::LogEnvironmentVariables()
|
||||
{
|
||||
char ** e;
|
||||
|
||||
cur.request->debug << "environment variables:\n";
|
||||
|
||||
for( e = fcgi_request.envp ; *e ; ++e )
|
||||
cur.request->debug << ' ' << *e << "\n";
|
||||
|
||||
cur.request->debug << '\n';
|
||||
for(char ** e = fcgi_request.envp ; *e ; ++e )
|
||||
log << log1 << "Env: " << *e << logend;
|
||||
}
|
||||
|
||||
|
||||
@@ -601,7 +590,6 @@ void App::ReadRequest()
|
||||
{
|
||||
ReadEnvVariables();
|
||||
CheckRequestMethod();
|
||||
CheckFCGIRole();
|
||||
CheckSSL();
|
||||
SetSubdomain();
|
||||
|
||||
@@ -611,14 +599,14 @@ void App::ReadRequest()
|
||||
cookie_parser.Parse(cur.request->env_http_cookie, cur.request->cookie_tab);
|
||||
accept_encoding_parser.ParseAndLog(cur.request->env_http_accept_encoding);
|
||||
|
||||
if( config.log_env_variables )
|
||||
LogEnvironmentVariables();
|
||||
|
||||
CheckIE();
|
||||
CheckKonqueror();
|
||||
|
||||
if( cur.request->using_ssl )
|
||||
log << log3 << "App: connection secure through SSL" << logend;
|
||||
|
||||
if( cur.request->role == Request::authorizer )
|
||||
log << log3 << "App: fast cgi role: authorizer" << logend;
|
||||
}
|
||||
|
||||
|
||||
@@ -658,7 +646,7 @@ void App::ReadEnvVariables()
|
||||
|
||||
void App::CheckRequestMethod()
|
||||
{
|
||||
cur.request->method = Request::none;
|
||||
cur.request->method = Request::unknown_method;
|
||||
|
||||
if( ToSmall(cur.request->env_request_method[0]) == 'g' )
|
||||
cur.request->method = Request::get;
|
||||
@@ -671,15 +659,6 @@ void App::CheckRequestMethod()
|
||||
}
|
||||
|
||||
|
||||
void App::CheckFCGIRole()
|
||||
{
|
||||
// default we assume 'responder'
|
||||
cur.request->role = Request::responder;
|
||||
|
||||
if( ToSmall(cur.request->env_fcgi_role[0]) == 'a' )
|
||||
cur.request->role = Request::authorizer;
|
||||
}
|
||||
|
||||
|
||||
void App::CheckSSL()
|
||||
{
|
||||
@@ -774,22 +753,21 @@ void App::PrepareSessionCookie()
|
||||
|
||||
if( !cur.session->puser || !cur.session->remember_me )
|
||||
{
|
||||
cur.request->SetCookie(config.http_session_id_name.c_str(), cur.session->id);
|
||||
cur.request->AddCookie(config.http_session_id_name, cur.session->id);
|
||||
}
|
||||
else
|
||||
{
|
||||
PT::Date expires = cur.request->start_time + config.session_remember_max_idle;
|
||||
cur.request->SetCookie(config.http_session_id_name.c_str(), cur.session->id, &expires);
|
||||
cur.request->AddCookie(config.http_session_id_name, cur.session->id, expires);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool App::SendHeadersStaticCreateResource()
|
||||
bool App::PrepareHeadersStaticCreateResource(PT::WTextStream & out_path)
|
||||
{
|
||||
size_t i = 0;
|
||||
Item * dir = system.dirs.GetDir(system.mounts.pmount->dir_id);
|
||||
sendh_t3.clear();
|
||||
|
||||
if( !dir )
|
||||
{
|
||||
@@ -808,18 +786,18 @@ bool App::SendHeadersStaticCreateResource()
|
||||
++i;
|
||||
|
||||
if( i > 0 )
|
||||
sendh_t3.assign(path, i);
|
||||
out_path.write(path, i);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void App::SendHeadersStatic()
|
||||
void App::PrepareHeadersStatic()
|
||||
{
|
||||
if( PathHasUpDir(cur.request->env_request_uri) )
|
||||
{
|
||||
log << log1 << "App: incorrect path for a static file" << logend;
|
||||
SendHeadersForbidden();
|
||||
PrepareHeadersForbidden();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -829,171 +807,213 @@ void App::SendHeadersStatic()
|
||||
if( index >= config.static_dirs.size() )
|
||||
{
|
||||
log << log1 << "App: static dir with index " << index << " is not defined in the config" << logend;
|
||||
SendHeadersForbidden();
|
||||
PrepareHeadersForbidden();
|
||||
return;
|
||||
}
|
||||
|
||||
PT::WideToUTF8(config.http_header_send_file, sendh_t);
|
||||
PT::WideToUTF8(config.static_dirs[index], sendh_t2);
|
||||
PT::WTextStream path;
|
||||
path << config.static_dirs[index] << L"/";
|
||||
|
||||
if( !SendHeadersStaticCreateResource() )
|
||||
if( !PrepareHeadersStaticCreateResource(path) )
|
||||
{
|
||||
SendHeadersForbidden();
|
||||
PrepareHeadersForbidden();
|
||||
return;
|
||||
}
|
||||
|
||||
FCGX_FPrintF(fcgi_request.out, "%s: %s/%s\r\n", sendh_t.c_str(), sendh_t2.c_str(), sendh_t3.c_str());
|
||||
FCGX_PutS("Status: 200 OK\r\n", fcgi_request.out);
|
||||
log << log2 << "App: sending a file from a static mountpoint: " << sendh_t2 << "/" << sendh_t3 << logend;
|
||||
cur.request->out_headers.Add(config.http_header_send_file, path);
|
||||
cur.request->out_headers.Add(L"Status", L"200 OK");
|
||||
log << log2 << "App: sending a file from a static mountpoint: " << path << logend;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void App::SendHeaderContentType()
|
||||
void App::PrepareHeaderContentType()
|
||||
{
|
||||
std::wstring * value = 0;
|
||||
|
||||
if( cur.request->return_json )
|
||||
{
|
||||
FCGX_PutS("Content-Type: application/json", fcgi_request.out);
|
||||
value = &cur.request->out_headers.Add(L"Content-Type", L"application/json");
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( config.content_type_header )
|
||||
{
|
||||
case 1:
|
||||
FCGX_PutS("Content-Type: application/xhtml+xml", fcgi_request.out);
|
||||
value = &cur.request->out_headers.Add(L"Content-Type", L"application/xhtml+xml");
|
||||
break;
|
||||
|
||||
case 2:
|
||||
FCGX_PutS("Content-Type: application/xml", fcgi_request.out);
|
||||
value = &cur.request->out_headers.Add(L"Content-Type", L"application/xml");
|
||||
break;
|
||||
|
||||
case 0:
|
||||
default:
|
||||
FCGX_PutS("Content-Type: text/html", fcgi_request.out);
|
||||
value = &cur.request->out_headers.Add(L"Content-Type", L"text/html");
|
||||
}
|
||||
}
|
||||
|
||||
if( config.utf8 )
|
||||
FCGX_PutS("; charset=UTF-8", fcgi_request.out);
|
||||
|
||||
FCGX_PutS("\r\n", fcgi_request.out);
|
||||
if( value && config.utf8 )
|
||||
*value += L"; charset=UTF-8";
|
||||
}
|
||||
|
||||
|
||||
|
||||
void App::SendHeadersForbidden()
|
||||
void App::PrepareHeadersForbidden()
|
||||
{
|
||||
FCGX_PutS("Status: 403 Forbidden\r\n", fcgi_request.out);
|
||||
SendHeaderContentType();
|
||||
cur.request->out_headers.Add(L"Status", L"403 Forbidden");
|
||||
PrepareHeaderContentType();
|
||||
}
|
||||
|
||||
|
||||
void App::SendHeadersRedirect()
|
||||
void App::PrepareHeadersRedirect()
|
||||
{
|
||||
switch(cur.request->redirect_type)
|
||||
{
|
||||
case 300:
|
||||
FCGX_PutS("Status: 300 Multiple Choices\r\n", fcgi_request.out);
|
||||
cur.request->out_headers.Add(L"Status", L"300 Multiple Choices");
|
||||
break;
|
||||
|
||||
case 301:
|
||||
FCGX_PutS("Status: 301 Moved Permanently\r\n", fcgi_request.out);
|
||||
cur.request->out_headers.Add(L"Status", L"301 Moved Permanently");
|
||||
break;
|
||||
|
||||
case 302:
|
||||
FCGX_PutS("Status: 302 Found\r\n", fcgi_request.out);
|
||||
cur.request->out_headers.Add(L"Status", L"302 Found");
|
||||
break;
|
||||
|
||||
case 307:
|
||||
FCGX_PutS("Status: 307 Temporary Redirect\r\n", fcgi_request.out);
|
||||
cur.request->out_headers.Add(L"Status", L"307 Temporary Redirect");
|
||||
break;
|
||||
|
||||
case 303:
|
||||
default:
|
||||
FCGX_PutS("Status: 303 See Other\r\n", fcgi_request.out);
|
||||
cur.request->out_headers.Add(L"Status", L"303 See Other");
|
||||
break;
|
||||
}
|
||||
|
||||
PT::WideToUTF8(cur.request->redirect_to, cur.request->aredirect_to);
|
||||
FCGX_FPrintF(fcgi_request.out, "Location: %s\r\n", cur.request->aredirect_to.c_str());
|
||||
log << log2 << "App: redirect to: " << cur.request->aredirect_to << logend;
|
||||
cur.request->out_headers.Add(L"Location", cur.request->redirect_to);
|
||||
log << log2 << "App: redirect to: " << cur.request->redirect_to << logend;
|
||||
}
|
||||
|
||||
|
||||
void App::SendHeadersSendFile()
|
||||
void App::PrepareHeadersSendFile()
|
||||
{
|
||||
PT::WideToUTF8(config.http_header_send_file, sendfilea);
|
||||
PT::WideToUTF8(cur.request->x_sendfile, sendfile2a);
|
||||
FCGX_FPrintF(fcgi_request.out, "%s: %s\r\n", sendfilea.c_str(), sendfile2a.c_str());
|
||||
cur.request->out_headers.Add(L"Status", L"200 OK");
|
||||
cur.request->out_headers.Add(config.http_header_send_file, cur.request->x_sendfile);
|
||||
|
||||
FCGX_PutS("Status: 200 OK\r\n", fcgi_request.out);
|
||||
log << log2 << "App: sending file: " << cur.request->x_sendfile << logend;
|
||||
}
|
||||
|
||||
|
||||
void App::SendHeadersCompression(int compress_encoding)
|
||||
void App::PrepareHeadersCompression(int compress_encoding)
|
||||
{
|
||||
if( compress_encoding == 0 || compress_encoding == 1 )
|
||||
FCGX_PutS("Content-Encoding: deflate\r\n", fcgi_request.out);
|
||||
cur.request->out_headers.Add(L"Content-Encoding", L"deflate");
|
||||
else
|
||||
FCGX_PutS("Content-Encoding: gzip\r\n", fcgi_request.out);
|
||||
cur.request->out_headers.Add(L"Content-Encoding", L"gzip");
|
||||
}
|
||||
|
||||
|
||||
void App::SendHeadersNormal(Header header)
|
||||
void App::PrepareHeadersNormal(Header header)
|
||||
{
|
||||
switch( header )
|
||||
{
|
||||
case h_404:
|
||||
FCGX_PutS("Status: 404 Not Found\r\n", fcgi_request.out);
|
||||
SendHeaderContentType();
|
||||
cur.request->out_headers.Add(L"Status", L"404 Not Found");
|
||||
PrepareHeaderContentType();
|
||||
break;
|
||||
|
||||
case h_403:
|
||||
SendHeadersForbidden();
|
||||
PrepareHeadersForbidden();
|
||||
break;
|
||||
|
||||
default:
|
||||
FCGX_PutS("Status: 200 OK\r\n", fcgi_request.out);
|
||||
|
||||
if( cur.request->role != Request::authorizer )
|
||||
SendHeaderContentType();
|
||||
cur.request->out_headers.Add(L"Status", L"200 OK");
|
||||
PrepareHeaderContentType();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// we can improve SendHeaders and SendCookies methods by checking
|
||||
// whether there is a new line character in either a name or a value
|
||||
// and if such character exists and is being sent to the client it breaks the http headers and content
|
||||
// and if compression is enabled the client's browser will not be able to decompress the stream
|
||||
void App::SendHeaders()
|
||||
{
|
||||
PT::Space::TableSingle::iterator i;
|
||||
PT::Space & headers = cur.request->out_headers;
|
||||
|
||||
void App::SendHeaders(bool compressing, int compress_encoding, Header header)
|
||||
plugin.Call(WINIX_PREPARE_TO_SEND_HTTP_HEADERS, &headers);
|
||||
|
||||
for(i=headers.table_single.begin() ; i != headers.table_single.end() ; ++i)
|
||||
{
|
||||
PT::WideToUTF8(i->first, aheader_name);
|
||||
PT::WideToUTF8(i->second, aheader_value);
|
||||
|
||||
FCGX_PutS(aheader_name.c_str(), fcgi_request.out);
|
||||
FCGX_PutS(": ", fcgi_request.out);
|
||||
FCGX_PutS(aheader_value.c_str(), fcgi_request.out);
|
||||
FCGX_PutS("\r\n", fcgi_request.out);
|
||||
|
||||
if( config.log_http_answer_headers )
|
||||
log << "HTTP Header: " << aheader_name << ": " << aheader_value << logend;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void App::SendCookies()
|
||||
{
|
||||
PT::Space::TableSingle::iterator i;
|
||||
PT::Space & cookies = cur.request->out_cookies;
|
||||
|
||||
plugin.Call(WINIX_PREPARE_TO_SEND_HTTP_COOKIES, &cookies);
|
||||
|
||||
for(i=cookies.table_single.begin() ; i != cookies.table_single.end() ; ++i)
|
||||
{
|
||||
PT::WideToUTF8(i->first, aheader_name);
|
||||
PT::WideToUTF8(i->second, aheader_value);
|
||||
|
||||
FCGX_PutS("Set-Cookie: ", fcgi_request.out);
|
||||
FCGX_PutS(aheader_name.c_str(), fcgi_request.out);
|
||||
FCGX_PutS("=", fcgi_request.out);
|
||||
FCGX_PutS(aheader_value.c_str(), fcgi_request.out);
|
||||
FCGX_PutS("\r\n", fcgi_request.out);
|
||||
|
||||
if( config.log_http_answer_headers )
|
||||
log << "HTTP Header: " << "Set-Cookie: " << aheader_name << "=" << aheader_value << logend;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void App::PrepareHeaders(bool compressing, int compress_encoding, Header header)
|
||||
{
|
||||
PrepareSessionCookie();
|
||||
|
||||
if( cur.request->send_as_attachment )
|
||||
FCGX_PutS("Content-Disposition: attachment\r\n", fcgi_request.out);
|
||||
cur.request->out_headers.Add(L"Content-Disposition", L"attachment");
|
||||
|
||||
if( !cur.request->redirect_to.empty() )
|
||||
{
|
||||
SendHeadersRedirect();
|
||||
PrepareHeadersRedirect();
|
||||
}
|
||||
else
|
||||
if( system.mounts.pmount->type == system.mounts.MountTypeStatic() )
|
||||
{
|
||||
SendHeadersStatic();
|
||||
PrepareHeadersStatic();
|
||||
}
|
||||
else
|
||||
if( !cur.request->x_sendfile.empty() )
|
||||
{
|
||||
SendHeadersSendFile();
|
||||
PrepareHeadersSendFile();
|
||||
}
|
||||
else
|
||||
{
|
||||
SendHeadersNormal(header);
|
||||
PrepareHeadersNormal(header);
|
||||
}
|
||||
|
||||
if( compressing )
|
||||
SendHeadersCompression(compress_encoding);
|
||||
|
||||
FCGX_PutS(cur.request->headers.CStr(), fcgi_request.out);
|
||||
FCGX_PutS("\r\n", fcgi_request.out);
|
||||
PrepareHeadersCompression(compress_encoding);
|
||||
}
|
||||
|
||||
|
||||
@@ -1009,13 +1029,11 @@ void App::FilterCompressSend(bool compressing, int compress_encoding, const std:
|
||||
if( config.html_filter && cur.request->use_html_filter && !raw && !cur.request->return_json )
|
||||
{
|
||||
TemplatesFunctions::html_filter.Filter(*source, clean_html);
|
||||
AddDebugInfo(clean_html);
|
||||
source = &clean_html;
|
||||
}
|
||||
else
|
||||
{
|
||||
html_with_debug = *source;
|
||||
AddDebugInfo(html_with_debug);
|
||||
source = &html_with_debug;
|
||||
}
|
||||
|
||||
@@ -1024,6 +1042,7 @@ void App::FilterCompressSend(bool compressing, int compress_encoding, const std:
|
||||
else
|
||||
AssignString(*source, source_a);
|
||||
|
||||
// !! IMPROVE ME add to log the binary stream as well
|
||||
if( config.log_server_answer )
|
||||
log << log1 << "App: the server's answer is:\n" << source_a << "\nApp: end of the server's answer" << logend;
|
||||
|
||||
@@ -1054,7 +1073,6 @@ void App::SelectCompression(size_t source_len, bool & compression_allowed, int &
|
||||
compression_encoding = 0;
|
||||
|
||||
if( config.compression &&
|
||||
cur.request->role == Request::responder &&
|
||||
cur.request->redirect_to.empty() &&
|
||||
cur.request->x_sendfile.empty() &&
|
||||
!cur.request->browser_konqueror && /* !! sprawdzic czy Konqueror bedzie obslugiwal raw deflate */
|
||||
@@ -1102,10 +1120,6 @@ bool App::CanSendContent(Header header)
|
||||
// if there is a redirect or a file to send then we do not send a content
|
||||
return false;
|
||||
|
||||
if( header == h_200 && cur.request->role == Request::authorizer && cur.request->is_item && cur.request->item.file_type != WINIX_ITEM_FILETYPE_NONE )
|
||||
// if there is an item and the item has 'file' storage we do not send a content
|
||||
return false;
|
||||
|
||||
/*
|
||||
we don't have to check the HEAD method
|
||||
the server (lighttpd) doesn't send the body of its own
|
||||
@@ -1117,18 +1131,6 @@ return true;
|
||||
}
|
||||
|
||||
|
||||
void App::AddDebugInfo(std::wstring & out)
|
||||
{
|
||||
if( config.debug_info )
|
||||
{
|
||||
if( !cur.request->debug.Empty() )
|
||||
{
|
||||
out += L"\n<!--\n";
|
||||
out += cur.request->debug.Str();
|
||||
out += L"\n-->\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1165,7 +1167,10 @@ int compress_encoding;
|
||||
header = h_200;
|
||||
}
|
||||
|
||||
SendHeaders(compressing, compress_encoding, header);
|
||||
PrepareHeaders(compressing, compress_encoding, header);
|
||||
SendHeaders();
|
||||
SendCookies();
|
||||
FCGX_PutS("\r\n", fcgi_request.out);
|
||||
|
||||
if( CanSendContent(header) )
|
||||
{
|
||||
@@ -1193,7 +1198,7 @@ void App::SendData(const BinaryPage & page, FCGX_Stream * out)
|
||||
send_data_buf[s] = *i;
|
||||
|
||||
if( s > 0 )
|
||||
FCGX_PutStr(send_data_buf.c_str(), s, fcgi_request.out);
|
||||
FCGX_PutStr(send_data_buf.c_str(), s, out);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1216,7 +1221,7 @@ int compress_encoding;
|
||||
|
||||
// !! IMPROVE ME add header: content-size
|
||||
|
||||
SendHeaders(compressing, compress_encoding, header);
|
||||
PrepareHeaders(compressing, compress_encoding, header);
|
||||
|
||||
if( CanSendContent(header) )
|
||||
{
|
||||
@@ -1519,6 +1524,9 @@ void App::WaitForThreads()
|
||||
|
||||
void App::FetchPageOnExit()
|
||||
{
|
||||
// !! CHANGE ME use curl instead of BSD's fetch...
|
||||
// this allows to port to Linux systems
|
||||
|
||||
// stupid trick to break FCGX_Accept_r() function
|
||||
// even with FCGX_InitRequest(..., ..., FCGI_FAIL_ACCEPT_ON_INTR) the FCGX_Accept_r
|
||||
// doesn't want to break on a signal
|
||||
|
Reference in New Issue
Block a user