5 * \defgroup Subst Variable substitution type stuff
6 * \ingroup CitadelConfig
12 #include <sys/types.h>
19 #include "webserver.h"
21 extern char *static_dirs[PATH_MAX]; /**< Disk representation */
23 HashList *WirelessTemplateCache;
24 HashList *WirelessLocalTemplateCache;
25 HashList *TemplateCache;
26 HashList *LocalTemplateCache;
30 HashList *Contitionals;
33 #define SV_CONDITIONAL 2
34 #define SV_NEG_CONDITIONAL 3
36 typedef struct _WCTemplate {
40 WCTemplateToken **Tokens;
43 typedef struct _HashHandler {
46 WCHandlerFunc HandlerFunc;
49 void RegisterNS(const char *NSName, long len, int nMinArgs, int nMaxArgs, WCHandlerFunc HandlerFunc)
51 HashHandler *NewHandler;
53 NewHandler = (HashHandler*) malloc(sizeof(HashHandler));
54 NewHandler->nMinArgs = nMinArgs;
55 NewHandler->nMaxArgs = nMaxArgs;
56 NewHandler->HandlerFunc = HandlerFunc;
57 Put(GlobalNS, NSName, len, NewHandler, NULL);
62 * \brief debugging function to print array to log
64 void VarPrintTransition(void *vVar1, void *vVar2, int odd){}
66 * \brief debugging function to print array to log
68 void VarPrintEntry(const char *Key, void *vSubst, int odd)
71 lprintf(1,"Subst[%s] : ", Key);
72 ptr = (wcsubst*) vSubst;
74 switch(ptr->wcs_type) {
76 lprintf(1, " -> %s\n", ptr->wcs_value);
79 lprintf(1, " -> Server [%s]\n", ptr->wcs_value);
82 lprintf(1, " -> function at [%0xd]\n", ptr->wcs_function);
85 lprintf(1," WARNING: invalid type: [%ld]!\n", ptr->wcs_type);
92 * \brief Clear out the list of substitution variables local to this session
94 void clear_substs(struct wcsession *wc) {
96 if (wc->vars != NULL) {
98 DeleteHash(&wc->vars);
103 * \brief Clear out the list of substitution variables local to this session
105 void clear_local_substs(void) {
110 * \brief destructor; kill one entry.
112 void deletevar(void *data)
114 wcsubst *ptr = (wcsubst*)data;
115 // if ((wc->vars->wcs_type == WCS_STRING)
116 // || (wc->vars->wcs_type == WCS_SERVCMD)) {
117 if (ptr->wcs_type != WCS_FUNCTION)
118 free(ptr->wcs_value);
123 * \brief Add a substitution variable (local to this session) (strlen version...)
124 * \param keyname the replacementstring to substitute
125 * \param keytype the kind of the key
126 * \param format the format string ala printf
127 * \param ... the arguments to substitute in the formatstring
129 void SVPRINTF(char *keyname, int keytype, const char *format,...)
136 struct wcsession *WCC = WC;
138 keylen = strlen(keyname);
140 * First look if we're doing a replacement of
143 /*PrintHash(WCC->vars, VarPrintTransition, VarPrintEntry);*/
144 if (GetHash(WCC->vars, keyname, keylen, &vPtr)) {
145 ptr = (wcsubst*)vPtr;
146 if (ptr->wcs_value != NULL)
147 free(ptr->wcs_value);
149 else /** Otherwise allocate a new one */
151 ptr = (wcsubst *) malloc(sizeof(wcsubst));
152 safestrncpy(ptr->wcs_key, keyname, sizeof ptr->wcs_key);
153 Put(WCC->vars, keyname, keylen, ptr, deletevar);
156 /** Format the string and save it */
158 va_start(arg_ptr, format);
159 vsnprintf(wbuf, sizeof wbuf, format, arg_ptr);
162 ptr->wcs_function = NULL;
163 ptr->wcs_type = keytype;
164 ptr->wcs_value = strdup(wbuf);
168 * \brief Add a substitution variable (local to this session)
169 * \param keyname the replacementstring to substitute
170 * \param keytype the kind of the key
171 * \param format the format string ala printf
172 * \param ... the arguments to substitute in the formatstring
174 void svprintf(char *keyname, size_t keylen, int keytype, const char *format,...)
180 struct wcsession *WCC = WC;
184 * First look if we're doing a replacement of
187 /*PrintHash(WCC->vars, VarPrintTransition, VarPrintEntry);*/
188 if (GetHash(WCC->vars, keyname, keylen, &vPtr)) {
189 ptr = (wcsubst*)vPtr;
190 if (ptr->wcs_value != NULL)
191 free(ptr->wcs_value);
193 else /** Otherwise allocate a new one */
195 ptr = (wcsubst *) malloc(sizeof(wcsubst));
196 safestrncpy(ptr->wcs_key, keyname, sizeof ptr->wcs_key);
197 Put(WCC->vars, keyname, keylen, ptr, deletevar);
200 /** Format the string and save it */
202 va_start(arg_ptr, format);
203 len = vsnprintf(wbuf, sizeof wbuf, format, arg_ptr);
206 ptr->wcs_value = (char*) malloc(len + 1);
207 memcpy(ptr->wcs_value, wbuf, len + 1);
208 ptr->wcs_function = NULL;
209 ptr->wcs_type = keytype;
213 * \brief Add a substitution variable (local to this session)
214 * \param keyname the replacementstring to substitute
215 * \param keytype the kind of the key
216 * \param format the format string ala printf
217 * \param ... the arguments to substitute in the formatstring
219 void SVPut(char *keyname, size_t keylen, int keytype, char *Data)
223 struct wcsession *WCC = WC;
227 * First look if we're doing a replacement of
230 /*PrintHash(WCC->vars, VarPrintTransition, VarPrintEntry);*/
231 if (GetHash(WCC->vars, keyname, keylen, &vPtr)) {
232 ptr = (wcsubst*)vPtr;
233 if (ptr->wcs_value != NULL)
234 free(ptr->wcs_value);
236 else /** Otherwise allocate a new one */
238 ptr = (wcsubst *) malloc(sizeof(wcsubst));
239 safestrncpy(ptr->wcs_key, keyname, sizeof ptr->wcs_key);
240 Put(WCC->vars, keyname, keylen, ptr, deletevar);
243 ptr->wcs_function = NULL;
244 ptr->wcs_type = keytype;
245 ptr->wcs_value = strdup(Data);
249 * \brief Add a substitution variable (local to this session)
250 * \param keyname the replacementstring to substitute
251 * \param keytype the kind of the key
252 * \param format the format string ala printf
253 * \param ... the arguments to substitute in the formatstring
255 void SVPutLong(char *keyname, size_t keylen, long Data)
259 struct wcsession *WCC = WC;
263 * First look if we're doing a replacement of
266 /*PrintHash(WCC->vars, VarPrintTransition, VarPrintEntry);*/
267 if (GetHash(WCC->vars, keyname, keylen, &vPtr)) {
268 ptr = (wcsubst*)vPtr;
269 if (ptr->wcs_value != NULL)
270 free(ptr->wcs_value);
272 else /** Otherwise allocate a new one */
274 ptr = (wcsubst *) malloc(sizeof(wcsubst));
275 safestrncpy(ptr->wcs_key, keyname, sizeof ptr->wcs_key);
276 Put(WCC->vars, keyname, keylen, ptr, deletevar);
279 ptr->wcs_function = NULL;
280 ptr->wcs_type = WCS_LONG;
285 * \brief Add a substitution variable (local to this session) that does a callback
286 * \param keyname the keystring to substitute
287 * \param fcn_ptr the function callback to give the substitution string
289 void SVCallback(char *keyname, size_t keylen, var_callback_fptr fcn_ptr)
293 struct wcsession *WCC = WC;
296 * First look if we're doing a replacement of
299 /*PrintHash(WCC->vars, VarPrintTransition, VarPrintEntry);*/
300 if (GetHash(WCC->vars, keyname, keylen, &vPtr)) {
301 ptr = (wcsubst*)vPtr;
302 if (ptr->wcs_value != NULL)
303 free(ptr->wcs_value);
305 else /** Otherwise allocate a new one */
307 ptr = (wcsubst *) malloc(sizeof(wcsubst));
308 safestrncpy(ptr->wcs_key, keyname, sizeof ptr->wcs_key);
309 Put(WCC->vars, keyname, keylen, ptr, deletevar);
312 ptr->wcs_value = NULL;
313 ptr->wcs_type = WCS_FUNCTION;
314 ptr->wcs_function = fcn_ptr;
316 inline void SVCALLBACK(char *keyname, var_callback_fptr fcn_ptr)
318 SVCallback(keyname, strlen(keyname), fcn_ptr);
323 void SVPUTBuf(const char *keyname, int keylen, StrBuf *Buf, int ref)
327 struct wcsession *WCC = WC;
330 * First look if we're doing a replacement of
333 /*PrintHash(WCC->vars, VarPrintTransition, VarPrintEntry);*/
334 if (GetHash(WCC->vars, keyname, keylen, &vPtr)) {
335 ptr = (wcsubst*)vPtr;
336 if (ptr->wcs_value != NULL)
337 free(ptr->wcs_value);///TODO: respect type
339 else /** Otherwise allocate a new one */
341 ptr = (wcsubst *) malloc(sizeof(wcsubst));
342 safestrncpy(ptr->wcs_key, keyname, sizeof ptr->wcs_key);
343 Put(WCC->vars, keyname, keylen, ptr, deletevar);
346 ptr->wcs_value = NULL;
347 ptr->wcs_type = (ref)?WCS_STRBUF:WCS_STRBUF_REF;
348 ptr->wcs_function = (var_callback_fptr) Buf; ////TODO
352 * \brief back end for print_value_of() ... does a server command
353 * \param servcmd server command to execute on the citadel server
355 void pvo_do_cmd(StrBuf *Target, char *servcmd) {
360 len = serv_getln(buf, sizeof buf);
366 StrBufAppendPrintf(Target, "%s\n", &buf[4]);
369 _fmout(Target, "CENTER");
372 StrBufAppendPrintf(Target, "%s\n", &buf[4]);
379 * \brief Print the value of a variable
380 * \param keyname get a key to print
382 void print_value_of(StrBuf *Target, const char *keyname, size_t keylen) {
383 struct wcsession *WCC = WC;
388 /*if (WCC->vars != NULL) PrintHash(WCC->vars, VarPrintTransition, VarPrintEntry);*/
389 if (keyname[0] == '=') {
390 DoTemplate(keyname+1, keylen - 1, NULL, NULL);
392 /** Page-local variables */
393 if ((WCC->vars!= NULL) && GetHash(WCC->vars, keyname, keylen, &vVar)) {
394 ptr = (wcsubst*) vVar;
395 switch(ptr->wcs_type) {
397 StrBufAppendBufPlain(Target, (const char*)ptr->wcs_value, -1, 0);
400 pvo_do_cmd(Target, ptr->wcs_value);
403 (*ptr->wcs_function) ();
407 StrBufAppendBuf(Target, (StrBuf*) ptr->wcs_function, 0);
410 StrBufAppendPrintf(Target, "%l", ptr->lvalue);
413 lprintf(1,"WARNING: invalid value in SV-Hash at %s!", keyname);
419 void PutNewToken(WCTemplate *Template, WCTemplateToken *NewToken)
421 if (Template->nTokensUsed + 1 >= Template->TokenSpace) {
422 if (Template->TokenSpace <= 0) {
423 Template->Tokens = (WCTemplateToken**)malloc(
424 sizeof(WCTemplateToken*) * 10);
425 Template->TokenSpace = 10;
428 WCTemplateToken **NewTokens;
429 NewTokens= (WCTemplateToken**)malloc(
430 sizeof(WCTemplateToken*) *
431 Template->TokenSpace * 2);
432 memcpy(NewTokens, Template->Tokens,
433 sizeof(WCTemplateToken*) * Template->nTokensUsed);
434 free(Template->Tokens);
435 Template->TokenSpace *= 2;
436 Template->Tokens = NewTokens;
439 Template->Tokens[(Template->nTokensUsed)++] = NewToken;
442 TemplateParam *GetNextParamter(StrBuf *Buf, const char **pCh, const char *pe)
444 const char *pch = *pCh;
445 const char *pchs, *pche;
446 TemplateParam *Parm = (TemplateParam *) malloc(sizeof(TemplateParam));
449 /* Skip leading whitespaces */
450 while ((*pch == ' ' )||
453 (*pch == '\n')) pch ++;
456 else if (*pch == '\'')
461 Parm->Type = TYPE_STR;
464 ( (pch > pchs) && (*(pch - 1) == '\\'))
470 lprintf(1, "Error evaluating template param [%s]\n", *pCh);
476 StrBufPeek(Buf, pch, -1, '\0');
477 lprintf(1, "DBG: got param [%s]\n", pchs);
479 Parm->len = pche - pchs;
480 pch ++; /* move after trailing quote */
484 Parm->Type = TYPE_LONG;
486 while ((pch <= pe) &&
493 StrBufPeek(Buf, pch, -1, '\0');
494 Parm->lvalue = atol(pchs);
500 lprintf(1, "Error evaluating template long param [%s]", *pCh);
505 while ((*pch == ' ' )||
509 (*pch == '\n')) pch ++;
515 WCTemplateToken *NewTemplateSubstitute(StrBuf *Buf,
517 const char *pTmplStart,
518 const char *pTmplEnd)
521 TemplateParam *Param;
522 WCTemplateToken *NewToken = (WCTemplateToken*)malloc(sizeof(WCTemplateToken));
525 NewToken->pTokenStart = pTmplStart;
526 NewToken->TokenStart = pTmplStart - pStart;
527 NewToken->TokenEnd = (pTmplEnd - pStart) - NewToken->TokenStart;
528 NewToken->pTokenEnd = pTmplEnd;
529 NewToken->NameEnd = NewToken->TokenEnd - 2;
531 StrBufPeek(Buf, pTmplStart, + 1, '\0');
532 StrBufPeek(Buf, pTmplEnd, -1, '\0');
533 pch = NewToken->pName = pTmplStart + 2;
535 NewToken->HaveParameters = 0;;
536 NewToken->nParameters = 0;
538 while (pch < pTmplEnd - 1) {
540 StrBufPeek(Buf, pch, -1, '\0');
541 NewToken->NameEnd = pch - NewToken->pName;
543 while (pch < pTmplEnd - 1) {
544 Param = GetNextParamter(Buf, &pch, pTmplEnd - 1);
546 NewToken->HaveParameters = 1;
547 if (NewToken->nParameters > MAXPARAM) {
548 lprintf(1, "Only %ld Tokens supported!\n", MAXPARAM);
551 NewToken->Params[NewToken->nParameters++] = Param;
555 if((NewToken->NameEnd == 1) &&
556 (NewToken->HaveParameters == 1))
559 if ((NewToken->nParameters == 1) &&
560 (*(NewToken->pName) == '_'))
561 NewToken->Flags = SV_GETTEXT;
562 else if ((NewToken->nParameters >= 2) &&
563 (*(NewToken->pName) == '?'))
564 NewToken->Flags = SV_CONDITIONAL;
565 else if ((NewToken->nParameters >=2) &&
566 (*(NewToken->pName) == '!'))
567 NewToken->Flags = SV_NEG_CONDITIONAL;
575 void FreeWCTemplate(void *vFreeMe)
578 WCTemplate *FreeMe = (WCTemplate*)vFreeMe;
580 if (FreeMe->TokenSpace > 0) {
581 for (i = 0; i < FreeMe->nTokensUsed; i ++) {
582 free(FreeMe->Tokens[i]);
584 free(FreeMe->Tokens);
590 int EvaluateConditional(WCTemplateToken *Token, void *Context, int Neg, int state)
593 ConditionalStruct *Cond;
595 if ((Token->Params[0]->len == 1) &&
596 (Token->Params[0]->Start[0] == 'X'))
597 return (state != 0)?Token->Params[1]->lvalue:0;
599 if (!GetHash(Contitionals,
600 Token->Params[0]->Start,
601 Token->Params[0]->len,
603 lprintf(1, "Conditional %s Not found!\n",
604 Token->Params[0]->Start);
607 Cond = (ConditionalStruct *) vConditional;
610 lprintf(1, "Conditional %s Not found!\n",
611 Token->Params[0]->Start);
614 if (Token->nParameters < Cond->nParams) {
615 lprintf(1, "Conditional [%s] needs %ld Params!\n",
616 Token->Params[0]->Start,
620 if (Cond->CondF(Token, Context) == Neg)
621 return Token->Params[1]->lvalue;
625 int EvaluateToken(StrBuf *Target, WCTemplateToken *Token, void *Context, int state)
628 // much output, since pName is not terminated...
629 // lprintf(1,"Doing token: %s\n",Token->pName);
630 if (Token->Flags == SV_GETTEXT) {
631 TmplGettext(Target, Token->nParameters, Token);
633 else if (Token->Flags == SV_CONDITIONAL) {
634 return EvaluateConditional(Token, Context, 1, state);
636 else if (Token->Flags == SV_NEG_CONDITIONAL) {
637 return EvaluateConditional(Token, Context, 0, state);
639 else if (GetHash(GlobalNS, Token->pName, Token->NameEnd, &vVar)) {
640 HashHandler *Handler;
641 Handler = (HashHandler*) vVar;
642 if ((Token->nParameters < Handler->nMinArgs) ||
643 (Token->nParameters > Handler->nMaxArgs)) {
644 lprintf(1, "Handler [%s] doesn't work with %ld params",
649 Handler->HandlerFunc(Target,
652 Context); /*TODO: subset of that */
658 print_value_of(Target, Token->pName, Token->NameEnd);
663 void ProcessTemplate(WCTemplate *Tmpl, StrBuf *Target, void *Context)
667 const char *pData, *pS;
670 pS = pData = ChrPtr(Tmpl->Data);
671 len = StrLength(Tmpl->Data);
675 if (i >= Tmpl->nTokensUsed) {
676 StrBufAppendBufPlain(Target,
678 len - (pData - pS), 0);
682 StrBufAppendBufPlain(
684 Tmpl->Tokens[i]->pTokenStart - pData, 0);
685 state = EvaluateToken(Target, Tmpl->Tokens[i], Context, state);
686 while ((state != 0) && (i+1 < Tmpl->nTokensUsed)) {
687 /* condition told us to skip till its end condition */
689 if ((Tmpl->Tokens[i]->Flags == SV_CONDITIONAL) ||
690 (Tmpl->Tokens[i]->Flags == SV_NEG_CONDITIONAL)) {
691 if (state == EvaluateConditional(Tmpl->Tokens[i],
693 Tmpl->Tokens[i]->Flags,
698 pData = Tmpl->Tokens[i++]->pTokenEnd + 1;
699 if (i >= Tmpl->nTokensUsed)
708 * \brief Display a variable-substituted template
709 * \param templatename template file to load
711 void *load_template(StrBuf *filename, StrBuf *Key, HashList *PutThere)
715 const char *pS, *pE, *pch, *Err;
717 WCTemplate *NewTemplate;
719 fd = open(ChrPtr(filename), O_RDONLY);
721 lprintf(1, "ERROR: could not open template '%s' - %s\n",
722 ChrPtr(filename), strerror(errno));
726 if (fstat(fd, &statbuf) == -1) {
727 lprintf(1, "ERROR: could not stat template '%s' - %s\n",
728 ChrPtr(filename), strerror(errno));
732 NewTemplate = (WCTemplate *) malloc(sizeof(WCTemplate));
733 NewTemplate->Data = NewStrBufPlain(NULL, statbuf.st_size);
734 NewTemplate->nTokensUsed = 0;
735 NewTemplate->TokenSpace = 0;
736 NewTemplate->Tokens = NULL;
737 if (StrBufReadBLOB(NewTemplate->Data, &fd, 1, statbuf.st_size, &Err) < 0) {
739 FreeWCTemplate(NewTemplate);
740 lprintf(1, "ERROR: reading template '%s' - %s<br />\n",
741 ChrPtr(filename), strerror(errno));
746 pS = pch = ChrPtr(NewTemplate->Data);
747 pE = pS + StrLength(NewTemplate->Data);
749 const char *pts, *pte;
751 int InDoubleQuotes = 0;
753 for (; pch < pE; pch ++) {
754 if ((*pch=='<')&&(*(pch + 1)=='?'))
760 for (; pch < pE - 1; pch ++) {
762 InDoubleQuotes = ! InDoubleQuotes;
763 else if (*pch == '\'')
764 InQuotes = ! InQuotes;
765 else if ((!InQuotes && !InDoubleQuotes) &&
766 ((*pch!='\\')&&(*(pch + 1)=='>'))) {
774 PutNewToken(NewTemplate,
775 NewTemplateSubstitute(NewTemplate->Data, pS, pts, pte));
778 Put(PutThere, ChrPtr(Key), StrLength(Key), NewTemplate, FreeWCTemplate);
783 * \brief Display a variable-substituted template
784 * \param templatename template file to load
786 void DoTemplate(const char *templatename, long len, void *Context, StrBuf *Target)
789 HashList *StaticLocal;
795 Static = WirelessTemplateCache;
796 StaticLocal = WirelessLocalTemplateCache;
799 Static = TemplateCache;
800 StaticLocal = LocalTemplateCache;
803 if (!GetHash(StaticLocal, templatename, len, &vTmpl) &&
804 !GetHash(Static, templatename, len, &vTmpl)) {
805 printf ("didn't find %s\n", templatename);
810 ProcessTemplate(vTmpl, Target, Context);
813 int LoadTemplateDir(const char *DirName, HashList *wireless, HashList *big)
819 struct dirent *filedir_entry;
825 StrBufPrintf(Dir, "%s/t", DirName);
826 filedir = opendir (ChrPtr(Dir));
827 if (filedir == NULL) {
831 FileName = NewStrBuf();
833 while ((filedir_entry = readdir(filedir)))
837 #ifdef _DIRENT_HAVE_D_NAMELEN
838 d_namelen = filedir_entry->d_namelen;
840 d_namelen = strlen(filedir_entry->d_name);
842 d_without_ext = d_namelen;
843 while ((d_without_ext > 0) && (filedir_entry->d_name[d_without_ext] != '.'))
845 if ((d_without_ext == 0) || (d_namelen < 3))
848 IsMobile = (strstr(filedir_entry->d_name, ".m.html")!= NULL);
849 PStart = filedir_entry->d_name;
850 StrBufPrintf(FileName, "%s/%s", ChrPtr(Dir), filedir_entry->d_name);
851 MinorPtr = strchr(filedir_entry->d_name, '.');
852 if (MinorPtr != NULL)
854 StrBufPlain(Tag, filedir_entry->d_name, MinorPtr - filedir_entry->d_name);
857 printf("%s %d %s\n",ChrPtr(FileName), IsMobile, ChrPtr(Tag));
858 load_template(FileName, Tag, (IsMobile)?wireless:big);
861 FreeStrBuf(&FileName);
867 void InitTemplateCache(void)
869 LoadTemplateDir(static_dirs[0],
870 WirelessTemplateCache,
872 LoadTemplateDir(static_dirs[1],
873 WirelessLocalTemplateCache,
877 void tmplput_serv_ip(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context)
879 StrBufAppendPrintf(Target, "%d", WC->ctdl_pid);
882 void tmplput_serv_nodename(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context)
884 StrEscAppend(Target, NULL, serv_info.serv_nodename, 0, 0);
887 void tmplput_serv_humannode(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context)
889 StrEscAppend(Target, NULL, serv_info.serv_humannode, 0, 0);
892 void tmplput_serv_fqdn(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context)
894 StrEscAppend(Target, NULL, serv_info.serv_fqdn, 0, 0);
897 void tmmplput_serv_software(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context)
899 StrEscAppend(Target, NULL, serv_info.serv_software, 0, 0);
902 void tmplput_serv_rev_level(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context)
904 StrBufAppendPrintf(Target, "%d.%02d",
905 serv_info.serv_rev_level / 100,
906 serv_info.serv_rev_level % 100);
909 void tmmplput_serv_bbs_city(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context)
911 StrEscAppend(Target, NULL, serv_info.serv_bbs_city, 0, 0);
914 void tmplput_current_user(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context)
916 StrEscAppend(Target, NULL, WC->wc_fullname, 0, 0);
919 void tmplput_current_room(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context)
921 StrEscAppend(Target, NULL, WC->wc_roomname, 0, 0);
925 typedef struct _HashIterator {
926 HashList *StaticList;
927 RetrieveHashlistFunc GetHash;
928 HashDestructorFunc Destructor;
929 SubTemplFunc DoSubTemplate;
932 void tmpl_iterate_subtmpl(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context)
944 if (!GetHash(Iterators,
945 Tokens->Params[0]->Start,
946 Tokens->Params[0]->len,
949 It = (HashIterator*) vIt;
950 if (It->StaticList == NULL)
951 List = It->GetHash();
953 List = It->StaticList;
955 SubBuf = NewStrBuf();
956 it = GetNewHashPos();
957 while (GetNextHashPos(List, it, &len, &Key, &vContext)) {
958 svprintf(HKEY("ITERATE:ODDEVEN"), WCS_STRING, "%s", (oddeven)?"odd":"even");
959 It->DoSubTemplate(SubBuf, vContext);
960 DoTemplate(Tokens->Params[1]->Start,
961 Tokens->Params[1]->len,
964 StrBufAppendBuf(Target, SubBuf, 0);
968 It->Destructor(List);
971 int ConditionalVar(WCTemplateToken *Tokens, void *Context)
976 if (!GetHash(WC->vars,
977 Tokens->Params[2]->Start,
978 Tokens->Params[2]->len,
981 subst = (wcsubst*) vsubst;
982 switch(subst->wcs_type) {
984 if (Tokens->nParameters < 4)
986 return (strcmp(Tokens->Params[3]->Start, subst->wcs_value) == 0);
988 lprintf(1, " -> Server [%s]\n", subst->wcs_value);////todo
991 return (subst->wcs_function!=NULL);
994 if (Tokens->nParameters < 4)
996 return (strcmp(Tokens->Params[3]->Start, ChrPtr((StrBuf*) subst->wcs_function)) == 0);
998 if (Tokens->nParameters < 4)
999 return (subst->lvalue != 0);
1000 return (subst->lvalue == Tokens->Params[3]->lvalue);
1002 lprintf(1," WARNING: invalid type: [%ld]!\n", subst->wcs_type);
1007 void RegisterITERATOR(const char *Name, long len,
1008 HashList *StaticList,
1009 RetrieveHashlistFunc GetHash,
1010 SubTemplFunc DoSubTempl,
1011 HashDestructorFunc Destructor)
1013 HashIterator *It = (HashIterator*)malloc(sizeof(HashIterator));
1014 It->StaticList = StaticList;
1015 It->GetHash = GetHash;
1016 It->DoSubTemplate = DoSubTempl;
1017 It->Destructor = Destructor;
1018 Put(Iterators, Name, len, It, NULL);
1021 void RegisterConditional(const char *Name, long len,
1023 WCConditionalFunc CondF)
1025 ConditionalStruct *Cond = (ConditionalStruct*)malloc(sizeof(ConditionalStruct));
1026 Cond->nParams = nParams;
1027 Cond->CondF = CondF;
1028 Put(Contitionals, Name, len, Cond, NULL);
1035 RegisterNamespace("SERV_PID", 0, 0, tmplput_serv_ip);
1036 RegisterNamespace("SERV_NODENAME", 0, 0, tmplput_serv_nodename);
1037 RegisterNamespace("SERV_HUMANNODE", 0, 0, tmplput_serv_humannode);
1038 RegisterNamespace("SERV_FQDN", 0, 0, tmplput_serv_fqdn);
1039 RegisterNamespace("SERV_SOFTWARE", 0, 0, tmmplput_serv_software);
1040 RegisterNamespace("SERV_REV_LEVEL", 0, 0, tmplput_serv_rev_level);
1041 RegisterNamespace("SERV_BBS_CITY", 0, 0, tmmplput_serv_bbs_city);
1042 RegisterNamespace("CURRENT_USER", 0, 0, tmplput_current_user);
1043 RegisterNamespace("CURRENT_ROOM", 0, 0, tmplput_current_room);
1044 RegisterNamespace("ITERATE", 2, 4, tmpl_iterate_subtmpl);
1045 RegisterConditional(HKEY("COND:SUBST"), 3, ConditionalVar);