#include #include #include #include #include #include #include #include #include #include #include #include "cgicmsub.hpp" #include "xcgi.hpp" #include "xrandom.h" #include "dullcgi.hpp" //////////////////////////////////////////////////////////////// // The three objects expected to be implemented and exported // by the user-supplied module // extern const char *dullcgi_config_path; extern const char *dullcgi_program_name; int dullcgi_main(DullCgi *cgi); ///////////////////////////////////////////////////////////////// // The database and the macroprocessor class definitions // class DullCgiDb; class DullCgiDbSubstitution : public CommonCgiSubstitutions { const DullCgiDb *the_database; public: DullCgiDbSubstitution(const DullCgiDb *master, const Cgi *cgi); ~DullCgiDbSubstitution(); }; class VarHtmlSection : public ScriptMacroprocessorMacro { const DullCgiDbSubstitution *the_master; const DullCgiDb *the_database; public: VarHtmlSection(const DullCgiDbSubstitution *m, const DullCgiDb *db) : ScriptMacroprocessorMacro("html"), the_master(m), the_database(db) {} ScriptVariable Expand(const ScriptVector ¶ms) const; }; class DullCgiDb { class IniFileParser *inifile; class DullCgiDbSubstitution *subst; ScriptVector aux_args; public: DullCgiDb(const Cgi *cgi); ~DullCgiDb(); void AddMacro(class ScriptMacroprocessorMacro *p); void SetPositionals(const ScriptVector &v) { aux_args = v; } ScriptVariable GetConfigValue(const ScriptVariable §1, const ScriptVariable §2, const ScriptVariable ¶m, const ScriptVariable &qualif, bool expand_macros) const; int GetSectionNames(const ScriptVariable &group_id, class ScriptVector &names) const; bool Load(const ScriptVariable &filename); ScriptVariable MakeErrorMessage() const; ScriptVariable GetHtmlSnippet(const ScriptVariable &name) const; ScriptVariable MakeErrorPage(int code, const ScriptVariable &cmt) const; ScriptVariable BuildPage(const char *pageid) const; ScriptVariable BuildRedirectPage(const ScriptVariable &url) const; ScriptMacroprocessor *GetMacroprocessor() const { return subst; } }; ///////////////////////////////////////////////////////////////// // The database and the macroprocessor implementation // DullCgiDbSubstitution::DullCgiDbSubstitution(const DullCgiDb *m, const Cgi *c) : CommonCgiSubstitutions(c), the_database(m) { AddMacro(new VarHtmlSection(this, m)); // [html: ] } DullCgiDbSubstitution::~DullCgiDbSubstitution() { } ///////////////////////////////////// DullCgiDb::DullCgiDb(const Cgi *cgi) { inifile = new IniFileParser; subst = new DullCgiDbSubstitution(this, cgi); } DullCgiDb::~DullCgiDb() { delete subst; delete inifile; } void DullCgiDb::AddMacro(class ScriptMacroprocessorMacro *p) { subst->AddMacro(p); } bool DullCgiDb::Load(const ScriptVariable &filename) { return inifile->Load(filename.c_str()); } ScriptVariable DullCgiDb::MakeErrorMessage() const { ScriptVariable msg(""); int el = inifile->GetLastErrorLine(); if(el != -1) msg += ScriptNumber(el) + ": "; else msg += " "; msg += inifile->GetLastErrorDescription(); return msg; } ScriptVariable DullCgiDb::GetHtmlSnippet(const ScriptVariable &name) const { return inifile->GetTextParameter("html", 0, name.c_str(), ""); } static const char *c_str_if_notempty(const ScriptVariable &v) { if(v.IsInvalid() || v == "") return 0; return v.c_str(); } ScriptVariable DullCgiDb::GetConfigValue(const ScriptVariable §1, const ScriptVariable §2, const ScriptVariable ¶m, const ScriptVariable &qualif, bool expand_macros) const { const char *qs = c_str_if_notempty(qualif); const char *tmp = qs ? inifile->GetModifiedTextParameter(sect1.c_str(), c_str_if_notempty(sect2), param.c_str(), qs, 0) : inifile->GetTextParameter(sect1.c_str(), c_str_if_notempty(sect2), param.c_str(), 0); if(!tmp) return ScriptVariableInv(); if(!expand_macros) return tmp; return subst->Process(tmp, aux_args); } int DullCgiDb::GetSectionNames(const ScriptVariable &group_id, class ScriptVector &names) const { const char *gn = group_id.c_str(); int cnt = inifile->GetSectionCount(gn); names.Clear(); int i; for(i = 0; i < cnt; i++) names[i] = inifile->GetSectionName(gn, i); return cnt; } static const char default_error_page_template[] = "\n" "\n" "\n" "%progname% default error page\n" "

