X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Fsubst.c;h=b54e921ee9946b3c1c738ad9576f96dd26bb83ab;hb=HEAD;hp=2ab6e6b407c04dd3ba83924a4cfd2a31297b13e5;hpb=a4ec41fd6e5840659d79f265aca66669df3c341a;p=citadel.git diff --git a/webcit/subst.c b/webcit/subst.c index 2ab6e6b40..f6725cd58 100644 --- a/webcit/subst.c +++ b/webcit/subst.c @@ -1,11 +1,12 @@ -#include "sysdep.h" - +// This is a template substitution engine, which began with good intentions, but ended up becoming +// more complex and unmaintainable than what it replaced. We are barely hanging on with this until +// webcit-ng replaces webcit classic. +#include "sysdep.h" #include #include #include #include - #include #include #include @@ -14,7 +15,7 @@ #define SHOW_ME_VAPPEND_PRINTF #include "webcit.h" -#include "webserver.h" + extern char *static_dirs[PATH_MAX]; /* Disk representation */ @@ -219,7 +220,6 @@ void DestroySortStruct(void *vSort) void LogTemplateError (StrBuf *Target, const char *Type, int ErrorPos, WCTemplputParams *TP, const char *Format, ...) { - wcsession *WCC; StrBuf *Error; StrBuf *Info; va_list arg_ptr; @@ -258,14 +258,13 @@ void LogTemplateError (StrBuf *Target, const char *Type, int ErrorPos, WCTemplpu Type, ChrPtr(Error)); } - WCC = WC; - if (WCC == NULL) { + if (WC == NULL) { FreeStrBuf(&Info); FreeStrBuf(&Error); return; } - if (WCC->WFBuf == NULL) WCC->WFBuf = NewStrBuf(); + if (WC->WFBuf == NULL) WC->WFBuf = NewStrBuf(); if (TP->Tokens != NULL) { /* deprecated: @@ -286,45 +285,25 @@ void LogTemplateError (StrBuf *Target, const char *Type, int ErrorPos, WCTemplpu ChrPtr(TP->Tokens->FlatToken)); - SerializeJson(WCC->WFBuf, WildFireException(SKEY(TP->Tokens->FileName), + SerializeJson(WC->WFBuf, WildFireException(SKEY(TP->Tokens->FileName), TP->Tokens->Line, Info, 1), 1); -/* - SerializeJson(Header, WildFireMessage(SKEY(TP->Tokens->FileName), - TP->Tokens->Line, - Error, - eERROR), 1); -*/ - } - else - { - /* deprecated. - StrBufAppendPrintf( - Target, - "
\n%s: %s\n
\n", - Type, - ChrPtr(Error)); - */ + else { StrBufPrintf(Info, "%s [%s] %s; [%s]", Type, Err, ChrPtr(Error), ChrPtr(TP->Tokens->FlatToken)); - SerializeJson(WCC->WFBuf, WildFireException(HKEY(__FILE__), __LINE__, Info, 1), 1); + SerializeJson(WC->WFBuf, WildFireException(HKEY(__FILE__), __LINE__, Info, 1), 1); } FreeStrBuf(&Info); FreeStrBuf(&Error); -/* - if (dbg_backtrace_template_errors) - wc_backtrace(LOG_DEBUG); -*/ } -void LogError (StrBuf *Target, const char *Type, const char *Format, ...) -{ - wcsession *WCC; + +void LogError (StrBuf *Target, const char *Type, const char *Format, ...) { StrBuf *Error; StrBuf *Info; va_list arg_ptr; @@ -338,20 +317,15 @@ void LogError (StrBuf *Target, const char *Type, const char *Format, ...) syslog(LOG_WARNING, "%s", ChrPtr(Error)); - WCC = WC; - if (WCC->WFBuf == NULL) WCC->WFBuf = NewStrBuf(); + if (WC->WFBuf == NULL) WC->WFBuf = NewStrBuf(); - SerializeJson(WCC->WFBuf, WildFireException(Type, strlen(Type), + SerializeJson(WC->WFBuf, WildFireException(Type, strlen(Type), 0, Info, 1), 1); FreeStrBuf(&Info); FreeStrBuf(&Error); -/* - if (dbg_backtrace_template_errors) - wc_backtrace(LOG_DEBUG); -*/ } @@ -402,29 +376,10 @@ int CheckContext(StrBuf *Target, ContextFilter *Need, WCTemplputParams *TP, cons ContextName(TP->Filter.ContextType)); return 0; } -/* - if (TP->Tokens->nParameters < Need->nMinArgs) { - LogTemplateError(Target, ErrType, ERR_NAME, TP, - "needs at least %ld params, have %ld", - Need->nMinArgs, - TP->Tokens->nParameters); - return 0; - - } - else if (TP->Tokens->nParameters > Need->nMaxArgs) { - LogTemplateError(Target, ErrType, ERR_NAME, TP, - "just needs %ld params, you gave %ld", - Need->nMaxArgs, - TP->Tokens->nParameters); - return 0; - - } -*/ return 1; } -void FreeToken(WCTemplateToken **Token) -{ +void FreeToken(WCTemplateToken **Token) { int i; FreeStrBuf(&(*Token)->FlatToken); if ((*Token)->HaveParameters) @@ -435,9 +390,7 @@ void FreeToken(WCTemplateToken **Token) } - -void FreeWCTemplate(void *vFreeMe) -{ +void FreeWCTemplate(void *vFreeMe) { int i; WCTemplate *FreeMe = (WCTemplate*)vFreeMe; @@ -479,14 +432,8 @@ int HaveTemplateTokenString(StrBuf *Target, } } -void GetTemplateTokenString(StrBuf *Target, - WCTemplputParams *TP, - int N, - const char **Value, - long *len) -{ +void GetTemplateTokenString(StrBuf *Target, WCTemplputParams *TP, int N, const char **Value, long *len) { StrBuf *Buf; -/// WCTemplputParams SubTP; if (N >= TP->Tokens->nParameters) { LogTemplateError(Target, @@ -584,8 +531,7 @@ void GetTemplateTokenString(StrBuf *Target, } } -long GetTemplateTokenNumber(StrBuf *Target, WCTemplputParams *TP, int N, long dflt) -{ +long GetTemplateTokenNumber(StrBuf *Target, WCTemplputParams *TP, int N, long dflt) { long Ret; if (N >= TP->Tokens->nParameters) { LogTemplateError(Target, @@ -680,6 +626,7 @@ void StrBufAppendTemplate(StrBuf *Target, char EscapeAs = ' '; if ((FormatTypeIndex < TP->Tokens->nParameters) && + (TP->Tokens->Params[FormatTypeIndex] != NULL) && (TP->Tokens->Params[FormatTypeIndex]->Type == TYPE_STR) && (TP->Tokens->Params[FormatTypeIndex]->len >= 1)) { pFmt = TP->Tokens->Params[FormatTypeIndex]->Start; @@ -692,14 +639,19 @@ void StrBufAppendTemplate(StrBuf *Target, StrEscAppend(Target, Source, NULL, 0, 2); break; case 'X': - StrEscAppend(Target, Source, NULL, 0, 0); + if (!IsEmptyStr(ChrPtr(Source))) { + StrEscAppend(Target, Source, NULL, 0, 0); + if (pFmt[1]) { + StrBufAppendBufPlain(Target, pFmt, -1, 1); + } + } break; case 'J': StrECMAEscAppend(Target, Source, NULL); - break; + break; case 'K': StrHtmlEcmaEscAppend(Target, Source, NULL, 0, 0); - break; + break; case 'U': StrBufUrlescAppend(Target, Source, NULL); break; @@ -759,7 +711,7 @@ void StrBufAppendTemplateStr(StrBuf *Target, break; */ default: - StrBufAppendBufPlain(Target, Source, 0, 0); + StrBufAppendBufPlain(Target, Source, -1, 0); } } @@ -1293,12 +1245,11 @@ WCTemplateToken *NewTemplateSubstitute(StrBuf *Buf, -/** - * \brief Display a variable-substituted template - * \param templatename template file to load +/* + * Display a variable-substituted template + * templatename template file to load */ -void *prepare_template(StrBuf *filename, StrBuf *Key, HashList *PutThere) -{ +void *prepare_template(StrBuf *filename, StrBuf *Key, HashList *PutThere) { WCTemplate *NewTemplate; NewTemplate = (WCTemplate *) malloc(sizeof(WCTemplate)); @@ -1322,12 +1273,11 @@ void *prepare_template(StrBuf *filename, StrBuf *Key, HashList *PutThere) return NewTemplate; } -/** - * \brief Display a variable-substituted template - * \param templatename template file to load +/* + * Display a variable-substituted template + * templatename template file to load */ -void *duplicate_template(WCTemplate *OldTemplate) -{ +void *duplicate_template(WCTemplate *OldTemplate) { WCTemplate *NewTemplate; NewTemplate = (WCTemplate *) malloc(sizeof(WCTemplate)); @@ -1343,16 +1293,13 @@ void *duplicate_template(WCTemplate *OldTemplate) } -void SanityCheckTemplate(StrBuf *Target, WCTemplate *CheckMe) -{ +void SanityCheckTemplate(StrBuf *Target, WCTemplate *CheckMe) { int i = 0; int j; int FoundConditionalEnd; - for (i = 0; i < CheckMe->nTokensUsed; i++) - { - switch(CheckMe->Tokens[i]->Flags) - { + for (i = 0; i < CheckMe->nTokensUsed; i++) { + switch(CheckMe->Tokens[i]->Flags) { case SV_CONDITIONAL: case SV_NEG_CONDITIONAL: FoundConditionalEnd = 0; @@ -1388,9 +1335,9 @@ void SanityCheckTemplate(StrBuf *Target, WCTemplate *CheckMe) } } -/** - * \brief Display a variable-substituted template - * \param templatename template file to load +/* + * Display a variable-substituted template + * templatename template file to load */ void *load_template(StrBuf *Target, WCTemplate *NewTemplate) { @@ -1527,8 +1474,7 @@ int LoadTemplateDir(const StrBuf *DirName, HashList *big, const StrBuf *BaseKey) char *MinorPtr; #ifdef _DIRENT_HAVE_D_NAMLEN - d_namelen = filedir_entry->d_namelen; - + d_namelen = filedir_entry->d_namlen; #else d_namelen = strlen(filedir_entry->d_name); #endif @@ -1647,22 +1593,16 @@ void InitTemplateCache(void) /* Primary Template set... */ StrBufPrintf(Dir, "%s/t", static_dirs[0]); - LoadTemplateDir(Dir, - TemplateCache, - Key); + LoadTemplateDir(Dir, TemplateCache, Key); /* User local Template set */ StrBufPrintf(Dir, "%s/t", static_dirs[1]); - LoadTemplateDir(Dir, - LocalTemplateCache, - Key); + LoadTemplateDir(Dir, LocalTemplateCache, Key); /* Debug Templates, just to be loaded while debugging. */ StrBufPrintf(Dir, "%s/dbg", static_dirs[0]); - LoadTemplateDir(Dir, - TemplateCache, - Key); + LoadTemplateDir(Dir, TemplateCache, Key); Templates[0] = TemplateCache; Templates[1] = LocalTemplateCache; @@ -1675,13 +1615,7 @@ void InitTemplateCache(void) void *vTemplate; At = GetNewHashPos(Templates[i], 0); - while (GetNextHashPos(Templates[i], - At, - &KLen, - &Key, - &vTemplate) && - (vTemplate != NULL)) - { + while (GetNextHashPos(Templates[i], At, &KLen, &Key, &vTemplate) && (vTemplate != NULL)) { load_template(NULL, (WCTemplate *)vTemplate); } DeleteHashPos(&At); @@ -1744,17 +1678,11 @@ int EvaluateToken(StrBuf *Target, int state, WCTemplputParams **TPP) if (TP->Tokens->nParameters >= 6) { if (EvaluateConditional(Target, 0, state, TPP)) { GetTemplateTokenString(Target, TP, 5, &AppendMe, &AppendMeLen); - StrBufAppendBufPlain(Target, - AppendMe, - AppendMeLen, - 0); + StrBufAppendBufPlain(Target, AppendMe, AppendMeLen, 0); } else{ GetTemplateTokenString(Target, TP, 4, &AppendMe, &AppendMeLen); - StrBufAppendBufPlain(Target, - AppendMe, - AppendMeLen, - 0); + StrBufAppendBufPlain(Target, AppendMe, AppendMeLen, 0); } if (*TPP != TP) { @@ -1762,9 +1690,7 @@ int EvaluateToken(StrBuf *Target, int state, WCTemplputParams **TPP) } } else { - LogTemplateError( - Target, "Conditional", ERR_NAME, TP, - "needs at least 6 Params!"); + LogTemplateError( Target, "Conditional", ERR_NAME, TP, "needs at least 6 Params!"); } break; case SV_SUBTEMPL: @@ -1824,8 +1750,7 @@ const StrBuf *ProcessTemplate(WCTemplate *Tmpl, StrBuf *Target, WCTemplputParams ChrPtr(Tmpl->FileName)); pTmpl = duplicate_template(Tmpl); if(load_template(Target, pTmpl) == NULL) { - StrBufAppendPrintf( - Target, + StrBufAppendPrintf( Target, "
\nError loading Template [%s]\n See Logfile for details\n
\n", ChrPtr(Tmpl->FileName)); FreeWCTemplate(pTmpl); @@ -1840,30 +1765,22 @@ const StrBuf *ProcessTemplate(WCTemplate *Tmpl, StrBuf *Target, WCTemplputParams state = eNext; while (!done) { if (i >= pTmpl->nTokensUsed) { - StrBufAppendBufPlain(Target, - pData, - len - (pData - pS), 0); + StrBufAppendBufPlain(Target, pData, len - (pData - pS), 0); done = 1; } else { - int TokenRc; + int TokenRc = 0; - StrBufAppendBufPlain( - Target, pData, - pTmpl->Tokens[i]->pTokenStart - pData, 0); + StrBufAppendBufPlain( Target, pData, pTmpl->Tokens[i]->pTokenStart - pData, 0); TPtr->Tokens = pTmpl->Tokens[i]; TPtr->nArgs = pTmpl->Tokens[i]->nParameters; TokenRc = EvaluateToken(Target, TokenRc, &TPtr); - if (TokenRc > 0) - { + if (TokenRc > 0) { state = eSkipTilEnd; } - else if (TokenRc < 0) - { - if ((TPtr != &TP) && - (TPtr->ExitCTXID == -TokenRc)) - { + else if (TokenRc < 0) { + if ((TPtr != &TP) && (TPtr->ExitCTXID == -TokenRc)) { UnStackDynamicContext(Target, &TPtr); } TokenRc = 0; @@ -1883,13 +1800,10 @@ const StrBuf *ProcessTemplate(WCTemplate *Tmpl, StrBuf *Target, WCTemplputParams pTmpl->Tokens[i]->Flags, TokenRc, &TPtr); - if (-rc == TokenRc) - { + if (-rc == TokenRc) { TokenRc = 0; state = eNext; - if ((TPtr != &TP) && - (TPtr->ExitCTXID == - rc)) - { + if ((TPtr != &TP) && (TPtr->ExitCTXID == - rc)) { UnStackDynamicContext(Target, &TPtr); } } @@ -1908,6 +1822,8 @@ const StrBuf *ProcessTemplate(WCTemplate *Tmpl, StrBuf *Target, WCTemplputParams } + +StrBuf *textPlainType; /** * \brief Display a variable-substituted template * \param templatename template file to load @@ -1930,27 +1846,31 @@ const StrBuf *DoTemplate(const char *templatename, long len, StrBuf *Target, WCT Static = TemplateCache; StaticLocal = LocalTemplateCache; - if (len == 0) - { + if (len == 0) { syslog(LOG_WARNING, "Can't to load a template with empty name!\n"); StrBufAppendPrintf(Target, "
\nCan't to load a template with empty name!\n
"); - return NULL; + return textPlainType; } if (!GetHash(StaticLocal, templatename, len, &vTmpl) && !GetHash(Static, templatename, len, &vTmpl)) { - syslog(LOG_WARNING, "didn't find Template [%s] %ld %ld\n", templatename, len , (long)strlen(templatename)); + StrBuf *escapedString = NewStrBufPlain(NULL, len); + + StrHtmlEcmaEscAppend(escapedString, NULL, templatename, 1, 1); + syslog(LOG_WARNING, "didn't find Template [%s] %ld %ld\n", ChrPtr(escapedString), len , (long)strlen(templatename)); StrBufAppendPrintf(Target, "
\ndidn't find Template [%s] %ld %ld\n
", - templatename, len, + ChrPtr(escapedString), len, (long)strlen(templatename)); + WC->isFailure = 1; #if 0 dbg_PrintHash(Static, PrintTemplate, NULL); PrintHash(Static, VarPrintTransition, PrintTemplate); #endif - return NULL; + FreeStrBuf(&escapedString); + return textPlainType; } if (vTmpl == NULL) - return NULL; + return textPlainType; return ProcessTemplate(vTmpl, Target, TP); } @@ -1985,6 +1905,7 @@ typedef struct _HashIterator { RetrieveHashlistFunc GetHash; HashDestructorFunc Destructor; SubTemplFunc DoSubTemplate; + FilterByParamFunc Filter; } HashIterator; void RegisterITERATOR(const char *Name, long len, @@ -1993,6 +1914,7 @@ void RegisterITERATOR(const char *Name, long len, RetrieveHashlistFunc GetHash, SubTemplFunc DoSubTempl, HashDestructorFunc Destructor, + FilterByParamFunc Filter, CtxType ContextType, CtxType XPectContextType, int Flags) @@ -2006,6 +1928,7 @@ void RegisterITERATOR(const char *Name, long len, It->GetHash = GetHash; It->DoSubTemplate = DoSubTempl; It->Destructor = Destructor; + It->Filter = Filter; It->ContextType = ContextType; It->XPectContextType = XPectContextType; It->Flags = Flags; @@ -2131,7 +2054,7 @@ void tmpl_iterate_subtmpl(StrBuf *Target, WCTemplputParams *TP) /** Ok, its us, lets see in which direction we should sort... */ (havebstr("SortOrder"))) { int SortOrder; - SortOrder = LBSTR("SortOrder"); + SortOrder = lbstr("SortOrder"); if (SortOrder != 0) DetectGroupChange = 1; } @@ -2159,6 +2082,13 @@ void tmpl_iterate_subtmpl(StrBuf *Target, WCTemplputParams *TP) } while (GetNextHashPos(List, it, &Status.KeyLen, &Status.Key, &vContext)) { if ((Status.n >= StartAt) && (Status.n <= StopAt)) { + + if ((It->Filter != NULL) && + !It->Filter(Status.Key, Status.KeyLen, vContext, Target, TP)) + { + continue; + } + if (DetectGroupChange && Status.n > 0) { Status.GroupChange = SortBy->GroupChange(vContext, vLastContext); } @@ -2213,8 +2143,17 @@ void tmplput_ITERATE_KEY(StrBuf *Target, WCTemplputParams *TP) StrBufAppendBufPlain(Target, Ctx->Key, Ctx->KeyLen, 0); } +void tmplput_ITERATE_N_DIV(StrBuf *Target, WCTemplputParams *TP) +{ + IterateStruct *Ctx = CTX(CTX_ITERATE); + long div; + long divisor = GetTemplateTokenNumber(Target, TP, 0, 1); +///TODO divisor == 0 -> log error exit + div = Ctx->n / divisor; + StrBufAppendPrintf(Target, "%ld", div); +} -void tmplput_ITERATE_LASTN(StrBuf *Target, WCTemplputParams *TP) +void tmplput_ITERATE_N(StrBuf *Target, WCTemplputParams *TP) { IterateStruct *Ctx = CTX(CTX_ITERATE); StrBufAppendPrintf(Target, "%d", Ctx->n); @@ -2232,6 +2171,16 @@ int conditional_ITERATE_LASTN(StrBuf *Target, WCTemplputParams *TP) return Ctx->LastN; } +int conditional_ITERATE_ISMOD(StrBuf *Target, WCTemplputParams *TP) +{ + IterateStruct *Ctx = CTX(CTX_ITERATE); + + long divisor = GetTemplateTokenNumber(Target, TP, 2, 1); + long expectRemainder = GetTemplateTokenNumber(Target, TP, 3, 0); + + return Ctx->n % divisor == expectRemainder; +} + /*----------------------------------------------------------------------------- @@ -2533,8 +2482,6 @@ void tmpl_do_tabbed(StrBuf *Target, WCTemplputParams *TP) } StackContext (TP, &SubTP, &TS, CTX_TAB, 0, NULL); { -//// TODO jetzt memcpy (&SubTP, TP, sizeof(WCTemplputParams)); -// SubTP.Filter.ControlContextType = ; StrTabbedDialog(Target, nTabs, TabNames); for (i = 0; i < ntabs; i++) { memset(&TS, 0, sizeof(tab_struct)); @@ -2649,7 +2596,7 @@ CompareFunc RetrieveSort(WCTemplputParams *TP, /** Ok, its us, lets see in which direction we should sort... */ if (havebstr("SortOrder")) { - SortOrder = LBSTR("SortOrder"); + SortOrder = lbstr("SortOrder"); } else { /** Try to fallback to our remembered values... */ StrBuf *Buf = NULL; @@ -2741,7 +2688,7 @@ int GetSortMetric(WCTemplputParams *TP, SortStruct **Next, SortStruct **Param, l /** Ok, its us, lets see in which direction we should sort... */ if (havebstr("SortOrder")) { - *SortOrder = LBSTR("SortOrder"); + *SortOrder = lbstr("SortOrder"); } else { /** Try to fallback to our remembered values... */ if ((*Param)->PrefPrepend == NULL) { @@ -2964,10 +2911,14 @@ InitModule_SUBST RegisterConditional("COND:ITERATE:FIRSTN", 2, conditional_ITERATE_FIRSTN, CTX_ITERATE); + RegisterConditional("COND:ITERATE:ISMOD", 3, + conditional_ITERATE_ISMOD, + CTX_ITERATE); RegisterNamespace("ITERATE:ODDEVEN", 0, 0, tmplput_ITERATE_ODDEVEN, NULL, CTX_ITERATE); RegisterNamespace("ITERATE:KEY", 0, 0, tmplput_ITERATE_KEY, NULL, CTX_ITERATE); - RegisterNamespace("ITERATE:N", 0, 0, tmplput_ITERATE_LASTN, NULL, CTX_ITERATE); + RegisterNamespace("ITERATE:N", 0, 0, tmplput_ITERATE_N, NULL, CTX_ITERATE); + RegisterNamespace("ITERATE:N:DIV", 1, 1, tmplput_ITERATE_N_DIV, NULL, CTX_ITERATE); RegisterNamespace("CURRENTFILE", 0, 1, tmplput_CURRENT_FILE, NULL, CTX_NONE); RegisterNamespace("DEF:STR", 1, 1, tmplput_DefStr, NULL, CTX_NONE); RegisterNamespace("DEF:VAL", 1, 1, tmplput_DefVal, NULL, CTX_NONE); @@ -2981,9 +2932,9 @@ void ServerStartModule_SUBST (void) { + textPlainType = NewStrBufPlain(HKEY("text/plain")); LocalTemplateCache = NewHash(1, NULL); TemplateCache = NewHash(1, NULL); - GlobalNS = NewHash(1, NULL); Iterators = NewHash(1, NULL); Conditionals = NewHash(1, NULL); @@ -3009,9 +2960,11 @@ void ServerShutdownModule_SUBST (void) { + FreeStrBuf(&textPlainType); + DeleteHash(&TemplateCache); DeleteHash(&LocalTemplateCache); - + DeleteHash(&GlobalNS); DeleteHash(&Iterators); DeleteHash(&Conditionals);