added: a new mount type: static

some path in winix can be redirected to a specified static directory


git-svn-id: svn://ttmath.org/publicrep/winix/trunk@738 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
Tomasz Sowa 2011-06-14 23:45:42 +00:00
parent fb4742e165
commit c49c35cfbd
15 changed files with 355 additions and 31 deletions

View File

@ -211,10 +211,11 @@ void App::ProcessRequestThrow()
plugin.Call(WINIX_SESSION_CHANGED);
functions.Parse();
functions.Parse(); // parsing directories,files,functions and parameters
system.mounts.CalcCurMount();
Make();
if( system.mounts.pmount->type != system.mounts.MountTypeStatic() )
Make();
}
SendAnswer();
@ -418,15 +419,15 @@ void App::ReadEnvVariables()
// we store that values because FCGX_GetParam has O(n) complexity
// with this variables (env_*) we have O(1)
SetEnv(cur.request->env_request_method, "REQUEST_METHOD"); // !! mozna nie uzywac tego, teraz mamy w strukturze fcgi_request
SetEnv(cur.request->env_request_method, "REQUEST_METHOD"); // !! mozna nie uzywac tego, teraz mamy w strukturze fcgi_request
SetEnv(cur.request->env_request_uri, "REQUEST_URI");
SetEnv(cur.request->env_http_cookie, "HTTP_COOKIE");
SetEnv(cur.request->env_remote_addr, "REMOTE_ADDR");
SetEnv(cur.request->env_http_host, "HTTP_HOST");
SetEnv(cur.request->env_http_host, "HTTP_HOST");
SetEnv(cur.request->env_http_user_agent, "HTTP_USER_AGENT");
SetEnv(cur.request->env_fcgi_role, "FCGI_ROLE");
SetEnv(cur.request->env_content_type, "CONTENT_TYPE");
SetEnv(cur.request->env_http_accept_encoding,"HTTP_ACCEPT_ENCODING");
SetEnv(cur.request->env_fcgi_role, "FCGI_ROLE");
SetEnv(cur.request->env_content_type, "CONTENT_TYPE");
SetEnv(cur.request->env_http_accept_encoding, "HTTP_ACCEPT_ENCODING");
}
@ -539,6 +540,59 @@ void App::PrepareSessionCookie()
void App::SendHeadersStatic()
{
if( PathHasUpDir(cur.request->env_request_uri) )
{
log << log1 << "App: incorrect path for a static file" << logend;
SendHeadersForbidden();
return;
}
const std::wstring & index_str = system.mounts.pmount->FirstArg(system.mounts.MountParStatic());
size_t index = Toi(index_str);
if( index >= config.static_dirs.size() )
{
log << log1 << "App: static dir with index " << index << " is not defined in the config" << logend;
SendHeadersForbidden();
return;
}
Ezc::WideToUTF8(config.http_header_send_file, sendheadersstatic_t);
Ezc::WideToUTF8(config.static_dirs[index], sendheadersstatic_t2);
Item * dir = system.dirs.GetDir(system.mounts.pmount->dir_id);
if( !dir )
{
log << log1 << "App: cannot find the mount directory" << logend;
SendHeadersForbidden();
return;
}
size_t how_many_dirs = system.dirs.DirLevel(dir->id);
const char * path = SkipDirs(cur.request->env_request_uri, how_many_dirs);
// the path begins with a slash only if how_many_dirs is zero
while( *path == '/' )
path += 1;
FCGX_FPrintF(fcgi_request.out, "%s: %s/%s\r\n", sendheadersstatic_t.c_str(), sendheadersstatic_t2.c_str(), path);
FCGX_PutS("Status: 200 OK\r\n", fcgi_request.out);
log << log2 << "Sending file from a static mountpoint: " << sendheadersstatic_t2 << "/" << path << logend;
}
void App::SendHeadersForbidden()
{
FCGX_PutS("Status: 403 Forbidden\r\n", fcgi_request.out);
FCGX_PutS("Content-Type: text/html\r\n", fcgi_request.out);
log << log2 << "Request: response: 403 Forbidden" << logend;
}
void App::SendHeaders(bool compressing, int compress_encoding, Header header)
{
@ -555,6 +609,11 @@ void App::SendHeaders(bool compressing, int compress_encoding, Header header)
log << log2 << "Redirect to: " << cur.request->aredirect_to << logend;
}
else
if( system.mounts.pmount->type == system.mounts.MountTypeStatic() )
{
SendHeadersStatic();
}
else
if( !cur.request->x_sendfile.empty() )
{
static std::string temp, temp2; // !! wrzucic gdzies to
@ -577,9 +636,7 @@ void App::SendHeaders(bool compressing, int compress_encoding, Header header)
break;
case h_403:
FCGX_PutS("Status: 403 Forbidden\r\n", fcgi_request.out);
FCGX_PutS("Content-Type: text/html\r\n", fcgi_request.out);
log << log2 << "Request: response: 403 Forbidden" << logend;
SendHeadersForbidden();
break;
default:

View File

@ -130,6 +130,7 @@ private:
pthread_t signal_thread;
std::string url_to_fetch_on_exit;
std::string source_a;
std::string sendheadersstatic_t, sendheadersstatic_t2;
void ProcessRequestThrow();
void ProcessRequest();
@ -154,6 +155,8 @@ private:
void PrepareSessionCookie();
void AddDebugInfo(std::wstring & out);
void FilterCompressSend(bool compressing, int compress_encoding, const std::wstring & source_ref);
void SendHeadersStatic();
void SendHeadersForbidden();
void SendHeaders(bool compressing, int compress_encoding, Header header);
int SelectDeflateVersion();
void SelectCompression(size_t source_len, bool & compression_allowed, int & compression_encoding);

View File

@ -116,6 +116,8 @@ void Config::AssignValues(bool stdout_is_closed)
upload_dir = Text(L"upload_dir");
upload_dirs_chmod = Int(L"upload_dirs_chmod", 0750);
upload_files_chmod = Int(L"upload_files_chmod", 0640);
ListText(L"static_dirs", static_dirs);
dont_use_static_dirs = Bool(L"dont_use_static_dirs", false);
create_thumb = Bool(L"create_thumb", true);
thumb_mode = Int(L"thumb_mode", 2);
thumb_cx = Size(L"thumb_cx", 150);
@ -215,6 +217,9 @@ void Config::SetAdditionalVariables()
else
html_filter_orphans_mode = HTMLFilter::orphan_nbsp;
for(size_t i=0 ; i<static_dirs.size() ; ++i)
NoLastSlash(static_dirs[i]);
CheckLocale();
CheckPasswd();
}

