HashList *SortHash;
int LoadTemplates = 0;
+int dbg_bactrace_template_errors = 0;
WCTemplputParams NoCtx;
#define SV_GETTEXT 1
#define SV_SUBTEMPL 5
#define SV_PREEVALUATED 6
+
+/*
+ * \brief Dynamic content for variable substitution in templates
+ */
+typedef struct _wcsubst {
+ ContextFilter Filter;
+ int wcs_type; /* which type of Substitution are we */
+ char wcs_key[32]; /* copy of our hashkey for debugging */
+ StrBuf *wcs_value; /* if we're a string, keep it here */
+ long lvalue; /* type long? keep data here */
+ WCHandlerFunc wcs_function; /* funcion hook ???*/
+} wcsubst;
+
+
typedef struct _WCTemplate {
StrBuf *Data;
StrBuf *FileName;
int nTokensUsed;
int TokenSpace;
+ StrBuf *MimeType;
WCTemplateToken **Tokens;
} WCTemplate;
void *load_template(StrBuf *filename, StrBuf *Key, HashList *PutThere);
int EvaluateConditional(StrBuf *Target, int Neg, int state, WCTemplputParams *TP);
+
+
typedef struct _SortStruct {
StrBuf *Name;
StrBuf *PrefPrepend;
"Context LONGVECTOR",
"Context ROOMS",
"Context FLOORS",
- "Context ITERATE"
+ "Context ITERATE",
+ "Context UNKNOWN"
};
free (Sort);
}
+const char *ContextName(int ContextType)
+{
+ if (ContextType < CTX_UNKNOWN)
+ return CtxNames[ContextType];
+ else
+ return CtxNames[CTX_UNKNOWN];
+}
+
void LogTemplateError (StrBuf *Target, const char *Type, int ErrorPos, WCTemplputParams *TP, const char *Format, ...)
{
+ wcsession *WCC;
+ StrBuf *Header;
StrBuf *Error;
StrBuf *Info;
va_list arg_ptr;
switch (ErrorPos) {
default:
case ERR_NAME: /* the main token name... */
- Err = TP->Tokens->pName;
+ Err = (TP->Tokens!= NULL)? TP->Tokens->pName:"";
break;
case ERR_PARM1:
- Err = TP->Tokens->Params[0]->Start;
+ Err = (TP->Tokens!= NULL)? TP->Tokens->Params[0]->Start:"";
break;
case ERR_PARM2:
- Err = TP->Tokens->Params[1]->Start;
+ Err = (TP->Tokens!= NULL)? TP->Tokens->Params[1]->Start:"";
break;
}
- lprintf(1, "%s [%s] (in '%s' line %ld); %s; [%s]\n",
- Type,
- Err,
- ChrPtr(TP->Tokens->FileName),
- TP->Tokens->Line,
- ChrPtr(Error),
- ChrPtr(TP->Tokens->FlatToken));
- if (Target != NULL) {
+ if (TP->Tokens != NULL)
+ {
+ lprintf(1, "%s [%s] (in '%s' line %ld); %s; [%s]\n",
+ Type,
+ Err,
+ ChrPtr(TP->Tokens->FileName),
+ TP->Tokens->Line,
+ ChrPtr(Error),
+ ChrPtr(TP->Tokens->FlatToken));
+ }
+ else
+ {
+ lprintf(1, "%s: %s;\n",
+ Type,
+ ChrPtr(Error));
+ }
+ if (Target == NULL)
+ return;
+ WCC = WC;
+ Header = NewStrBuf();
+ if (TP->Tokens != NULL)
+ {
+ /* deprecated:
StrBufAppendPrintf(
Target,
"<pre>\n%s [%s] (in '%s' line %ld); %s\n[%s]\n</pre>\n",
TP->Tokens->Line,
ChrPtr(Error),
ChrPtr(TP->Tokens->FlatToken));
+ */
+ StrBufPrintf(Info, "%s [%s] %s; [%s]",
+ Type,
+ Err,
+ ChrPtr(Error),
+ ChrPtr(TP->Tokens->FlatToken));
+
+
+ SerializeJson(Header, WildFireException(SKEY(TP->Tokens->FileName),
+ TP->Tokens->Line,
+ Info,
+ 1), 1);
+/*
+ SerializeJson(Header, WildFireMessage(SKEY(TP->Tokens->FileName),
+ TP->Tokens->Line,
+ Error,
+ eERROR), 1);
+*/
+ WildFireSerializePayload(Header, WCC->HBuf, &WCC->nWildfireHeaders, NULL);
}
+ else
+ {
+ /* deprecated.
+ StrBufAppendPrintf(
+ Target,
+ "<pre>\n%s: %s\n</pre>\n",
+ Type,
+ ChrPtr(Error));
+ */
+ StrBufPrintf(Info, "%s [%s] %s; [%s]",
+ Type,
+ Err,
+ ChrPtr(Error),
+ ChrPtr(TP->Tokens->FlatToken));
+ SerializeJson(Header, WildFireException(HKEY(__FILE__), __LINE__, Info, 1), 1);
+ WildFireSerializePayload(Header, WCC->HBuf, &WCC->nWildfireHeaders, NULL);
+ }
+ FreeStrBuf(&Header);
+ FreeStrBuf(&Info);
+ FreeStrBuf(&Error);
+/*
+ if (dbg_bactrace_template_errors)
+ wc_backtrace();
+*/
}
LogTemplateError(
Target, ErrType, ERR_PARM1, TP,
" WARNING: requires Context: [%s], have [%s]!",
- CtxNames[Need->ContextType],
- CtxNames[TP->Filter.ContextType]);
+ ContextName(Need->ContextType),
+ ContextName(TP->Filter.ContextType));
return 0;
}
LogTemplateError(
Target, ErrType, ERR_PARM1, TP,
" WARNING: requires Control Context: [%s], have [%s]!",
- CtxNames[Need->ControlContextType],
- CtxNames[TP->Filter.ControlContextType]);
+ ContextName(Need->ControlContextType),
+ ContextName(TP->Filter.ControlContextType));
return 0;
}
/*
}
FreeStrBuf(&FreeMe->FileName);
FreeStrBuf(&FreeMe->Data);
+ FreeStrBuf(&FreeMe->MimeType);
free(FreeMe);
}
}
}
-void GetTemplateTokenString(WCTemplputParams *TP,
+void GetTemplateTokenString(StrBuf *Target,
+ WCTemplputParams *TP,
int N,
const char **Value,
long *len)
WCTemplputParams SubTP;
if (TP->Tokens->nParameters < N) {
- lprintf(1, "invalid token. this shouldn't have come till here.\n");
- wc_backtrace();
+ LogTemplateError(Target,
+ "TokenParameter", N, TP,
+ "invalid token %d. this shouldn't have come till here.\n", N);
*Value = "";
*len = 0;
return;
*len = StrLength(Buf);
break;
case TYPE_LONG:
+ LogTemplateError(Target,
+ "TokenParameter", N, TP,
+ "Requesting parameter %d; of type LONG, want string.", N);
+ break;
case TYPE_PREFINT:
- break; /* todo: string to text? */
+ LogTemplateError(Target,
+ "TokenParameter", N, TP,
+ "Requesting parameter %d; of type PREFINT, want string.", N);
+ break;
case TYPE_GETTEXT:
*Value = _(TP->Tokens->Params[N]->Start);
*len = strlen(*Value);
break;
default:
+ LogTemplateError(Target,
+ "TokenParameter", N, TP,
+ "unknown param type %d; [%d]", N, TP->Tokens->Params[N]->Type);
+ break;
+ }
+}
+
+long GetTemplateTokenNumber(StrBuf *Target, WCTemplputParams *TP, int N, long dflt)
+{
+ long Ret;
+ if (TP->Tokens->nParameters < N) {
+ LogTemplateError(Target,
+ "TokenParameter", N, TP,
+ "invalid token %d. this shouldn't have come till here.\n", N);
+ wc_backtrace();
+ return 0;
+ }
+
+ switch (TP->Tokens->Params[N]->Type) {
+
+ case TYPE_STR:
+ return atol(TP->Tokens->Params[N]->Start);
+ break;
+ case TYPE_BSTR:
+ return LBstr(TKEY(N));
break;
-/*/todo log error */
+ case TYPE_PREFSTR:
+ LogTemplateError(Target,
+ "TokenParameter", N, TP,
+ "requesting a prefstring in param %d want a number", N);
+ if (get_PREF_LONG(TKEY(N), &Ret, dflt))
+ return Ret;
+ return 0;
+ case TYPE_LONG:
+ return TP->Tokens->Params[N]->lvalue;
+ case TYPE_PREFINT:
+ if (get_PREF_LONG(TKEY(N), &Ret, dflt))
+ return Ret;
+ return 0;
+ case TYPE_GETTEXT:
+ LogTemplateError(Target,
+ "TokenParameter", N, TP,
+ "requesting a I18N string in param %d; want a number", N);
+ return 0;
+ case TYPE_SUBTEMPLATE:
+ LogTemplateError(Target,
+ "TokenParameter", N, TP,
+ "requesting a subtemplate in param %d; not supported for numbers", N);
+ return 0;
+ default:
+ LogTemplateError(Target,
+ "TokenParameter", N, TP,
+ "unknown param type %d; [%d]", N, TP->Tokens->Params[N]->Type);
+ return 0;
}
}
else {
LogTemplateError(
Target, "Token", ERR_NAME, TP,
- "didn't find Handler");
+ "didn't find Handler \"%s\"", TP->Tokens->pName);
wc_backtrace();
}
}
const StrBuf *Source, int FormatTypeIndex)
{
wcsession *WCC;
- StrBuf *Buf;
char EscapeAs = ' ';
if ((FormatTypeIndex < TP->Tokens->nParameters) &&
{
case 'H':
WCC = WC;
- Buf = NewStrBufPlain(NULL, StrLength(Source));
- StrBuf_RFC822_to_Utf8(Buf,
- Source,
- (WCC!=NULL)? WCC->DefaultCharset : NULL,
- NULL);
- StrEscAppend(Target, Buf, NULL, 0, 0);
- FreeStrBuf(&Buf);
+ StrEscAppend(Target, Source, NULL, 0, 2);
break;
case 'X':
StrEscAppend(Target, Source, NULL, 0, 0);
if (NewToken->nParameters > MAXPARAM) {
LogTemplateError(
NULL, "Parseerror", ERR_NAME, &TP,
- "only [%ld] Params allowed in Tokens",
+ "only [%d] Params allowed in Tokens",
MAXPARAM);
free(Param);
(NewToken->nParameters > Handler->Filter.nMaxArgs)) {
LogTemplateError(
NULL, "Token", ERR_NAME, &TP,
- "doesn't work with %ld params",
+ "doesn't work with %d params",
NewToken->nParameters);
}
if (NewToken->nParameters !=1) {
LogTemplateError(
NULL, "Gettext", ERR_NAME, &TP,
- "requires exactly 1 parameter, you gave %ld params",
+ "requires exactly 1 parameter, you gave %d params",
NewToken->nParameters);
NewToken->Flags = 0;
break;
if (NewToken->nParameters != 1) {
LogTemplateError(
NULL, "Subtemplates", ERR_NAME, &TP,
- "require exactly 1 parameter, you gave %ld params",
+ "require exactly 1 parameter, you gave %d params",
NewToken->nParameters);
break;
}
if (NewToken->nParameters <2) {
LogTemplateError(
NULL, "Conditional", ERR_NAME, &TP,
- "require at least 2 parameters, you gave %ld params",
+ "require at least 2 parameters, you gave %d params",
NewToken->nParameters);
NewToken->Flags = 0;
break;
NewTemplate->nTokensUsed = 0;
NewTemplate->TokenSpace = 0;
NewTemplate->Tokens = NULL;
+ NewTemplate->MimeType = NewStrBufPlain(GuessMimeByFilename (SKEY(NewTemplate->FileName)), -1);
+ if (strstr(ChrPtr(NewTemplate->MimeType), "text") != NULL) {
+ StrBufAppendBufPlain(NewTemplate->MimeType, HKEY("; charset=utf-8"), 0);
+ }
Put(PutThere, ChrPtr(Key), StrLength(Key), NewTemplate, FreeWCTemplate);
return NewTemplate;
NewTemplate->nTokensUsed = 0;
NewTemplate->TokenSpace = 0;
NewTemplate->Tokens = NULL;
+ NewTemplate->MimeType = NewStrBufPlain(GuessMimeByFilename (SKEY(NewTemplate->FileName)), -1);
+ if (strstr(ChrPtr(NewTemplate->MimeType), "text") != NULL) {
+ StrBufAppendBufPlain(NewTemplate->MimeType, HKEY("; charset=utf-8"), 0);
+ }
+
if (StrBufReadBLOB(NewTemplate->Data, &fd, 1, statbuf.st_size, &Err) < 0) {
close(fd);
FreeWCTemplate(NewTemplate);
case SV_CUST_STR_CONDITIONAL: /** Conditional put custom strings from params */
if (TP->Tokens->nParameters >= 6) {
if (EvaluateConditional(Target, 0, state, TP)) {
- GetTemplateTokenString(TP, 5, &AppendMe, &AppendMeLen);
+ GetTemplateTokenString(Target, TP, 5, &AppendMe, &AppendMeLen);
StrBufAppendBufPlain(Target,
AppendMe,
AppendMeLen,
0);
}
else{
- GetTemplateTokenString(TP, 4, &AppendMe, &AppendMeLen);
+ GetTemplateTokenString(Target, TP, 4, &AppendMe, &AppendMeLen);
StrBufAppendBufPlain(Target,
AppendMe,
AppendMeLen,
-void ProcessTemplate(WCTemplate *Tmpl, StrBuf *Target, void *Context, int ContextType)
+const StrBuf *ProcessTemplate(WCTemplate *Tmpl, StrBuf *Target, WCTemplputParams *CallingTP)
{
WCTemplate *pTmpl = Tmpl;
int done = 0;
long len;
WCTemplputParams TP;
- TP.Context = Context;
- TP.Filter.ContextType = ContextType;
+ memcpy(&TP.Filter, &CallingTP->Filter, sizeof(ContextFilter));
+
+ TP.Context = CallingTP->Context;
+ TP.ControlContext = CallingTP->ControlContext;
if (LoadTemplates != 0) {
if (LoadTemplates > 1)
Target,
"<pre>\nError loading Template [%s]\n See Logfile for details\n</pre>\n",
ChrPtr(Tmpl->FileName));
- return;
+ return NULL;
}
}
if (LoadTemplates != 0) {
FreeWCTemplate(pTmpl);
}
+ return Tmpl->MimeType;
+
}
/**
* \brief Display a variable-substituted template
* \param templatename template file to load
+ * \returns the mimetype of the template its doing
*/
-void DoTemplate(const char *templatename, long len, StrBuf *Target, WCTemplputParams *TP)
+const StrBuf *DoTemplate(const char *templatename, long len, StrBuf *Target, WCTemplputParams *TP)
{
+ WCTemplputParams LocalTP;
HashList *Static;
HashList *StaticLocal;
void *vTmpl;
if (Target == NULL)
Target = WC->WBuf;
+ if (TP == NULL) {
+ memset(&LocalTP, 0, sizeof(WCTemplputParams));
+ TP = &LocalTP;
+ }
+
if (WC->is_mobile) {
Static = WirelessTemplateCache;
StaticLocal = WirelessLocalTemplateCache;
{
lprintf (1, "Can't to load a template with empty name!\n");
StrBufAppendPrintf(Target, "<pre>\nCan't to load a template with empty name!\n</pre>");
- return;
+ return NULL;
}
if (!GetHash(StaticLocal, templatename, len, &vTmpl) &&
dbg_PrintHash(Static, PrintTemplate, NULL);
PrintHash(Static, VarPrintTransition, PrintTemplate);
#endif
- return;
+ return NULL;
}
if (vTmpl == NULL)
- return;
- ProcessTemplate(vTmpl, Target, TP->Context, TP->Filter.ContextType);
+ return NULL;
+ return ProcessTemplate(vTmpl, Target, TP);
+
}
/*-----------------------------------------------------------------------------
long KeyLen;
int n;
int LastN;
-}IterateStruct;
+ }IterateStruct;
void tmpl_iterate_subtmpl(StrBuf *Target, WCTemplputParams *TP)
{
WCTemplputParams SubTP;
IterateStruct Status;
+ long StartAt = 0;
+ long StepWidth = 0;
+ long StopAt = -1;
+
memset(&Status, 0, sizeof(IterateStruct));
memcpy (&SubTP, &TP, sizeof(WCTemplputParams));
if (TP->Tokens->nParameters < It->AdditionalParams + 2) {
LogTemplateError(
Target, "Iterator", ERR_PARM1, TP,
- "doesn't work with %ld params",
+ "doesn't work with %d params",
TP->Tokens->nParameters);
return;
}
(It->XPectContextType != TP->Filter.ContextType)) {
LogTemplateError(
Target, "Iterator", ERR_PARM1, TP,
- "requires context of type %ld, have %ld",
+ "requires context of type %d, have %d",
It->XPectContextType,
TP->Filter.ContextType);
return ;
SubTP.Filter.ContextType = It->ContextType;
SubTP.Filter.ControlContextType = CTX_ITERATE;
SubTP.ControlContext = &Status;
- it = GetNewHashPos(List, 0);
+
+ if (HAVE_PARAM(2)) {
+ StartAt = GetTemplateTokenNumber(Target, TP, 2, 0);
+ }
+ if (HAVE_PARAM(3)) {
+ StepWidth = GetTemplateTokenNumber(Target, TP, 3, 0);
+ }
+ if (HAVE_PARAM(4)) {
+ StopAt = GetTemplateTokenNumber(Target, TP, 4, -1);
+ }
+ it = GetNewHashPos(List, StepWidth);
+ if (StopAt < 0) {
+ StopAt = GetCount(List);
+ }
while (GetNextHashPos(List, it, &Status.KeyLen, &Status.Key, &vContext)) {
- if (DetectGroupChange && Status.n > 0) {
- Status.GroupChange = (SortBy->GroupChange(vContext, vLastContext))? 1:0;
- }
- Status.LastN = ++Status.LastN == nMembersUsed;
- SubTP.Context = vContext;
- if (It->DoSubTemplate != NULL)
- It->DoSubTemplate(SubBuf, &SubTP);
- DoTemplate(TKEY(1), SubBuf, &SubTP);
+ if ((Status.n >= StartAt) && (Status.n <= StopAt)) {
+ if (DetectGroupChange && Status.n > 0) {
+ Status.GroupChange = (SortBy->GroupChange(vContext, vLastContext))? 1:0;
+ }
+ Status.LastN = (Status.n + 1) == nMembersUsed;
+ SubTP.Context = vContext;
+ if (It->DoSubTemplate != NULL)
+ It->DoSubTemplate(SubBuf, &SubTP);
+ DoTemplate(TKEY(1), SubBuf, &SubTP);
- StrBufAppendBuf(Target, SubBuf, 0);
- FlushStrBuf(SubBuf);
- Status.oddeven = ! Status.oddeven;
- vLastContext = vContext;
+ StrBufAppendBuf(Target, SubBuf, 0);
+ FlushStrBuf(SubBuf);
+ Status.oddeven = ! Status.oddeven;
+ vLastContext = vContext;
+ }
+ Status.n++;
}
FreeStrBuf(&SubBuf);
DeleteHashPos(&it);
const char *CompareToken;
long len;
- GetTemplateTokenString(TP, 2, &CompareToken, &len);
+ GetTemplateTokenString(Target, TP, 2, &CompareToken, &len);
return strcmp(ChrPtr(TokenText), CompareToken) == 0;
}
else {
const char *Ch;
long len;
- GetTemplateTokenString(TP,
+ GetTemplateTokenString(Target,
+ TP,
1,
&Ch,
&len);
else if (TP->Tokens->Params[i * 2]->Type == TYPE_GETTEXT) {
const char *Ch;
long len;
- GetTemplateTokenString(TP,
+ GetTemplateTokenString(Target,
+ TP,
i * 2,
&Ch,
&len);