* implement conditional switches; if true will skip to next "X" with the same value.
authorWilfried Göesgens <willi@citadel.org>
Sat, 23 Aug 2008 18:56:16 +0000 (18:56 +0000)
committerWilfried Göesgens <willi@citadel.org>
Sat, 23 Aug 2008 18:56:16 +0000 (18:56 +0000)
webcit/auth.c
webcit/preferences.c
webcit/subst.c
webcit/webcit.h
webcit/webserver.c
webcit/who.c

index d5b77ab86f63802fc89ccdd9775ca3d445f2274d..ff1350be14c43bc1f53c60d497a69324a9013064 100644 (file)
@@ -881,6 +881,18 @@ void changepw(void)
        }
 }
 
+int ConditionalAide(WCTemplateToken *Token, void *Context)
+{
+       return (WC->is_aide == 0);
+}
+
+int ConditionalRoomAide(WCTemplateToken *Token, void *Context)
+{
+       return (WC->is_room_aide == 0);
+}
+
+
+
 void _display_openid_login(void) {display_openid_login(NULL);}
 void _display_reg(void) {display_reg(0);}
 
@@ -901,5 +913,9 @@ InitModule_AUTH
        WebcitAddUrlHandler(HKEY("display_changepw"), display_changepw, 0);
        WebcitAddUrlHandler(HKEY("changepw"), changepw, 0);
        WebcitAddUrlHandler(HKEY("termquit"), do_logout, 0);
+
+       RegisterConditional(HKEY("COND:AIDE"), 2, ConditionalAide);
+       RegisterConditional(HKEY("COND:ROOMAIDE"), 2, ConditionalRoomAide);
+
        return ;
 }
index e84d911a7939e3c6cbd1c36a13857906a4f9e89d..c48916f31e92459c6478e02f42db8974ffa9d033 100644 (file)
@@ -694,6 +694,21 @@ void CfgZoneTempl(StrBuf *TemplBuffer, void *Context)
 
 }
 
+int ConditionalPreference(WCTemplateToken *Token, void *Context)
+{
+
+       void *hash_value;
+
+       if (!GetHash(PreferenceHooks, 
+                    Token->Params[2]->Start,
+                    Token->Params[2]->len,
+                    &hash_value))
+               return 0;
+
+       Prefs *Newpref = (Prefs*) hash_value;
+       return (strcmp(Token->Params[3]->Start, Newpref->PrefStr) == 0);
+}
+
 
 void 
 InitModule_PREFERENCES
@@ -716,5 +731,7 @@ InitModule_PREFERENCES
        RegisterNamespace("PREF:VALUE", 1, 1, tmplput_CFG_Value);
        RegisterNamespace("PREF:DESCR", 1, 1, tmplput_CFG_Descr);
        RegisterIterator("PREF:ZONE", ZoneHash, NULL, CfgZoneTempl, NULL);
+
+       RegisterConditional(HKEY("COND:PREF"), 4, ConditionalPreference);
 }
 /*@}*/
index 139e91932995914e363df01e9e31df4b4d102466..c46b0855edc64c1719df2edb8b1bcdc6cee14fad 100644 (file)
@@ -27,6 +27,11 @@ HashList *LocalTemplateCache;
 
 HashList *GlobalNS;
 HashList *Iterators;
+HashList *Contitionals;
+
+#define SV_GETTEXT 1
+#define SV_CONDITIONAL 2
+#define SV_NEG_CONDITIONAL 3
 
 typedef struct _WCTemplate {
        StrBuf *Data;
@@ -240,6 +245,42 @@ void SVPut(char *keyname, size_t keylen, int keytype, char *Data)
        ptr->wcs_value = strdup(Data);
 }
 
