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);
393 //////TODO: if param[1] == "U" -> urlescape
395 /** Page-local variables */
396 if ((WCC->vars!= NULL) && GetHash(WCC->vars, keyname, keylen, &vVar)) {
397 ptr = (wcsubst*) vVar;
398 switch(ptr->wcs_type) {
400 StrBufAppendBufPlain(Target, (const char*)ptr->wcs_value, -1, 0);
403 pvo_do_cmd(Target, ptr->wcs_value);
406 (*ptr->wcs_function) ();
410 StrBufAppendBuf(Target, (StrBuf*) ptr->wcs_function, 0);
413 StrBufAppendPrintf(Target, "%l", ptr->lvalue);
416 lprintf(1,"WARNING: invalid value in SV-Hash at %s!", keyname);
422 void PutNewToken(WCTemplate *Template, WCTemplateToken *NewToken)
424 if (Template->nTokensUsed + 1 >= Template->TokenSpace) {
425 if (Template->TokenSpace <= 0) {
426 Template->Tokens = (WCTemplateToken**)malloc(
427 sizeof(WCTemplateToken*) * 10);
428 Template->TokenSpace = 10;
431 WCTemplateToken **NewTokens;
432 NewTokens= (WCTemplateToken**)malloc(
433 sizeof(WCTemplateToken*) *
434 Template->TokenSpace * 2);
435 memcpy(NewTokens, Template->Tokens,
436 sizeof(WCTemplateToken*) * Template->nTokensUsed);
437 free(Template->Tokens);
438 Template->TokenSpace *= 2;
439 Template->Tokens = NewTokens;
442 Template->Tokens[(Template->nTokensUsed)++] = NewToken;
445 TemplateParam *GetNextParamter(StrBuf *Buf, const char **pCh, const char *pe)
447 const char *pch = *pCh;
448 const char *pchs, *pche;
449 TemplateParam *Parm = (TemplateParam *) malloc(sizeof(TemplateParam));
452 /* Skip leading whitespaces */
453 while ((*pch == ' ' )||
456 (*pch == '\n')) pch ++;
459 else if (*pch == '\'')
464 Parm->Type = TYPE_STR;
467 ( (pch > pchs) && (*(pch - 1) == '\\'))
473 lprintf(1, "Error evaluating template param [%s]\n", *pCh);
479 StrBufPeek(Buf, pch, -1, '\0');
480 lprintf(1, "DBG: got param [%s]\n", pchs);
482 Parm->len = pche - pchs;
483 pch ++; /* move after trailing quote */
487 Parm->Type = TYPE_LONG;
489 while ((pch <= pe) &&
496 StrBufPeek(Buf, pch, -1, '\0');
497 Parm->lvalue = atol(pchs);
503 lprintf(1, "Error evaluating template long param [%s]", *pCh);
508 while ((*pch == ' ' )||
512 (*pch == '\n')) pch ++;
518 WCTemplateToken *NewTemplateSubstitute(StrBuf *Buf,
520 const char *pTmplStart,
521 const char *pTmplEnd)
524 TemplateParam *Param;
525 WCTemplateToken *NewToken = (WCTemplateToken*)malloc(sizeof(WCTemplateToken));
528 NewToken->pTokenStart = pTmplStart;
529 NewToken->TokenStart = pTmplStart - pStart;
530 NewToken->TokenEnd = (pTmplEnd - pStart) - NewToken->TokenStart;
531 NewToken->pTokenEnd = pTmplEnd;
532 NewToken->NameEnd = NewToken->TokenEnd - 2;
534 StrBufPeek(Buf, pTmplStart, + 1, '\0');
535 StrBufPeek(Buf, pTmplEnd, -1, '\0');
536 pch = NewToken->pName = pTmplStart + 2;
538 NewToken->HaveParameters = 0;;
539 NewToken->nParameters = 0;
541 while (pch < pTmplEnd - 1) {
543 StrBufPeek(Buf, pch, -1, '\0');
544 NewToken->NameEnd = pch - NewToken->pName;
546 while (pch < pTmplEnd - 1) {
547 Param = GetNextParamter(Buf, &pch, pTmplEnd - 1);
549 NewToken->HaveParameters = 1;
550 if (NewToken->nParameters > MAXPARAM) {
551 lprintf(1, "Only %ld Tokens supported!\n", MAXPARAM);
554 NewToken->Params[NewToken->nParameters++] = Param;
558 if((NewToken->NameEnd == 1) &&
559 (NewToken->HaveParameters == 1))
562 if ((NewToken->nParameters == 1) &&
563 (*(NewToken->pName) == '_'))
564 NewToken->Flags = SV_GETTEXT;
565 else if ((NewToken->nParameters >= 2) &&
566 (*(NewToken->pName) == '?'))
567 NewToken->Flags = SV_CONDITIONAL;
568 else if ((NewToken->nParameters >=2) &&
569 (*(NewToken->pName) == '!'))
570 NewToken->Flags = SV_NEG_CONDITIONAL;
578 void FreeWCTemplate(void *vFreeMe)
581 WCTemplate *FreeMe = (WCTemplate*)vFreeMe;
583 if (FreeMe->TokenSpace > 0) {
584 for (i = 0; i < FreeMe->nTokensUsed; i ++) {
585 free(FreeMe->Tokens[i]);
587 free(FreeMe->Tokens);
593 int EvaluateConditional(WCTemplateToken *Token, void *Context, int Neg, int state)
596 ConditionalStruct *Cond;
598 if ((Token->Params[0]->len == 1) &&
599 (Token->Params[0]->Start[0] == 'X'))
600 return (state != 0)?Token->Params[1]->lvalue:0;
602 if (!GetHash(Contitionals,
603 Token->Params[0]->Start,
604 Token->Params[0]->len,
606 lprintf(1, "Conditional %s Not found!\n",
607 Token->Params[0]->Start);
610 Cond = (ConditionalStruct *) vConditional;
613 lprintf(1, "Conditional %s Not found!\n",
614 Token->Params[0]->Start);
617 if (Token->nParameters < Cond->nParams) {
618 lprintf(1, "Conditional [%s] needs %ld Params!\n",
619 Token->Params[0]->Start,
623 if (Cond->CondF(Token, Context) == Neg)
624 return Token->Params[1]->lvalue;
628 int EvaluateToken(StrBuf *Target, WCTemplateToken *Token, void *Context, int state)
631 // much output, since pName is not terminated...
632 // lprintf(1,"Doing token: %s\n",Token->pName);
633 if (Token->Flags == SV_GETTEXT) {
634 TmplGettext(Target, Token->nParameters, Token);
636 else if (Token->Flags == SV_CONDITIONAL) {
637 return EvaluateConditional(Token, Context, 1, state);
639 else if (Token->Flags == SV_NEG_CONDITIONAL) {
640 return EvaluateConditional(Token, Context, 0, state);
642 else if (GetHash(GlobalNS, Token->pName, Token->NameEnd, &vVar)) {
643 HashHandler *Handler;
644 Handler = (HashHandler*) vVar;
645 if ((Token->nParameters < Handler->nMinArgs) ||
646 (Token->nParameters > Handler->nMaxArgs)) {
647 lprintf(1, "Handler [%s] doesn't work with %ld params",
652 Handler->HandlerFunc(Target,
655 Context); /*TODO: subset of that */
661 print_value_of(Target, Token->pName, Token->NameEnd);
666 void ProcessTemplate(WCTemplate *Tmpl, StrBuf *Target, void *Context)
670 const char *pData, *pS;
673 pS = pData = ChrPtr(Tmpl->Data);
674 len = StrLength(Tmpl->Data);
678 if (i >= Tmpl->nTokensUsed) {
679 StrBufAppendBufPlain(Target,
681 len - (pData - pS), 0);
685 StrBufAppendBufPlain(
687 Tmpl->Tokens[i]->pTokenStart - pData, 0);
688 state = EvaluateToken(Target, Tmpl->Tokens[i], Context, state);
689 while ((state != 0) && (i+1 < Tmpl->nTokensUsed)) {
690 /* condition told us to skip till its end condition */
692 if ((Tmpl->Tokens[i]->Flags == SV_CONDITIONAL) ||
693 (Tmpl->Tokens[i]->Flags == SV_NEG_CONDITIONAL)) {
694 if (state == EvaluateConditional(Tmpl->Tokens[i],
696 Tmpl->Tokens[i]->Flags,
701 pData = Tmpl->Tokens[i++]->pTokenEnd + 1;
702 if (i >= Tmpl->nTokensUsed)
711 * \brief Display a variable-substituted template
712 * \param templatename template file to load
714 void *load_template(StrBuf *filename, StrBuf *Key, HashList *PutThere)
718 const char *pS, *pE, *pch, *Err;
720 WCTemplate *NewTemplate;
722 fd = open(ChrPtr(filename), O_RDONLY);
724 lprintf(1, "ERROR: could not open template '%s' - %s\n",
725 ChrPtr(filename), strerror(errno));
729 if (fstat(fd, &statbuf) == -1) {
730 lprintf(1, "ERROR: could not stat template '%s' - %s\n",
731 ChrPtr(filename), strerror(errno));
735 NewTemplate = (WCTemplate *) malloc(sizeof(WCTemplate));
736 NewTemplate->Data = NewStrBufPlain(NULL, statbuf.st_size);
737 NewTemplate->nTokensUsed = 0;
738 NewTemplate->TokenSpace = 0;
739 NewTemplate->Tokens = NULL;
740 if (StrBufReadBLOB(NewTemplate->Data, &fd, 1, statbuf.st_size, &Err) < 0) {
742 FreeWCTemplate(NewTemplate);
743 lprintf(1, "ERROR: reading template '%s' - %s<br />\n",
744 ChrPtr(filename), strerror(errno));
749 pS = pch = ChrPtr(NewTemplate->Data);
750 pE = pS + StrLength(NewTemplate->Data);
752 const char *pts, *pte;
754 int InDoubleQuotes = 0;
756 for (; pch < pE; pch ++) {
757 if ((*pch=='<')&&(*(pch + 1)=='?'))
763 for (; pch < pE - 1; pch ++) {
765 InDoubleQuotes = ! InDoubleQuotes;
766 else if (*pch == '\'')
767 InQuotes = ! InQuotes;
768 else if ((!InQuotes && !InDoubleQuotes) &&
769 ((*pch!='\\')&&(*(pch + 1)=='>'))) {
777 PutNewToken(NewTemplate,
778 NewTemplateSubstitute(NewTemplate->Data, pS, pts, pte));
781 Put(PutThere, ChrPtr(Key), StrLength(Key), NewTemplate, FreeWCTemplate);
786 * \brief Display a variable-substituted template
787 * \param templatename template file to load
789 void DoTemplate(const char *templatename, long len, void *Context, StrBuf *Target)
792 HashList *StaticLocal;
798 Static = WirelessTemplateCache;
799 StaticLocal = WirelessLocalTemplateCache;
802 Static = TemplateCache;
803 StaticLocal = LocalTemplateCache;
806 if (!GetHash(StaticLocal, templatename, len, &vTmpl) &&
807 !GetHash(Static, templatename, len, &vTmpl)) {
808 printf ("didn't find %s\n", templatename);
813 ProcessTemplate(vTmpl, Target, Context);
816 int LoadTemplateDir(const char *DirName, HashList *wireless, HashList *big)
822 struct dirent *filedir_entry;
828 StrBufPrintf(Dir, "%s/t", DirName);
829 filedir = opendir (ChrPtr(Dir));
830 if (filedir == NULL) {
834 FileName = NewStrBuf();
836 while ((filedir_entry = readdir(filedir)))
840 #ifdef _DIRENT_HAVE_D_NAMELEN
841 d_namelen = filedir_entry->d_namelen;
843 d_namelen = strlen(filedir_entry->d_name);
845 d_without_ext = d_namelen;
846 while ((d_without_ext > 0) && (filedir_entry->d_name[d_without_ext] != '.'))
848 if ((d_without_ext == 0) || (d_namelen < 3))
851 IsMobile = (strstr(filedir_entry->d_name, ".m.html")!= NULL);
852 PStart = filedir_entry->d_name;
853 StrBufPrintf(FileName, "%s/%s", ChrPtr(Dir), filedir_entry->d_name);
854 MinorPtr = strchr(filedir_entry->d_name, '.');
855 if (MinorPtr != NULL)
857 StrBufPlain(Tag, filedir_entry->d_name, MinorPtr - filedir_entry->d_name);
860 printf("%s %d %s\n",ChrPtr(FileName), IsMobile, ChrPtr(Tag));
861 load_template(FileName, Tag, (IsMobile)?wireless:big);
864 FreeStrBuf(&FileName);
870 void InitTemplateCache(void)
872 LoadTemplateDir(static_dirs[0],
873 WirelessTemplateCache,
875 LoadTemplateDir(static_dirs[1],
876 WirelessLocalTemplateCache,
880 void tmplput_serv_ip(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context)
882 StrBufAppendPrintf(Target, "%d", WC->ctdl_pid);
885 void tmplput_serv_nodename(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context)
887 StrEscAppend(Target, NULL, serv_info.serv_nodename, 0, 0);
890 void tmplput_serv_humannode(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context)
892 StrEscAppend(Target, NULL, serv_info.serv_humannode, 0, 0);
895 void tmplput_serv_fqdn(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context)
897 StrEscAppend(Target, NULL, serv_info.serv_fqdn, 0, 0);
900 void tmmplput_serv_software(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context)
902 StrEscAppend(Target, NULL, serv_info.serv_software, 0, 0);
905 void tmplput_serv_rev_level(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context)
907 StrBufAppendPrintf(Target, "%d.%02d",
908 serv_info.serv_rev_level / 100,
909 serv_info.serv_rev_level % 100);
912 void tmmplput_serv_bbs_city(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context)
914 StrEscAppend(Target, NULL, serv_info.serv_bbs_city, 0, 0);
917 void tmplput_current_user(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context)
919 StrEscAppend(Target, NULL, WC->wc_fullname, 0, 0);
922 void tmplput_current_room(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context)
924 StrEscAppend(Target, NULL, WC->wc_roomname, 0, 0);
928 typedef struct _HashIterator {
929 HashList *StaticList;
930 RetrieveHashlistFunc GetHash;
931 HashDestructorFunc Destructor;
932 SubTemplFunc DoSubTemplate;
935 void tmpl_iterate_subtmpl(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context)
947 if (!GetHash(Iterators,
948 Tokens->Params[0]->Start,
949 Tokens->Params[0]->len,
952 It = (HashIterator*) vIt;
953 if (It->StaticList == NULL)
954 List = It->GetHash();
956 List = It->StaticList;
958 SubBuf = NewStrBuf();
959 it = GetNewHashPos();
960 while (GetNextHashPos(List, it, &len, &Key, &vContext)) {
961 svprintf(HKEY("ITERATE:ODDEVEN"), WCS_STRING, "%s", (oddeven)?"odd":"even");
962 It->DoSubTemplate(SubBuf, vContext);
963 DoTemplate(Tokens->Params[1]->Start,
964 Tokens->Params[1]->len,
967 StrBufAppendBuf(Target, SubBuf, 0);
971 It->Destructor(List);
974 int ConditionalVar(WCTemplateToken *Tokens, void *Context)
979 if (!GetHash(WC->vars,
980 Tokens->Params[2]->Start,
981 Tokens->Params[2]->len,
984 subst = (wcsubst*) vsubst;
985 switch(subst->wcs_type) {
987 if (Tokens->nParameters < 4)
989 return (strcmp(Tokens->Params[3]->Start, subst->wcs_value) == 0);
991 lprintf(1, " -> Server [%s]\n", subst->wcs_value);////todo
994 return (subst->wcs_function!=NULL);
997 if (Tokens->nParameters < 4)
999 return (strcmp(Tokens->Params[3]->Start, ChrPtr((StrBuf*) subst->wcs_function)) == 0);
1001 if (Tokens->nParameters < 4)
1002 return (subst->lvalue != 0);
1003 return (subst->lvalue == Tokens->Params[3]->lvalue);
1005 lprintf(1," WARNING: invalid type: [%ld]!\n", subst->wcs_type);
1010 void RegisterITERATOR(const char *Name, long len,
1011 HashList *StaticList,
1012 RetrieveHashlistFunc GetHash,
1013 SubTemplFunc DoSubTempl,
1014 HashDestructorFunc Destructor)
1016 HashIterator *It = (HashIterator*)malloc(sizeof(HashIterator));
1017 It->StaticList = StaticList;
1018 It->GetHash = GetHash;
1019 It->DoSubTemplate = DoSubTempl;
1020 It->Destructor = Destructor;
1021 Put(Iterators, Name, len, It, NULL);
1024 void RegisterConditional(const char *Name, long len,
1026 WCConditionalFunc CondF)
1028 ConditionalStruct *Cond = (ConditionalStruct*)malloc(sizeof(ConditionalStruct));
1029 Cond->nParams = nParams;
1030 Cond->CondF = CondF;
1031 Put(Contitionals, Name, len, Cond, NULL);
1038 RegisterNamespace("SERV_PID", 0, 0, tmplput_serv_ip);
1039 RegisterNamespace("SERV_NODENAME", 0, 0, tmplput_serv_nodename);
1040 RegisterNamespace("SERV_HUMANNODE", 0, 0, tmplput_serv_humannode);
1041 RegisterNamespace("SERV_FQDN", 0, 0, tmplput_serv_fqdn);
1042 RegisterNamespace("SERV_SOFTWARE", 0, 0, tmmplput_serv_software);
1043 RegisterNamespace("SERV_REV_LEVEL", 0, 0, tmplput_serv_rev_level);
1044 RegisterNamespace("SERV_BBS_CITY", 0, 0, tmmplput_serv_bbs_city);
1045 RegisterNamespace("CURRENT_USER", 0, 0, tmplput_current_user);
1046 RegisterNamespace("CURRENT_ROOM", 0, 0, tmplput_current_room);
1047 RegisterNamespace("ITERATE", 2, 4, tmpl_iterate_subtmpl);
1048 RegisterConditional(HKEY("COND:SUBST"), 3, ConditionalVar);