messages.l
上传用户:seven77cht
上传日期:2007-01-04
资源大小:486k
文件大小:18k
- VAR $[a-z_0-9]+
- %x ASSIGNMENT_START
- %x ASSIGNMENT_WORD ASSIGNMENT_DOUBLE_QUOTES ASSIGNMENT_SINGLE_QUOTES
- %x ALTERNATE_TEST
- %x ALTERNATE_SKIP_FIRST ALTERNATE_USE_FIRST
- %x ALTERNATE_SKIP_SECOND ALTERNATE_USE_SECOND
- %{
- /***************************************
- $Header: /home/amb/wwwoffle/RCS/messages.l 1.28 2000/03/22 18:34:45 amb Exp $
- WWWOFFLE - World Wide Web Offline Explorer - Version 2.5e.
- Parse the HTML to create the messages and serve the local web-pages.
- ******************/ /******************
- Written by Andrew M. Bishop
- This file Copyright 1998,99,2000 Andrew M. Bishop
- It may be distributed under the GNU Public License, version 2, or
- any higher version. See section COPYING of the GNU Public license
- for conditions under which this file may be redistributed.
- ***************************************/
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #ifdef __STDC__
- #include <stdarg.h>
- #else
- #include <varargs.h>
- #endif
- #include <time.h>
- #include <sys/stat.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include "version.h"
- #include "wwwoffle.h"
- #include "errors.h"
- #include "config.h"
- #include "misc.h"
- extern int msg_yylex(void);
- #define msg_yywrap() 1
- #define YY_NO_UNPUT
- static void html_message_body(char *template, va_list ap);
- static void write_or_append_string(char *str);
- static void add_variable(char *var,char *val);
- static void delete_variables(void);
- static char *get_value(char *var);
- static void strip_trailing_whitespace(char *string);
- /*+ A known fixed empty string. +*/
- static char *empty="";
- /*+ The file descriptor that we are reading from. +*/
- static int msg_yyfd=-1;
- /*+ The file descriptor that we are writing to. +*/
- static int out_fd=-1;
- /*+ The string we are appending to. +*/
- static char *out_str=NULL;
- /*+ The list of variables. +*/
- static char **variables=NULL;
- /*+ The list of values. +*/
- static char **values=NULL;
- /*+ The number of variables. +*/
- static int nvariables=0;
- /*++++++++++++++++++++++++++++++++++++++
- Output a local page.
- int fd The file descriptor to write to.
- char *path The path of the page.
- Header *request_head The request that was made for this page.
- ++++++++++++++++++++++++++++++++++++++*/
- void LocalPage(int fd,char *path,Header *request_head)
- {
- struct stat buf;
- char *file;
- /* Don't allow paths backwards */
- if(strstr(path,"/../"))
- {
- PrintMessage(Warning,"Illegal path containing '/../' for the local page '%s'.",path);
- HTMLMessage(fd,404,"WWWOFFLE Page Not Found",NULL,"PageNotFound",
- "url",path,
- NULL);
- return;
- }
- file=(char*)malloc(strlen(path)+16);
- strcpy(file,"html");
- strcat(file,path);
- if(path[strlen(path)-1]=='/')
- strcat(file,"index.html");
- if(stat(file,&buf))
- {
- PrintMessage(Warning,"Cannot access the local page '%s' [%!s].",file);
- HTMLMessage(fd,404,"WWWOFFLE Page Not Found",NULL,"PageNotFound",
- "url",path,
- NULL);
- }
- else if(S_ISREG(buf.st_mode) && buf.st_mode&S_IROTH)
- {
- int htmlfd=open(file,O_RDONLY);
- if(htmlfd==-1)
- {
- PrintMessage(Warning,"Cannot open the local page '%s' [%!s].",file);
- HTMLMessage(fd,404,"WWWOFFLE Page Not Found",NULL,"PageNotFound",
- "url",path,
- NULL);
- }
- else
- {
- char *ims=NULL;
- time_t since=0;
- if((ims=GetHeader(request_head,"If-Modified-Since",NULL)))
- since=DateToTimeT(ims);
- if(since>=buf.st_mtime)
- HTMLMessageHead(fd,304,"WWWOFFLE Not Modified",
- NULL);
- else
- {
- char buffer[READ_BUFFER_SIZE];
- int n;
- HTMLMessageHead(fd,200,"WWWOFFLE Local OK",
- "Last-Modified",RFC822Date(buf.st_mtime,1),
- "Content-Type",WhatMIMEType(file),
- NULL);
- init_buffer(htmlfd);
- while((n=read_data(htmlfd,buffer,READ_BUFFER_SIZE))>0)
- write_data(fd,buffer,n);
- }
- close(htmlfd);
- }
- }
- else if(S_ISDIR(buf.st_mode))
- {
- char *localhost=GetLocalHost(1);
- char *dir=(char*)malloc(strlen(path)+strlen(localhost)+12);
- strcpy(dir,"http://");
- strcat(dir,localhost);
- strcat(dir,path);
- strcat(dir,"/");
- HTMLMessage(fd,301,"WWWOFFLE Local Dir Redirect",dir,"LocalDirRedirect",
- "dir",path,
- NULL);
- free(dir);
- free(localhost);
- }
- else
- {
- PrintMessage(Warning,"Not a regular file or wrong permissions for the local page '%s'.",file);
- HTMLMessage(fd,404,"WWWOFFLE Page Not Found",NULL,"PageNotFound",
- "url",path,
- NULL);
- }
- }
- /*++++++++++++++++++++++++++++++++++++++
- Create a simple message using the template in the html directory.
- char *HTMLMessage Returns a string instead of writing to a file if fd==-1.
- int fd The file descriptor to write it to.
- int status_val The numeric status value.
- char *status_str The status string.
- char *location A Location: HTTP header or NULL for none.
- char *template The name of the template for the message.
- ... A list of variable-value pairs to use in the parsing (NULL terminated).
- ++++++++++++++++++++++++++++++++++++++*/
- char *HTMLMessage(int fd,int status_val,char *status_str,char *location,char *template, ...)
- {
- va_list ap;
- if(location)
- HTMLMessageHead(fd,status_val,status_str,
- "Location",location,
- NULL);
- else
- HTMLMessageHead(fd,status_val,status_str,
- NULL);
- #ifdef __STDC__
- va_start(ap,template);
- #else
- va_start(ap);
- #endif
- html_message_body(template,ap);
- va_end(ap);
- return(out_str);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Create an html header using the specified fields.
- char *HTMLMessageHead Returns a string instead of writing to a file if fd==-1.
- int fd The file descriptor to write it to.
- int status_val The numeric status value.
- char *status_str The status string.
- ... A list of variable-value pairs to use in the header (NULL terminated).
- ++++++++++++++++++++++++++++++++++++++*/
- char *HTMLMessageHead(int fd,int status_val,char *status_str, ...)
- {
- char *headline;
- char *var,*val;
- va_list ap;
- int content_type=0;
- out_fd=fd;
- out_str=NULL;
- #ifdef __STDC__
- va_start(ap,status_str);
- #else
- va_start(ap);
- #endif
- /* The start of the header */
- headline=(char*)malloc(strlen(status_str)+32);
- sprintf(headline,"HTTP/1.0 %d %srn",status_val,status_str);
- write_or_append_string(headline);
- free(headline);
- write_or_append_string("Server: WWWOFFLE/" WWWOFFLE_VERSION "rn");
- write_or_append_string("Date: ");
- write_or_append_string(RFC822Date(time(NULL),1));
- write_or_append_string("rn");
- /* Start filling in the header. */
- while((var=va_arg(ap,char*)))
- {
- val=va_arg(ap,char*);
- if(!strcmp(var,"Content-Type"))
- content_type=1;
- if(val)
- {
- write_or_append_string(var);
- write_or_append_string(": ");
- write_or_append_string(val);
- write_or_append_string("rn");
- }
- }
- va_end(ap);
- /* The end of the header. */
- if(!content_type)
- write_or_append_string("Content-type: text/htmlrn");
- write_or_append_string("rn");
- return(out_str);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Create a HTML message body by passing the specified template through the micro-language processor.
- char *HTMLMessageBody Returns a string instead of writing to a file if fd==-1.
- int fd The file descriptor to write to.
- char *template The name of the template for the message.
- ... A list of variable-value pairs to use in the parsing (NULL terminated).
- ++++++++++++++++++++++++++++++++++++++*/
- char *HTMLMessageBody(int fd,char *template, ...)
- {
- va_list ap;
- out_fd=fd;
- out_str=NULL;
- #ifdef __STDC__
- va_start(ap,template);
- #else
- va_start(ap);
- #endif
- html_message_body(template,ap);
- va_end(ap);
- return(out_str);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Create a HTML message body by passing the specified template through the micro-language processor.
- int fd The file descriptor to write to.
- char *template The name of the template for the message.
- va_list ap A list of variable-value pairs to use in the parsing (NULL terminated).
- ++++++++++++++++++++++++++++++++++++++*/
- static void html_message_body(char *template,va_list ap)
- {
- char *localhost;
- char *file,*var,*val;
- static int first=1;
- /* Set up the variables. */
- localhost=GetLocalHost(1);
- add_variable("localhost",localhost);
- while((var=va_arg(ap,char*)))
- {
- val=va_arg(ap,char*);
- add_variable(var,val);
- }
- /* Open the template file. */
- file=(char*)malloc(sizeof("html/messages/")+strlen(template)+sizeof(".html")+1);
- strcpy(file,"html/messages/");
- strcat(file,template);
- strcat(file,".html");
- msg_yyfd=open(file,O_RDONLY);
- if(msg_yyfd==-1)
- PrintMessage(Fatal,"Cannot open the message template '%s' [%!s].",file);
- init_buffer(msg_yyfd);
- /* Parse the template and fill in the gaps. */
- if(!first)
- msg_yyrestart(NULL);
- msg_yylex();
- close(msg_yyfd);
- delete_variables();
- first=0;
- }
- /*++++++++++++++++++++++++++++++++++++++
- Write the string to the file descriptor out_fd or append to the string out_str.
- char *str The string to write or append.
- ++++++++++++++++++++++++++++++++++++++*/
- static void write_or_append_string(char *str)
- {
- if(out_fd==-1)
- {
- if(out_str)
- {
- out_str=(char*)realloc((void*)out_str,strlen(out_str)+strlen(str)+1);
- strcat(out_str,str);
- }
- else
- {
- out_str=(char*)malloc(256+strlen(str));
- strcpy(out_str,str);
- }
- }
- else
- write_string(out_fd,str);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Add a new variable.
- char *var The variable to add.
- char *val The value of the variable.
- ++++++++++++++++++++++++++++++++++++++*/
- static void add_variable(char *var,char *val)
- {
- int i;
- for(i=0;i<nvariables;i++)
- if(!strcmp(var,variables[i]))
- {
- if(values[i]!=empty)
- free(values[i]);
- if(val)
- {values[i]=(char*)malloc(strlen(val)+1); strcpy(values[i],val);}
- else
- values[i]=empty;
- return;
- }
- if(nvariables==0)
- {
- variables=(char**)malloc(8*sizeof(char*));
- values =(char**)malloc(8*sizeof(char*));
- }
- else if(nvariables%8==0)
- {
- variables=(char**)realloc((void*)variables,(nvariables+8)*sizeof(char*));
- values =(char**)realloc((void*)values ,(nvariables+8)*sizeof(char*));
- }
- variables[nvariables]=(char*)malloc(strlen(var)+1); strcpy(variables[nvariables],var);
- if(val)
- {values[nvariables]=(char*)malloc(strlen(val)+1); strcpy(values[nvariables],val);}
- else
- values[i]=empty;
- nvariables++;
- }
- /*++++++++++++++++++++++++++++++++++++++
- Delete all of the variables.
- ++++++++++++++++++++++++++++++++++++++*/
- static void delete_variables(void)
- {
- int i;
- for(i=0;i<nvariables;i++)
- {
- free(variables[i]);
- if(values[i]!=empty)
- free(values[i]);
- }
- if(nvariables)
- {
- free(variables);
- free(values);
- nvariables=0;
- variables=NULL;
- values=NULL;
- }
- }
- /*++++++++++++++++++++++++++++++++++++++
- Get the value of the named variable.
- char *get_value Return the value of the variable or an empty string.
- char *var The variable to get the value of.
- ++++++++++++++++++++++++++++++++++++++*/
- static char *get_value(char *var)
- {
- int i;
- for(i=0;i<nvariables;i++)
- if(!strcmp(var,variables[i]))
- return(values[i]);
- return("");
- }
- /*++++++++++++++++++++++++++++++++++++++
- Strip trailing white-space (this is done so that the lex is simpler, no variable trailing context).
- char *string The string to strip the spaces from.
- ++++++++++++++++++++++++++++++++++++++*/
- static void strip_trailing_whitespace(char *string)
- {
- char *p=string;
- while(*p && !isspace(*p))
- p++;
- *p=0;
- }
- /*+ A macro to read data that can be used by the lexer. +*/
- #define YY_INPUT(buf,result,max_size)
- if((result=read_data(msg_yyfd,buf,max_size))==-1)
- result=0;
- /*+ A macro to append a string to the end of the existing one. +*/
- #define APPEND_VAL(xxx)
- {
- if(val)
- {
- val=(char*)realloc((void*)val,strlen(val)+strlen(xxx)+1);
- strcat(val,xxx);
- }
- else
- {
- val=(char*)malloc(strlen(xxx)+1);
- strcpy(val,xxx);
- }
- }
- %}
- %%
- char *var=NULL;
- char *val=NULL;
- int previous=INITIAL;
- int any=0;
- [^$\n]+ { write_or_append_string(msg_yytext); any++; }
- n { write_or_append_string(msg_yytext); any=0; }
- \["'${}?] { write_or_append_string(msg_yytext+1); any++; }
- $ { write_or_append_string(msg_yytext); any++; }
- {VAR} { char *str=get_value(msg_yytext+1); write_or_append_string(str); }
- {VAR}[ t]*/= { strip_trailing_whitespace(msg_yytext);
- var=(char*)malloc(strlen(msg_yytext)); strcpy(var,msg_yytext+1); val=NULL;
- previous=INITIAL; val=NULL; BEGIN(ASSIGNMENT_START); }
- {VAR}[ t]*/? { strip_trailing_whitespace(msg_yytext);
- val=get_value(msg_yytext+1); while(input()!='{');
- if(*val) BEGIN(ALTERNATE_USE_FIRST); else BEGIN(ALTERNATE_SKIP_FIRST); }
- {VAR}[ t]*/?= { strip_trailing_whitespace(msg_yytext);
- val=get_value(msg_yytext+1); while(input()!='=');
- BEGIN(ALTERNATE_TEST); }
- <ASSIGNMENT_START>[^'" trn=}] { yyless(0); BEGIN(ASSIGNMENT_WORD); }
- <ASSIGNMENT_START>" { BEGIN(ASSIGNMENT_DOUBLE_QUOTES); }
- <ASSIGNMENT_START>' { BEGIN(ASSIGNMENT_SINGLE_QUOTES); }
- <ASSIGNMENT_START>[ t]+ { }
- <ASSIGNMENT_START>= { }
- <ASSIGNMENT_START>} { yyless(0); add_variable(var,NULL); free(var); BEGIN(previous); }
- <ASSIGNMENT_START>r*n { add_variable(var,NULL); free(var); BEGIN(previous); }
- <ASSIGNMENT_WORD>[^}$ trn] { APPEND_VAL(msg_yytext); }
- <ASSIGNMENT_WORD>$ { APPEND_VAL("$"); }
- <ASSIGNMENT_WORD>\} { APPEND_VAL("}"); }
- <ASSIGNMENT_WORD>{VAR} { APPEND_VAL(get_value(msg_yytext+1)); }
- <ASSIGNMENT_WORD>} { yyless(0); add_variable(var,val); if(val)free(val); free(var); BEGIN(previous); }
- <ASSIGNMENT_WORD>[ trn]+ { add_variable(var,val); if(val)free(val); free(var); BEGIN(previous); }
- <ASSIGNMENT_DOUBLE_QUOTES>[^\"$]+ { APPEND_VAL(msg_yytext); }
- <ASSIGNMENT_DOUBLE_QUOTES>\" { APPEND_VAL("""); }
- <ASSIGNMENT_DOUBLE_QUOTES>\ { APPEND_VAL("\"); }
- <ASSIGNMENT_DOUBLE_QUOTES>$ { APPEND_VAL("$"); }
- <ASSIGNMENT_DOUBLE_QUOTES>{VAR} { APPEND_VAL(get_value(msg_yytext+1)); }
- <ASSIGNMENT_DOUBLE_QUOTES>" { add_variable(var,val); if(val)free(val); free(var); BEGIN(previous); }
- <ASSIGNMENT_SINGLE_QUOTES>[^\'$]+ { APPEND_VAL(msg_yytext); }
- <ASSIGNMENT_SINGLE_QUOTES>\' { APPEND_VAL("'"); }
- <ASSIGNMENT_SINGLE_QUOTES>\ { APPEND_VAL("\"); }
- <ASSIGNMENT_SINGLE_QUOTES>$ { APPEND_VAL("$"); }
- <ASSIGNMENT_SINGLE_QUOTES>{VAR} { APPEND_VAL(get_value(msg_yytext+1)); }
- <ASSIGNMENT_SINGLE_QUOTES>' { add_variable(var,val); if(val)free(val); free(var); BEGIN(previous); }
- <ALTERNATE_TEST>[ t]+ { }
- <ALTERNATE_TEST>[^'" trn{]+ { while(input()!='{');
- if(!strcmp(val,msg_yytext)) BEGIN(ALTERNATE_USE_FIRST); else BEGIN(ALTERNATE_SKIP_FIRST); }
- <ALTERNATE_TEST>["'rn{] { BEGIN(INITIAL); }
- <ALTERNATE_USE_FIRST>[^\}$n]+ { write_or_append_string(msg_yytext); any++; }
- <ALTERNATE_USE_FIRST>n { if(any) write_or_append_string(msg_yytext); any=0; }
- <ALTERNATE_USE_FIRST>\} { write_or_append_string("}"); any++; }
- <ALTERNATE_USE_FIRST>\$ { write_or_append_string("$"); any++; }
- <ALTERNATE_USE_FIRST>\ { write_or_append_string(msg_yytext); any++; }
- <ALTERNATE_USE_FIRST>$ { write_or_append_string(msg_yytext); any++; }
- <ALTERNATE_USE_FIRST>{VAR} { char *str=get_value(msg_yytext+1); write_or_append_string(str); any++; }
- <ALTERNATE_USE_FIRST>{VAR}[ t]*/= { strip_trailing_whitespace(msg_yytext);
- var=(char*)malloc(strlen(msg_yytext)); strcpy(var,msg_yytext+1);
- previous=ALTERNATE_USE_FIRST; val=NULL; BEGIN(ASSIGNMENT_START); }
- <ALTERNATE_USE_FIRST>}[^{]*{ { BEGIN(ALTERNATE_SKIP_SECOND); }
- <ALTERNATE_SKIP_FIRST>[^\}]+ { }
- <ALTERNATE_SKIP_FIRST>\} { }
- <ALTERNATE_SKIP_FIRST>\ { }
- <ALTERNATE_SKIP_FIRST>}[^{]*{ { BEGIN(ALTERNATE_USE_SECOND); }
- <ALTERNATE_USE_SECOND>[^\}$n]+ { write_or_append_string(msg_yytext); any++; }
- <ALTERNATE_USE_SECOND>n { if(any) write_or_append_string(msg_yytext); any=0; }
- <ALTERNATE_USE_SECOND>\} { write_or_append_string("}"); any++; }
- <ALTERNATE_USE_SECOND>\$ { write_or_append_string("$"); any++; }
- <ALTERNATE_USE_SECOND>\ { write_or_append_string(msg_yytext); any++; }
- <ALTERNATE_USE_SECOND>$ { write_or_append_string(msg_yytext); any++; }
- <ALTERNATE_USE_SECOND>{VAR} { char *str=get_value(msg_yytext+1); write_or_append_string(str); any++; }
- <ALTERNATE_USE_SECOND>{VAR}[ t]*/= { strip_trailing_whitespace(msg_yytext);
- var=(char*)malloc(strlen(msg_yytext)); strcpy(var,msg_yytext+1);
- previous=ALTERNATE_USE_SECOND; val=NULL; BEGIN(ASSIGNMENT_START); }
- <ALTERNATE_USE_SECOND>}[ t]*r*n { BEGIN(INITIAL); if(any) write_or_append_string("n"); any=0; }
- <ALTERNATE_USE_SECOND>}[ t]+ { BEGIN(INITIAL); write_or_append_string(" "); }
- <ALTERNATE_USE_SECOND>} { BEGIN(INITIAL); }
- <ALTERNATE_SKIP_SECOND>[^\}]+ { }
- <ALTERNATE_SKIP_SECOND>\} { }
- <ALTERNATE_SKIP_SECOND>\ { }
- <ALTERNATE_SKIP_SECOND>}[ t]*r*n { BEGIN(INITIAL); if(any) write_or_append_string("n"); any=0; }
- <ALTERNATE_SKIP_SECOND>}[ t]+ { BEGIN(INITIAL); write_or_append_string(" "); }
- <ALTERNATE_SKIP_SECOND>} { BEGIN(INITIAL); }
- %%