+/**
+ * \brief Add a substitution variable (local to this session)
+ * \param keyname the replacementstring to substitute
+ * \param keytype the kind of the key
+ * \param format the format string ala printf
+ * \param ... the arguments to substitute in the formatstring
+ */
+void SVPutLong(char *keyname, size_t keylen, long Data)
+{
+       void *vPtr;
+       wcsubst *ptr = NULL;
+       struct wcsession *WCC = WC;
+
+       
+       /**
+        * First look if we're doing a replacement of
+        * an existing key
+        */
+       /*PrintHash(WCC->vars, VarPrintTransition, VarPrintEntry);*/
+       if (GetHash(WCC->vars, keyname, keylen, &vPtr)) {
+               ptr = (wcsubst*)vPtr;
+               if (ptr->wcs_value != NULL)
+                       free(ptr->wcs_value);
+       }
+       else    /** Otherwise allocate a new one */
+       {
+               ptr = (wcsubst *) malloc(sizeof(wcsubst));
+               safestrncpy(ptr->wcs_key, keyname, sizeof ptr->wcs_key);
+               Put(WCC->vars, keyname, keylen, ptr,  deletevar);
+       }
+
+       ptr->wcs_function = NULL;
+       ptr->wcs_type = WCS_LONG;
+       ptr->lvalue = Data;
+}
+
 /**
  * \brief Add a substitution variable (local to this session) that does a callback
  * \param keyname the keystring to substitute
@@ -365,6 +406,9 @@ void print_value_of(StrBuf *Target, const char *keyname, size_t keylen) {
                case WCS_STRBUF_REF:
                        StrBufAppendBuf(Target, (StrBuf*) ptr->wcs_function, 0);
                        break;
+               case WCS_LONG:
+                       StrBufAppendPrintf(Target, "%l", ptr->lvalue);
+                       break;
                default:
                        lprintf(1,"WARNING: invalid value in SV-Hash at %s!", keyname);
                }
@@ -477,7 +521,7 @@ WCTemplateToken *NewTemplateSubstitute(StrBuf *Buf,
        TemplateParam *Param;
        WCTemplateToken *NewToken = (WCTemplateToken*)malloc(sizeof(WCTemplateToken));
 
-       NewToken->IsGettext = 0;
+       NewToken->Flags = 0;
        NewToken->pTokenStart = pTmplStart;
        NewToken->TokenStart = pTmplStart - pStart;
        NewToken->TokenEnd =  (pTmplEnd - pStart) - NewToken->TokenStart;
@@ -509,10 +553,19 @@ WCTemplateToken *NewTemplateSubstitute(StrBuf *Buf,
                                else break;
                        }
                        if((NewToken->NameEnd == 1) &&
-                          (NewToken->HaveParameters == 1) && 
-                          (NewToken->nParameters == 1) &&
-                          (*(NewToken->pName) == '_'))
-                               NewToken->IsGettext = 1;
+                          (NewToken->HaveParameters == 1))
+                          
+                       {
+                               if ((NewToken->nParameters == 1) &&
+                                   (*(NewToken->pName) == '_'))
+                                       NewToken->Flags = SV_GETTEXT;
+                               else if ((NewToken->nParameters >= 2) &&
+                                        (*(NewToken->pName) == '?'))
+                                       NewToken->Flags = SV_CONDITIONAL;
+                               else if ((NewToken->nParameters >=2) &&
+                                        (*(NewToken->pName) == '!'))
+                                       NewToken->Flags = SV_NEG_CONDITIONAL;
+                       }
                }
                else pch ++;            
        }
@@ -533,13 +586,56 @@ void FreeWCTemplate(void *vFreeMe)
        free(FreeMe);
 }
 
-void EvaluateToken(StrBuf *Target, WCTemplateToken *Token, void *Context)
+
+int EvaluateConditional(WCTemplateToken *Token, void *Context, int Neg, int state)
+{
+       void *vConditional;
+       ConditionalStruct *Cond;
+
+       if ((Token->Params[0]->len == 1) &&
+           (Token->Params[0]->Start[0] == 'X'))
+               return (state != 0)?Token->Params[1]->lvalue:0;
+
+       if (!GetHash(Contitionals, 
+                Token->Params[0]->Start,
+                Token->Params[0]->len,
+                &vConditional)) {
+               lprintf(1, "Conditional %s Not found!\n", 
+                       Token->Params[0]->Start);
+       }
+           
+       Cond = (ConditionalStruct *) vConditional;
+
+       if (Cond == NULL) {
+               lprintf(1, "Conditional %s Not found!\n", 
+                       Token->Params[0]->Start);
+               return 0;
+       }
+       if (Token->nParameters < Cond->nParams) {
+               lprintf(1, "Conditional [%s] needs %ld Params!\n", 
+                       Token->Params[0]->Start,
+                       Cond->nParams);
+               return 0;
+       }
+       if (Cond->CondF(Token, Context) == Neg)
+               return Token->Params[1]->lvalue;
+       return 0;
+}
+
+int EvaluateToken(StrBuf *Target, WCTemplateToken *Token, void *Context, int state)
 {
        void *vVar;
 // much output, since pName is not terminated...
 //     lprintf(1,"Doing token: %s\n",Token->pName);
-       if (Token->IsGettext)
+       if (Token->Flags == SV_GETTEXT) {
                TmplGettext(Target, Token->nParameters, Token);
+       }
+       else if (Token->Flags == SV_CONDITIONAL) {
+               return EvaluateConditional(Token, Context, 1, state);
+       }
+       else if (Token->Flags == SV_NEG_CONDITIONAL) {
+               return EvaluateConditional(Token, Context, 0, state);
+       }
        else if (GetHash(GlobalNS, Token->pName, Token->NameEnd, &vVar)) {
                HashHandler *Handler;
                Handler = (HashHandler*) vVar;
@@ -561,18 +657,20 @@ void EvaluateToken(StrBuf *Target, WCTemplateToken *Token, void *Context)
        else {
                print_value_of(Target, Token->pName, Token->NameEnd);
        }
+       return 0;
 }
 
 void ProcessTemplate(WCTemplate *Tmpl, StrBuf *Target, void *Context)
 {
        int done = 0;
-       int i;
+       int i, state;
        const char *pData, *pS;
        long len;
 
        pS = pData = ChrPtr(Tmpl->Data);
        len = StrLength(Tmpl->Data);
        i = 0;
+       state = 0;
        while (!done) {
                if (i >= Tmpl->nTokensUsed) {
                        StrBufAppendBufPlain(Target, 
@@ -584,8 +682,22 @@ void ProcessTemplate(WCTemplate *Tmpl, StrBuf *Target, void *Context)
                        StrBufAppendBufPlain(
                                Target, pData, 
                                Tmpl->Tokens[i]->pTokenStart - pData, 0);
-                       EvaluateToken(Target, Tmpl->Tokens[i], Context);
+                       state = EvaluateToken(Target, Tmpl->Tokens[i], Context, state);
+                       while ((state != 0) && (i+1 < Tmpl->nTokensUsed)) {
+                       /* condition told us to skip till its end condition */
+                               i++;
+                               if ((Tmpl->Tokens[i]->Flags == SV_CONDITIONAL) ||
+                                   (Tmpl->Tokens[i]->Flags == SV_NEG_CONDITIONAL)) {
+                                       if (state == EvaluateConditional(Tmpl->Tokens[i], 
+                                                                        Context, 
+                                                                        Tmpl->Tokens[i]->Flags,
+                                                                        state))
+                                               state = 0;
+                               }
+                       }
                        pData = Tmpl->Tokens[i++]->pTokenEnd + 1;
