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:
parent
3e32f3784f
commit
375604edd6
236
core/app.cpp
236
core/app.cpp
|
@ -162,6 +162,8 @@ bool App::Init()
|
||||||
post_parser.LogValueSize(config.log_post_value_size);
|
post_parser.LogValueSize(config.log_post_value_size);
|
||||||
// post_multi_parser has a pointer to the config
|
// post_multi_parser has a pointer to the config
|
||||||
|
|
||||||
|
cookie_parser.UTF8(config.utf8);
|
||||||
|
|
||||||
plugin.Call((Session*)0, WINIX_PLUGIN_INIT);
|
plugin.Call((Session*)0, WINIX_PLUGIN_INIT);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -572,26 +574,13 @@ void App::Make()
|
||||||
|
|
||||||
plugin.Call(WINIX_CONTENT_MAKE);
|
plugin.Call(WINIX_CONTENT_MAKE);
|
||||||
MakePage();
|
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;
|
for(char ** e = fcgi_request.envp ; *e ; ++e )
|
||||||
|
log << log1 << "Env: " << *e << logend;
|
||||||
cur.request->debug << "environment variables:\n";
|
|
||||||
|
|
||||||
for( e = fcgi_request.envp ; *e ; ++e )
|
|
||||||
cur.request->debug << ' ' << *e << "\n";
|
|
||||||
|
|
||||||
cur.request->debug << '\n';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -601,7 +590,6 @@ void App::ReadRequest()
|
||||||
{
|
{
|
||||||
ReadEnvVariables();
|
ReadEnvVariables();
|
||||||
CheckRequestMethod();
|
CheckRequestMethod();
|
||||||
CheckFCGIRole();
|
|
||||||
CheckSSL();
|
CheckSSL();
|
||||||
SetSubdomain();
|
SetSubdomain();
|
||||||
|
|
||||||
|
@ -611,14 +599,14 @@ void App::ReadRequest()
|
||||||
cookie_parser.Parse(cur.request->env_http_cookie, cur.request->cookie_tab);
|
cookie_parser.Parse(cur.request->env_http_cookie, cur.request->cookie_tab);
|
||||||
accept_encoding_parser.ParseAndLog(cur.request->env_http_accept_encoding);
|
accept_encoding_parser.ParseAndLog(cur.request->env_http_accept_encoding);
|
||||||
|
|
||||||
|
if( config.log_env_variables )
|
||||||
|
LogEnvironmentVariables();
|
||||||
|
|
||||||
CheckIE();
|
CheckIE();
|
||||||
CheckKonqueror();
|
CheckKonqueror();
|
||||||
|
|
||||||
if( cur.request->using_ssl )
|
if( cur.request->using_ssl )
|
||||||
log << log3 << "App: connection secure through SSL" << logend;
|
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()
|
void App::CheckRequestMethod()
|
||||||
{
|
{
|
||||||
cur.request->method = Request::none;
|
cur.request->method = Request::unknown_method;
|
||||||
|
|
||||||
if( ToSmall(cur.request->env_request_method[0]) == 'g' )
|
if( ToSmall(cur.request->env_request_method[0]) == 'g' )
|
||||||
cur.request->method = Request::get;
|
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()
|
void App::CheckSSL()
|
||||||
{
|
{
|
||||||
|
@ -774,22 +753,21 @@ void App::PrepareSessionCookie()
|
||||||
|
|
||||||
if( !cur.session->puser || !cur.session->remember_me )
|
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
|
else
|
||||||
{
|
{
|
||||||
PT::Date expires = cur.request->start_time + config.session_remember_max_idle;
|
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;
|
size_t i = 0;
|
||||||
Item * dir = system.dirs.GetDir(system.mounts.pmount->dir_id);
|
Item * dir = system.dirs.GetDir(system.mounts.pmount->dir_id);
|
||||||
sendh_t3.clear();
|
|
||||||
|
|
||||||
if( !dir )
|
if( !dir )
|
||||||
{
|
{
|
||||||
|
@ -808,18 +786,18 @@ bool App::SendHeadersStaticCreateResource()
|
||||||
++i;
|
++i;
|
||||||
|
|
||||||
if( i > 0 )
|
if( i > 0 )
|
||||||
sendh_t3.assign(path, i);
|
out_path.write(path, i);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void App::SendHeadersStatic()
|
void App::PrepareHeadersStatic()
|
||||||
{
|
{
|
||||||
if( PathHasUpDir(cur.request->env_request_uri) )
|
if( PathHasUpDir(cur.request->env_request_uri) )
|
||||||
{
|
{
|
||||||
log << log1 << "App: incorrect path for a static file" << logend;
|
log << log1 << "App: incorrect path for a static file" << logend;
|
||||||
SendHeadersForbidden();
|
PrepareHeadersForbidden();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -829,171 +807,213 @@ void App::SendHeadersStatic()
|
||||||
if( index >= config.static_dirs.size() )
|
if( index >= config.static_dirs.size() )
|
||||||
{
|
{
|
||||||
log << log1 << "App: static dir with index " << index << " is not defined in the config" << logend;
|
log << log1 << "App: static dir with index " << index << " is not defined in the config" << logend;
|
||||||
SendHeadersForbidden();
|
PrepareHeadersForbidden();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PT::WideToUTF8(config.http_header_send_file, sendh_t);
|
PT::WTextStream path;
|
||||||
PT::WideToUTF8(config.static_dirs[index], sendh_t2);
|
path << config.static_dirs[index] << L"/";
|
||||||
|
|
||||||
if( !SendHeadersStaticCreateResource() )
|
if( !PrepareHeadersStaticCreateResource(path) )
|
||||||
{
|
{
|
||||||
SendHeadersForbidden();
|
PrepareHeadersForbidden();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FCGX_FPrintF(fcgi_request.out, "%s: %s/%s\r\n", sendh_t.c_str(), sendh_t2.c_str(), sendh_t3.c_str());
|
cur.request->out_headers.Add(config.http_header_send_file, path);
|
||||||
FCGX_PutS("Status: 200 OK\r\n", fcgi_request.out);
|
cur.request->out_headers.Add(L"Status", L"200 OK");
|
||||||
log << log2 << "App: sending a file from a static mountpoint: " << sendh_t2 << "/" << sendh_t3 << logend;
|
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 )
|
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
|
else
|
||||||
{
|
{
|
||||||
switch( config.content_type_header )
|
switch( config.content_type_header )
|
||||||
{
|
{
|
||||||
case 1:
|
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;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
FCGX_PutS("Content-Type: application/xml", fcgi_request.out);
|
value = &cur.request->out_headers.Add(L"Content-Type", L"application/xml");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
default:
|
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 )
|
if( value && config.utf8 )
|
||||||
FCGX_PutS("; charset=UTF-8", fcgi_request.out);
|
*value += L"; charset=UTF-8";
|
||||||
|
|
||||||
FCGX_PutS("\r\n", fcgi_request.out);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void App::SendHeadersForbidden()
|
void App::PrepareHeadersForbidden()
|
||||||
{
|
{
|
||||||
FCGX_PutS("Status: 403 Forbidden\r\n", fcgi_request.out);
|
cur.request->out_headers.Add(L"Status", L"403 Forbidden");
|
||||||
SendHeaderContentType();
|
PrepareHeaderContentType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void App::SendHeadersRedirect()
|
void App::PrepareHeadersRedirect()
|
||||||
{
|
{
|
||||||
switch(cur.request->redirect_type)
|
switch(cur.request->redirect_type)
|
||||||
{
|
{
|
||||||
case 300:
|
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;
|
break;
|
||||||
|
|
||||||
case 301:
|
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;
|
break;
|
||||||
|
|
||||||
case 302:
|
case 302:
|
||||||
FCGX_PutS("Status: 302 Found\r\n", fcgi_request.out);
|
cur.request->out_headers.Add(L"Status", L"302 Found");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 307:
|
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;
|
break;
|
||||||
|
|
||||||
case 303:
|
case 303:
|
||||||
default:
|
default:
|
||||||
FCGX_PutS("Status: 303 See Other\r\n", fcgi_request.out);
|
cur.request->out_headers.Add(L"Status", L"303 See Other");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
PT::WideToUTF8(cur.request->redirect_to, cur.request->aredirect_to);
|
cur.request->out_headers.Add(L"Location", cur.request->redirect_to);
|
||||||
FCGX_FPrintF(fcgi_request.out, "Location: %s\r\n", cur.request->aredirect_to.c_str());
|
log << log2 << "App: redirect to: " << cur.request->redirect_to << logend;
|
||||||
log << log2 << "App: redirect to: " << cur.request->aredirect_to << logend;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void App::SendHeadersSendFile()
|
void App::PrepareHeadersSendFile()
|
||||||
{
|
{
|
||||||
PT::WideToUTF8(config.http_header_send_file, sendfilea);
|
cur.request->out_headers.Add(L"Status", L"200 OK");
|
||||||
PT::WideToUTF8(cur.request->x_sendfile, sendfile2a);
|
cur.request->out_headers.Add(config.http_header_send_file, cur.request->x_sendfile);
|
||||||
FCGX_FPrintF(fcgi_request.out, "%s: %s\r\n", sendfilea.c_str(), sendfile2a.c_str());
|
|
||||||
|
|
||||||
FCGX_PutS("Status: 200 OK\r\n", fcgi_request.out);
|
|
||||||
log << log2 << "App: sending file: " << cur.request->x_sendfile << logend;
|
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 )
|
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
|
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 )
|
switch( header )
|
||||||
{
|
{
|
||||||
case h_404:
|
case h_404:
|
||||||
FCGX_PutS("Status: 404 Not Found\r\n", fcgi_request.out);
|
cur.request->out_headers.Add(L"Status", L"404 Not Found");
|
||||||
SendHeaderContentType();
|
PrepareHeaderContentType();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case h_403:
|
case h_403:
|
||||||
SendHeadersForbidden();
|
PrepareHeadersForbidden();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
FCGX_PutS("Status: 200 OK\r\n", fcgi_request.out);
|
cur.request->out_headers.Add(L"Status", L"200 OK");
|
||||||
|
PrepareHeaderContentType();
|
||||||
if( cur.request->role != Request::authorizer )
|
|
||||||
SendHeaderContentType();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 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();
|
PrepareSessionCookie();
|
||||||
|
|
||||||
if( cur.request->send_as_attachment )
|
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() )
|
if( !cur.request->redirect_to.empty() )
|
||||||
{
|
{
|
||||||
SendHeadersRedirect();
|
PrepareHeadersRedirect();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if( system.mounts.pmount->type == system.mounts.MountTypeStatic() )
|
if( system.mounts.pmount->type == system.mounts.MountTypeStatic() )
|
||||||
{
|
{
|
||||||
SendHeadersStatic();
|
PrepareHeadersStatic();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if( !cur.request->x_sendfile.empty() )
|
if( !cur.request->x_sendfile.empty() )
|
||||||
{
|
{
|
||||||
SendHeadersSendFile();
|
PrepareHeadersSendFile();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SendHeadersNormal(header);
|
PrepareHeadersNormal(header);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( compressing )
|
if( compressing )
|
||||||
SendHeadersCompression(compress_encoding);
|
PrepareHeadersCompression(compress_encoding);
|
||||||
|
|
||||||
FCGX_PutS(cur.request->headers.CStr(), fcgi_request.out);
|
|
||||||
FCGX_PutS("\r\n", fcgi_request.out);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 )
|
if( config.html_filter && cur.request->use_html_filter && !raw && !cur.request->return_json )
|
||||||
{
|
{
|
||||||
TemplatesFunctions::html_filter.Filter(*source, clean_html);
|
TemplatesFunctions::html_filter.Filter(*source, clean_html);
|
||||||
AddDebugInfo(clean_html);
|
|
||||||
source = &clean_html;
|
source = &clean_html;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
html_with_debug = *source;
|
html_with_debug = *source;
|
||||||
AddDebugInfo(html_with_debug);
|
|
||||||
source = &html_with_debug;
|
source = &html_with_debug;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1024,6 +1042,7 @@ void App::FilterCompressSend(bool compressing, int compress_encoding, const std:
|
||||||
else
|
else
|
||||||
AssignString(*source, source_a);
|
AssignString(*source, source_a);
|
||||||
|
|
||||||
|
// !! IMPROVE ME add to log the binary stream as well
|
||||||
if( config.log_server_answer )
|
if( config.log_server_answer )
|
||||||
log << log1 << "App: the server's answer is:\n" << source_a << "\nApp: end of the server's answer" << logend;
|
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;
|
compression_encoding = 0;
|
||||||
|
|
||||||
if( config.compression &&
|
if( config.compression &&
|
||||||
cur.request->role == Request::responder &&
|
|
||||||
cur.request->redirect_to.empty() &&
|
cur.request->redirect_to.empty() &&
|
||||||
cur.request->x_sendfile.empty() &&
|
cur.request->x_sendfile.empty() &&
|
||||||
!cur.request->browser_konqueror && /* !! sprawdzic czy Konqueror bedzie obslugiwal raw deflate */
|
!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
|
// if there is a redirect or a file to send then we do not send a content
|
||||||
return false;
|
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
|
we don't have to check the HEAD method
|
||||||
the server (lighttpd) doesn't send the body of its own
|
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;
|
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) )
|
if( CanSendContent(header) )
|
||||||
{
|
{
|
||||||
|
@ -1193,7 +1198,7 @@ void App::SendData(const BinaryPage & page, FCGX_Stream * out)
|
||||||
send_data_buf[s] = *i;
|
send_data_buf[s] = *i;
|
||||||
|
|
||||||
if( s > 0 )
|
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
|
// !! IMPROVE ME add header: content-size
|
||||||
|
|
||||||
SendHeaders(compressing, compress_encoding, header);
|
PrepareHeaders(compressing, compress_encoding, header);
|
||||||
|
|
||||||
if( CanSendContent(header) )
|
if( CanSendContent(header) )
|
||||||
{
|
{
|
||||||
|
@ -1519,6 +1524,9 @@ void App::WaitForThreads()
|
||||||
|
|
||||||
void App::FetchPageOnExit()
|
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
|
// stupid trick to break FCGX_Accept_r() function
|
||||||
// even with FCGX_InitRequest(..., ..., FCGI_FAIL_ACCEPT_ON_INTR) the FCGX_Accept_r
|
// even with FCGX_InitRequest(..., ..., FCGI_FAIL_ACCEPT_ON_INTR) the FCGX_Accept_r
|
||||||
// doesn't want to break on a signal
|
// doesn't want to break on a signal
|
||||||
|
|
27
core/app.h
27
core/app.h
|
@ -119,12 +119,11 @@ private:
|
||||||
pthread_t signal_thread;
|
pthread_t signal_thread;
|
||||||
std::string url_to_fetch_on_exit;
|
std::string url_to_fetch_on_exit;
|
||||||
std::string source_a;
|
std::string source_a;
|
||||||
std::string sendh_t, sendh_t2, sendh_t3;
|
|
||||||
std::string sendfilea, sendfile2a;
|
|
||||||
std::string send_data_buf;
|
std::string send_data_buf;
|
||||||
PT::SpaceToJSON json_generic_serializer;
|
PT::SpaceToJSON json_generic_serializer;
|
||||||
TextStream<std::wstring> json_out_stream;
|
TextStream<std::wstring> json_out_stream;
|
||||||
BinaryPage out_bin_stream_compressed;
|
BinaryPage out_bin_stream_compressed;
|
||||||
|
std::string aheader_name, aheader_value;
|
||||||
|
|
||||||
bool CheckAccessFromPlugins();
|
bool CheckAccessFromPlugins();
|
||||||
void ProcessRequestThrow();
|
void ProcessRequestThrow();
|
||||||
|
@ -146,7 +145,7 @@ private:
|
||||||
void SendBinaryAnswer();
|
void SendBinaryAnswer();
|
||||||
void SendAnswer();
|
void SendAnswer();
|
||||||
|
|
||||||
void PrintEnv();
|
void LogEnvironmentVariables();
|
||||||
|
|
||||||
void SetEnv(const char * & env, const char * name);
|
void SetEnv(const char * & env, const char * name);
|
||||||
void ReadEnvVariables();
|
void ReadEnvVariables();
|
||||||
|
@ -155,23 +154,23 @@ private:
|
||||||
void CheckIE();
|
void CheckIE();
|
||||||
void CheckKonqueror();
|
void CheckKonqueror();
|
||||||
void CheckRequestMethod();
|
void CheckRequestMethod();
|
||||||
void CheckFCGIRole();
|
|
||||||
void CheckSSL();
|
void CheckSSL();
|
||||||
void SetSubdomain();
|
void SetSubdomain();
|
||||||
|
|
||||||
|
|
||||||
void PrepareSessionCookie();
|
void PrepareSessionCookie();
|
||||||
void AddDebugInfo(std::wstring & out);
|
|
||||||
void FilterCompressSend(bool compressing, int compress_encoding, const std::wstring & source_ref);
|
void FilterCompressSend(bool compressing, int compress_encoding, const std::wstring & source_ref);
|
||||||
bool SendHeadersStaticCreateResource();
|
void SendHeaders();
|
||||||
void SendHeadersStatic();
|
void SendCookies();
|
||||||
void SendHeaderContentType();
|
bool PrepareHeadersStaticCreateResource(PT::WTextStream & out_path);
|
||||||
void SendHeadersForbidden();
|
void PrepareHeadersStatic();
|
||||||
void SendHeadersRedirect();
|
void PrepareHeaderContentType();
|
||||||
void SendHeadersSendFile();
|
void PrepareHeadersForbidden();
|
||||||
void SendHeadersCompression(int compress_encoding);
|
void PrepareHeadersRedirect();
|
||||||
void SendHeadersNormal(Header header);
|
void PrepareHeadersSendFile();
|
||||||
void SendHeaders(bool compressing, int compress_encoding, Header header);
|
void PrepareHeadersCompression(int compress_encoding);
|
||||||
|
void PrepareHeadersNormal(Header header);
|
||||||
|
void PrepareHeaders(bool compressing, int compress_encoding, Header header);
|
||||||
int SelectDeflateVersion();
|
int SelectDeflateVersion();
|
||||||
void SelectCompression(size_t source_len, bool & compression_allowed, int & compression_encoding);
|
void SelectCompression(size_t source_len, bool & compression_allowed, int & compression_encoding);
|
||||||
bool CanSendContent(Header header);
|
bool CanSendContent(Header header);
|
||||||
|
|
|
@ -118,6 +118,8 @@ void Config::AssignValues(bool stdout_is_closed)
|
||||||
log_db_query = Bool(L"log_db_query", false);
|
log_db_query = Bool(L"log_db_query", false);
|
||||||
log_plugin_call = Bool(L"log_plugin_call", false);
|
log_plugin_call = Bool(L"log_plugin_call", false);
|
||||||
log_post_value_size = Size(L"log_post_value_size", 80);
|
log_post_value_size = Size(L"log_post_value_size", 80);
|
||||||
|
log_env_variables = Bool(L"log_env_variables", false);
|
||||||
|
log_http_answer_headers = Bool(L"log_http_answer_headers", false);
|
||||||
|
|
||||||
post_file_max = Size(L"post_file_max", 8388608); // 8 MB
|
post_file_max = Size(L"post_file_max", 8388608); // 8 MB
|
||||||
|
|
||||||
|
@ -151,7 +153,7 @@ void Config::AssignValues(bool stdout_is_closed)
|
||||||
templates_index = Text(L"templates_index", L"index.html");
|
templates_index = Text(L"templates_index", L"index.html");
|
||||||
template_only_root_use_template_fun = Bool(L"template_only_root_use_template_fun", false);
|
template_only_root_use_template_fun = Bool(L"template_only_root_use_template_fun", false);
|
||||||
|
|
||||||
http_session_id_name = AText(L"http_session_id_name");
|
http_session_id_name = Text(L"http_session_id_name", L"session_id");
|
||||||
db_database = AText(L"db_database");
|
db_database = AText(L"db_database");
|
||||||
db_user = AText(L"db_user");
|
db_user = AText(L"db_user");
|
||||||
db_pass = AText(L"db_pass");
|
db_pass = AText(L"db_pass");
|
||||||
|
@ -206,7 +208,6 @@ void Config::AssignValues(bool stdout_is_closed)
|
||||||
title_separator = Text(L"title_separator", L" / ");
|
title_separator = Text(L"title_separator", L" / ");
|
||||||
|
|
||||||
http_header_send_file = Text(L"http_header_send_file", L"X-LIGHTTPD-send-file");
|
http_header_send_file = Text(L"http_header_send_file", L"X-LIGHTTPD-send-file");
|
||||||
debug_info = Bool(L"debug_info", false);
|
|
||||||
|
|
||||||
editors_html_safe_mode = Bool(L"editors_html_safe_mode", true);
|
editors_html_safe_mode = Bool(L"editors_html_safe_mode", true);
|
||||||
editors_html_safe_mode_skip_root = Bool(L"editors_html_safe_mode_skip_root", true);
|
editors_html_safe_mode_skip_root = Bool(L"editors_html_safe_mode_skip_root", true);
|
||||||
|
@ -237,6 +238,7 @@ void Config::AssignValues(bool stdout_is_closed)
|
||||||
|
|
||||||
ezc_max_elements = Size(L"ezc_max_elements", 50000);
|
ezc_max_elements = Size(L"ezc_max_elements", 50000);
|
||||||
ezc_max_loop_elements = Size(L"ezc_max_loop_elements", 5000);
|
ezc_max_loop_elements = Size(L"ezc_max_loop_elements", 5000);
|
||||||
|
ezc_out_streams_size = Size(L"ezc_out_streams_size", 16);
|
||||||
|
|
||||||
account_need_email_verification = Bool(L"account_need_email_verification", true);
|
account_need_email_verification = Bool(L"account_need_email_verification", true);
|
||||||
reset_password_code_expiration_time = Long(L"reset_password_code_expiration_time", 86400);
|
reset_password_code_expiration_time = Long(L"reset_password_code_expiration_time", 86400);
|
||||||
|
@ -259,6 +261,7 @@ void Config::AssignValues(bool stdout_is_closed)
|
||||||
incorrect_login_cannot_login_mode = Int(L"incorrect_login_cannot_login_mode", 0);
|
incorrect_login_cannot_login_mode = Int(L"incorrect_login_cannot_login_mode", 0);
|
||||||
incorrect_login_cannot_login_treshold = Size(L"incorrect_login_cannot_login_treshold", 20);
|
incorrect_login_cannot_login_treshold = Size(L"incorrect_login_cannot_login_treshold", 20);
|
||||||
incorrect_login_cannot_login_delay = Size(L"incorrect_login_cannot_login_delay", 1800);
|
incorrect_login_cannot_login_delay = Size(L"incorrect_login_cannot_login_delay", 1800);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -91,6 +91,14 @@ public:
|
||||||
// request delimiter in the log file, default "---------"
|
// request delimiter in the log file, default "---------"
|
||||||
std::wstring log_delimiter;
|
std::wstring log_delimiter;
|
||||||
|
|
||||||
|
// log environment variables (fastcgi environment)
|
||||||
|
bool log_env_variables;
|
||||||
|
|
||||||
|
// log headers (+cookies) which are returned to the client
|
||||||
|
// this is what winix has generated -- the web server can change or add other headers
|
||||||
|
// default: false
|
||||||
|
bool log_http_answer_headers;
|
||||||
|
|
||||||
// fast cgi: socket (unix domain)
|
// fast cgi: socket (unix domain)
|
||||||
std::string fcgi_socket;
|
std::string fcgi_socket;
|
||||||
|
|
||||||
|
@ -128,7 +136,7 @@ public:
|
||||||
std::string db_user;
|
std::string db_user;
|
||||||
std::string db_pass;
|
std::string db_pass;
|
||||||
|
|
||||||
std::string http_session_id_name;
|
std::wstring http_session_id_name;
|
||||||
|
|
||||||
// string used in a place where is a user (or group) selected
|
// string used in a place where is a user (or group) selected
|
||||||
std::wstring priv_no_user;
|
std::wstring priv_no_user;
|
||||||
|
@ -389,9 +397,6 @@ public:
|
||||||
// default: X-LIGHTTPD-send-file
|
// default: X-LIGHTTPD-send-file
|
||||||
std::wstring http_header_send_file;
|
std::wstring http_header_send_file;
|
||||||
|
|
||||||
// prints additional information (in the end of the html page as a commentary)
|
|
||||||
bool debug_info;
|
|
||||||
|
|
||||||
// in editors (emacs, ckeditor,...) the html will be filtered and unsafe tags
|
// in editors (emacs, ckeditor,...) the html will be filtered and unsafe tags
|
||||||
// will be dropped (script, frame, etc.)
|
// will be dropped (script, frame, etc.)
|
||||||
// default: true;
|
// default: true;
|
||||||
|
@ -485,6 +490,10 @@ public:
|
||||||
// default: 5000 (from ezc generator)
|
// default: 5000 (from ezc generator)
|
||||||
size_t ezc_max_loop_elements;
|
size_t ezc_max_loop_elements;
|
||||||
|
|
||||||
|
// how many output streams do we have in Request class
|
||||||
|
// default: 16 (64 maximum)
|
||||||
|
size_t ezc_out_streams_size;
|
||||||
|
|
||||||
// when true then when a user want to create a new account
|
// when true then when a user want to create a new account
|
||||||
// he has to provide his email and a message will be sent back to him
|
// he has to provide his email and a message will be sent back to him
|
||||||
// with a link to activate the account
|
// with a link to activate the account
|
||||||
|
@ -591,6 +600,7 @@ public:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Config();
|
Config();
|
||||||
bool ReadConfig(bool errors_to_stdout_, bool stdout_is_closed = true);
|
bool ReadConfig(bool errors_to_stdout_, bool stdout_is_closed = true);
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* This file is a part of Winix
|
* This file is a part of Winix
|
||||||
* and is not publicly distributed
|
* and is not publicly distributed
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008-2010, Tomasz Sowa
|
* Copyright (c) 2008-2013, Tomasz Sowa
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -22,6 +22,8 @@ class CookieParser : public HttpSimpleParser
|
||||||
|
|
||||||
const char * cookie_string;
|
const char * cookie_string;
|
||||||
CookieTab * cookie_tab;
|
CookieTab * cookie_tab;
|
||||||
|
std::wstring temp_name, temp_value;
|
||||||
|
bool input_as_utf8;
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -35,19 +37,29 @@ protected:
|
||||||
return (int)(unsigned char)*(cookie_string++);
|
return (int)(unsigned char)*(cookie_string++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConvStr(const std::string & src, std::wstring & dst)
|
||||||
|
{
|
||||||
|
if( input_as_utf8 )
|
||||||
|
PT::UTF8ToWide(src, dst);
|
||||||
|
else
|
||||||
|
AssignString(src, dst);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void Parameter(std::string & name, std::string & value)
|
virtual void Parameter(std::string & name, std::string & value)
|
||||||
{
|
{
|
||||||
// Cookie names are case insensitive according to section 3.1 of RFC 2965
|
// Cookie names are case insensitive according to section 3.1 of RFC 2965
|
||||||
|
// (we don't use locale here)
|
||||||
ToLower(name);
|
ToLower(name);
|
||||||
|
|
||||||
std::pair<CookieTab::iterator, bool> res = cookie_tab->insert( std::make_pair(name, value) );
|
ConvStr(name, temp_name);
|
||||||
|
ConvStr(value, temp_value);
|
||||||
|
|
||||||
log << log2 << "Cookie, name: \"" << name << "\", value: \"" << value << "\"";
|
std::pair<CookieTab::iterator, bool> res = cookie_tab->insert( std::make_pair(temp_name, temp_value) );
|
||||||
|
log << log2 << "Cookie, name: \"" << temp_name << "\", value: \"" << temp_value << "\"";
|
||||||
|
|
||||||
if( res.second == false )
|
if( res.second == false )
|
||||||
{
|
{
|
||||||
res.first->second = value;
|
res.first->second = temp_value;
|
||||||
log << " (overwritten)";
|
log << " (overwritten)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +72,7 @@ public:
|
||||||
|
|
||||||
CookieParser()
|
CookieParser()
|
||||||
{
|
{
|
||||||
|
input_as_utf8 = false;
|
||||||
HttpSimpleParser::separator = ';';
|
HttpSimpleParser::separator = ';';
|
||||||
HttpSimpleParser::value_can_be_quoted = true;
|
HttpSimpleParser::value_can_be_quoted = true;
|
||||||
HttpSimpleParser::skip_white_chars = true;
|
HttpSimpleParser::skip_white_chars = true;
|
||||||
|
@ -67,6 +80,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void UTF8(bool utf)
|
||||||
|
{
|
||||||
|
input_as_utf8 = utf;
|
||||||
|
}
|
||||||
|
|
||||||
// cookie_string can be null
|
// cookie_string can be null
|
||||||
void Parse(const char * cookie_string_, CookieTab & cookie_tab_)
|
void Parse(const char * cookie_string_, CookieTab & cookie_tab_)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* This file is a part of Winix
|
* This file is a part of Winix
|
||||||
* and is not publicly distributed
|
* and is not publicly distributed
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008-2012, Tomasz Sowa
|
* Copyright (c) 2008-2013, Tomasz Sowa
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -255,6 +255,15 @@
|
||||||
// to the resource
|
// to the resource
|
||||||
#define WINIX_CHECK_PLUGIN_ACCESS 31060
|
#define WINIX_CHECK_PLUGIN_ACCESS 31060
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -34,7 +34,12 @@ void Request::SetConfig(Config * pconfig)
|
||||||
|
|
||||||
void Request::ClearOutputStreams()
|
void Request::ClearOutputStreams()
|
||||||
{
|
{
|
||||||
out_streams.resize(16); // !! IMPROVE ME add as a constant somewhere
|
size_t len = config->ezc_out_streams_size;
|
||||||
|
|
||||||
|
if( len < 1 || len > 64 )
|
||||||
|
len = 16;
|
||||||
|
|
||||||
|
out_streams.resize(len);
|
||||||
|
|
||||||
for(size_t i=0 ; i<out_streams.size() ; ++i)
|
for(size_t i=0 ; i<out_streams.size() ; ++i)
|
||||||
out_streams[i].Clear();
|
out_streams[i].Clear();
|
||||||
|
@ -54,13 +59,10 @@ void Request::Clear()
|
||||||
post_file_tab.clear();
|
post_file_tab.clear();
|
||||||
cookie_tab.clear();
|
cookie_tab.clear();
|
||||||
|
|
||||||
method = none;
|
method = unknown_method;
|
||||||
role = responder;
|
|
||||||
|
|
||||||
headers.Clear();
|
out_headers.Clear();
|
||||||
|
out_cookies.Clear();
|
||||||
|
|
||||||
debug.Clear();
|
|
||||||
|
|
||||||
page_generated = false;
|
page_generated = false;
|
||||||
use_html_filter = true;
|
use_html_filter = true;
|
||||||
|
@ -81,7 +83,7 @@ void Request::Clear()
|
||||||
dir_tab.clear();
|
dir_tab.clear();
|
||||||
last_item = &item;
|
last_item = &item;
|
||||||
is_item = false;
|
is_item = false;
|
||||||
function = 0; // !! dodac jakas empty funkcje
|
function = 0;
|
||||||
param_tab.clear();
|
param_tab.clear();
|
||||||
anchor.clear();
|
anchor.clear();
|
||||||
|
|
||||||
|
@ -128,43 +130,6 @@ void Request::RequestStarts()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// value can be null
|
|
||||||
void Request::SetCookie(const char * name, const char * value, PT::Date * expires)
|
|
||||||
{
|
|
||||||
headers << "Set-Cookie: " << name << "=";
|
|
||||||
|
|
||||||
if( value && value[0]!=0 )
|
|
||||||
headers << value;
|
|
||||||
else
|
|
||||||
headers << "\"\"";
|
|
||||||
|
|
||||||
if( expires )
|
|
||||||
headers << "; expires=" << DateToStrCookie(*expires) << " GMT";
|
|
||||||
|
|
||||||
headers << "; path=/; domain=" << config->base_url << "\r\n";
|
|
||||||
|
|
||||||
/*
|
|
||||||
don't use '; secure' flag if you are using both sites (with SSL
|
|
||||||
and without SSL) -- with secure flag the cookie is sent only through
|
|
||||||
SSL and if you accidentally open a new window without SSL (http://)
|
|
||||||
then winix will create a new session for you and the previous session (https://)
|
|
||||||
will be lost (cookie is overwritten on the client browser)
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Request::SetCookie(const char * name, long value, PT::Date * expires)
|
|
||||||
{
|
|
||||||
headers << "Set-Cookie: " << name << "=" << value;
|
|
||||||
|
|
||||||
if( expires )
|
|
||||||
headers << "; expires=" << DateToStrCookie(*expires) << " GMT";
|
|
||||||
|
|
||||||
headers << "; path=/; domain=" << config->base_url << "\r\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool Request::IsPostVar(const wchar_t * var)
|
bool Request::IsPostVar(const wchar_t * var)
|
||||||
{
|
{
|
||||||
|
|
332
core/request.h
332
core/request.h
|
@ -22,6 +22,7 @@
|
||||||
#include "date/date.h"
|
#include "date/date.h"
|
||||||
#include "space/space.h"
|
#include "space/space.h"
|
||||||
#include "space/spacetojson.h"
|
#include "space/spacetojson.h"
|
||||||
|
#include "textstream/textstream.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,23 +33,164 @@ class FunctionBase;
|
||||||
|
|
||||||
struct Request
|
struct Request
|
||||||
{
|
{
|
||||||
// request id
|
/*
|
||||||
// is incremented for each request and is never 0
|
request id
|
||||||
// (from -1 will be incremented twice)
|
is incremented for each request and is never 0
|
||||||
// it's used for some optimalizations e.g. in templates
|
(from -1 will be incremented to one)
|
||||||
|
it's used for some optimizations e.g. in templates
|
||||||
|
*/
|
||||||
size_t id;
|
size_t id;
|
||||||
|
|
||||||
// !! moze pozbyc sie tego none?
|
|
||||||
enum Method { get, post, head, none } method;
|
|
||||||
enum Role { responder, authorizer } role;
|
|
||||||
|
|
||||||
// headers, page and debug
|
/*
|
||||||
//std::ostringstream headers, page, debug;
|
request start time
|
||||||
// !! IMPROVE ME change headers to some kind of a map, may PT::Space ?
|
Time() methods are very slow so it is better to directly use those two values
|
||||||
TextStream<std::string> headers;
|
they are set when a request starts
|
||||||
HtmlTextStream debug;
|
*/
|
||||||
|
time_t start_time;
|
||||||
|
PT::Date start_date;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* variables representing input from client's browser
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
the HTTP method
|
||||||
|
!! IMPROVE ME add the rest methods here
|
||||||
|
*/
|
||||||
|
enum Method { get, post, head, unknown_method } method;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
subdomain
|
||||||
|
subdomain = HTTP_HOST environment variable - config->base_url
|
||||||
|
*/
|
||||||
|
std::wstring subdomain;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
raw parameters
|
||||||
|
!! CHECK ME may post_tab and cookie_tab should be changed to PT::Space now?
|
||||||
|
or may change the name to cookie_in? or in_cookie?
|
||||||
|
*/
|
||||||
|
PostTab post_tab;
|
||||||
|
PostFileTab post_file_tab;
|
||||||
|
CookieTab cookie_tab;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
html anchor (those part of URI after '#' character)
|
||||||
|
*/
|
||||||
|
std::wstring anchor;
|
||||||
|
|
||||||
|
|
||||||
|
// environment variables
|
||||||
|
// they are not null -- when the server doesn't have such a variable
|
||||||
|
// it will be pointing into 'char_empty' which is default '\0'
|
||||||
|
// !! IMPROVE ME change it to std::wstring, or may PT::Space too?
|
||||||
|
const char * env_request_method;
|
||||||
|
const char * env_request_uri;
|
||||||
|
const char * env_http_cookie;
|
||||||
|
const char * env_remote_addr;
|
||||||
|
const char * env_http_host;
|
||||||
|
const char * env_http_user_agent;
|
||||||
|
const char * env_http_accept_encoding;
|
||||||
|
const char * env_fcgi_role;
|
||||||
|
const char * env_content_type;
|
||||||
|
const char * env_https;
|
||||||
|
|
||||||
|
// current IP address of the remote host (read from REMOTE_ADDR environment variable)
|
||||||
|
// (at the moment only IPv4 are supported)
|
||||||
|
int ip;
|
||||||
|
|
||||||
|
// true if the browser is Microsoft Internet Explorer
|
||||||
|
bool browser_msie;
|
||||||
|
|
||||||
|
// true if the browser is Konqueror
|
||||||
|
bool browser_konqueror;
|
||||||
|
|
||||||
|
// true if we are using an encrypted connection (SSL)
|
||||||
|
bool using_ssl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
request input variables representing the winix filesystem
|
||||||
|
*/
|
||||||
|
|
||||||
|
// current directory
|
||||||
|
std::vector<Item*> dir_tab;
|
||||||
|
|
||||||
|
// true if a file exists
|
||||||
|
bool is_item;
|
||||||
|
|
||||||
|
// current file (valid if is_item is true)
|
||||||
|
Item item;
|
||||||
|
|
||||||
|
// current winix function
|
||||||
|
// null if there is no a function
|
||||||
|
FunctionBase * function;
|
||||||
|
|
||||||
|
// parameters (name:value)
|
||||||
|
// !! CHECK ME may it should be changed to PT::Space?
|
||||||
|
ParamTab param_tab;
|
||||||
|
|
||||||
|
// this is a pointer either to the item (if exists) or to the last directory
|
||||||
|
Item * last_item;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* variables for generating output to the client's browser
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// request status
|
||||||
|
// !! CHANGE ME it'll be better to use ordinary http result codes
|
||||||
|
Error status;
|
||||||
|
|
||||||
|
|
||||||
|
// if not empty means an address for redirecting to
|
||||||
|
// it should be url-encoded
|
||||||
|
std::wstring redirect_to;
|
||||||
|
|
||||||
|
|
||||||
|
// a redirect type
|
||||||
|
// following redirect types are supported:
|
||||||
|
// 300 Multiple Choices
|
||||||
|
// 301 Moved Permanently
|
||||||
|
// 302 Found
|
||||||
|
// 303 See Other (default)
|
||||||
|
// 307 Temporary Redirect
|
||||||
|
int redirect_type;
|
||||||
|
|
||||||
|
// send header X-LIGHTTPD-send-file with path to a file
|
||||||
|
std::wstring x_sendfile;
|
||||||
|
|
||||||
|
// send as attachment (causes generating header: content-disposition: attachment)
|
||||||
|
bool send_as_attachment;
|
||||||
|
|
||||||
|
// headers send to the client (without cookies)
|
||||||
|
PT::Space out_headers;
|
||||||
|
|
||||||
|
// cookies send to the client
|
||||||
|
// a value can be either a cookie value or the whole cookie string (with domain, date etc)
|
||||||
|
PT::Space out_cookies;
|
||||||
|
|
||||||
// winix can return either a text answer or a binary answer
|
// winix can return either a text answer or a binary answer
|
||||||
// if send_bin_stream is true then the binary answer is sent (out_bin_stream)
|
// if send_bin_stream is true then the binary answer is sent (out_bin_stream)
|
||||||
// or if send_bin_stream is false then the text answer is sent
|
// or if send_bin_stream is false then the text answer is sent
|
||||||
|
@ -147,100 +289,7 @@ struct Request
|
||||||
// default: true
|
// default: true
|
||||||
bool use_html_filter;
|
bool use_html_filter;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// raw parameters
|
|
||||||
PostTab post_tab;
|
|
||||||
PostFileTab post_file_tab;
|
|
||||||
CookieTab cookie_tab;
|
|
||||||
|
|
||||||
// html anchor (those part of URI after '#' character)
|
|
||||||
std::wstring anchor;
|
|
||||||
|
|
||||||
// environment variables
|
|
||||||
// they are not null -- when the server doesn't have such a variable
|
|
||||||
// it will be pointing into 'char_empty' which is default '\0'
|
|
||||||
const char * env_request_method;
|
|
||||||
const char * env_request_uri;
|
|
||||||
const char * env_http_cookie;
|
|
||||||
const char * env_remote_addr;
|
|
||||||
const char * env_http_host;
|
|
||||||
const char * env_http_user_agent;
|
|
||||||
const char * env_http_accept_encoding;
|
|
||||||
const char * env_fcgi_role;
|
|
||||||
const char * env_content_type;
|
|
||||||
const char * env_https;
|
|
||||||
|
|
||||||
// current IP address of the remote host (read from REMOTE_ADDR environment variable)
|
|
||||||
// (at the moment only IPv4 are supported)
|
|
||||||
int ip;
|
|
||||||
|
|
||||||
// true if the browser is Microsoft Internet Explorer
|
|
||||||
bool browser_msie;
|
|
||||||
|
|
||||||
// true if the browser is Konqueror
|
|
||||||
bool browser_konqueror;
|
|
||||||
|
|
||||||
// true if we are using encrypted connection (SSL)
|
|
||||||
bool using_ssl;
|
|
||||||
|
|
||||||
// current directory
|
|
||||||
std::vector<Item*> dir_tab;
|
|
||||||
|
|
||||||
// true if a file exists
|
|
||||||
bool is_item;
|
|
||||||
|
|
||||||
// current file (if exists)
|
|
||||||
Item item;
|
|
||||||
|
|
||||||
// current winix function
|
|
||||||
// null if there is no a function
|
|
||||||
FunctionBase * function;
|
|
||||||
|
|
||||||
// parameters (name:value)
|
|
||||||
ParamTab param_tab;
|
|
||||||
|
|
||||||
// request status
|
|
||||||
Error status;
|
|
||||||
|
|
||||||
// usually items in the current directory (depends on the function)
|
|
||||||
std::vector<Item> item_tab;
|
|
||||||
|
|
||||||
// if not empty means an address for redirecting to
|
|
||||||
// it should be url-encoded
|
|
||||||
std::wstring redirect_to;
|
|
||||||
std::string aredirect_to;
|
|
||||||
|
|
||||||
// a redirect type
|
|
||||||
// following redirect types are supported:
|
|
||||||
// 300 Multiple Choices
|
|
||||||
// 301 Moved Permanently
|
|
||||||
// 302 Found
|
|
||||||
// 303 See Other (default)
|
|
||||||
// 307 Temporary Redirect
|
|
||||||
int redirect_type;
|
|
||||||
|
|
||||||
// send header X-LIGHTTPD-send-file with path to a file
|
|
||||||
std::wstring x_sendfile;
|
|
||||||
|
|
||||||
// send as attachment (causes header: content-disposition: attachment)
|
|
||||||
bool send_as_attachment;
|
|
||||||
|
|
||||||
// this is a pointer either to the item (if exists) or to the last directory
|
|
||||||
Item * last_item;
|
|
||||||
|
|
||||||
// request start time
|
|
||||||
// Time() methods are very slow so it is better to directly use those two values
|
|
||||||
// they are set when a request starts
|
|
||||||
time_t start_time;
|
|
||||||
PT::Date start_date;
|
|
||||||
|
|
||||||
// a subdomain
|
|
||||||
// subdomain = HTTP_HOST environment variable - config->base_url
|
|
||||||
std::wstring subdomain;
|
|
||||||
|
|
||||||
// if this variable is true then winix always return 200 OK header
|
// if this variable is true then winix always return 200 OK header
|
||||||
// when the status would be 404 (not found) or 403 (permission denied)
|
// when the status would be 404 (not found) or 403 (permission denied)
|
||||||
// default: false
|
// default: false
|
||||||
|
@ -252,6 +301,24 @@ struct Request
|
||||||
bool gen_use_special_chars;
|
bool gen_use_special_chars;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
additional variables used for common uses
|
||||||
|
*/
|
||||||
|
|
||||||
|
// usually items in the current directory (depends on the function)
|
||||||
|
std::vector<Item> item_tab;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Request();
|
Request();
|
||||||
void SetConfig(Config * pconfig);
|
void SetConfig(Config * pconfig);
|
||||||
void RequestStarts();
|
void RequestStarts();
|
||||||
|
@ -261,29 +328,32 @@ struct Request
|
||||||
|
|
||||||
bool IsParam(const wchar_t * param_name);
|
bool IsParam(const wchar_t * param_name);
|
||||||
bool IsParam(const std::wstring & param_name);
|
bool IsParam(const std::wstring & param_name);
|
||||||
|
|
||||||
const std::wstring & ParamValue(const wchar_t * param_name); // returns an empty string if there is no such a parameter
|
const std::wstring & ParamValue(const wchar_t * param_name); // returns an empty string if there is no such a parameter
|
||||||
const std::wstring & ParamValue(const std::wstring & param_name); // returns an empty string if there is no such a parameter
|
const std::wstring & ParamValue(const std::wstring & param_name); // returns an empty string if there is no such a parameter
|
||||||
|
|
||||||
void SetCookie(const char * name, const char * value, PT::Date * expires = 0);
|
|
||||||
void SetCookie(const char * name, long value, PT::Date * expires = 0);
|
|
||||||
|
|
||||||
bool IsPostVar(const wchar_t * var);
|
bool IsPostVar(const wchar_t * var);
|
||||||
bool IsPostVar(const std::wstring & var);
|
bool IsPostVar(const std::wstring & var);
|
||||||
|
|
||||||
const std::wstring & PostVar(const wchar_t * var); // returns an empty string if there is no such a parameter
|
const std::wstring & PostVar(const wchar_t * var); // returns an empty string if there is no such a parameter
|
||||||
const std::wstring & PostVar(const std::wstring & var); // returns an empty string if there is no such a parameter
|
const std::wstring & PostVar(const std::wstring & var); // returns an empty string if there is no such a parameter
|
||||||
|
|
||||||
|
|
||||||
bool PostVar(const wchar_t * var, std::wstring & result);
|
bool PostVar(const wchar_t * var, std::wstring & result);
|
||||||
bool PostVar(const std::wstring & var, std::wstring & result);
|
bool PostVar(const std::wstring & var, std::wstring & result);
|
||||||
|
|
||||||
std::wstring * PostVarp(const wchar_t * var);
|
std::wstring * PostVarp(const wchar_t * var);
|
||||||
std::wstring * PostVarp(const std::wstring & var);
|
std::wstring * PostVarp(const std::wstring & var);
|
||||||
|
|
||||||
bool AllPostVarEmpty(); // returning true if all post vars are empty
|
bool AllPostVarEmpty(); // returning true if all post vars are empty
|
||||||
|
|
||||||
void SendAll();
|
|
||||||
|
// setting a cookie
|
||||||
|
// name - cookie name (either const wchar_t, or std::wstring or PT::WTextStream)
|
||||||
|
// value - cookie value (can be everything which can be put to PT::WTextStream stream)
|
||||||
|
// the return std::wstring reference is a reference to the cookie inserted value (in out_cookies structure)
|
||||||
|
template<typename NameType, typename ValueType>
|
||||||
|
std::wstring & AddCookie(const NameType & name, const ValueType & value, PT::Date * expires = 0);
|
||||||
|
|
||||||
|
template<typename NameType, typename ValueType>
|
||||||
|
std::wstring & AddCookie(const NameType & name, const ValueType & value, PT::Date & expires);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -303,8 +373,42 @@ private:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<typename NameType, typename ValueType>
|
||||||
|
std::wstring & Request::AddCookie(const NameType & name, const ValueType & value, PT::Date * expires)
|
||||||
|
{
|
||||||
|
PT::WTextStream cookie;
|
||||||
|
|
||||||
|
cookie << value;
|
||||||
|
|
||||||
|
if( cookie.empty() )
|
||||||
|
cookie << L"\"\""; // cookie empty value
|
||||||
|
|
||||||
|
if( expires )
|
||||||
|
cookie << L"; expires=" << DateToStrCookie(*expires) << L" GMT";
|
||||||
|
|
||||||
|
cookie << L"; path=/; domain=" << config->base_url;
|
||||||
|
|
||||||
|
/*
|
||||||
|
!! IMPROVE ME add an option to the config
|
||||||
|
|
||||||
|
don't use '; secure' flag if you are using both sites (with SSL
|
||||||
|
and without SSL) -- with secure flag the cookie is sent only through
|
||||||
|
SSL and if you accidentally open a new window without SSL (http://)
|
||||||
|
then winix will create a new session for you and the previous session (https://)
|
||||||
|
will be lost (the session cookie will be overwritten in the client's browser)
|
||||||
|
*/
|
||||||
|
|
||||||
|
return out_cookies.Add(name, cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename NameType, typename ValueType>
|
||||||
|
std::wstring & Request::AddCookie(const NameType & name, const ValueType & value, PT::Date & expires)
|
||||||
|
{
|
||||||
|
return AddCookie(name, value, &expires);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* This file is a part of Winix
|
* This file is a part of Winix
|
||||||
* and is not publicly distributed
|
* and is not publicly distributed
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008-2011, Tomasz Sowa
|
* Copyright (c) 2008-2013, Tomasz Sowa
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -16,6 +16,7 @@
|
||||||
#include "textstream/textstream.h"
|
#include "textstream/textstream.h"
|
||||||
|
|
||||||
|
|
||||||
|
// !! IMPROVE ME
|
||||||
// !! narazie uzywane tylko w post multi parserze
|
// !! narazie uzywane tylko w post multi parserze
|
||||||
// dodac do zwyklego parsera post
|
// dodac do zwyklego parsera post
|
||||||
#define WINIX_POSTTABLE_MAXSIZE 50
|
#define WINIX_POSTTABLE_MAXSIZE 50
|
||||||
|
@ -43,7 +44,7 @@ typedef std::map<std::wstring, std::wstring> PostTab;
|
||||||
typedef std::map<std::wstring, PostFile> PostFileTab;
|
typedef std::map<std::wstring, PostFile> PostFileTab;
|
||||||
typedef std::vector<Param> ParamTab;
|
typedef std::vector<Param> ParamTab;
|
||||||
|
|
||||||
typedef std::map<std::string, std::string> CookieTab;
|
typedef std::map<std::wstring, std::wstring> CookieTab;
|
||||||
|
|
||||||
|
|
||||||
typedef PT::TextStreamBase<char, 1, 4096> BinaryPage;
|
typedef PT::TextStreamBase<char, 1, 4096> BinaryPage;
|
||||||
|
|
|
@ -157,7 +157,7 @@ void SessionManager::SetTemporarySession()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool SessionManager::SetSessionFromCookie(const std::string & cookie)
|
bool SessionManager::SetSessionFromCookie(const std::wstring & cookie)
|
||||||
{
|
{
|
||||||
long id = Tol(cookie.c_str());
|
long id = Tol(cookie.c_str());
|
||||||
SessionContainer::Iterator s = session_tab.FindById(id);
|
SessionContainer::Iterator s = session_tab.FindById(id);
|
||||||
|
|
|
@ -88,7 +88,7 @@ private:
|
||||||
|
|
||||||
long CreateSessionId();
|
long CreateSessionId();
|
||||||
void CreateSession();
|
void CreateSession();
|
||||||
bool SetSessionFromCookie(const std::string & cookie);
|
bool SetSessionFromCookie(const std::wstring & cookie);
|
||||||
void SetTemporarySession();
|
void SetTemporarySession();
|
||||||
|
|
||||||
// second thread
|
// second thread
|
||||||
|
|
Loading…
Reference in New Issue