the first part of reimplementing has been done
now we have app object and singletons are only: log logn plugin and app git-svn-id: svn://ttmath.org/publicrep/winix/trunk@628 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
398
core/app.cpp
Executable file
398
core/app.cpp
Executable file
@@ -0,0 +1,398 @@
|
||||
/*
|
||||
* This file is a part of Winix
|
||||
* and is not publicly distributed
|
||||
*
|
||||
* Copyright (c) 2010, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "app.h"
|
||||
#include "plugin.h"
|
||||
|
||||
|
||||
|
||||
App::App()
|
||||
{
|
||||
stdout_is_closed = false;
|
||||
last_sessions_save = time(0);
|
||||
|
||||
plugin.SetDb(&db);
|
||||
plugin.SetConfig(&config);
|
||||
plugin.SetRequest(&request);
|
||||
plugin.SetSystem(&system);
|
||||
plugin.SetFunctions(&functions);
|
||||
plugin.SetTemplates(&templates);
|
||||
plugin.SetSessionManager(&session_manager);
|
||||
|
||||
request.SetConfig(&config);
|
||||
|
||||
functions.SetConfig(&config);
|
||||
functions.SetRequest(&request);
|
||||
functions.SetDb(&db);
|
||||
functions.SetSystem(&system);
|
||||
functions.SetTemplates(&templates);
|
||||
functions.SetNotify(¬ify);
|
||||
|
||||
system.SetConfig(&config);
|
||||
system.SetRequest(&request);
|
||||
system.SetDb(&db);
|
||||
system.SetFunctions(&functions); // !! czy model musi cos wiedziec o funkcjach?
|
||||
system.SetTemplates(&templates);
|
||||
|
||||
templates_notify.SetConfig(&config);
|
||||
|
||||
notify.SetRequest(&request);
|
||||
notify.SetConfig(&config);
|
||||
notify.SetSystem(&system);
|
||||
notify.SetTemplatesNotify(&templates_notify);
|
||||
|
||||
templates.SetConfig(&config);
|
||||
templates.SetRequest(&request);
|
||||
templates.SetDb(&db);
|
||||
templates.SetSystem(&system);
|
||||
templates.SetFunctions(&functions);
|
||||
templates.SetSessionManager(&session_manager);
|
||||
|
||||
session_manager.SetLastContainer(&system.users.last);
|
||||
session_manager.SetConfig(&config);
|
||||
session_manager.SetRequest(&request);
|
||||
session_manager.SetSystem(&system);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool App::CreateFCGISocket()
|
||||
{
|
||||
const char * sock = config.fcgi_socket.c_str();
|
||||
|
||||
unlink(sock);
|
||||
|
||||
|
||||
|
||||
int s = FCGX_OpenSocket(sock, 10);
|
||||
|
||||
if( s < 0 )
|
||||
{
|
||||
log << log1 << "An error during creating a socket" << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
chmod(sock, config.fcgi_socket_chmod);
|
||||
|
||||
passwd * pw = getpwnam(config.fcgi_socket_user.c_str());
|
||||
|
||||
if( !pw )
|
||||
{
|
||||
log << log1 << "There is no user: " << config.fcgi_socket_user << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
group * gr = getgrnam(config.fcgi_socket_group.c_str());
|
||||
|
||||
if( !gr )
|
||||
{
|
||||
log << log1 << "There is no group: " << config.fcgi_socket_group << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
chown(sock, pw->pw_uid, gr->gr_gid);
|
||||
|
||||
|
||||
if( setuid(pw->pw_uid) < 0 )
|
||||
{
|
||||
log << log1 << "I can't change the user into: " << config.fcgi_socket_user << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
if( setgid(gr->gr_gid) < 0 )
|
||||
{
|
||||
int e = errno;
|
||||
|
||||
log << log1 << "I can't change the group into: " << config.fcgi_socket_group << " " << gr->gr_gid << logend;
|
||||
log << log1 << "errno: " << e << logend;
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
dup2(s, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool App::Init()
|
||||
{
|
||||
request.Init();
|
||||
|
||||
if( !CreateFCGISocket() )
|
||||
return false;
|
||||
|
||||
system.Init();
|
||||
|
||||
functions.Create();
|
||||
|
||||
// !! teraz mamy dwa katalogi z templetami
|
||||
// !! o co chodzilo?
|
||||
if( !notify.Init() )
|
||||
return false;
|
||||
|
||||
|
||||
templates.ReadIndexFileNames();
|
||||
templates.ReadTemplates();
|
||||
templates.CreateFunctions();
|
||||
|
||||
|
||||
session_manager.LoadSessions();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void App::Close()
|
||||
{
|
||||
session_manager.SaveSessions();
|
||||
session_manager.DeleteAllPluginsData();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool App::BaseUrlRedirect()
|
||||
{
|
||||
if( request.role == Request::responder )
|
||||
{
|
||||
if( config.base_url_http_host.empty() )
|
||||
return false;
|
||||
|
||||
if( config.base_url_http_host == request.env_http_host )
|
||||
return false;
|
||||
|
||||
request.redirect_to = config.base_url + request.env_request_uri;
|
||||
}
|
||||
else
|
||||
{
|
||||
// authorizer
|
||||
|
||||
if( config.base_url_auth_http_host.empty() )
|
||||
return false;
|
||||
|
||||
if( config.base_url_auth_http_host == request.env_http_host )
|
||||
return false;
|
||||
|
||||
request.redirect_to = config.base_url_auth + request.env_request_uri;
|
||||
}
|
||||
|
||||
log << log3 << "RC: BaseUrlRedirect from: " << request.env_http_host << logend;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void App::ProcessRequest()
|
||||
{
|
||||
request.Clear();
|
||||
request.Read();
|
||||
|
||||
// when BaseUrlRedirect() return true we didn't have to set everything in request.Read()
|
||||
// in the future request.Read() can be split and at the beginning only environment variables will be read
|
||||
// and then BaseUrlRedirect() will be called (for performance)
|
||||
if( !BaseUrlRedirect() )
|
||||
{
|
||||
session_manager.DeleteOldSessions();
|
||||
session_manager.SetSession(); // set request.session as well
|
||||
|
||||
// !! tutaj dodac to ustawianie request.session
|
||||
|
||||
functions.Parse();
|
||||
|
||||
system.mounts.CalcCurMount();
|
||||
|
||||
ReadAdditionalInfo();
|
||||
Make();
|
||||
}
|
||||
|
||||
request.SendAll(); // !! czemu request sam sie chce wyslac? wrzucic to tutaj do app
|
||||
notify.ItemChanged(request.notify_code);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void App::Start()
|
||||
{
|
||||
while( FCGX_Accept(&request.in, &request.out, &request.err, &request.env) == 0 )
|
||||
{
|
||||
system.load_avg.StartRequest();
|
||||
log << log2 << "---------------------------------------------------------------------------------" << logend;
|
||||
|
||||
try
|
||||
{
|
||||
ProcessRequest();
|
||||
}
|
||||
catch(const std::logic_error & e)
|
||||
{
|
||||
log << log1 << "std logic exception: " << e.what() << logend;
|
||||
}
|
||||
catch(const std::exception & e)
|
||||
{
|
||||
log << log1 << "std exception: " << e.what() << logend;
|
||||
}
|
||||
catch(const Error & e)
|
||||
{
|
||||
log << log1 << "exception: Error: " << e << logend;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
log << log1 << "uncaught unknown exception" << logend;
|
||||
}
|
||||
|
||||
SaveSessionsIfNeeded();
|
||||
|
||||
// !! this should be immediately after FCGX_Accept() but signals don't want to break FCGX_Accept
|
||||
//if( signal_hup )
|
||||
if( false )
|
||||
{
|
||||
log << logsave;
|
||||
FCGX_Finish();
|
||||
return;
|
||||
}
|
||||
|
||||
request.ClearPostFileTmp();
|
||||
system.load_avg.StopRequest();
|
||||
log << logsave;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void App::SaveSessionsIfNeeded()
|
||||
{
|
||||
time_t t = time(0);
|
||||
|
||||
if( last_sessions_save + 86400 > t )
|
||||
return;
|
||||
|
||||
// saving once a day for safety
|
||||
last_sessions_save = t;
|
||||
session_manager.SaveSessions();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// !! zmienic na lepsza nazwe
|
||||
void App::MakePage()
|
||||
{
|
||||
bool sent = false;
|
||||
|
||||
if( !request.redirect_to.empty() || !request.x_sendfile.empty() )
|
||||
return;
|
||||
|
||||
|
||||
if( request.is_item && request.item.auth == Item::auth_none &&
|
||||
request.item.content_type == Item::ct_raw && request.status == WINIX_ERR_OK && request.pfunction )
|
||||
{
|
||||
if( request.pfunction->fun.url == "cat" )
|
||||
{
|
||||
request.page << request.item.content;
|
||||
sent = true;
|
||||
}
|
||||
else
|
||||
if( request.pfunction->fun.url == "run" )
|
||||
{
|
||||
templates.GenerateRunRaw();
|
||||
sent = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( !sent )
|
||||
{
|
||||
templates.Generate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void App::Make()
|
||||
{
|
||||
if( request.dir_table.empty() )
|
||||
{
|
||||
log << log1 << "Content: there is no a root dir (dir_table is empty)" << logend;
|
||||
return;
|
||||
}
|
||||
|
||||
// request->status can be changed by function_parser
|
||||
if( request.status == WINIX_ERR_OK )
|
||||
{
|
||||
if( system.DirsHaveReadExecPerm() )
|
||||
{
|
||||
if( request.method == Request::post )
|
||||
functions.MakePost();
|
||||
|
||||
if( request.redirect_to.empty() && request.status == WINIX_ERR_OK )
|
||||
functions.MakeGet();
|
||||
}
|
||||
else
|
||||
request.status = WINIX_ERR_PERMISSION_DENIED;
|
||||
}
|
||||
|
||||
if( request.session->spam_score > 0 )
|
||||
log << log1 << "App: spam score: " << request.session->spam_score << logend;
|
||||
|
||||
if( request.IsParam("noredirect") )
|
||||
request.redirect_to.clear();
|
||||
|
||||
if( !request.redirect_to.empty() )
|
||||
return;
|
||||
|
||||
if( request.dir_table.empty() )
|
||||
{
|
||||
log << log1 << "App: there is no a root dir (dir_table is empty -- after calling a function)" << logend;
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.Call(WINIX_CONTENT_MAKE);
|
||||
MakePage();
|
||||
|
||||
// !! dodac parametr do konfiga wlaczajacy te informacje
|
||||
//request->PrintGetTable();
|
||||
//request->PrintEnv();
|
||||
//request->PrintIn();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// !! dac lepsza nazwe i czy napewno w app to ma byc?
|
||||
void App::ReadAdditionalInfo()
|
||||
{
|
||||
if( request.dir_table.empty() )
|
||||
return;
|
||||
|
||||
if( system.mounts.pmount->type == Mount::thread )
|
||||
{
|
||||
if( db.GetThreadByDirId(request.dir_table.back()->id, request.thread) == WINIX_ERR_OK )
|
||||
request.is_thread = true;
|
||||
}
|
||||
else
|
||||
if( system.mounts.pmount->type == Mount::ticket )
|
||||
{
|
||||
if( db.GetTicketByDirId(request.dir_table.back()->id, request.ticket) == WINIX_ERR_OK )
|
||||
{
|
||||
request.is_ticket = true;
|
||||
|
||||
if( !request.is_item && (!request.pfunction || request.pfunction->fun.url == "ticket") )
|
||||
{
|
||||
db.GetItemById(request.ticket.item_id, request.item);
|
||||
// don't set request->is_item here
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user