From c49c35cfbd737afed525ea7ba719a6e95e984bed Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Tue, 14 Jun 2011 23:45:42 +0000 Subject: [PATCH] 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 --- core/app.cpp | 77 +++++++++++++-- core/app.h | 3 + core/config.cpp | 5 + core/config.h | 18 ++++ core/dirs.cpp | 26 ++++- core/dirs.h | 8 +- core/misc.h | 154 +++++++++++++++++++++++++++++ core/mountparser.cpp | 33 ++++++- core/mountparser.h | 8 +- core/mounts.cpp | 17 +++- core/mounts.h | 14 ++- core/system.cpp | 3 +- functions/functionparser.cpp | 8 +- html/index_head_functions_add.html | 6 +- templates/winix.cpp | 6 +- 15 files changed, 355 insertions(+), 31 deletions(-) diff --git a/core/app.cpp b/core/app.cpp index d99395e..a11dae5 100755 --- a/core/app.cpp +++ b/core/app.cpp @@ -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: diff --git a/core/app.h b/core/app.h index 46693c0..afc6ac6 100755 --- a/core/app.h +++ b/core/app.h @@ -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); diff --git a/core/config.cpp b/core/config.cpp index e3c9f65..bc72c7f 100755 --- a/core/config.cpp +++ b/core/config.cpp @@ -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; + + // 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; diff --git a/core/dirs.cpp b/core/dirs.cpp index 663a462..fb5cd26 100755 --- a/core/dirs.cpp +++ b/core/dirs.cpp @@ -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) { diff --git a/core/dirs.h b/core/dirs.h index acdc967..fc75a2e 100755 --- a/core/dirs.h +++ b/core/dirs.h @@ -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; diff --git a/core/misc.h b/core/misc.h index 7b05006..b4bc044 100755 --- a/core/misc.h +++ b/core/misc.h @@ -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 +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 +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 +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 +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 +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); diff --git a/core/mountparser.cpp b/core/mountparser.cpp index bdf3b89..71b9e3b 100755 --- a/core/mountparser.cpp +++ b/core/mountparser.cpp @@ -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 & output) if( err == WINIX_ERR_OK ) { - std::pair::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::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(); diff --git a/core/mountparser.h b/core/mountparser.h index 7e26b54..301be76 100755 --- a/core/mountparser.h +++ b/core/mountparser.h @@ -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 & output); void SetDirs(Dirs * pdirs); void SetMountTypeTab(const std::vector & tab); @@ -37,6 +41,8 @@ public: private: Dirs * dirs; + bool skip_static; + int static_mount_id; const std::vector * mount_type_tab; const std::vector * mount_fs_tab; diff --git a/core/mounts.cpp b/core/mounts.cpp index 761a864..6e782aa 100755 --- a/core/mounts.cpp +++ b/core/mounts.cpp @@ -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); diff --git a/core/mounts.h b/core/mounts.h index 98395ae..ae5b2c7 100755 --- a/core/mounts.h +++ b/core/mounts.h @@ -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 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; diff --git a/core/system.cpp b/core/system.cpp index cb04dff..11a3aaa 100755 --- a/core/system.cpp +++ b/core/system.cpp @@ -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(¬ify); dirs.ReadDirs(); + mounts.SkipStaticDirs(config->dont_use_static_dirs); mounts.SetDirs(&dirs); mounts.SetDb(db); mounts.SetCur(cur); diff --git a/functions/functionparser.cpp b/functions/functionparser.cpp index 8729ece..1e9c9db 100755 --- a/functions/functionparser.cpp +++ b/functions/functionparser.cpp @@ -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(); diff --git a/html/index_head_functions_add.html b/html/index_head_functions_add.html index 0c127c2..1beb99e 100755 --- a/html/index_head_functions_add.html +++ b/html/index_head_functions_add.html @@ -5,10 +5,10 @@ [end] -[# in the future tinymce will be placed in doc_base_url_common] [if winix_function_is "tinymce"] - - + + + [end] diff --git a/templates/winix.cpp b/templates/winix.cpp index eb15fda..9e450aa 100755 --- a/templates/winix.cpp +++ b/templates/winix.cpp @@ -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 ); }