#include "udm_config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <ctype.h>
#include "udmsearch.h"
#include "udm_db.h"
#include "udm_http.h"
#include "udm_parsehtml.h"
#include "udm_host.h"
#include "udm_contentencoding.h"
#include "udm_utils.h"
static size_t out_string(FILE * stream, char * dst, size_t dst_len, const char * src){
if(src){
if(stream)fputs(src,stream);
if(dst){
strncat(dst, src, dst_len - 1);
return(strlen(src));
}
}
return(0);
}
static char * HiLightDup(const char * src,const char * beg, const char * end){
size_t len=1;
size_t blen=strlen(beg);
size_t elen=strlen(end);
const char * s;
char * res, *d;
for(s=src;*s;s++){
switch(*s){
case '\2':
len+=blen;
break;
case '\3':
len+=elen;
break;
default:
len++;
}
}
res=(char*)malloc(len);
for(s=src,d=res;*s;s++){
switch(*s){
case '\2':
strcpy(d,beg);
d+=blen;
break;
case '\3':
strcpy(d,end);
d+=elen;
break;
default:
*d=*s;
d++;
}
}
*d='\0';
return(res);
}
static size_t PrintTextTemplate(UDM_AGENT *A, FILE * stream, char * dst, size_t dst_len, UDM_VARLIST * vars, const char * templ) {
const char * s;
size_t dlen=0;
const char * HlBeg=UdmVarListFindStrTxt(vars,"HlBeg","");
const char * HlEnd=UdmVarListFindStrTxt(vars,"HlEnd","");
for(s=templ; (*s) && ((stream) || (dlen < dst_len)); s++){
int type=0;
char *value=NULL, *eval=NULL, *newvalue = NULL;
char empty[]="";
size_t maxlen=0;
size_t curlen=0;
if(*s=='$'){
const char * vbeg=NULL, * vend;
int pcount=0;
if(!strncmp(s,"$(",2)){vbeg=s+2;type='(';}
else if(!strncmp(s,"$%(",3)){vbeg=s+3;type='%';}
else if(!strncmp(s,"$&(",3)){vbeg=s+3;type='&';}
else if(!strncmp(s,"$^(",3)){vbeg=s+3;type='^';}
for (vend=s; vend[0]; vend++){
if(vend[0]=='(')pcount++;
if(vend[0]==')' && (--pcount)==0)
break;
}
if((type)&&(vend)){
UDM_VAR * var;
size_t len;
char name[100]="";
char * sem;
len=(vend-vbeg);
if(len>=sizeof(name))len=sizeof(name)-1;
strncpy(name,vbeg,len);name[len]='\0';
if((sem=strchr(name,':'))){
*sem=0;
maxlen=atoi(sem+1);
}
if ((A->doccount == 0) && !strcasecmp(name, "ndocs")) {
UdmURLAction(A, NULL, UDM_URL_ACTION_DOCCOUNT);
UdmVarListReplaceInt(vars, "ndocs", A->doccount);
}
if((var=UdmVarListFind(vars,name))){
switch(type) {
case '&': value = var->val; break;
default: value = (var->txt_val) ? var->txt_val : var->val;
}
if(!value)value=empty;
}else{
value=empty;
}
s=vend;
}else{
type=0;
}
}
if(!value)value=empty;
curlen=strlen(value);
if((curlen>maxlen)&&(maxlen>0)){
char *p = value + maxlen, *S, *e;
S = e = p;
if (isdigit(*e)) {
while(isdigit(*S) && S > (value + 1)) S--;
S--;
if (*S == '&' && S[1] == '#') {
while(isdigit(*e)) e++;
if (*e == ';') p = e + 1;
}
} else if (isalpha(*e)) {
while(isalpha(*S) && S > value) S--;
if (*S == '&') {
while(isalpha(*e)) e++;
if (*e == ';') p = e + 1;
}
} else if (*e == ';' && S < value ) {
S--;
if (isdigit(*S)) {
while(isdigit(*S) && S > (value + 1)) S--;
S--;
if (*S == '&' && S[1] == '#') {
p = e + 1;
}
} else if (isalpha(*S)) {
while(isalpha(*S) && S > value) S--;
if (*S == '&') {
p = e + 1;
}
}
}
if ((newvalue = (char*)malloc((size_t)(p - value) + 8))) {
char *c2, *c3;
strncpy(newvalue, value, (size_t)(p - value));
newvalue[(p - value)] = '\0';
c2 = strrchr(newvalue, '\2');
c3 = strrchr(newvalue, '\3');
if ((c2 != NULL) && ((c3 == NULL) || (c2 > c3))) {
strcpy(newvalue + (p - value), "\3...");
} else {
strcpy(newvalue + (p - value), "...");
}
value = newvalue;
}
}
switch(type){
case '(':
eval = UdmRemoveHiLightDup(value);
dlen+=out_string(stream, dst + dlen, dst_len - dlen, eval);
UDM_FREE(eval);
break;
case '&':
case '^':
eval=HiLightDup(value,HlBeg,HlEnd);
dlen+=out_string(stream, dst + dlen, dst_len - dlen, eval);
UDM_FREE(eval);
break;
case '%':
eval=(char*)malloc(strlen(value)*3);
UdmEscapeURL(eval,value);
dlen+=out_string(stream, dst + dlen, dst_len - dlen, eval);
UDM_FREE(eval);break;
default:
if((stream)&&(*s))fputc(*s,stream);
if(dst){
dst[dlen]=*s;
dlen++;
dst[dlen]='\0';
}
}
UDM_FREE(newvalue);
}
return dlen;
}
static char * GetHtmlTok(const char * src,const char ** lt){
char * res;
size_t len;
if((!src)&&!(src=*lt))return(NULL);
if(*src=='<'){
if((*lt=strchr(src,'>')))(*lt)++;
}else{
*lt=strchr(src,'<');
}
if(!(*lt)){
res = (char*)strdup(src);
}else{
len=(*lt)-src;
res=(char*)malloc(len+2);
strncpy(res,src,len);
res[len]='\0';
}
return(res);
}
static void TemplateInclude(UDM_AGENT *Agent,FILE *stream,UDM_VARLIST *vars,const char *tok){
size_t i;
UDM_HTMLTOK ltag, *tag = <ag;
const char *last;
char *tag_content = NULL;
UDM_DOCUMENT * Inc=UdmDocInit(NULL);
size_t max_doc_size = (size_t)UdmVarListFindInt(vars,"MaxDocSize",UDM_MAXDOCSIZE);
if(!Inc->Buf.buf)Inc->Buf.buf=malloc(max_doc_size);
Inc->Buf.maxsize=max_doc_size;
UdmHTMLTOKInit(tag);
UdmHTMLToken(tok, &last, tag);
for(i = 0; i < ltag.ntoks; i++) {
if (ISTAG(i, "content")) {
tag_content = strndup(ltag.toks[i].val, ltag.toks[i].vlen);
break;
}
}
if(tag_content){
const char *ce;
size_t vurlen = 256 + 4 * strlen(tag_content);
char *vurl = (char*)malloc(vurlen);
PrintTextTemplate(Agent, NULL, vurl, vurlen, vars, tag_content);
UdmURLParse(&Inc->CurURL,vurl);
UDM_FREE(vurl);
UdmVarListReplaceStr(&Inc->RequestHeaders, "Host", UDM_NULL2EMPTY(Inc->CurURL.hostname));
Inc->connp.hostname = (char*)strdup(UDM_NULL2EMPTY(Inc->CurURL.hostname));
Inc->connp.port = Inc->CurURL.port ? Inc->CurURL.port : Inc->CurURL.default_port;
if(UdmHostLookup(&Agent->Conf->Hosts, &Inc->connp)){
}
if(UdmGetURL(Agent,Inc)==UDM_OK){
UdmParseHTTPResponse(Agent,Inc);
if(Inc->Buf.content){
ce=UdmVarListFindStr(&Inc->Sections,"Content-Encoding","");
#ifdef HAVE_ZLIB
if(!strcasecmp(ce,"gzip") || !strcasecmp(ce,"x-gzip")){
UdmUnGzip(Inc);
}else
if(!strcasecmp(ce,"deflate")){
UdmInflate(Inc);
}else
if(!strcasecmp(ce,"compress") || !strcasecmp(ce,"x-compress")){
UdmUncompress(Inc);
}
#endif
if(stream){
fprintf(stream,"%s",Inc->Buf.content);
}else{
}
}
}
UDM_FREE(tag_content);
}
UdmDocFree(Inc);
}
static size_t TemplateTag(UDM_AGENT *Agent,FILE *stream,char *dst,size_t dst_len,UDM_VARLIST *vars,const char *tok){
char * opt;
UDM_HTMLTOK ltag, *tag = <ag;
const char *last;
UDM_VAR * var=NULL;
char * vname = NULL, *value = NULL;
size_t i, res = 0;
opt=(char*)malloc(strlen(tok)+200);
UdmHTMLTOKInit(tag);
UdmHTMLToken(tok, &last, tag);
sprintf(opt, "<");
for (i = 0; i < ltag.ntoks; i++) {
if (ISTAG(i, "selected")) {
vname = strndup(ltag.toks[i].val, ltag.toks[i].vlen);
} else if (ISTAG(i, "value")) {
value = strndup(ltag.toks[i].val, ltag.toks[i].vlen);
sprintf(UDM_STREND(opt), "value=\"%s\" ", value);
} else if (ISTAG(i, "/")) { sprintf(UDM_STREND(opt), " %s", "/");
} else {
char *tname = strndup(ltag.toks[i].name, ltag.toks[i].nlen);
if (ltag.toks[i].vlen) {
char *tval = strndup(ltag.toks[i].val, ltag.toks[i].vlen);
sprintf(UDM_STREND(opt), "%s=\"%s\" ", tname, tval);
UDM_FREE(tval);
} else {
sprintf(UDM_STREND(opt), "%s ", tname);
}
UDM_FREE(tname);
}
}
if(vname) {
var = UdmVarListFindWithValue(vars, UdmTrim(vname, "$()"), value ? value:"");
}
sprintf(UDM_STREND(opt), "%s>", var ? "SELECTED":"");
if (vname) { UDM_FREE(vname); }
if (value) { UDM_FREE(value); }
res = PrintTextTemplate(Agent, stream, dst, dst_len, vars, opt);
UDM_FREE(opt);
return res;
}
#define UDM_IFSTACKMAX 15
typedef struct udm_if_stack_item_st {
int condition;
int showelse;
} UDM_IFITEM;
typedef struct udm_if_stack_st {
size_t pos;
UDM_IFITEM Items[UDM_IFSTACKMAX+1];
} UDM_IFSTACK;
static void UdmIfStackInit(UDM_IFSTACK *S){
UDM_IFITEM *top=&S->Items[0];
bzero((void*)S, sizeof(*S));
top->condition=1;
top->showelse=1;
}
static UDM_IFITEM *UdmIfStackPush(UDM_IFSTACK *S){
if(S->pos<UDM_IFSTACKMAX){
UDM_IFITEM *cur=&S->Items[S->pos+1];
UDM_IFITEM *prev=&S->Items[S->pos];
S->pos++;
cur->condition=prev->condition;
cur->showelse=prev->condition;
}
return &S->Items[S->pos];
}
static UDM_IFITEM *UdmIfStackPop(UDM_IFSTACK *S){
if(S->pos>0)S->pos--;
return &S->Items[S->pos];
}
static void HTMLTokToVarList(UDM_VARLIST *vars,UDM_HTMLTOK *tag){
size_t toks;
for(toks=0;toks<tag->ntoks;toks++){
char *vr=tag->toks[toks].name ? strndup(tag->toks[toks].name,tag->toks[toks].nlen) : (char*)strdup("");
char *vl=tag->toks[toks].val ? strndup(tag->toks[toks].val,tag->toks[toks].vlen) : (char*)strdup("");
UdmVarListAddStr(vars,vr,vl);
UDM_FREE(vr);
UDM_FREE(vl);
}
}
static void TemplateSet(UDM_AGENT *Agent,UDM_VARLIST *vars,const char *tok,UDM_IFSTACK *is){
UDM_HTMLTOK tag;
UDM_VARLIST attr;
const char *var,*val,*hlast=NULL;
UdmHTMLTOKInit(&tag);
UdmHTMLToken(tok,&hlast,&tag);
UdmVarListInit(&attr);
HTMLTokToVarList(&attr,&tag);
var=UdmVarListFindStr(&attr,"Name","");
val=UdmVarListFindStr(&attr,"Content","");
UdmVarListReplaceStr(vars,var,val);
UdmVarListFree(&attr);
}
static void TemplateCopy(UDM_AGENT *Agent,UDM_VARLIST *vars,const char *tok,UDM_IFSTACK *is){
UDM_HTMLTOK tag;
UDM_VARLIST attr;
const char *var,*val,*hlast=NULL;
UdmHTMLTOKInit(&tag);
UdmHTMLToken(tok,&hlast,&tag);
UdmVarListInit(&attr);
HTMLTokToVarList(&attr,&tag);
var=UdmVarListFindStr(&attr,"Name","");
val=UdmVarListFindStr(&attr,"Content","");
val=UdmVarListFindStr(vars,val,"");
UdmVarListReplaceStr(vars,var,val);
UdmVarListFree(&attr);
}
static void TemplateCondition(UDM_AGENT *Agent,UDM_VARLIST *vars,const char *tok,UDM_IFSTACK *is){
UDM_HTMLTOK tag;
UDM_VARLIST attr;
const char *var,*val,*hlast=NULL;
UDM_IFITEM *it=&is->Items[is->pos];
UdmHTMLTOKInit(&tag);
UdmHTMLToken(tok,&hlast,&tag);
UdmVarListInit(&attr);
HTMLTokToVarList(&attr,&tag);
var=UdmVarListFindStr(&attr,"Name","");
val=UdmVarListFindStr(&attr,"Content","");
var=UdmVarListFindStr(vars,var,"");
if(!(strncasecmp(tok,"<!IFNOT",7))){
it->condition=strcasecmp(var,val);
}else
if( !(strncasecmp(tok, "<!IF", 4)) || !(strncasecmp(tok, "<!ELIF", 6)) || !(strncasecmp(tok, "<!ELSEIF", 8)) ) {
it->condition=!strcasecmp(var,val);
}
UdmVarListFree(&attr);
}
static void TemplateIf(UDM_AGENT *Agent,UDM_VARLIST *vars,const char *tok,UDM_IFSTACK *is){
UDM_IFITEM *it=UdmIfStackPush(is);
if(it->condition){
TemplateCondition(Agent,vars,tok,is);
if(it->condition)it->showelse=0;
}
}
static void TemplateEndIf(UDM_AGENT *Agent,UDM_VARLIST *vars,const char *tok,UDM_IFSTACK *is){
UdmIfStackPop(is);
}
static void TemplateElseIf(UDM_AGENT *Agent,UDM_VARLIST *vars,const char *tok,UDM_IFSTACK *is){
UDM_IFITEM *it=&is->Items[is->pos];
if(it->showelse){
TemplateCondition(Agent,vars,tok,is);
if(it->condition)it->showelse=0;
}else{
it->condition=0;
}
}
static void TemplateElse(UDM_AGENT *Agent,UDM_VARLIST *vars,const char *tok,UDM_IFSTACK *is){
UDM_IFITEM *it=&is->Items[is->pos];
it->condition=it->showelse;
}
static void PrintHtmlTemplate(UDM_AGENT * Agent, FILE * stream, char * dst, size_t dst_len, UDM_VARLIST * vars, const char * template){
const char *lt;
char *tok;
size_t dlen=0;
UDM_IFSTACK is;
UdmIfStackInit(&is);
tok=GetHtmlTok(template,<);
while(tok){
if(!(strncasecmp(tok,"<!SET",5))){
TemplateSet(Agent,vars,tok,&is);
}else
if(!(strncasecmp(tok,"<!COPY",6))){
TemplateCopy(Agent,vars,tok,&is);
}else
if(!(strncasecmp(tok,"<!IF",4))){
TemplateIf(Agent,vars,tok,&is);
}else
if(!(strncasecmp(tok,"<!ELSEIF",8))){
TemplateElseIf(Agent,vars,tok,&is);
}else
if(!(strncasecmp(tok,"<!ELIF",6))){
TemplateElseIf(Agent,vars,tok,&is);
}else
if(!(strncasecmp(tok,"<!ELSE",6))){
TemplateElse(Agent,vars,tok,&is);
}else
if(!(strncasecmp(tok,"<!ENDIF",7))){
TemplateEndIf(Agent,vars,tok,&is);
}else
if(!(strncasecmp(tok,"<!/IF",5))){
TemplateEndIf(Agent,vars,tok,&is);
}else
if(is.Items[is.pos].condition){
if(!(strncasecmp(tok,"<OPTION",7))){
dlen += TemplateTag(Agent,stream,dst+dlen,dst_len-dlen,vars,tok);
}else
if(!(strncasecmp(tok,"<INPUT",6))){
dlen += TemplateTag(Agent,stream,dst+dlen,dst_len-dlen,vars,tok);
}else
if(!strncasecmp(tok,"<!INCLUDE",9)){
if(Agent)TemplateInclude(Agent,stream,vars,tok);
}else{
dlen += PrintTextTemplate(Agent, stream, dst + dlen, dst_len - dlen, vars, tok);
}
}
UDM_FREE(tok);
tok=GetHtmlTok(NULL,<);
}
}
void __UDMCALL UdmTemplatePrint(UDM_AGENT * Agent, FILE *stream, char *dst, size_t dst_len, UDM_VARLIST *vars, UDM_VARLIST *tm, const char *w){
size_t t;
size_t matches=0;
size_t format=(size_t)UdmVarListFindInt(vars,"o",0);
UDM_VAR *First=NULL;
if(dst)*dst='\0';
for(t=0;t<tm->nvars;t++){
if(!strcasecmp(w,tm->Var[t].name)){
if(!First)First=&tm->Var[t];
if(matches==format){
PrintHtmlTemplate(Agent, stream, dst, dst_len, vars, tm->Var[t].val);
return;
}
matches++;
}
}
if (First) PrintHtmlTemplate(Agent, stream, dst, dst_len, vars, First->val);
return;
}
static int ParseVariable(UDM_ENV *Env,UDM_VARLIST *vars,char *str){
char *tok,*lt;
if((tok = udm_strtok_r(str, " \t\r\n", <))) {
char * arg=NULL;
if(!strcasecmp(str,"Affix")){
char aname[1024];
char * args[5];
size_t narg=0;
while((tok)&&(narg<5)){
args[narg++]=tok;
tok = udm_strtok_r(NULL, " \t", <);
}
if(narg!=4){
sprintf(Env->errstr,"Bad Affix command");
return UDM_ERROR;
}
if(args[3][0]=='/')strncpy(aname,args[3],sizeof(aname)-1);
else udm_snprintf(aname,sizeof(aname)-1,"%s/%s",UDM_CONF_DIR,args[3]);
if(UdmImportAffixes(Env,args[1],args[2],aname)){
udm_snprintf(Env->errstr,sizeof(Env->errstr)-1,"Can't load affix :%s",aname);
return UDM_ERROR;
}
}else
if(!strcasecmp(str,"Spell")){
char aname[1024];
char * args[5];
size_t narg=0;
while((tok)&&(narg<5)){
args[narg++]=tok;
tok = udm_strtok_r(NULL, " \t", <);
}
if(narg!=4){
sprintf(Env->errstr,"Bad Spell command");
return UDM_ERROR;
}
if(args[3][0]=='/')strncpy(aname,args[3],sizeof(aname)-1);
else udm_snprintf(aname,sizeof(aname)-1,"%s/%s",UDM_CONF_DIR,args[3]);
if(UdmImportDictionary(Env,args[1],args[2],aname,0,"")){
udm_snprintf(Env->errstr,sizeof(Env->errstr)-1,"Can't load dictionary :%s",aname);
return UDM_ERROR;
}
}else
if(!strcasecmp(str, "IspellUsePrefixes")) {
char sel[8];
int val = 1;
sscanf(str+17, "%4s", sel);
if (!strncasecmp(sel, "no", 2)) {
val = 0;
}
UdmVarListReplaceInt(&Env->Vars, "IspellUsePrefixes", val);
}else
if(!strcasecmp(str,"StopwordFile")){
char aname[1024];
arg = udm_strtok_r(NULL, " \t\r\n", <);
if(arg){
if(arg[0]=='/')strncpy(aname,arg,sizeof(aname)-1);
else udm_snprintf(aname,sizeof(aname)-1,"%s/%s",UDM_CONF_DIR,arg);
if(UdmStopListLoad(Env,aname)){
return UDM_ERROR;
}
}else{
sprintf(Env->errstr,"Bad StopwordFile command");
return UDM_ERROR;
}
}else
if(!strcasecmp(str,"Synonym")){
char aname[1024];
arg = udm_strtok_r(NULL, " \t\r\n", <);
if(arg){
if(arg[0]=='/')strncpy(aname,arg,sizeof(aname)-1);
else udm_snprintf(aname,sizeof(aname)-1,"%s/%s",UDM_CONF_DIR,arg);
if(UdmSynonymListLoad(Env,aname)){
return UDM_ERROR;
}
}else{
sprintf(Env->errstr,"Bad Synonym command");
return UDM_ERROR;
}
}else
if(!strcasecmp(str,"DBAddr")){
if((arg = udm_strtok_r(NULL, " \t\r\n", <))) {
UdmDBListAdd(&Env->dbl, arg, UDM_OPEN_MODE_READ);
}
}else
if((str[0]=='R'||str[0]=='r')&&(str[1]>='0')&&(str[1]<='9')){
float r;
int ir;
arg = udm_strtok_r(NULL, " =\t\r\n", <);
if(arg){
r = (float)UDM_ATOF(arg);
srand((unsigned)time(0));
r = r * rand() / RAND_MAX; ir = (int)r;
UdmVarListReplaceInt(vars,str,ir);
}
}else
if(!strcasecmp(str,"HlBeg")){
UdmVarListReplaceStr(vars,"HlBeg",lt);
}else
if(!strcasecmp(str,"HlEnd")){
UdmVarListReplaceStr(vars,"HlEnd",lt);
}else
if(!strcasecmp(str,"DateFormat")){
UdmVarListReplaceStr(vars, "DateFormat", lt);
}else
if(!strcasecmp(str,"Limit")){
char * sc, * nm;
arg = udm_strtok_r(NULL, " \t\r\n", <);
if((sc=strchr(arg,':'))){
*sc='\0';sc++;
nm=(char*)malloc(strlen(arg)+8);
sprintf(nm,"Limit-%s",arg);
UdmVarListReplaceStr(vars,nm,sc);
UDM_FREE(nm);
}
}else
if(!strcasecmp(str,"CrossWords")){
UdmVarListReplaceStr(vars,"CrossWords",lt);
}else
if(!strcasecmp(str,"Alias")){
char * arg1;
arg = udm_strtok_r(NULL, " \t\r\n", <);
arg1 = udm_strtok_r(NULL, " \t\r\n", <);
if(arg1){
UDM_MATCH Alias;
Alias.pattern=arg;
Alias.arg=arg1;
Alias.match_type=UDM_MATCH_BEGIN;
Alias.case_sense=0;
UdmMatchListAdd(&Env->Aliases,&Alias,Env->errstr,sizeof(Env->errstr));
}
}else
if(!strcasecmp(str,"MaxWordLen")){
arg = udm_strtok_r(NULL, " \t\r\n", <);
if(arg)Env->WordParam.max_word_len=atoi(arg);
}else
if(!strcasecmp(str,"MinWordLen")){
arg = udm_strtok_r(NULL, " \t\r\n", <);
if(arg)Env->WordParam.min_word_len=atoi(arg);
}else
if(!strcasecmp(str,"ExcerptSize")){
arg = udm_strtok_r(NULL, " \t\r\n", <);
if (arg) UdmVarListReplaceInt(vars, tok, atoi(arg));
}else
if(!strcasecmp(str,"LocalCharset")){
arg = udm_strtok_r(NULL, " \t\r\n", <);
if (arg) {
UdmVarListReplaceStr(vars, tok, arg);
Env->lcs = UdmGetCharSet(arg);
}
}else
if(!strcasecmp(str,"BrowserCharset")){
arg = udm_strtok_r(NULL, " \t\r\n", <);
if (arg) {
UdmVarListReplaceStr(vars, tok, arg);
Env->bcs = UdmGetCharSet(arg);
}
}else
if(!strcasecmp(str,"Mime")){
char *mime_arg[4];
int argn = 0;
tok = udm_strtok_r(NULL, " \t\r\n", <);
while((tok)&&(argn<3)){
mime_arg[argn++]=tok;
tok = udm_strtok_r(NULL, " \t", <);
}
if(argn != 3){
sprintf(Env->errstr, "Error: too %s arguments for Mime command\n", (argn < 3 ? "few" : "many"));
return UDM_ERROR;
}else{
UDM_PARSER P;
P.from_mime = mime_arg[0];
P.to_mime = mime_arg[1];
P.cmd = mime_arg[2];
UdmParserAdd(&Env->Parsers, &P);
}
}else{
arg = udm_strtok_r(NULL, " \t\r\n", <);
UdmVarListReplaceStr(vars,tok,arg);
}
}
return UDM_OK;
}
int UdmTemplateLoad(UDM_ENV * Env,UDM_VARLIST * vars,const char * tname, UDM_VARLIST *tmpl){
FILE *file;
char str[1024];
char ostr[1024];
const char *dbaddr=NULL;
int variables=0;
char cursection[128]="";
char *cur=NULL;
char nameletter[]=
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789._";
if(!(file=fopen(tname,"r"))){
udm_snprintf(Env->errstr,sizeof(Env->errstr)-1,"Unable to open template '%s': %s",tname,strerror(errno));
return(1);
}
while(fgets(str,sizeof(str)-1,file)){
char *s;
str[sizeof(str)-1]='\0';
strcpy(ostr,str);
s=UdmTrim(str," \r\n");
if(!strcasecmp(s,"<!--variables")){
variables=1;
continue;
}
if(!strcmp(s,"-->") && variables){
variables=0;
continue;
}
if(variables){
int r;
if(!*s)continue;
if(*s=='#')continue;
if(UDM_OK!=(r=ParseVariable(Env,vars,s)))
return r;
continue;
}
if(!memcmp(s,"<!--",4)){
char *e;
for(e=s+4;(*e)&&(strchr(nameletter,*e)||(*e=='/'));e++);
if(!strcmp(e,"-->")){
*e='\0';
s+=4;
if(s[0]=='/'){
if(!strcasecmp(s+1,cursection) && cursection[0]){
UDM_VAR *I;
tmpl->Var=(UDM_VAR*)realloc(tmpl->Var,(tmpl->nvars+1)*sizeof(UDM_VAR));
I=&tmpl->Var[tmpl->nvars];
I->name = (char*)strdup(cursection);
I->val = (char*)strdup(cur?cur:"");
I->txt_val = (char*)strdup(cur?cur:"");
tmpl->nvars++;
cursection[0]='\0';
UDM_FREE(cur);
continue;
}
}else
if(s[1]){
strncpy(cursection,s,sizeof(cursection));
cursection[sizeof(cursection)-1]='\0';
continue;
}
}
}
if(!cursection[0])
continue;
if(!cur){
cur = (char*)strdup(ostr);
}else{
cur=(char*)realloc(cur,strlen(cur)+strlen(ostr)+1);
strcat(cur,ostr);
}
}
fclose(file);
UDM_FREE(cur);
if(Env->Spells.nspell) {
UdmSortDictionary(&Env->Spells);