From 9f0d926e9bb2845bf755773377792ac2269db3e0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Wilfried=20G=C3=B6esgens?= Date: Sat, 23 Aug 2008 18:56:16 +0000 Subject: [PATCH] * implement conditional switches; if true will skip to next "X" with the same value. --- webcit/auth.c | 16 ++++ webcit/preferences.c | 17 +++++ webcit/subst.c | 176 ++++++++++++++++++++++++++++++++++++++++--- webcit/webcit.h | 24 +++++- webcit/webserver.c | 2 + webcit/who.c | 10 +-- 6 files changed, 228 insertions(+), 17 deletions(-) diff --git a/webcit/auth.c b/webcit/auth.c index d5b77ab86..ff1350be1 100644 --- a/webcit/auth.c +++ b/webcit/auth.c @@ -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 ; } diff --git a/webcit/preferences.c b/webcit/preferences.c index e84d911a7..c48916f31 100644 --- a/webcit/preferences.c +++ b/webcit/preferences.c @@ -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); } /*@}*/ diff --git a/webcit/subst.c b/webcit/subst.c index 139e91932..c46b0855e 100644 --- a/webcit/subst.c +++ b/webcit/subst.c @@ -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); } /*@}*/ diff --git a/webcit/webcit.h b/webcit/webcit.h index 92e5b6102..41485b8e8 100644 --- a/webcit/webcit.h +++ b/webcit/webcit.h @@ -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); diff --git a/webcit/webserver.c b/webcit/webserver.c index 6f8105997..3e453db14 100644 --- a/webcit/webserver.c +++ b/webcit/webserver.c @@ -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 diff --git a/webcit/who.c b/webcit/who.c index 5bf70b1a8..112487aaf 100644 --- a/webcit/who.c +++ b/webcit/who.c @@ -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) -- 2.30.2