View File

@ -206,6 +206,24 @@ public:
// directory for static files
std::wstring upload_dir;
// additional static directories *not* managed by winix
// you can refer to this directories by using 'static' mount point
// e.g.
// let we say in the config you have:
// static_dirs = ("/home/a", "/home/b", "/home/c")
// and in /etc/fstab (in winix) you have such a line:
// "static /my/dir simplefs static(2)"
// above line in /etc/fstab means that when a user enters http://domain.com/my/dir/file.txt
// then "file.txt" will be taken from "/home/c/file.txt"
// this is useful for some javascript files which are protected from running from other domains
std::vector<std::wstring> static_dirs;
// sometimes you can have trouble when you have set an incorrect static path in /etc/fstab
// in such a case set dont_use_static_dirs to true
// and winix will behave as there are not any static directories
// so you can correct your mistake and then set this value to false
bool dont_use_static_dirs;
// chmod of newly created directories (under upload_dir)
// default: 0750
int upload_dirs_chmod;

View File

@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2008-2010, Tomasz Sowa
* Copyright (c) 2008-2011, Tomasz Sowa
* All rights reserved.
*
*/
@ -196,6 +196,30 @@ DirContainer::Iterator i;
}
size_t Dirs::DirLevel(long id)
{
DirContainer::Iterator i;
size_t level = 0;
while( true )
{
i = dir_tab.FindId(id);
if( i == dir_tab.End() ||
i->parent_id == id ) // means a loop (something wrong in the db)
{
// we don't change path if there is no such a directory
return level;
}
if( i->parent_id == -1 )
return level;
id = i->parent_id;
level += 1;
}
}
bool Dirs::ChangeParent(long dir_id, long new_parent_id)
{

View File

@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2008-2010, Tomasz Sowa
* Copyright (c) 2008-2011, Tomasz Sowa
* All rights reserved.
*
*/
@ -77,6 +77,12 @@ public:
// !! jak juz wczesniejsze nazwy beda zmienione to tutaj damy AddDir() /AddDir() juz istnieje przeciez?/
Error AddDirectory(Item & item, bool add_to_dir_tab = false, Item ** pdir = 0, int notify_code = 0);
// returns how many levels of directories there are
// "/" -> 0 (root dir)
// "/abc" -> 1
// "/abc/def" -> 2
size_t DirLevel(long id);
private:
Cur * cur;

View File

@ -389,6 +389,160 @@ void NoFirstHttp(StringType & s)
/*
this method returns true if there are two dots meaning 'go up' somewhere in the path
for example such paths return true:
".."
"test/../path"
"test/where/../"
"test/where/.."
"../abc"
*/
template<class StringType>
bool PathHasUpDir(const StringType * str)
{
size_t i = 0;
while( str[i] )
{
if( str[i]=='.' && str[i+1]=='.' )
{
i += 2;
if( str[i]=='/' || str[i]==0 )
return true;
}
// skipping until to next slash
while( str[i] && str[i]!='/' )
i += 1;
// skipping the slash (or slashes)
while( str[i]=='/' )
i += 1;
}
return false;
}
template<class StringType>
bool PathHasUpDir(const StringType & str)
{
return PathHasUpDir(str.c_str());
}
/*
this method calculates how many directories there are in the given path
input:
str - path
last_is_dir - true if the last part of the path should be treated as a directory too
samples:
HowManyDirs("", false) -> 0
HowManyDirs("", true) -> 0
HowManyDirs("abc", false) -> 0
HowManyDirs("abc", true) -> 1
HowManyDirs("/abc/", true) -> 1
HowManyDirs("////", false) -> 0
HowManyDirs("////", true) -> 0
HowManyDirs("////abc", false) -> 0
HowManyDirs("////abc", true) -> 1
HowManyDirs("/var/static", false) -> 1
HowManyDirs("/var/static", true) -> 2
HowManyDirs("/var/static/", false) -> 2
HowManyDirs("/var/static/", true) -> 2
*/
template<class StringType>
size_t HowManyDirs(const StringType * str, bool is_last_dir = false)
{
size_t res = 0;
size_t i = 0;
// first slash (root dir) is not calculated
while( str[i]=='/' )
i += 1;
while( str[i] )
{
if( str[i]=='/' )
{
res += 1;
while( str[i]=='/' )
i += 1;
}
else
{
i += 1;
}
}
if( is_last_dir && i>0 && str[i-1]!='/' )
res += 1;
return res;
}
template<class StringType>
size_t HowManyDirs(const StringType & str, bool is_last_dir = false)
{
return HowManyDirs(str.c_str(), is_last_dir);
}
/*
this method skips some first directories from given path
samples:
SkipDirs("/var/test", 1) -> "test"
SkipDirs("/var/test/somewhere", 1) -> "test/somewhere"
SkipDirs("/var/test/somewhere", 2) -> "somewhere"
SkipDirs("/var/test/somewhere", 10) -> ""
*/
template<class StringType>
const StringType * SkipDirs(const StringType * str, size_t how_many_skip)
{
size_t i = 0;
size_t skipped = 0;
if( how_many_skip == 0 )
return str;
// first slash (root dir) is not calculated
while( str[i]=='/' )
i += 1;
while( str[i] )
{
if( str[i]=='/' )
{
skipped += 1;
while( str[i]=='/' )
i += 1;
if( skipped == how_many_skip )
return str+i;
}
else
{
i += 1;
}
}
return str + i;
}
bool ValidateEmail(const std::wstring & email);

View File

@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2010, Tomasz Sowa
* Copyright (c) 2010-2011, Tomasz Sowa
* All rights reserved.
*
*/
@ -15,9 +15,24 @@
MountParser::MountParser()
{
dirs = 0;
skip_static = false;
mount_type_tab = 0;
mount_fs_tab = 0;
mount_par_tab = 0;
static_mount_id = -1;
}
void MountParser::SkipStaticDirs(bool skip)
{
skip_static = skip;
}
void MountParser::SetStaticMountId(int id)
{
static_mount_id = id;
}
@ -361,10 +376,18 @@ void MountParser::ReadRow(std::map<long, Mount> & output)
if( err == WINIX_ERR_OK )
{
std::pair<std::map<long, Mount>::iterator, bool> res = output.insert( std::make_pair(mount.dir_id, mount) );
if( !res.second )
log << log1 << "MP: this mount point exists (skipped)" << logend;
if( skip_static && mount.type==static_mount_id )
{
log << log1 << "MP: static mount points are skipped (dont_use_static_dirs in config is true)" << logend;
}
else
{
std::pair<std::map<long, Mount>::iterator, bool> res = output.insert( std::make_pair(mount.dir_id, mount) );
if( !res.second )
log << log1 << "MP: this mount point exists (skipped)" << logend;
}
}
SkipLine();

View File

@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2010, Tomasz Sowa
* Copyright (c) 2010-2011, Tomasz Sowa
* All rights reserved.
*
*/
@ -28,6 +28,10 @@ class MountParser
public:
MountParser();
void SkipStaticDirs(bool skip);
void SetStaticMountId(int id);
Error Parse(const std::wstring & input, std::map<long, Mount> & output);
void SetDirs(Dirs * pdirs);
void SetMountTypeTab(const std::vector<std::wstring> & tab);
@ -37,6 +41,8 @@ public:
private:
Dirs * dirs;
bool skip_static;
int static_mount_id;
const std::vector<std::wstring> * mount_type_tab;
const std::vector<std::wstring> * mount_fs_tab;

View File

@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2009-2010, Tomasz Sowa
* Copyright (c) 2009-2011, Tomasz Sowa
* All rights reserved.
*
*/
@ -19,12 +19,21 @@
Mounts::Mounts()
{
pmount = &empty_mount;
skip_static = false;
}
void Mounts::SkipStaticDirs(bool skip)
{
skip_static = skip;
}
void Mounts::CreateMountType()
{
mount_type_cms = AddMountType(L"cms");
mount_type_cms = AddMountType(L"cms");
mount_type_static = AddMountType(L"static");
}
@ -47,6 +56,8 @@ void Mounts::CreateMountPar()
mount_par_mkdir_on = AddMountPar(L"mkdir_on");
mount_par_app = AddMountPar(L"app");
mount_par_html_template = AddMountPar(L"html_template");
mount_par_static = AddMountPar(L"static");
mount_par_css = AddMountPar(L"css");
}
@ -167,6 +178,8 @@ const std::wstring & Mounts::GetMountPar(int id)
// reading from 'mounts'
Error Mounts::ReadMounts(const std::wstring & mounts)
{
mount_parser.SkipStaticDirs(skip_static);
mount_parser.SetStaticMountId(mount_type_static);
mount_parser.SetDirs(dirs);
mount_parser.SetMountTypeTab(mount_type_tab);
mount_parser.SetMountFsTab(mount_fs_tab);

View File

@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2009-2010, Tomasz Sowa
* Copyright (c) 2009-2011, Tomasz Sowa
* All rights reserved.
*
*/
@ -28,6 +28,9 @@ class Mounts
{
public:
void SkipStaticDirs(bool skip);
/*
mount point's types
*/
@ -37,6 +40,7 @@ public:
// id of a specific mount type (the id is always valid)
int MountTypeCms() { return mount_type_cms; }
int MountTypeStatic() { return mount_type_static; }
// return -1 if there is no such a mount type
// or index otherwhise
@ -72,7 +76,8 @@ public:
int MountParMkdirOn() { return mount_par_mkdir_on; }
int MountParApp() { return mount_par_app; }
int MountParHtmlTemplate() { return mount_par_html_template; }
int MountParStatic() { return mount_par_static; }
int MountParCss() { return mount_par_css; }
void SetDirs(Dirs * pdirs);
void SetDb(Db * pdb);
@ -103,6 +108,8 @@ private:
Dirs * dirs;
Cur * cur;
bool skip_static;
Mount empty_mount;
const std::wstring empty_str;
@ -111,6 +118,7 @@ private:
std::vector<std::wstring> mount_type_tab;
int mount_type_cms;
int mount_type_static;
// simplefs
// hashfs
@ -131,6 +139,8 @@ private:
int mount_par_mkdir_on;
int mount_par_app;
int mount_par_html_template;
int mount_par_static;
int mount_par_css;
MountTab mount_tab;

View File

@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2010, Tomasz Sowa
* Copyright (c) 2010-2011, Tomasz Sowa
* All rights reserved.
*
*/
@ -48,6 +48,7 @@ void System::Init()
dirs.SetNotify(&notify);
dirs.ReadDirs();
mounts.SkipStaticDirs(config->dont_use_static_dirs);
mounts.SetDirs(&dirs);
mounts.SetDb(db);
mounts.SetCur(cur);

View File

@ -178,11 +178,11 @@ void FunctionParser::Parse(Cur * pcur, Db * pdb, Functions * pfunctions, System
system = psystem;
functions = pfunctions;
cur->request->status = WINIX_ERR_OK;
get_index = 0;
get_tab_len = cur->request->get_tab.size();
cur->request->status = WINIX_ERR_OK;
get_index = 0;
get_tab_len = cur->request->get_tab.size();
cur->request->function = 0;
cur->request->is_item = false;
cur->request->is_item = false;
ParseDirectories();

View File

@ -5,10 +5,10 @@
[end]
[# in the future tinymce will be placed in doc_base_url_common]
[if winix_function_is "tinymce"]
<script type="text/javascript" src="[doc_base_url_static]/tiny_mce/tiny_mce.js"></script>
<script type="text/javascript" src="[doc_base_url_static]/tinymce.js"></script>
<!--<script type="text/javascript">document.domain = "www.slimaczek.pl";</script>-->
<script type="text/javascript" src="[doc_base_url]/var/staticcommon/tiny_mce/tiny_mce.js"></script>
<script type="text/javascript" src="[doc_base_url]/var/staticcommon/tinymce.js"></script>
[end]

View File

@ -205,7 +205,11 @@ size_t buff_len = sizeof(buff) / sizeof(wchar_t);
void winix_show_content_in_full_window(Info & i)
{
if( cur->request->function )
i.res = (cur->request->function == &functions->fun_ckeditor || cur->request->function == &functions->fun_tinymce);
i.res = (cur->request->function == &functions->fun_ckeditor ||
cur->request->function == &functions->fun_tinymce ||
cur->request->function == &functions->fun_nicedit ||
cur->request->function == &functions->fun_vim ||
cur->request->function == &functions->fun_emacs );
}