+                       if (i >= Tmpl->nTokensUsed)
+                               done = 1;
                }
        }
 }
@@ -856,6 +968,41 @@ void tmpl_iterate_subtmpl(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, vo
        It->Destructor(List);
 }
 
+int ConditionalVar(WCTemplateToken *Tokens, void *Context)
+{
+       void *vsubst;
+       wcsubst *subst;
+       
+       if (!GetHash(WC->vars, 
+                    Tokens->Params[2]->Start,
+                    Tokens->Params[2]->len,
+                    &vsubst))
+               return 0;
+       subst = (wcsubst*) vsubst;
+       switch(subst->wcs_type) {
+       case WCS_STRING:
+               if (Tokens->nParameters < 4)
+                       return 0;
+               return (strcmp(Tokens->Params[3]->Start, subst->wcs_value) == 0);
+       case WCS_SERVCMD:
+               lprintf(1, "  -> Server [%s]\n", subst->wcs_value);////todo
+               return 0;
+       case WCS_FUNCTION:
+               return (subst->wcs_function!=NULL);
+       case WCS_STRBUF:
+       case WCS_STRBUF_REF:
+               if (Tokens->nParameters < 4)
+                       return 0;
+               return (strcmp(Tokens->Params[3]->Start, ChrPtr((StrBuf*) subst->wcs_function)) == 0);
+       case WCS_LONG:
+               if (Tokens->nParameters < 4)
+                       return (subst->lvalue != 0);
+               return (subst->lvalue == Tokens->Params[3]->lvalue);
+       default:
+               lprintf(1,"  WARNING: invalid type: [%ld]!\n", subst->wcs_type);
+       }
+       return 0;
+}
 
 void RegisterITERATOR(const char *Name, long len, 
                      HashList *StaticList, 
@@ -871,6 +1018,16 @@ void RegisterITERATOR(const char *Name, long len,
        Put(Iterators, Name, len, It, NULL);
 }
 
+void RegisterConditional(const char *Name, long len, 
+                        int nParams,
+                        WCConditionalFunc CondF)
+{
+       ConditionalStruct *Cond = (ConditionalStruct*)malloc(sizeof(ConditionalStruct));
+       Cond->nParams = nParams;
+       Cond->CondF = CondF;
+       Put(Contitionals, Name, len, Cond, NULL);
+}
+
 void 
 InitModule_SUBST
 (void)
@@ -885,6 +1042,7 @@ InitModule_SUBST
        RegisterNamespace("CURRENT_USER", 0, 0, tmplput_current_user);
        RegisterNamespace("CURRENT_ROOM", 0, 0, tmplput_current_room);
        RegisterNamespace("ITERATE", 2, 4, tmpl_iterate_subtmpl);
+       RegisterConditional(HKEY("COND:SUBST"), 3, ConditionalVar);
 }
 
 /*@}*/
