@ -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 : : unk now n_m ethod ;
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 - > Set Cookie( config . http_session_id_name . c_str ( ) , cur . session - > id ) ;
cur . request - > Add Cookie( config . http_session_id_name , cur . session - > id ) ;
}
else
{
PT : : Date expires = cur . request - > start_time + config . session_remember_max_idle ;
cur . request - > Set Cookie( config . http_session_id_name .c_str ( ) , cur . session - > id , & expires ) ;
cur . request - > Add Cookie( 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 : : Send HeadersStatic( )
void App : : Prepare HeadersStatic( )
{
if ( PathHasUpDir ( cur . request - > env_request_uri ) )
{
log < < log1 < < " App: incorrect path for a static file " < < logend ;
Send HeadersForbidden( ) ;
Prepare HeadersForbidden( ) ;
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 ;
Send HeadersForbidden( ) ;
Prepare HeadersForbidden( ) ;
return ;
}
PT : : W ideToUTF8( config . http_header_send_file , sendh_t ) ;
PT: : WideToUTF8 ( config . static_dirs [ index ] , sendh_t2 ) ;
PT : : W TextStream path ;
path < < config . static_dirs [ index ] < < L " / " ;
if ( ! SendHeadersStaticCreateResource( ) )
if ( ! PrepareHeadersStaticCreateResource( path ) )
{
Send HeadersForbidden( ) ;
Prepare HeadersForbidden( ) ;
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 : : Send HeaderContentType( )
void App : : Prepare HeaderContentType( )
{
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 : : Send HeadersForbidden( )
void App : : Prepare HeadersForbidden( )
{
FCGX_PutS( " Status: 403 Forbidden \r \n " , fcgi_request . out ) ;
Send HeaderContentType( ) ;
cur. request - > out_headers . Add ( L " Status " , L " 403 Forbidden " ) ;
Prepare HeaderContentType( ) ;
}
void App : : Send HeadersRedirect( )
void App : : Prepare HeadersRedirect( )
{
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 : : Send HeadersSendFile( )
void App : : Prepare HeadersSendFile( )
{
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 : : Send HeadersCompression( int compress_encoding )
void App : : Prepare HeadersCompression( 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 : : Send HeadersNormal( Header header )
void App : : Prepare HeadersNormal( Header header )
{
switch ( header )
{
case h_404 :
FCGX_PutS( " Status: 404 Not Found \r \n " , fcgi_request . out ) ;
Send HeaderContentType( ) ;
cur. request - > out_headers . Add ( L " Status " , L " 404 Not Found " ) ;
Prepare HeaderContentType( ) ;
break ;
case h_403 :
Send HeadersForbidden( ) ;
Prepare HeadersForbidden( ) ;
break ;
default :
FCGX_PutS ( " Status: 200 OK \r \n " , fcgi_request . out ) ;
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 ;
plugin . Call ( WINIX_PREPARE_TO_SEND_HTTP_HEADERS , & headers ) ;
if ( cur . request - > role ! = Request : : authorizer )
SendHeaderContentType ( ) ;
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 : : SendHeaders ( bool compressing , int compress_encoding , Header header )
void App : : Prepare Headers( 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 ( ) ;
Prepare HeadersRedirect( ) ;
}
else
if ( system . mounts . pmount - > type = = system . mounts . MountTypeStatic ( ) )
{
SendHeadersStatic ( ) ;
Prepare HeadersStatic( ) ;
}
else
if ( ! cur . request - > x_sendfile . empty ( ) )
{
SendHeadersSendFile ( ) ;
Prepare HeadersSendFile( ) ;
}
else
{
Send HeadersNormal( header ) ;
Prepare HeadersNormal( 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 < < " \n App: 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
Send Headers( compressing , compress_encoding , header ) ;
Prepare Headers( 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