]> code.citadel.org Git - citadel.git/blobdiff - webcit/subst.c
* add support for defines
[citadel.git] / webcit / subst.c
index fbbb6b8e108f0653a3d10fd453c80f581d19c678..4b85aa1066a7fe639db69ad3e1f4d5cd96e49fce 100644 (file)
@@ -25,6 +25,7 @@ HashList *GlobalNS;
 HashList *Iterators;
 HashList *Conditionals;
 HashList *SortHash;
+HashList *Defines;
 
 int DumpTemplateI18NStrings = 0;
 int LoadTemplates = 0;
@@ -66,7 +67,7 @@ typedef struct _WCTemplate {
 
 typedef struct _HashHandler {
        ContextFilter Filter;
-
+       WCPreevalFunc PreEvalFunc;
        WCHandlerFunc HandlerFunc;
 }HashHandler;
 
@@ -104,6 +105,7 @@ const char *CtxNames[]  = {
        "Context FLOORS",
        "Context ITERATE",
        "Context ICAL",
+       "Context DavNamespace",
        "Context UNKNOWN"
 };
 
@@ -178,8 +180,11 @@ void LogTemplateError (StrBuf *Target, const char *Type, int ErrorPos, WCTemplpu
                return;
 */
        WCC = WC;
-       if (WCC == NULL)
-               return;
+       if (WCC == NULL) {
+               FreeStrBuf(&Info);
+               FreeStrBuf(&Error);
+               return; 
+       }
 
        Header = NewStrBuf();
        if (TP->Tokens != NULL) 
@@ -285,6 +290,7 @@ void RegisterNS(const char *NSName,
                int nMinArgs, 
                int nMaxArgs, 
                WCHandlerFunc HandlerFunc, 
+               WCPreevalFunc PreevalFunc,
                int ContextRequired)
 {
        HashHandler *NewHandler;
@@ -296,6 +302,7 @@ void RegisterNS(const char *NSName,
        NewHandler->Filter.ContextType = ContextRequired;
        NewHandler->Filter.ControlContextType = CTX_NONE;
 
+       NewHandler->PreEvalFunc = PreevalFunc;
        NewHandler->HandlerFunc = HandlerFunc;  
        Put(GlobalNS, NSName, len, NewHandler, NULL);
 }
@@ -763,7 +770,7 @@ void GetTemplateTokenString(StrBuf *Target,
        StrBuf *Buf;
        WCTemplputParams SubTP;
 
-       if (TP->Tokens->nParameters < N) {
+       if (N >= TP->Tokens->nParameters) {
                LogTemplateError(Target, 
                                 "TokenParameter", N, TP, 
                                 "invalid token %d. this shouldn't have come till here.\n", N);
@@ -774,6 +781,7 @@ void GetTemplateTokenString(StrBuf *Target,
 
        switch (TP->Tokens->Params[N]->Type) {
 
+       case TYPE_INTDEFINE:
        case TYPE_STR:
                *Value = TP->Tokens->Params[N]->Start;
                *len = TP->Tokens->Params[N]->len;
@@ -850,7 +858,7 @@ void GetTemplateTokenString(StrBuf *Target,
 long GetTemplateTokenNumber(StrBuf *Target, WCTemplputParams *TP, int N, long dflt)
 {
        long Ret;
-       if (TP->Tokens->nParameters < N) {
+       if (N >= TP->Tokens->nParameters) {
                LogTemplateError(Target, 
                                 "TokenParameter", N, TP, 
                                 "invalid token %d. this shouldn't have come till here.\n", N);
@@ -884,7 +892,8 @@ long GetTemplateTokenNumber(StrBuf *Target, WCTemplputParams *TP, int N, long df
                }
                if (get_PREF_LONG(TKEY(N), &Ret, dflt))
                        return Ret;
-               return 0;               
+               return 0;
+       case TYPE_INTDEFINE:
        case TYPE_LONG:
                return TP->Tokens->Params[N]->lvalue;
        case TYPE_PREFINT:
@@ -1069,6 +1078,9 @@ void StrBufAppendTemplate(StrBuf *Target,
        case 'J':
                StrECMAEscAppend(Target, Source, NULL);
          break;
+       case 'K':
+               StrHtmlEcmaEscAppend(Target, Source, NULL, 0, 0);
+         break;
        case 'U':
                StrBufUrlescAppend(Target, Source, NULL);
                break;
@@ -1102,7 +1114,12 @@ void PutNewToken(WCTemplate *Template, WCTemplateToken *NewToken)
        Template->Tokens[(Template->nTokensUsed)++] = NewToken;
 }
 
-TemplateParam *GetNextParameter(StrBuf *Buf, const char **pCh, const char *pe, WCTemplateToken *Tokens, WCTemplate *pTmpl)
+TemplateParam *GetNextParameter(StrBuf *Buf, 
+                               const char **pCh, 
+                               const char *pe, 
+                               WCTemplateToken *Tokens, 
+                               WCTemplate *pTmpl, 
+                               WCTemplputParams *TP)
 {
        const char *pch = *pCh;
        const char *pchs, *pche;
@@ -1136,6 +1153,10 @@ TemplateParam *GetNextParameter(StrBuf *Buf, const char **pCh, const char *pe, W
                        ParamBrace = 1;
                }
        }
+       else if (*pch == '#') {
+               Parm->Type = TYPE_INTDEFINE;
+               pch ++;
+       }
        else if (*pch == '_') {
                Parm->Type = TYPE_GETTEXT;
                pch ++;
@@ -1240,6 +1261,25 @@ TemplateParam *GetNextParameter(StrBuf *Buf, const char **pCh, const char *pe, W
        if (DumpTemplateI18NStrings && (Parm->Type == TYPE_GETTEXT)) {
                StrBufAppendPrintf(I18nDump, "_(\"%s\");\n", Parm->Start);
        }
+       if (Parm->Type == TYPE_INTDEFINE)
+       {
+               void *vPVal;
+
+               if (GetHash(Defines, Parm->Start, Parm->len, &vPVal) &&
+                   (vPVal != NULL))
+               {
+                       long *PVal;
+                       PVal = (long*) vPVal;
+               
+                       Parm->lvalue = *PVal;
+               }
+               else 
+               {
+                       LogTemplateError(NULL, "Define", ERR_PARM1, TP,
+                                        "%s isn't known!!",
+                                        Parm->Start);
+               }
+       }
        *pCh = pch;
        return Parm;
 }
@@ -1290,7 +1330,7 @@ WCTemplateToken *NewTemplateSubstitute(StrBuf *Buf,
                                        "Warning, Non welformed Token; missing right parenthesis");
                        }
                        while (pch < pTmplEnd - 1) {
-                               Param = GetNextParameter(Buf, &pch, pTmplEnd - 1, NewToken, pTmpl);
+                               Param = GetNextParameter(Buf, &pch, pTmplEnd - 1, NewToken, pTmpl, &TP);
                                if (Param != NULL) {
                                        NewToken->HaveParameters = 1;
                                        if (NewToken->nParameters > MAXPARAM) {
@@ -1343,6 +1383,8 @@ WCTemplateToken *NewTemplateSubstitute(StrBuf *Buf,
                        else {
                                NewToken->PreEval = Handler;
                                NewToken->Flags = SV_PREEVALUATED;              
+                               if (Handler->PreEvalFunc != NULL)
+                                       Handler->PreEvalFunc(NewToken);
                        }
                }
                break;
@@ -1505,7 +1547,11 @@ void *load_template(StrBuf *filename, StrBuf *Key, HashList *PutThere)
                /** Find one <? > */
                pos = (-1);
                for (; pch < pE; pch ++) {
-                       if ((*pch=='<')&&(*(pch + 1)=='?'))
+                       if ((*pch=='<')&&(*(pch + 1)=='?') &&
+                           !((pch == pS) && /* we must ommit a <?xml */
+                             (*(pch + 2) == 'x') && 
+                             (*(pch + 3) == 'm') && 
+                             (*(pch + 4) == 'l')))                          
                                break;
                        if (*pch=='\n') Line ++;
                }
@@ -1881,9 +1927,27 @@ typedef struct _iteratestruct {
        int LastN;
        }IterateStruct; 
 
-void tmpl_iterate_subtmpl(StrBuf *Target, WCTemplputParams *TP)
+int preeval_iterate(WCTemplateToken *Token)
 {
+       WCTemplputParams TPP;
+       WCTemplputParams *TP;
        void *vIt;
+
+       memset(&TPP, 0, sizeof(WCTemplputParams));
+       TP = &TPP;
+       TP->Tokens = Token;
+       if (!GetHash(Iterators, TKEY(0), &vIt)) {
+               LogTemplateError(
+                       NULL, "Iterator", ERR_NAME, TP,
+                       "not found");
+               return 0;
+       }
+       Token->Preeval2 = vIt;
+       return 1;
+}
+
+void tmpl_iterate_subtmpl(StrBuf *Target, WCTemplputParams *TP)
+{
        HashIterator *It;
        HashList *List;
        HashPos  *it;
@@ -1904,14 +1968,13 @@ void tmpl_iterate_subtmpl(StrBuf *Target, WCTemplputParams *TP)
        memset(&Status, 0, sizeof(IterateStruct));
        memcpy (&SubTP, &TP, sizeof(WCTemplputParams));
        
-       if (!GetHash(Iterators, TKEY(0), &vIt)) {
+       It = (HashIterator*) TP->Tokens->Preeval2;
+       if (It == NULL) {
                LogTemplateError(
                        Target, "Iterator", ERR_PARM1, TP, "Unknown!");
                return;
        }
 
-       It = (HashIterator*) vIt;
-
        if (TP->Tokens->nParameters < It->AdditionalParams + 2) {
                LogTemplateError(                               
                        Target, "Iterator", ERR_PARM1, TP,
@@ -2142,6 +2205,18 @@ void RegisterControlConditional(const char *Name, long len,
        Put(Conditionals, Name, len, Cond, NULL);
 }
 
+void RegisterTokenParamDefine(const char *Name, long len, 
+                             long Value)
+{
+       long *PVal;
+
+       PVal = (long*)malloc(sizeof(long));
+       *PVal = Value;
+       Put(Defines, Name, len, PVal, NULL);
+}
+
+HashList *Defines;
+
 /*-----------------------------------------------------------------------------
  *                      Context Strings
  */
@@ -2262,6 +2337,11 @@ void RegisterSortFunc(const char *name, long len,
        NewSort->Reverse = Reverse;
        NewSort->GroupChange = GroupChange;
        NewSort->ContextType = ContextType;
+       if (ContextType == CTX_NONE) {
+               lprintf(1, "sorting requires a context. CTX_NONE won't make it.\n");
+               exit(1);
+       }
+               
        Put(SortHash, name, len, NewSort, DestroySortStruct);
 }
 
@@ -2314,6 +2394,9 @@ CompareFunc RetrieveSort(WCTemplputParams *TP,
        }
        SortBy = (SortStruct*)vSortBy;
 
+       if (SortBy->ContextType != TP->Filter.ContextType)
+               return NULL;
+
        /** Ok, its us, lets see in which direction we should sort... */
        if (havebstr("SortOrder")) {
                SortOrder = LBSTR("SortOrder");
@@ -2587,19 +2670,25 @@ int ConditionalLongVector(StrBuf *Target, WCTemplputParams *TP)
        return 0;
 }
 
+
+void tmplput_CURRENT_FILE(StrBuf *Target, WCTemplputParams *TP)
+{
+       StrBufAppendTemplate(Target, TP, TP->Tokens->FileName, 0);
+}
+
 void 
 InitModule_SUBST
 (void)
 {
        memset(&NoCtx, 0, sizeof(WCTemplputParams));
-       RegisterNamespace("SORT:ICON", 1, 2, tmplput_SORT_ICON, CTX_NONE);
-       RegisterNamespace("SORT:ORDER", 1, 2, tmplput_SORT_ORDER, CTX_NONE);
-       RegisterNamespace("SORT:NEXT", 1, 2, tmplput_SORT_NEXT, CTX_NONE);
-       RegisterNamespace("CONTEXTSTR", 0, 1, tmplput_ContextString, CTX_STRBUF);
-       RegisterNamespace("ITERATE", 2, 100, tmpl_iterate_subtmpl, CTX_NONE);
-       RegisterNamespace("DOBOXED", 1, 2, tmpl_do_boxed, CTX_NONE);
-       RegisterNamespace("DOTABBED", 2, 100, tmpl_do_tabbed, CTX_NONE);
-       RegisterNamespace("LONGVECTOR", 1, 1, tmplput_long_vector, CTX_LONGVECTOR);
+       RegisterNamespace("SORT:ICON", 1, 2, tmplput_SORT_ICON, NULL, CTX_NONE);
+       RegisterNamespace("SORT:ORDER", 1, 2, tmplput_SORT_ORDER, NULL, CTX_NONE);
+       RegisterNamespace("SORT:NEXT", 1, 2, tmplput_SORT_NEXT, NULL, CTX_NONE);
+       RegisterNamespace("CONTEXTSTR", 0, 1, tmplput_ContextString, NULL, CTX_STRBUF);
+       RegisterNamespace("ITERATE", 2, 100, tmpl_iterate_subtmpl, preeval_iterate, CTX_NONE);
+       RegisterNamespace("DOBOXED", 1, 2, tmpl_do_boxed, NULL, CTX_NONE);
+       RegisterNamespace("DOTABBED", 2, 100, tmpl_do_tabbed, NULL, CTX_NONE);
+       RegisterNamespace("LONGVECTOR", 1, 1, tmplput_long_vector, NULL, CTX_LONGVECTOR);
        RegisterConditional(HKEY("COND:SUBST"), 3, ConditionalVar, CTX_NONE);
        RegisterConditional(HKEY("COND:CONTEXTSTR"), 3, ConditionalContextStr, CTX_STRBUF);
        RegisterConditional(HKEY("COND:LONGVECTOR"), 4, ConditionalLongVector, CTX_LONGVECTOR);
@@ -2617,6 +2706,9 @@ InitModule_SUBST
        RegisterControlNS(HKEY("ITERATE:ODDEVEN"), 0, 0, tmplput_ITERATE_ODDEVEN, CTX_ITERATE);
        RegisterControlNS(HKEY("ITERATE:KEY"), 0, 0, tmplput_ITERATE_KEY, CTX_ITERATE);
        RegisterControlNS(HKEY("ITERATE:N"), 0, 0, tmplput_ITERATE_LASTN, CTX_ITERATE);
+       RegisterNamespace("CURRENTFILE", 0, 1, tmplput_CURRENT_FILE, NULL, CTX_NONE);
+
+
 }
 
 void
@@ -2632,6 +2724,7 @@ ServerStartModule_SUBST
        Iterators = NewHash(1, NULL);
        Conditionals = NewHash(1, NULL);
        SortHash = NewHash(1, NULL);
+       Defines = NewHash(1, NULL);
 }
 
 void
@@ -2654,7 +2747,7 @@ ServerShutdownModule_SUBST
        DeleteHash(&Iterators);
        DeleteHash(&Conditionals);
        DeleteHash(&SortHash);
-
+       DeleteHash(&Defines);
 }