index 92e5b610264e70502f29bc3988703e7bc00341d6..41485b8e872c2a7d71603652754e85dc8246cd62 100644 (file)
@@ -285,6 +285,7 @@ typedef struct _wcsubst {
        int wcs_type;                       /**< which type of ??? */
        char wcs_key[32];                   /**< ??? what?*/
        void *wcs_value;                    /**< ???? what?*/
+       long lvalue;                        /**< type long? keep data here */
        void (*wcs_function)(void); /**< funcion hook ???*/
 } wcsubst;
 
@@ -303,7 +304,7 @@ typedef struct _TemplateToken {
        size_t TokenStart;
        size_t TokenEnd;
        const char *pTokenEnd;
-       int IsGettext;
+       int Flags;
 
        const char *pName;
        size_t NameEnd;
@@ -313,6 +314,7 @@ typedef struct _TemplateToken {
        TemplateParam *Params[MAXPARAM];
 } WCTemplateToken;
 
+
 typedef void (*WCHandlerFunc)(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context);
 void RegisterNS(const char *NSName, long len, 
                int nMinArgs, 
@@ -321,6 +323,18 @@ void RegisterNS(const char *NSName, long len,
 #define RegisterNamespace(a, b, c, d) RegisterNS(a, sizeof(a)-1, b, c, d)
 
 
+
+typedef int (*WCConditionalFunc)(WCTemplateToken *Token, void *Context);
+typedef struct _ConditionalStruct {
+       int nParams;
+       WCConditionalFunc CondF;
+} ConditionalStruct;
+void RegisterConditional(const char *Name, long len, 
+                        int nParams,
+                        WCConditionalFunc CondF);
+
+
+
 typedef void (*SubTemplFunc)(StrBuf *TemplBuffer, void *Context);
 typedef HashList *(*RetrieveHashlistFunc)(void);
 typedef void (*HashDestructorFunc) (HashList *KillMe);
@@ -340,7 +354,8 @@ enum {
        WCS_FUNCTION,     /**< its a function callback */
        WCS_SERVCMD,      /**< its a command to send to the citadel server */
        WCS_STRBUF,       /**< its a strbuf we own */
-       WCS_STRBUF_REF    /**< its a strbuf we mustn't free */
+       WCS_STRBUF_REF,   /**< its a strbuf we mustn't free */
+       WCS_LONG          /**< its an integer */
 };
 
 /**
@@ -352,6 +367,7 @@ struct wc_attachment {
        char content_type[SIZ];    /**< the content itself ???*/
        char filename[SIZ];                /**< the filename hooked to this content ??? */
        char *data;                /**< the data pool; aka this content */
+       long lvalue;               /**< if we put a long... */
 };
 
 /**
@@ -520,7 +536,7 @@ extern HashList *LocalTemplateCache;
 extern HashList *GlobalNS;
 extern HashList *Iterators;
 extern HashList *ZoneHash;
-
+extern HashList *Contitionals;
 
 
 void InitialiseSemaphores(void);
@@ -665,6 +681,8 @@ typedef void (*var_callback_fptr)();
 
 void SVPut(char *keyname, size_t keylen, int keytype, char *Data);
 #define svput(a, b, c) SVPut(a, sizeof(a) - 1, b, c)
+void SVPutLong(char *keyname, size_t keylen, long Data);
+#define svputlong(a, b) SVPutLong(a, sizeof(a) - 1, b)
 void svprintf(char *keyname, size_t keylen, int keytype, const char *format,...) __attribute__((__format__(__printf__,4,5)));
 void SVPRINTF(char *keyname, int keytype, const char *format,...) __attribute__((__format__(__printf__,3,4)));
 void SVCALLBACK(char *keyname, var_callback_fptr fcn_ptr);
index 6f8105997d09603880aba78e7eaa95734c678998..3e453db140dce5f554920728323e409327020891 100644 (file)
@@ -619,6 +619,7 @@ int main(int argc, char **argv)
        TemplateCache = NewHash(1, NULL);
        GlobalNS = NewHash(1, NULL);
        Iterators = NewHash(1, NULL);
+       Contitionals = NewHash(1, NULL);
        LoadZoneFiles();
 
 
@@ -951,6 +952,7 @@ void worker_entry(void)
                                DeleteHash(&TemplateCache);
                                DeleteHash(&LocalTemplateCache);
                                DeleteHash(&Iterators);
+                               DeleteHash(&Contitionals);
 #ifdef ENABLE_NLS
                                void ShutdownLocale(void);
 #endif
index 5bf70b1a8634659f0bdf2b218cea256a6fec0c52..112487aaf05a275c022d0dfe1ac6ab4a7fe2c185 100644 (file)
@@ -471,11 +471,11 @@ void WholistSubst(StrBuf *TemplBuffer, void *vContext)
        SVPutBuf("WHO:HOST", User->Host, 1);
        SVPutBuf("WHO:REALROOM", User->RealRoom, 1);
        SVPutBuf("WHO:REALHOST", User->RealHost, 1);
-       svprintf(HKEY("WHO:LASTACTIVE"), WCS_STRING, "%ld", User->LastActive);
-       svprintf(HKEY("WHO:SESSION"), WCS_STRING, "%d", User->Session);
-       svprintf(HKEY("WHO:IDLE"), WCS_STRING, "%s", (User->Idle)? "Idle":"Active");
-       svprintf(HKEY("WHO:NSESSIONS"), WCS_STRING, "%d", User->SessionCount);
-       
+       svputlong("WHO:LASTACTIVE", User->LastActive);
+       svputlong("WHO:SESSION", User->Session);
+       svputlong("WHO:IDLE", User->Idle);
+       svputlong("WHO:NSESSIONS", User->SessionCount);
+       svputlong("WHO:ISME", (User->Session == WC->ctdl_pid));
 }
 
 void DeleteWholistHash(HashList *KillMe)