%progname% default error page

\n" "

%errcode% %errmessage%

\n" "

If you see this page it probably means the configuration\n" "file for %progname% CGI program is either missing or\n" "broken. Please check.

\n"; ScriptVariable DullCgiDb::MakeErrorPage(int code, const ScriptVariable &comment) const { ScriptVariable templ = inifile->GetTextParameter("errorpage", 0, "template", default_error_page_template); ScriptNumber code_s(code); ScriptMacroprocessor sub_sub(subst); sub_sub.AddMacro(new ScriptMacroConst("progname", dullcgi_program_name)); sub_sub.AddMacro(new ScriptMacroConst("errcode", code_s)); sub_sub.AddMacro(new ScriptMacroConst("errmessage", comment)); return sub_sub.Process(templ); } ScriptVariable DullCgiDb::BuildPage(const char *pgid) const { const char *tmp; #if 0 tmp = inifile->GetTextParameter("page", pgid, "selector", 0); if(tmp) { data.selector = subst->Process(tmp, aux_args); data.selector.Trim(); } else { data.selector = ScriptVariableInv(); } #endif tmp = inifile->GetTextParameter("page", pgid, "template", 0); if(!tmp) return ScriptVariable("No template found for ") + pgid + "\n"; ScriptVariable res = subst->Process(tmp, aux_args); return res; } ScriptVariable DullCgiDb::BuildRedirectPage(const ScriptVariable &url) const { const char *tmp; tmp = inifile->GetTextParameter("redirectpage", 0, "template", 0); if(!tmp) return "No template configured for the redirect page"; ScriptMacroprocessor sub_sub(subst); sub_sub.AddMacro(new ScriptMacroConst("url", url)); return sub_sub.Process(tmp); } ///////////////////////////////////////////////////////////////// // ScriptVariable VarHtmlSection::Expand(const ScriptVector ¶ms) const { int len = params.Length(); if(len < 1) return ScriptVariableInv(); ScriptVariable sn = the_database->GetHtmlSnippet(params[0].Trim()); return the_master->Process(sn, params, 1, len-1); } // ///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// // DullCgi methods implementation // void DullCgi::AddMacro(class ScriptMacroprocessorMacro *p) { if(!the_database) return; the_database->AddMacro(p); } void DullCgi::SetPositionals(const ScriptVector &v) { if(!the_database) return; the_database->SetPositionals(v); } ScriptMacroprocessor *DullCgi::MakeMacroprocessorClone() const { if(!the_database) return new ScriptMacroprocessor; return new ScriptMacroprocessor(the_database->GetMacroprocessor()); } void DullCgi::DisposeMacroprocessorClone(ScriptMacroprocessor *p) { delete p; } ScriptVariable DullCgi::GetConfigValue(const ScriptVariable §1, const ScriptVariable §2, const ScriptVariable &par, const ScriptVariable &qual, bool expand) const { if(!the_database) return ScriptVariableInv(); return the_database->GetConfigValue(sect1, sect2, par, qual, expand); } int DullCgi::GetSectionNames(const ScriptVariable &group_id, class ScriptVector &names) const { if(!the_database) return -1; return the_database->GetSectionNames(group_id, names); } void DullCgi::SendErrorPage(int code, const ScriptVariable &cmt) { ScriptVariable pg = the_database->MakeErrorPage(code, cmt); SetStatus(code, cmt); SetBody(pg); Commit(); } void DullCgi::SendPage(const ScriptVariable &pgid) { ScriptVariable pg = the_database->BuildPage(pgid.c_str()); SetBody(pg); Commit(); } void DullCgi::SendRedirect(const ScriptVariable &url) { ScriptVariable pg = the_database->BuildRedirectPage(url); SetBody(pg); SetSeeOther(url); Commit(); } // ///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// // the main function int main() { DullCgi cgi; DullCgiDb db(&cgi); cgi.SetDatabase(&db); if(!db.Load(dullcgi_config_path)) { ScriptVariable diag = db.MakeErrorMessage(); cgi.SendErrorPage(500, diag.c_str()); return 0; } randomize(); if(!cgi.ParseHead()) { cgi.Commit(); return 0; } if(cgi.IsPost()) { cgi.SendErrorPage(405, "Method not allowed"); return 0; } return dullcgi_main(&cgi); }