From 60fccea703b8446a9d8fbe2f85d68d4431e6d66b Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Wed, 30 Dec 2009 20:46:12 +0000 Subject: [PATCH] fixed: dots in url-es (now only one dot is available in the whole name and it cannot be only one dot ".") added: cmslu can act as an authorizer (fast cgi authorize role) added: Item::static_auth we can have additional static content on the file system this content is authorized through cmslu (fastcgi authorizer mode) changed: some changes in config changed: the way how the www server is using cmslu added new virtuals: static static_auth changed: cmslu returns correct http headers (200, 404, 403) changed: in cookie parser: we get the last cookie (if the server has more than one cookie with the same name) git-svn-id: svn://ttmath.org/publicrep/cmslu/trunk@540 e52654a7-88a9-db11-a3e9-0013d4bc506e --- content/content.cpp | 29 ++++++- core/Makefile.dep | 6 +- core/config.cpp | 39 ++++++++-- core/config.h | 3 +- core/cookieparser.h | 7 +- core/data.cpp | 15 ++-- core/data.h | 30 ++++++- core/db.cpp | 15 ++-- core/db.h | 6 +- core/db_itemcolumns.cpp | 4 +- core/functionparser.cpp | 11 ++- core/item.h | 25 ++++-- core/log.cpp | 27 ++++--- core/misc.cpp | 155 ++++++++++++++++++++++++++----------- core/misc.h | 10 ++- core/request.cpp | 65 +++++++++++++--- core/request.h | 14 +++- core/requestcontroller.cpp | 29 +++++-- main/main.cpp | 4 + templates/doc.cpp | 13 ++++ templates/item.cpp | 25 ++++++ templates/templates.cpp | 21 +++-- templates/templates.h | 6 ++ 23 files changed, 431 insertions(+), 128 deletions(-) diff --git a/content/content.cpp b/content/content.cpp index ce14779..226f1bb 100755 --- a/content/content.cpp +++ b/content/content.cpp @@ -107,15 +107,31 @@ void Content::SetDefaultFunction() void Content::MakeStandardFunction() { + if( request.role == Request::authorizer ) + { + // in authorizer mode only cat function is available + // (and must be default) + + if( request.pfunction ) + { + request.status = Error::db_no_item; + log << log1 << "Content: in authorizer mode only 'cat' funtion is available and must " + "be default (not in the url)" << logend; + return; + } + + request.pfunction = data.functions.GetFunction(FUN_CAT); + } + if( !request.pfunction ) SetDefaultFunction(); if( !request.redirect_to.empty() ) return; - if( !request.pfunction ) { + request.status = Error::no_function; log << log1 << "Content: no function (neither cat nor ls)" << logend; return; } @@ -176,17 +192,22 @@ void Content::MakeStandardFunction() void Content::MakePost() { + if( request.role == Request::authorizer ) + { + request.status = Error::permision_denied; + return; + } + if( !request.pfunction ) SetDefaultFunction(); if( !request.pfunction ) { - log << log1 << "Content: MakePost: no function" << logend; request.status = Error::no_function; + log << log1 << "Content: MakePost: no function" << logend; return; } - switch( request.pfunction->code ) { case FUN_RUN: @@ -355,7 +376,7 @@ void Content::PrepareUrl(Item & item) if( item.url.empty() ) item.url = item.subject; // if the subject is empty then the url will be corrected by CorrectUrl() - CorrectUrl(item); + CorrectUrlOnlyAllowedChar(item.url); if( data.functions.GetFunction(item.url) ) { diff --git a/core/Makefile.dep b/core/Makefile.dep index dbc3ef4..cdbb808 100755 --- a/core/Makefile.dep +++ b/core/Makefile.dep @@ -7,7 +7,7 @@ config.o: dircontainer.h users.h user.h ugcontainer.h groups.h group.h config.o: functions.h function.h lastcontainer.h mounts.h mount.h rebus.h config.o: plugin.h request.h requesttypes.h session.h done.h error.h thread.h config.o: compress.h acceptencodingparser.h acceptbaseparser.h htmlfilter.h -config.o: pluginmsg.h +config.o: pluginmsg.h misc.h data.o: data.h dirs.h item.h dircontainer.h users.h user.h ugcontainer.h data.o: log.h groups.h group.h functions.h function.h lastcontainer.h data.o: mounts.h mount.h rebus.h @@ -36,7 +36,9 @@ htmlfilter.o: htmlfilter.h httpsimpleparser.o: httpsimpleparser.h lastcontainer.o: lastcontainer.h log.h log.o: log.h -misc.o: misc.h item.h log.h +misc.o: misc.h item.h log.h data.h dirs.h dircontainer.h users.h user.h +misc.o: ugcontainer.h groups.h group.h functions.h function.h lastcontainer.h +misc.o: mounts.h mount.h rebus.h mount.o: mount.h mountparser.o: mountparser.h mount.h item.h error.h log.h data.h dirs.h mountparser.o: dircontainer.h users.h user.h ugcontainer.h groups.h group.h diff --git a/core/config.cpp b/core/config.cpp index 84eecb4..d246217 100755 --- a/core/config.cpp +++ b/core/config.cpp @@ -11,6 +11,7 @@ #include "log.h" #include "data.h" #include "plugin.h" +#include "misc.h" Config::Config() @@ -109,9 +110,19 @@ void Config::AssignValues() data.db_database = Text("db_database"); data.db_user = Text("db_user"); data.db_pass = Text("db_pass"); - data.base_url = Text("base_url"); + data.item_url_empty = Text("item_url_empty"); - NoLastSlash(data.base_url); + data.base_server = Text("base_server"); + data.base_url_prefix = Text("base_url_prefix"); + data.base_url_static_prefix = Text("base_url_static_prefix"); + data.base_url_static_auth_prefix = Text("base_url_static_auth_prefix"); + + NoLastSlash(data.base_server); + NoFirstHttp(data.base_server); + + data.base_url = data.base_url_prefix + data.base_server; + data.base_url_static = data.base_url_static_prefix + data.base_server; + data.base_url_static_auth = data.base_url_static_auth_prefix + data.base_server; data.one_item_is_showed = Bool("one_item_is_showed"); @@ -199,18 +210,34 @@ void Config::NoLastSlash(std::string & s) if( s.empty() ) return; - log << log2 << "Config: removing the last slash from: " << s << logend; - if( *(--s.end()) == '/' ) s.erase(--s.end()); } +void Config::NoFirstHttp(std::string & s) +{ + if( s.empty() ) + return; + + const char http[] = "http://"; + const char https[] = "https://"; + + if( IsSubStringNoCase(http, s.c_str()) ) + { + s.erase(0, sizeof(http)/sizeof(char)); + } + else + if( IsSubStringNoCase(https, s.c_str()) ) + { + s.erase(0, sizeof(https)/sizeof(char)); + } +} + + - - diff --git a/core/config.h b/core/config.h index 7f560fe..1bfaaf7 100755 --- a/core/config.h +++ b/core/config.h @@ -45,7 +45,8 @@ private: bool errors_to_stdout; void NoLastSlash(std::string & s); - + void NoFirstHttp(std::string & s); + }; diff --git a/core/cookieparser.h b/core/cookieparser.h index f9ee8fc..c19536b 100755 --- a/core/cookieparser.h +++ b/core/cookieparser.h @@ -46,9 +46,12 @@ protected: log << log2 << "Cookie, name: \"" << name << "\", value: \"" << value << "\""; if( res.second == false ) - log << log2 << " (skipped)"; + { + res.first->second = value; + log << " (overwritten)"; + } - log << log2 << logend; + log << logend; } diff --git a/core/data.cpp b/core/data.cpp index 10ba1b9..e39cf6f 100755 --- a/core/data.cpp +++ b/core/data.cpp @@ -25,18 +25,19 @@ Data::Data() void Data::SetAdditionalVariables() { - SetHttpHost(); + SetHttpHost(base_url, base_url_http_host); + SetHttpHost(base_url_static_auth, base_url_static_auth_http_host); } -void Data::SetHttpHost() +void Data::SetHttpHost(const std::string & in, std::string & out) { - if( strncmp(base_url.c_str(), "http://", 7) == 0 ) - base_url_http_host = base_url.substr(7); + if( strncmp(in.c_str(), "http://", 7) == 0 ) + out = in.substr(7); else - if( strncmp(base_url.c_str(), "https://", 8) == 0 ) - base_url_http_host = base_url.substr(8); + if( strncmp(in.c_str(), "https://", 8) == 0 ) + out = in.substr(8); else - base_url_http_host.clear(); // if empty the RequestController::BaseUrlRedirect() returns false and no redirecting will be done + out.clear(); // if empty the RequestController::BaseUrlRedirect() returns false and no redirecting will be done } diff --git a/core/data.h b/core/data.h index 75a2b78..43df456 100755 --- a/core/data.h +++ b/core/data.h @@ -64,7 +64,12 @@ public: std::string db_database; std::string db_user; std::string db_pass; - std::string base_url; + + std::string base_server; + std::string base_url_prefix; + std::string base_url_static_prefix; + std::string base_url_static_auth_prefix; + std::string http_session_id_name; // when the HOST_HTTP environment variable doesn't point into 'base_url' (the part 'http://' and the last slash is removed) @@ -101,10 +106,25 @@ public: // the html code is cleaned by our filter bool html_filter; + // the url of a new empty item (if there is not the subject too) + std::string item_url_empty; + + // below variables are based on the other config variables + + // base_url_prefix + base_server + std::string base_url; + + // base_url_static_prefix + base_server + std::string base_url_static; + + // base_url_static_auth_prefix + base_server + std::string base_url_static_auth; + // end config members // ----------------------------------------------------------------- - + + // false at the beginning bool stdout_is_closed; @@ -116,7 +136,11 @@ public: // based on base_url // set by SetAdditionalVariables() + // without the first part http:// (or https://) or the whole string is empty std::string base_url_http_host; + std::string base_url_static_auth_http_host; + + // call this method after the config file is read void SetAdditionalVariables(); @@ -146,7 +170,7 @@ public: private: - void SetHttpHost(); + void SetHttpHost(const std::string & in, std::string & out); }; diff --git a/core/db.cpp b/core/db.cpp index dc37b66..d14e30d 100755 --- a/core/db.cpp +++ b/core/db.cpp @@ -420,7 +420,8 @@ Error Db::AddItemIntoItem(Item & item) { AssertConnection(); std::ostringstream query; - query << "insert into core.item (user_id, group_id, privileges, date_creation, date_modification, type, parent_id, content_id, default_item, subject, guest_name, url) values ("; + query << "insert into core.item (user_id, group_id, privileges, date_creation, date_modification, type, " + "parent_id, content_id, static_auth, default_item, subject, guest_name, url) values ("; query << '\'' << item.user_id << "', "; query << '\'' << item.group_id << "', "; query << '\'' << item.privileges << "', "; @@ -429,9 +430,11 @@ Error Db::AddItemIntoItem(Item & item) query << '\'' << static_cast(item.type) << "', "; query << '\'' << item.parent_id << "', "; query << '\'' << item.content_id << "', "; + query << '\'' << static_cast(item.static_auth) << "', "; query << '\'' << item.default_item << "', "; query << '\'' << Escape(item.subject) << "', "; query << '\'' << Escape(item.guest_name) << "', "; + url_without_id = AddItemCreateUrlSubject(item); @@ -523,7 +526,8 @@ Error Db::EditItemInItem(Item & item, bool with_url) { AssertConnection(); std::ostringstream query; - query << "update core.item set (user_id, group_id, privileges, date_creation, date_modification, type, default_item, parent_id, subject, guest_name"; + query << "update core.item set (user_id, group_id, privileges, date_creation, date_modification, type, " + "default_item, parent_id, subject, guest_name, static_auth"; if( with_url ) query << ", url"; @@ -538,7 +542,8 @@ Error Db::EditItemInItem(Item & item, bool with_url) query << '\'' << item.default_item << "', "; query << '\'' << item.parent_id << "', "; query << '\'' << Escape(item.subject) << "', "; - query << '\'' << Escape(item.guest_name) << "' "; + query << '\'' << Escape(item.guest_name) << "', "; + query << '\'' << static_cast(item.static_auth) << "' "; if( with_url ) { @@ -583,7 +588,6 @@ Error Db::EditItemInContent(Item & item) query << '\'' << Escape(item.content) << "', "; query << '\'' << item.content_type << "' "; - query << ") where id='" << item.content_id << "';"; r = AssertQuery(query.str()); @@ -751,7 +755,8 @@ return result; PGresult * Db::GetItemsQuery(long parent_id, Item::Type type, bool with_subject, bool with_content, bool sort_asc) { std::ostringstream query; - query << "select item.id, user_id, group_id, privileges, date_creation, date_modification, url, type, parent_id, content_id, default_item, guest_name"; + query << "select item.id, user_id, group_id, privileges, date_creation, date_modification, url, type, parent_id, " + "content_id, default_item, guest_name, static_auth"; if( type != Item::dir ) { diff --git a/core/db.h b/core/db.h index 7b5b9db..d8c27b9 100755 --- a/core/db.h +++ b/core/db.h @@ -129,9 +129,9 @@ protected: struct ItemColumns { - int id, user_id, group_id, privileges, date_creation, date_modification, url, type, parent_id, content_id, default_item, subject, content, content_type, guest_name; - - + int id, user_id, group_id, privileges, date_creation, date_modification, url, type, parent_id, + content_id, default_item, subject, content, content_type, guest_name, static_auth; + void SetColumns(PGresult * r); void SetItem(PGresult * r, long row, Item & item); }; diff --git a/core/db_itemcolumns.cpp b/core/db_itemcolumns.cpp index 742c42e..453a416 100755 --- a/core/db_itemcolumns.cpp +++ b/core/db_itemcolumns.cpp @@ -29,6 +29,7 @@ void Db::ItemColumns::SetColumns(PGresult * r) content = PQfnumber(r, "content"); content_type = PQfnumber(r, "content_type"); guest_name = PQfnumber(r, "guest_name"); + static_auth = PQfnumber(r, "static_auth"); } @@ -42,7 +43,7 @@ void Db::ItemColumns::SetItem(PGresult * r, long row, Item & item) if( date_creation != -1 ) item.date_creation = ConvertTime( Db::AssertValue(r, row, date_creation) ); if( date_modification != -1 ) item.date_modification = ConvertTime( Db::AssertValue(r, row, date_modification) ); if( url != -1 ) item.url = Db::AssertValue(r, row, url); - if( type != -1 ) item.type = static_cast( atoi( Db::AssertValue(r, row, type) ) ); + if( type != -1 ) item.type = static_cast( atoi(Db::AssertValue(r, row, type)) ); if( parent_id != -1 ) item.parent_id = atol( Db::AssertValue(r, row, parent_id) ); if( content_id != -1 ) item.content_id = atol( Db::AssertValue(r, row, content_id) ); if( default_item != -1 ) item.default_item = atol( Db::AssertValue(r, row, default_item) ); @@ -50,6 +51,7 @@ void Db::ItemColumns::SetItem(PGresult * r, long row, Item & item) if( content != -1 ) item.content = Db::AssertValue(r, row, content); if( content_type != -1 ) item.content_type = atoi( Db::AssertValue(r, row, content_type) ); if( guest_name != -1 ) item.guest_name = Db::AssertValue(r, row, guest_name); + if( static_auth != -1 ) item.static_auth = static_cast( atoi(Db::AssertValue(r, row, static_auth)) ); } diff --git a/core/functionparser.cpp b/core/functionparser.cpp index a59efbe..70bfb33 100755 --- a/core/functionparser.cpp +++ b/core/functionparser.cpp @@ -80,12 +80,21 @@ void FunctionParser::ParseItem() if( request.status == Error::ok ) { + if( request.role == Request::authorizer && request.item.static_auth == Item::static_none ) + { + log << log1 << "FP: item.url: " << url << " exists but has not a static content (authorizer role)" << logend; + request.status = Error::db_no_item; + return; + } + ++get_index; request.is_item = true; log << log3 << "FP: Item: id: " << request.item.id << ", url: " << request.item.url << logend; } else + { log << log3 << "FP: No Item: url: " << url << logend; + } } @@ -158,7 +167,7 @@ void FunctionParser::Parse() return; } } - + ParseParams(); } diff --git a/core/item.h b/core/item.h index f278ab5..f5cd74c 100755 --- a/core/item.h +++ b/core/item.h @@ -35,10 +35,10 @@ std::string content; std::string url; -// 0 - simple txt -// 1 - formatted txt -// 2 - html -// 3 - bbcode +// 0 - text: simple +// 1 - text: formatted +// 2 - text: html +// 3 - text: bbcode int content_type; @@ -65,6 +65,19 @@ long default_item; long content_id; +// external static file (saved in file system) +// the direct url is the same but the prefix is: base_url_static_auth +enum StaticAuth +{ + static_none = 0, + static_image = 1, + static_other = 2 +}; + + +StaticAuth static_auth; + + Item() { Clear(); @@ -93,7 +106,9 @@ void Clear() default_item = -1; content_id = -1; - + + static_auth = static_none; + time_t t = std::time(0); date_creation = *std::localtime( &t ); date_modification = date_creation; diff --git a/core/log.cpp b/core/log.cpp index 3788298..54cf021 100755 --- a/core/log.cpp +++ b/core/log.cpp @@ -142,33 +142,32 @@ return *this; void Log::SaveLog() { -int attempt = 2; + int attempt = 2; - if( current_level > log_level ) - return; + if( current_level > log_level ) + return; if( log_stdout ) std::cout << buffer.str() << std::endl; - if( log_file.empty() ) return; - std::ofstream file; + std::ofstream file; - do - { + do + { file.open( log_file.c_str(), std::ios_base::out | std::ios_base::app ); -// if( !file ) -// sleep(1); - } - while( --attempt > 0 && !file ); + // if( !file ) + // sleep(1); + } + while( --attempt > 0 && !file ); - if( !file ) - return; + if( !file ) + return; - file << buffer.str() << std::endl; + file << buffer.str() << std::endl; } diff --git a/core/misc.cpp b/core/misc.cpp index 57075d9..7af0f0f 100755 --- a/core/misc.cpp +++ b/core/misc.cpp @@ -9,7 +9,7 @@ #include "misc.h" #include "log.h" - +#include "data.h" @@ -48,11 +48,30 @@ return false; } -void CorrectUrl(Item & item) +void CorrectUrlDots(std::string & url) +{ +size_t i = url.size(); +bool was_dot = false; + + while( i-- > 0 ) + { + if( url[i] == '.' ) + { + if( was_dot ) + // only one dot is allowed + url[i] = '_'; + + was_dot = true; + } + } +} + + +void CorrectUrlChars(std::string & url) { std::string::iterator i; - - for(i = item.url.begin(); i!=item.url.end() ; ++i) + + for(i = url.begin(); i!=url.end() ; ++i) { if( !CorrectUrlChar(*i) ) { @@ -64,51 +83,34 @@ std::string::iterator i; *i = '_'; } } - - ToSmall(item.url); - - if( item.url.empty() ) - item.url = "bez_nazwy"; // !! wrzucic do pliku konfiguracyjnego - else - if( item.url[0] >= '0' && item.url[0] <= '9' ) - // url must begin with a letter - item.url.insert(item.url.begin(), '_'); } -void SetUrlFromSubject(Item & item) +void CorrectUrlOnlyAllowedChar(std::string & url) { - item.url = item.subject; - CorrectUrl(item); + CorrectUrlDots(url); + CorrectUrlChars(url); + ToSmall(url); + Trim(url, '_'); -/* -std::string::iterator i; - - item.url.clear(); - - for(i = item.subject.begin(); i!=item.subject.end() ; ++i) + if( url.empty() || url == "." ) { - int c = ChangeLocalChar(*i); - - if( (c >= 'a' && c <='z') || - (c >= 'A' && c <='Z') || - (c >= '0' && c <='9') || - (c == '(' || c == ')' || c == '.' || c == ',' || c == '_' ) - ) - { - item.url += c; - } - else - item.url += '_'; + if( data.item_url_empty.empty() ) + url = "unnamed"; + else + { + url = data.item_url_empty; + + CorrectUrlDots(url); + CorrectUrlChars(url); + ToSmall(url); + // we don't trim here and the string will not be empty + } } - if( item.url.empty() ) - item.url = "bez_nazwy"; // !! wrzucic do pliku konfiguracyjnego - else - if( item.url[0] >= '0' && item.url[0] <= '9' ) + if( url[0] >= '0' && url[0] <= '9' ) // url must begin with a letter - item.url.insert(item.url.begin(), '_'); -*/ + url.insert(url.begin(), '_'); } @@ -392,6 +394,36 @@ std::string::size_type i; } +void Trim(std::string & s, char c) +{ +std::string::size_type i; + + if( s.empty() ) + return; + + // looking for the 'c' characters at the end + for(i=s.size()-1 ; i>0 && s[i]==c ; --i); + + if( i==0 && s[i]==c ) + { + // the whole string has the 'c' characters + s.clear(); + return; + } + + // deleting 'c' characters at the end + if( i != s.size() - 1 ) + s.erase(i+1, std::string::npos); + + // looking for the 'c' characters at the beginning + for(i=0 ; i='A' && c<='Z' ) + c = c - 'A' + 'a'; + +return c; +} + + void ToSmall(std::string & s) { std::string::size_type i; for(i=0 ; i='A' && s[i]<='Z' ) - s[i] = s[i] - 'A' + 'a'; - } + s[i] = ToSmall(s[i]); } +bool IsSubString(const char * short_str, const char * long_str) +{ + while( *short_str && *long_str && *short_str == *long_str ) + { + ++short_str; + ++long_str; + } + + if( *short_str == 0 ) + return true; + +return false; +} + + +bool IsSubStringNoCase(const char * short_str, const char * long_str) +{ + while( *short_str && *long_str && ToSmall(*short_str) == ToSmall(*long_str) ) + { + ++short_str; + ++long_str; + } + + if( *short_str == 0 ) + return true; + +return false; +} + bool ValidateEmail(const std::string & email) { diff --git a/core/misc.h b/core/misc.h index 9726fd9..b82a138 100755 --- a/core/misc.h +++ b/core/misc.h @@ -26,8 +26,9 @@ void ToString(std::string & s, long value); int ChangeLocalChar(unsigned char c); bool CorrectUrlChar(char c); -void CorrectUrl(Item & item); -void SetUrlFromSubject(Item & item); +void CorrectUrlDots(std::string & url); +void CorrectUrlChars(std::string & url); +void CorrectUrlOnlyAllowedChar(std::string & url); void HtmlEscape(std::ostringstream & out, const std::string & in); void HtmlEscapeFormTxt(std::ostringstream & out, const std::string & in); @@ -46,10 +47,15 @@ const char * IpToStr(unsigned int ip_); bool IsWhite(int s); void TrimWhite(std::string & s); +void Trim(std::string & s, char c); +int ToSmall(int c); void ToSmall(std::string & s); const char * SkipWhite(const char * s); const char * ToStr(int value); +bool IsSubString(const char * short_str, const char * long_str); +bool IsSubStringNoCase(const char * short_str, const char * long_str); + bool ValidateEmail(const std::string & email); diff --git a/core/request.cpp b/core/request.cpp index 248233c..70b7684 100755 --- a/core/request.cpp +++ b/core/request.cpp @@ -45,7 +45,8 @@ void Request::Clear() cookie_table.clear(); method = none; - + role = responder; + headers.str(""); page.str(""); debug.str(""); @@ -58,6 +59,7 @@ void Request::Clear() env_http_host = &char_empty; env_http_user_agent = &char_empty; env_http_accept_encoding = &char_empty; + env_fcgi_role = &char_empty; session = 0; @@ -97,7 +99,7 @@ void Request::SetCookie(const char * name, const char * value, tm * expires) if( expires ) headers << "; expires=" << DateToStrCookie(expires) << " GMT"; - headers << "; path=/\r\n"; + headers << "; path=/; domain=." << data.base_server << "\r\n"; } @@ -109,7 +111,7 @@ void Request::SetCookie(const char * name, long value, tm * expires) if( expires ) headers << "; expires=" << DateToStrCookie(expires) << " GMT"; - headers << "; path=/\r\n"; + headers << "; path=/; domain=." << data.base_server << "\r\n"; } @@ -238,6 +240,7 @@ void Request::ReadEnvVariables() env_http_host = SetEnvVar("HTTP_HOST"); env_http_user_agent = SetEnvVar("HTTP_USER_AGENT"); env_http_accept_encoding = SetEnvVar("HTTP_ACCEPT_ENCODING"); + env_fcgi_role = SetEnvVar("FCGI_ROLE"); } @@ -268,11 +271,18 @@ void Request::CheckMethod() { method = none; - if( env_request_method[0] == 'G' ) + if( ToSmall(env_request_method[0]) == 'g' ) method = get; else - if( env_request_method[0] == 'P' ) + if( ToSmall(env_request_method[0]) == 'p' ) method = post; + + + // default we assume 'responder' + role = responder; + + if( ToSmall(env_fcgi_role[0]) == 'a' ) + role = authorizer; } @@ -310,7 +320,8 @@ void Request::ReadParameters() void Request::StandardLog() { log.PutDate(log1); - log << env_remote_addr << ' ' << env_request_method << ' ' << env_request_uri << ' ' << env_http_user_agent << logend; + log << env_remote_addr << ' ' << env_request_method << ' '; + log << env_http_host << env_request_uri << ' ' << env_http_user_agent << logend; } @@ -319,10 +330,14 @@ void Request::StandardLog() void Request::Read() { ReadEnvVariables(); - StandardLog(); CheckMethod(); + StandardLog(); ReadParameters(); CheckIE(); + + if( role == authorizer ) + log << log3 << "Request: fast cgi role: authorizer" << logend; + CheckKonqueror(); } @@ -353,7 +368,7 @@ void Request::SendSessionCookie() } -void Request::SendHeaders(bool compressing) +void Request::SendHeaders(bool compressing, Header header) { if( !redirect_to.empty() ) { @@ -364,8 +379,25 @@ void Request::SendHeaders(bool compressing) } else { - FCGX_PutS("Status: 200 OK\r\n", out); - FCGX_PutS("Content-Type: Text/Html\r\n", out); + switch(header) + { + case h_404: + FCGX_PutS("Status: 404 Not Found\r\n", out); + FCGX_PutS("Content-Type: Text/Html\r\n", out); + break; + + case h_403: + FCGX_PutS("Status: 403 Forbidden\r\n", out); + FCGX_PutS("Content-Type: Text/Html\r\n", out); + break; + + default: + FCGX_PutS("Status: 200 OK\r\n", out); + + if( role != authorizer ) + FCGX_PutS("Content-Type: Text/Html\r\n", out); + } + } if( compressing ) @@ -415,14 +447,25 @@ void Request::SendPage(bool compressing) void Request::SendAll() { bool compressing = data.compression && !browser_msie && !browser_konqueror && accept_encoding_parser.AcceptDeflate(); +Header header = h_200; + + if( status == Error::db_no_item || status == Error::no_function || status == Error::unknown_param ) + header = h_404; + + if( status == Error::permision_denied || status == Error::cant_change_user || status == Error::cant_change_group ) + header = h_403; SendSessionCookie(); - SendHeaders(compressing); + SendHeaders(compressing, header); if( !redirect_to.empty() ) // if there is a redirect we do not send a content return; + if( header == h_200 && role == authorizer && is_item && item.static_auth != Item::static_none ) + // if there is an item and the item has 'file' storage we do not send a content + return; + // adding debug info if exists AddDebugInfo(); diff --git a/core/request.h b/core/request.h index 31a1b83..0ad32cd 100755 --- a/core/request.h +++ b/core/request.h @@ -41,7 +41,7 @@ struct Request enum Method { get, post, none } method; - + enum Role { responder, authorizer } role; // headers, page and debug // notify (for mailing) @@ -62,7 +62,7 @@ struct Request const char * env_http_host; const char * env_http_user_agent; const char * env_http_accept_encoding; - + const char * env_fcgi_role; // true if the browser is Microsoft Internet Explorer bool browser_msie; @@ -152,11 +152,18 @@ struct Request private: + enum Header + { + h_200, + h_404, + h_403 + }; + void SendSessionCookie(); void CheckIE(); void CheckKonqueror(); - void SendHeaders(bool compressing); + void SendHeaders(bool compressing, Header header); void AddDebugInfo(); void SendPage(bool compressing); @@ -173,6 +180,7 @@ private: // html after filtering std::string clean_html; + }; diff --git a/core/requestcontroller.cpp b/core/requestcontroller.cpp index b8a84ff..135995e 100755 --- a/core/requestcontroller.cpp +++ b/core/requestcontroller.cpp @@ -148,14 +148,29 @@ void RequestController::SaveSessionsIfNeeded() bool RequestController::BaseUrlRedirect() { - if( data.base_url_http_host.empty() ) - return false; - - if( data.base_url_http_host == request.env_http_host ) - return false; + if( request.role == Request::responder ) + { + if( data.base_url_http_host.empty() ) + return false; + + if( data.base_url_http_host == request.env_http_host ) + return false; + + request.redirect_to = data.base_url + request.env_request_uri; + } + else + { + // authorizer + + if( data.base_url_static_auth_http_host.empty() ) + return false; + + if( data.base_url_static_auth_http_host == request.env_http_host ) + return false; + + request.redirect_to = data.base_url_static_auth + request.env_request_uri; + } - request.redirect_to = data.base_url + request.env_request_uri; - log << log3 << "RC: BaseUrlRedirect from: " << request.env_http_host << logend; return true; diff --git a/main/main.cpp b/main/main.cpp index db808e6..552d3c7 100755 --- a/main/main.cpp +++ b/main/main.cpp @@ -96,6 +96,10 @@ int main(int argv, char ** argc) nlog.Init(data.log_level, data.log_notify_file, false); db.Init(data.db_database, data.db_user, data.db_pass); + // data.base_server can be changed (stripped from 'http://' or a last slash) + // it is done when the config is read + log << log3 << "base_server: " << data.base_server << logend; + plugin.LoadPlugins(data.plugin_file); request.Init(); diff --git a/templates/doc.cpp b/templates/doc.cpp index 02c6d66..0866e4c 100755 --- a/templates/doc.cpp +++ b/templates/doc.cpp @@ -64,6 +64,19 @@ void doc_base_url(Info & i) +void doc_base_url_static(Info & i) +{ + i.out << data.base_url_static; +} + + + +void doc_base_url_static_auth(Info & i) +{ + i.out << data.base_url_static_auth; +} + + void doc_current_url(Info & i) { i.out << request.env_request_uri; diff --git a/templates/item.cpp b/templates/item.cpp index 7292842..60b6172 100755 --- a/templates/item.cpp +++ b/templates/item.cpp @@ -119,6 +119,31 @@ void item_link(Info & i) } +void item_link_static_auth(Info & i) +{ + HtmlEscape(i.out, data.base_url_static_auth); + item_dir(i); + item_url(i); +} + + +void item_static_auth_is_none(Info & i) +{ + i.result = request.item.static_auth == Item::static_none; +} + + +void item_static_auth_is_image(Info & i) +{ + i.result = request.item.static_auth == Item::static_image; +} + + +void item_static_auth_is_other(Info & i) +{ + i.result = request.item.static_auth == Item::static_other; +} + void item_can_read(Info & i) { diff --git a/templates/templates.cpp b/templates/templates.cpp index 9712508..5608c26 100755 --- a/templates/templates.cpp +++ b/templates/templates.cpp @@ -202,13 +202,15 @@ void Templates::CreateFunctions() /* doc */ - functions.Insert("doc_language", doc_language); - functions.Insert("doc_title", doc_title); - functions.Insert("doc_charset", doc_charset); - functions.Insert("doc_base_url", doc_base_url); - functions.Insert("doc_current_url", doc_current_url); - functions.Insert("doc_is_error", doc_is_error); - functions.Insert("doc_status", doc_status); + functions.Insert("doc_language", doc_language); + functions.Insert("doc_title", doc_title); + functions.Insert("doc_charset", doc_charset); + functions.Insert("doc_base_url", doc_base_url); + functions.Insert("doc_base_url_static", doc_base_url_static); + functions.Insert("doc_base_url_static_auth", doc_base_url_static_auth); + functions.Insert("doc_current_url", doc_current_url); + functions.Insert("doc_is_error", doc_is_error); + functions.Insert("doc_status", doc_status); /* item @@ -224,6 +226,11 @@ void Templates::CreateFunctions() functions.Insert("item_dir", item_dir); functions.Insert("item_url", item_url); functions.Insert("item_link", item_link); + functions.Insert("item_link_static_auth", item_link_static_auth); + functions.Insert("item_static_auth_is_none", item_static_auth_is_none); + functions.Insert("item_static_auth_is_image", item_static_auth_is_image); + functions.Insert("item_static_auth_is_other", item_static_auth_is_other); + functions.Insert("item_can_read", item_can_read); functions.Insert("item_can_write", item_can_write); functions.Insert("item_info", item_info); diff --git a/templates/templates.h b/templates/templates.h index b00c80b..f2328f3 100755 --- a/templates/templates.h +++ b/templates/templates.h @@ -45,6 +45,8 @@ namespace TemplatesFunctions void doc_title(Info & i); void doc_charset(Info & i); void doc_base_url(Info & i); + void doc_base_url_static(Info & i); + void doc_base_url_static_auth(Info & i); void doc_current_url(Info & i); void doc_is_error(Info & i); void doc_status(Info & i); @@ -64,6 +66,10 @@ namespace TemplatesFunctions void item_dir(Info & i); void item_url(Info & i); void item_link(Info & i); + void item_link_static_auth(Info & i); + void item_static_auth_is_none(Info & i); + void item_static_auth_is_image(Info & i); + void item_static_auth_is_other(Info & i); void item_can_read(Info & i); void item_can_write(Info & i); void item_info(Info & i);