X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Fsubst.c;h=130b1a12ac61bd7e2811d485d7775c11527f4803;hb=523dacbf093a836e18649e6e40454e22276ef6e7;hp=83f780875a068ba6024a2c5fda088f42033aea41;hpb=435f67c3f81d81428fb44a1788ff8d1a937556e1;p=citadel.git diff --git a/webcit/subst.c b/webcit/subst.c index 83f780875..130b1a12a 100644 --- a/webcit/subst.c +++ b/webcit/subst.c @@ -71,8 +71,13 @@ typedef struct _HashHandler { WCHandlerFunc HandlerFunc; }HashHandler; +typedef enum _estate { + eNext, + eSkipTilEnd +} TemplState; + void *load_template(StrBuf *Target, WCTemplate *NewTemplate); -int EvaluateConditional(StrBuf *Target, int Neg, int state, WCTemplputParams *TP); +int EvaluateConditional(StrBuf *Target, int Neg, int state, WCTemplputParams **TPP); @@ -83,46 +88,74 @@ typedef struct _SortStruct { CompareFunc Reverse; CompareFunc GroupChange; - long ContextType; + CtxType ContextType; }SortStruct; -const char *CtxNames[] = { - "Context NONE", - "Context SITECFG", - "Context SESSION", - "Context INETCFG", - "Context VNOTE", - "Context WHO", - "Context PREF", - "Context NODECONF", - "Context USERLIST", - "Context MAILSUM", - "Context MIME_ATACH", - "Context FILELIST", - "Context STRBUF", - "Context STRBUFARR", - "Context LONGVECTOR", - "Context ROOMS", - "Context FLOORS", - "Context ITERATE", - "Context ICAL", - "Context DavNamespace", - "Context TAB", - "Context VCARD", - "Context SIEVE List", - "Context SIEVE Script", - "Context MailQ-Item", - "Context MailQ-Recipient", - "Context ServLogStatus", - "Context UNKNOWN" -}; +HashList *CtxList = NULL; + +static CtxType CtxCounter = CTX_NONE; + +CtxType CTX_STRBUF = CTX_NONE; +CtxType CTX_STRBUFARR = CTX_NONE; +CtxType CTX_LONGVECTOR = CTX_NONE; + +CtxType CTX_ITERATE = CTX_NONE; +CtxType CTX_TAB = CTX_NONE; + +void HFreeContextType(void *pCtx) +{ + CtxTypeStruct *FreeStruct = (CtxTypeStruct *) pCtx; + FreeStrBuf(&FreeStruct->Name); + free(FreeStruct); +} +void PutContextType(const char *name, long len, CtxType TheCtx) +{ + CtxTypeStruct *NewStruct; + + NewStruct = (CtxTypeStruct*) malloc(sizeof(CtxTypeStruct)); + NewStruct->Name = NewStrBufPlain(name, len); + NewStruct->Type = TheCtx; + + Put(CtxList, IKEY(NewStruct->Type), NewStruct, HFreeContextType); +} +void RegisterContextType(const char *name, long len, CtxType *TheCtx) +{ + if (*TheCtx != CTX_NONE) + return; + + *TheCtx = ++CtxCounter; + PutContextType(name, len, *TheCtx); +} + +CtxTypeStruct *GetContextType(CtxType Type) +{ + void *pv = NULL; + GetHash(CtxList, IKEY(Type), &pv); + return pv; +} + +const char *UnknownContext = "CTX_UNKNOWN"; + +const char *ContextName(CtxType ContextType) +{ + CtxTypeStruct *pCtx; + + pCtx = GetContextType(ContextType); + + if (pCtx != NULL) + return ChrPtr(pCtx->Name); + else + return UnknownContext; +} -void StackContext(WCTemplputParams *Super, - WCTemplputParams *Sub, - void *Context, - int ContextType, - int nArgs, - WCTemplateToken *Tokens) +void StackDynamicContext(WCTemplputParams *Super, + WCTemplputParams *Sub, + void *Context, + CtxType ContextType, + int nArgs, + WCTemplateToken *Tokens, + WCConditionalFunc ExitCtx, + long ExitCTXID) { memset(Sub, 0, sizeof(WCTemplputParams)); @@ -130,12 +163,16 @@ void StackContext(WCTemplputParams *Super, Sub->Sub = Super->Sub; Super->Sub = Sub; } + if (Sub->Sub != NULL) + Sub->Sub->Super = Sub; Sub->Super = Super; Sub->Context = Context; Sub->Filter.ContextType = ContextType; Sub->nArgs = nArgs; Sub->Tokens = Tokens; + Sub->ExitCtx = ExitCtx; + Sub->ExitCTXID = ExitCTXID; } void UnStackContext(WCTemplputParams *Sub) @@ -144,9 +181,20 @@ void UnStackContext(WCTemplputParams *Sub) { Sub->Super->Sub = Sub->Sub; } + if (Sub->Sub != NULL) + { + Sub->Sub->Super = Sub->Super; + } +} +void UnStackDynamicContext(StrBuf *Target, WCTemplputParams **TPP) +{ + WCTemplputParams *TP = *TPP; + WCTemplputParams *Super = TP->Super; + TP->ExitCtx(Target, TP); + *TPP = Super; } -void *GetContextPayload(WCTemplputParams *TP, int ContextType) +void *GetContextPayload(WCTemplputParams *TP, CtxType ContextType) { WCTemplputParams *whichTP = TP; @@ -167,13 +215,6 @@ void DestroySortStruct(void *vSort) free (Sort); } -const char *ContextName(int ContextType) -{ - if (ContextType < CTX_UNKNOWN) - return CtxNames[ContextType]; - else - return CtxNames[CTX_UNKNOWN]; -} void LogTemplateError (StrBuf *Target, const char *Type, int ErrorPos, WCTemplputParams *TP, const char *Format, ...) { @@ -280,9 +321,6 @@ void LogTemplateError (StrBuf *Target, const char *Type, int ErrorPos, WCTemplpu */ } - - - void LogError (StrBuf *Target, const char *Type, const char *Format, ...) { wcsession *WCC; @@ -322,7 +360,7 @@ void RegisterNS(const char *NSName, int nMaxArgs, WCHandlerFunc HandlerFunc, WCPreevalFunc PreevalFunc, - int ContextRequired) + CtxType ContextRequired) { HashHandler *NewHandler; @@ -357,7 +395,7 @@ int CheckContext(StrBuf *Target, ContextFilter *Need, WCTemplputParams *TP, cons return 1; LogTemplateError( - Target, ErrType, ERR_PARM1, TP, + Target, ErrType, ERR_NAME, TP, " WARNING: requires Context: [%s], have [%s]!", ContextName(Need->ContextType), ContextName(TP->Filter.ContextType)); @@ -429,6 +467,7 @@ int HaveTemplateTokenString(StrBuf *Target, case TYPE_STR: case TYPE_BSTR: case TYPE_PREFSTR: + case TYPE_ROOMPREFSTR: case TYPE_GETTEXT: case TYPE_SUBTEMPLATE: return 1; @@ -490,6 +529,19 @@ void GetTemplateTokenString(StrBuf *Target, *Value = ChrPtr(Buf); *len = StrLength(Buf); break; + case TYPE_ROOMPREFSTR: + if (TP->Tokens->Params[N]->len == 0) { + LogTemplateError(Target, + "TokenParameter", N, TP, + "Requesting parameter %d; of type PREFSTR, empty lookup string not admitted.", N); + *len = 0; + *Value = EmptyStr; + break; + } + Buf = get_ROOM_PREFS(TKEY(N)); + *Value = ChrPtr(Buf); + *len = StrLength(Buf); + break; case TYPE_LONG: LogTemplateError(Target, "TokenParameter", N, TP, @@ -569,6 +621,19 @@ long GetTemplateTokenNumber(StrBuf *Target, WCTemplputParams *TP, int N, long df if (get_PREF_LONG(TKEY(N), &Ret, dflt)) return Ret; return 0; + case TYPE_ROOMPREFSTR: + LogTemplateError(Target, + "TokenParameter", N, TP, + "requesting a prefstring in param %d want a number", N); + if (TP->Tokens->Params[N]->len == 0) { + LogTemplateError(Target, + "TokenParameter", N, TP, + "Requesting parameter %d; of type PREFSTR, empty lookup string not admitted.", N); + return 0; + } + if (get_ROOM_PREFS_LONG(TKEY(N), &Ret, dflt)) + return Ret; + return 0; case TYPE_INTDEFINE: case TYPE_LONG: return TP->Tokens->Params[N]->lvalue; @@ -648,6 +713,55 @@ void StrBufAppendTemplate(StrBuf *Target, } } +/* + * puts string into the template and computes which escape methon we should use + * Source = the string we should put into the template + * FormatTypeIndex = where should we look for escape types if? + */ +void StrBufAppendTemplateStr(StrBuf *Target, + WCTemplputParams *TP, + const char *Source, int FormatTypeIndex) +{ + const char *pFmt = NULL; + char EscapeAs = ' '; + + if ((FormatTypeIndex < TP->Tokens->nParameters) && + (TP->Tokens->Params[FormatTypeIndex]->Type == TYPE_STR) && + (TP->Tokens->Params[FormatTypeIndex]->len >= 1)) { + pFmt = TP->Tokens->Params[FormatTypeIndex]->Start; + EscapeAs = *pFmt; + } + + switch(EscapeAs) + { + case 'H': + StrEscAppend(Target, NULL, Source, 0, 2); + break; + case 'X': + StrEscAppend(Target, NULL, Source, 0, 0); + break; + case 'J': + StrECMAEscAppend(Target, NULL, Source); + break; + case 'K': + StrHtmlEcmaEscAppend(Target, NULL, Source, 0, 0); + break; + case 'U': + StrBufUrlescAppend(Target, NULL, Source); + break; +/* + case 'F': + if (pFmt != NULL) pFmt++; + else pFmt = "JUSTIFY"; + if (*pFmt == '\0') pFmt = "JUSTIFY"; + FmOut(Target, pFmt, Source); + break; +*/ + default: + StrBufAppendBufPlain(Target, Source, 0, 0); + } +} + void PutNewToken(WCTemplate *Template, WCTemplateToken *NewToken) { @@ -711,6 +825,14 @@ int GetNextParameter(StrBuf *Buf, ParamBrace = 1; } } + else if (*pch == '.') { + Parm->Type = TYPE_ROOMPREFSTR; + pch ++; + if (*pch == '(') { + pch ++; + ParamBrace = 1; + } + } else if (*pch == ';') { Parm->Type = TYPE_PREFINT; pch ++; @@ -779,7 +901,7 @@ int GetNextParameter(StrBuf *Buf, StrBufPeek(Buf, pch, -1, '\0'); if (LoadTemplates > 1) { syslog(1, - "DBG: got param [%s] %d %d\n", + "DBG: got param [%s] "SIZE_T_FMT" "SIZE_T_FMT"\n", pchs, pche - pchs, strlen(pchs) ); } @@ -1077,8 +1199,7 @@ WCTemplateToken *NewTemplateSubstitute(StrBuf *Buf, } else { LogTemplateError( NULL, "Token ", ERR_NAME, &TP, - " isn't known to us.", - NULL); + " isn't known to us."); } break; case SV_GETTEXT: @@ -1579,12 +1700,13 @@ void InitTemplateCache(void) * \param state are we in conditional state? * \param ContextType what type of information does context giv us? */ -int EvaluateToken(StrBuf *Target, int state, WCTemplputParams *TP) +int EvaluateToken(StrBuf *Target, int state, WCTemplputParams **TPP) { const char *AppendMe; long AppendMeLen; HashHandler *Handler; void *vVar; + WCTemplputParams *TP = *TPP; /* much output, since pName is not terminated... syslog(1,"Doing token: %s\n",Token->pName); @@ -1597,24 +1719,24 @@ int EvaluateToken(StrBuf *Target, int state, WCTemplputParams *TP) case SV_CONDITIONAL: /** Forward conditional evaluation */ Handler = (HashHandler*) TP->Tokens->PreEval; if (!CheckContext(Target, &Handler->Filter, TP, "Conditional")) { - return -1; + return 0; } - return EvaluateConditional(Target, 1, state, TP); + return EvaluateConditional(Target, 1, state, TPP); break; case SV_NEG_CONDITIONAL: /** Reverse conditional evaluation */ Handler = (HashHandler*) TP->Tokens->PreEval; if (!CheckContext(Target, &Handler->Filter, TP, "Conditional")) { - return -1; + return 0; } - return EvaluateConditional(Target, 0, state, TP); + return EvaluateConditional(Target, 0, state, TPP); break; case SV_CUST_STR_CONDITIONAL: /** Conditional put custom strings from params */ Handler = (HashHandler*) TP->Tokens->PreEval; if (!CheckContext(Target, &Handler->Filter, TP, "Conditional")) { - return -1; + return 0; } if (TP->Tokens->nParameters >= 6) { - if (EvaluateConditional(Target, 0, state, TP)) { + if (EvaluateConditional(Target, 0, state, TPP)) { GetTemplateTokenString(Target, TP, 5, &AppendMe, &AppendMeLen); StrBufAppendBufPlain(Target, AppendMe, @@ -1628,6 +1750,10 @@ int EvaluateToken(StrBuf *Target, int state, WCTemplputParams *TP) AppendMeLen, 0); } + if (*TPP != TP) + { + UnStackDynamicContext(Target, TPP); + } } else { LogTemplateError( @@ -1642,7 +1768,7 @@ int EvaluateToken(StrBuf *Target, int state, WCTemplputParams *TP) case SV_PREEVALUATED: Handler = (HashHandler*) TP->Tokens->PreEval; if (!CheckContext(Target, &Handler->Filter, TP, "Token")) { - return -1; + return 0; } Handler->HandlerFunc(Target, TP); break; @@ -1650,7 +1776,7 @@ int EvaluateToken(StrBuf *Target, int state, WCTemplputParams *TP) if (GetHash(GlobalNS, TP->Tokens->pName, TP->Tokens->NameEnd, &vVar)) { Handler = (HashHandler*) vVar; if (!CheckContext(Target, &Handler->Filter, TP, "Token")) { - return -1; + return 0; } else { Handler->HandlerFunc(Target, TP); @@ -1671,10 +1797,14 @@ const StrBuf *ProcessTemplate(WCTemplate *Tmpl, StrBuf *Target, WCTemplputParams { WCTemplate *pTmpl = Tmpl; int done = 0; - int i, state; + int i; + TemplState state; const char *pData, *pS; long len; WCTemplputParams TP; + WCTemplputParams *TPtr = &TP; + + memset(TPtr, 0, sizeof(WCTemplputParams)); memcpy(&TP.Filter, &CallingTP->Filter, sizeof(ContextFilter)); @@ -1701,7 +1831,7 @@ const StrBuf *ProcessTemplate(WCTemplate *Tmpl, StrBuf *Target, WCTemplputParams pS = pData = ChrPtr(pTmpl->Data); len = StrLength(pTmpl->Data); i = 0; - state = 0; + state = eNext; while (!done) { if (i >= pTmpl->nTokensUsed) { StrBufAppendBufPlain(Target, @@ -1710,28 +1840,56 @@ const StrBuf *ProcessTemplate(WCTemplate *Tmpl, StrBuf *Target, WCTemplputParams done = 1; } else { + int TokenRc; + StrBufAppendBufPlain( Target, pData, pTmpl->Tokens[i]->pTokenStart - pData, 0); - TP.Tokens = pTmpl->Tokens[i]; - TP.nArgs = pTmpl->Tokens[i]->nParameters; - state = EvaluateToken(Target, state, &TP); + TPtr->Tokens = pTmpl->Tokens[i]; + TPtr->nArgs = pTmpl->Tokens[i]->nParameters; - while ((state != 0) && (i+1 < pTmpl->nTokensUsed)) { + TokenRc = EvaluateToken(Target, TokenRc, &TPtr); + if (TokenRc > 0) + { + state = eSkipTilEnd; + } + else if (TokenRc < 0) + { + if ((TPtr != &TP) && + (TPtr->ExitCTXID == -TokenRc)) + { + UnStackDynamicContext(Target, &TPtr); + } + TokenRc = 0; + } + + while ((state != eNext) && (i+1 < pTmpl->nTokensUsed)) { /* condition told us to skip till its end condition */ i++; - TP.Tokens = pTmpl->Tokens[i]; - TP.nArgs = pTmpl->Tokens[i]->nParameters; + TPtr->Tokens = pTmpl->Tokens[i]; + TPtr->nArgs = pTmpl->Tokens[i]->nParameters; if ((pTmpl->Tokens[i]->Flags == SV_CONDITIONAL) || - (pTmpl->Tokens[i]->Flags == SV_NEG_CONDITIONAL)) { - if (state == EvaluateConditional( - Target, - pTmpl->Tokens[i]->Flags, - state, - &TP)) - state = 0; + (pTmpl->Tokens[i]->Flags == SV_NEG_CONDITIONAL)) + { + int rc; + rc = EvaluateConditional( + Target, + pTmpl->Tokens[i]->Flags, + TokenRc, + &TPtr); + if (-rc == TokenRc) + { + TokenRc = 0; + state = eNext; + if ((TPtr != &TP) && + (TPtr->ExitCTXID == - rc)) + { + UnStackDynamicContext(Target, &TPtr); + } + } } } + pData = pTmpl->Tokens[i++]->pTokenEnd + 1; if (i > pTmpl->nTokensUsed) done = 1; @@ -1815,8 +1973,8 @@ void tmplput_Comment(StrBuf *Target, WCTemplputParams *TP) typedef struct _HashIterator { HashList *StaticList; int AdditionalParams; - int ContextType; - int XPectContextType; + CtxType ContextType; + CtxType XPectContextType; int Flags; RetrieveHashlistFunc GetHash; HashDestructorFunc Destructor; @@ -1829,8 +1987,8 @@ void RegisterITERATOR(const char *Name, long len, RetrieveHashlistFunc GetHash, SubTemplFunc DoSubTempl, HashDestructorFunc Destructor, - int ContextType, - int XPectContextType, + CtxType ContextType, + CtxType XPectContextType, int Flags) { HashIterator *It; @@ -2073,22 +2231,25 @@ int conditional_ITERATE_LASTN(StrBuf *Target, WCTemplputParams *TP) /*----------------------------------------------------------------------------- * Conditionals */ -int EvaluateConditional(StrBuf *Target, int Neg, int state, WCTemplputParams *TP) +int EvaluateConditional(StrBuf *Target, int Neg, int state, WCTemplputParams **TPP) { ConditionalStruct *Cond; int rc = 0; int res; + WCTemplputParams *TP = *TPP; if ((TP->Tokens->Params[0]->len == 1) && (TP->Tokens->Params[0]->Start[0] == 'X')) - return (state != 0)?TP->Tokens->Params[1]->lvalue:0; + { + return - (TP->Tokens->Params[1]->lvalue); + } Cond = (ConditionalStruct *) TP->Tokens->PreEval; if (Cond == NULL) { LogTemplateError( Target, "Conditional", ERR_PARM1, TP, "unknown!"); - return 1; + return 0; } if (!CheckContext(Target, &Cond->Filter, TP, "Conditional")) { @@ -2098,17 +2259,24 @@ int EvaluateConditional(StrBuf *Target, int Neg, int state, WCTemplputParams *TP res = Cond->CondF(Target, TP); if (res == Neg) rc = TP->Tokens->Params[1]->lvalue; + if (LoadTemplates > 5) syslog(1, "<%s> : %d %d==%d\n", ChrPtr(TP->Tokens->FlatToken), rc, res, Neg); + + if (TP->Sub != NULL) + { + *TPP = TP->Sub; + } return rc; } -void RegisterConditional(const char *Name, long len, - int nParams, - WCConditionalFunc CondF, - int ContextRequired) +void RegisterContextConditional(const char *Name, long len, + int nParams, + WCConditionalFunc CondF, + WCConditionalFunc ExitCtxCond, + int ContextRequired) { ConditionalStruct *Cond; @@ -2118,6 +2286,7 @@ void RegisterConditional(const char *Name, long len, Cond->Filter.nMaxArgs = nParams; Cond->Filter.nMinArgs = nParams; Cond->CondF = CondF; + Cond->CondExitCtx = ExitCtxCond; Cond->Filter.ContextType = ContextRequired; Put(Conditionals, Name, len, Cond, NULL); } @@ -2400,7 +2569,7 @@ void RegisterSortFunc(const char *name, long len, CompareFunc Forward, CompareFunc Reverse, CompareFunc GroupChange, - long ContextType) + CtxType ContextType) { SortStruct *NewSort; @@ -2756,6 +2925,9 @@ void InitModule_SUBST (void) { + RegisterCTX(CTX_TAB); + RegisterCTX(CTX_ITERATE); + memset(&NoCtx, 0, sizeof(WCTemplputParams)); RegisterNamespace("--", 0, 2, tmplput_Comment, NULL, CTX_NONE); RegisterNamespace("SORT:ICON", 1, 2, tmplput_SORT_ICON, NULL, CTX_NONE); @@ -2773,18 +2945,18 @@ InitModule_SUBST RegisterNamespace("LONGVECTOR", 1, 1, tmplput_long_vector, NULL, CTX_LONGVECTOR); - RegisterConditional(HKEY("COND:CONTEXTSTR"), 3, ConditionalContextStr, CTX_STRBUF); - RegisterConditional(HKEY("COND:CONTEXTSTRARR"), 4, ConditionalContextStrinArray, CTX_STRBUFARR); - RegisterConditional(HKEY("COND:LONGVECTOR"), 4, ConditionalLongVector, CTX_LONGVECTOR); + RegisterConditional("COND:CONTEXTSTR", 3, ConditionalContextStr, CTX_STRBUF); + RegisterConditional("COND:CONTEXTSTRARR", 4, ConditionalContextStrinArray, CTX_STRBUFARR); + RegisterConditional("COND:LONGVECTOR", 4, ConditionalLongVector, CTX_LONGVECTOR); - RegisterConditional(HKEY("COND:ITERATE:ISGROUPCHANGE"), 2, + RegisterConditional("COND:ITERATE:ISGROUPCHANGE", 2, conditional_ITERATE_ISGROUPCHANGE, CTX_ITERATE); - RegisterConditional(HKEY("COND:ITERATE:LASTN"), 2, + RegisterConditional("COND:ITERATE:LASTN", 2, conditional_ITERATE_LASTN, CTX_ITERATE); - RegisterConditional(HKEY("COND:ITERATE:FIRSTN"), 2, + RegisterConditional("COND:ITERATE:FIRSTN", 2, conditional_ITERATE_FIRSTN, CTX_ITERATE); @@ -2812,6 +2984,13 @@ ServerStartModule_SUBST Conditionals = NewHash(1, NULL); SortHash = NewHash(1, NULL); Defines = NewHash(1, NULL); + CtxList = NewHash(1, NULL); + + PutContextType(HKEY("CTX_NONE"), 0); + + RegisterCTX(CTX_STRBUF); + RegisterCTX(CTX_STRBUFARR); + RegisterCTX(CTX_LONGVECTOR); } void @@ -2833,6 +3012,7 @@ ServerShutdownModule_SUBST DeleteHash(&Conditionals); DeleteHash(&SortHash); DeleteHash(&Defines); + DeleteHash(&CtxList); }