home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dream 52
/
Amiga_Dream_52.iso
/
Linux
/
Magazine
/
wwwoffle-2.1.tar.gz
/
wwwoffle-2.1
/
html.l
< prev
next >
Wrap
Text File
|
1998-02-26
|
14KB
|
532 lines
W [ \t\r\n]
F [-a-z0-9$_.!*(),%;/?:@&=+~|]
%x HEADER
%x COMMENT
%x ANGLE_START ANGLE
%x IMAGE IMAGE_SRC
%x BODY BODY_BACK
%x ANCHOR ANCHOR_HREF
%x LINK LINK_HREF
%x FRAME FRAME_SRC
%x META META_REFRESH META_REFRESH_URL
%{
/***************************************
$Header: /home/amb/wwwoffle/RCS/html.l 2.13 1998/02/26 20:04:43 amb Exp $
WWWOFFLE - World Wide Web Offline Explorer - Version 2.1.
Parse the HTML and look for the images, links and end of body.
******************/ /******************
Written by Andrew M. Bishop
This file Copyright 1997 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>
#include <unistd.h>
#include "wwwoffle.h"
#include "misc.h"
extern int yylex(void);
#define yywrap() 1
/*+ The type of reference that has been found. +*/
typedef enum _RefType
{
Image, /*+ An inlined image. +*/
Link, /*+ A link to another page. +*/
Frame /*+ The contents of a frame. +*/
}
RefType;
static void free_list(RefType type);
static char **get_list(RefType type);
static void add_reference(char* name,RefType type);
static void canonicalise_references(RefType type);
/*+ The file descriptor that we are reading from. +*/
static int yyfd=-1;
/*+ If the file is parsed as an HTML file. +*/
static int is_html=0;
/*+ The list of images. +*/
static char **images=NULL;
/*+ The number of images. +*/
static int nimages=0;
/*+ The list of links. +*/
static char **links=NULL;
/*+ The number of links. +*/
static int nlinks=0;
/*+ The list of frames. +*/
static char **frames=NULL;
/*+ The number of frames. +*/
static int nframes=0;
/*+ The refresh content of a Meta tag. +*/
static char *meta_refresh=NULL;
/*+ Just before the end of body tag (or the end of html tag (or end of file)). +*/
static int body_or_html_end=0;
/*+ The URL that this is referenced from. +*/
static URL *refUrl=NULL;
/*++++++++++++++++++++++++++++++++++++++
Parse the HTML and look for references to image/links/frames.
int ParseHTML Returns 1 if it was parsed as an HTML file.
int fd The file descriptor of the file to parse.
URL *Url The reference URL to use.
int html For files without a header, force html selection.
++++++++++++++++++++++++++++++++++++++*/
int ParseHTML(int fd,URL *Url,int html)
{
refUrl=Url;
is_html=html;
body_or_html_end=0;
free_list(Image);
free_list(Link);
free_list(Frame);
meta_refresh=NULL;
yyfd=fd;
yyrestart(NULL);
yylex();
add_reference(NULL,Image);
add_reference(NULL,Link);
add_reference(NULL,Frame);
return(is_html);
}
/*++++++++++++++++++++++++++++++++++++++
Return the list of references.
char **ListImages Returns a null terminated list of images.
++++++++++++++++++++++++++++++++++++++*/
char **ListImages(void)
{
return(get_list(Image));
}
/*++++++++++++++++++++++++++++++++++++++
List the links found in the HTML file.
char **ListLinks Returns a null terminated list of links.
++++++++++++++++++++++++++++++++++++++*/
char **ListLinks(void)
{
return(get_list(Link));
}
/*++++++++++++++++++++++++++++++++++++++
List the frames found in the HTML file.
char **ListFrames Returns a null terminated list of frames.
++++++++++++++++++++++++++++++++++++++*/
char **ListFrames(void)
{
return(get_list(Frame));
}
/*++++++++++++++++++++++++++++++++++++++
Return the URL from the Meta Refresh tag if there is one.
char *MetaRefresh Returns the new URL or NULL if none.
++++++++++++++++++++++++++++++++++++++*/
char *MetaRefresh(void)
{
return(meta_refresh);
}
/*++++++++++++++++++++++++++++++++++++++
Return the position of the end of the html in the document.
int GetHTMLEnd Returns the position of the end of the html.
++++++++++++++++++++++++++++++++++++++*/
int GetHTMLEnd(void)
{
return(body_or_html_end);
}
/*++++++++++++++++++++++++++++++++++++++
Free up a list of references.
RefType type The type of list that is to be freed.
++++++++++++++++++++++++++++++++++++++*/
static void free_list(RefType type)
{
char ***list=NULL;
int *nlist=0;
switch(type)
{
case Image:
list=&images;
nlist=&nimages;
break;
case Link:
list=&links;
nlist=&nlinks;
break;
case Frame:
list=&frames;
nlist=&nframes;
break;
}
if(*list)
{
int i;
for(i=0;(*list)[i];i++)
free((*list)[i]);
free(*list);
}
*list=NULL;
*nlist=0;
}
/*++++++++++++++++++++++++++++++++++++++
Get a list of the references of the specified type.
char **get_list Returns the list of URLs.
RefType type The type of list that is required.
++++++++++++++++++++++++++++++++++++++*/
static char **get_list(RefType type)
{
char ***list=NULL;
switch(type)
{
case Image:
list=&images;
break;
case Link:
list=&links;
break;
case Frame:
list=&frames;
break;
}
if(*list)
canonicalise_references(type);
return(*list);
}
/*++++++++++++++++++++++++++++++++++++++
A function to add a name to the list of references.
char* name The name to add.
RefType type The type of reference.
++++++++++++++++++++++++++++++++++++++*/
static void add_reference(char* name,RefType type)
{
char ***list=NULL;
int *nlist=0;
if(name && !strncmp("mailto:",name,7))
return;
switch(type)
{
case Image:
list=&images;
nlist=&nimages;
break;
case Link:
list=&links;
nlist=&nlinks;
break;
case Frame:
list=&frames;
nlist=&nframes;
break;
}
if((*nlist)==0)
(*list)=(char**)malloc(16*sizeof(char*));
else if(((*nlist)%16)==0)
(*list)=(char**)realloc((*list),((*nlist)+16)*sizeof(char*));
if(name)
{
(*list)[(*nlist)]=(char*)malloc(strlen(name)+1);
strcpy((*list)[(*nlist)],name);
}
else
(*list)[(*nlist)]=NULL;
(*nlist)++;
}
/*++++++++++++++++++++++++++++++++++++++
Fix the list up with canonical URLs not the relative ones.
RefType type The type of reference.
++++++++++++++++++++++++++++++++++++++*/
static void canonicalise_references(RefType type)
{
char ***list=NULL;
int *nlist=0;
int i,j;
switch(type)
{
case Image:
list=&images;
nlist=&nimages;
break;
case Link:
list=&links;
nlist=&nlinks;
break;
case Frame:
list=&frames;
nlist=&nframes;
break;
}
for(i=0;(*list)[i];i++)
{
char **item=&(*list)[i];
char *name=*item;
char *colon=strchr(name,':');
char *slash=strchr(name,'/');
if(colon && slash && colon<slash)
;
else
{
if(*name=='/')
{
*item=(char*)malloc(strlen(refUrl->proto)+strlen(refUrl->host)+strlen(name)+8);
sprintf(*item,"%s://%s%s",refUrl->proto,refUrl->host,name);
}
else
{
int j;
char *path=(char*)malloc(strlen(refUrl->path)+strlen(name)+2);
char *match;
strcpy(path,refUrl->path);
for(j=strlen(path);j>0;j--)
if(path[j]=='/')
break;
path[j]=0;
strcat(path,"/");
strcat(path,name);
while((match=strstr(path,"/../")))
{
char *prev=match; match+=3;
while(prev>path && *--prev!='/');
while((*prev++=*match++));
}
while((match=strstr(path,"/./")))
{
char *prev=match; match+=2;
while((*prev++=*match++));
}
while((match=strstr(path,"//")))
{
char *prev=match; match++;
while((*prev++=*match++));
}
match=&path[strlen(path)-2];
if(match>=path && !strcmp(match,"/."))
*match=0;
match=&path[strlen(path)-3];
if(match>=path && !strcmp(match,"/.."))
if(match==path)
*match=0;
else
while(match>path && *--match!='/')
*match=0;
*item=(char*)malloc(strlen(refUrl->proto)+strlen(refUrl->host)+strlen(path)+8);
sprintf(*item,"%s://%s%s",refUrl->proto,refUrl->host,path);
free(path);
}
free(name);
}
}
/* remove the duplicates */
for(i=0;(*list)[i];i++)
{
for(j=i+1;(*list)[j];j++)
if(!strcmp((*list)[i],(*list)[j]))
break;
if((*list)[j])
{
free((*list)[j]);
do
{
(*list)[j]=(*list)[j+1];
}
while((*list)[j++]);
i--;
(*nlist)--;
}
}
}
#define YY_INPUT(buf,result,max_size) \
if((result=read_data(yyfd,buf,max_size))==-1) \
result=0;
%}
%%
int open_angle=0,position=0,html_end=0,body_end=0;
if(is_html)
BEGIN(INITIAL);
else
BEGIN(HEADER);
<HEADER>\r*\n { if(is_html) BEGIN(INITIAL); else return(EOF); }
<HEADER>"Content-Type:"[ \t]+"text/html"[ \t]*\r*\n { is_html=1; }
<HEADER>.+\r*\n { }
[^<]+ { position+=yyleng; }
"<!--" { position+=yyleng; BEGIN(COMMENT); }
"<"{W}* { position+=yyleng; BEGIN(ANGLE_START); open_angle=yyleng; }
<COMMENT>"-" { position+=yyleng; }
<COMMENT>">" { position+=yyleng; }
<COMMENT>"-->" { position+=yyleng; BEGIN(INITIAL); }
<COMMENT>[^->]+ { position+=yyleng; }
<ANGLE_START>"img"{W} { position+=yyleng; BEGIN(IMAGE); }
<ANGLE_START>"body"{W} { position+=yyleng; BEGIN(BODY); }
<ANGLE_START>"a"{W} { position+=yyleng; BEGIN(ANCHOR); }
<ANGLE_START>"link"{W} { position+=yyleng; BEGIN(LINK); }
<ANGLE_START>"frame"{W} { position+=yyleng; BEGIN(FRAME); }
<ANGLE_START>"meta"{W} { position+=yyleng; BEGIN(META); }
<ANGLE_START>"/body" { position+=yyleng; BEGIN(ANGLE); body_end=position-yyleng-open_angle; }
<ANGLE_START>"/html" { position+=yyleng; BEGIN(ANGLE); html_end=position-yyleng-open_angle; }
<ANGLE_START>">" { position+=yyleng; BEGIN(INITIAL); }
<ANGLE_START>.|\n { position+=yyleng; BEGIN(ANGLE); }
<ANGLE>">" { position+=yyleng; BEGIN(INITIAL); }
<ANGLE>[^>]+ { position+=yyleng; }
<IMAGE>">" { position+=yyleng; BEGIN(INITIAL); }
<IMAGE>"src"{W}*"="{W}*["']* { position+=yyleng; BEGIN(IMAGE_SRC); }
<IMAGE>.|\n { position+=yyleng; }
<IMAGE_SRC>{F}+ { position+=yyleng; BEGIN(IMAGE); add_reference(yytext,Image); }
<IMAGE_SRC>.|\n { position+=yyleng; BEGIN(IMAGE); }
<BODY>">" { position+=yyleng; BEGIN(INITIAL); }
<BODY>"background"{W}*"="{W}*["']* { position+=yyleng; BEGIN(BODY_BACK); }
<BODY>.|\n { position+=yyleng; }
<BODY_BACK>{F}+ { position+=yyleng; BEGIN(BODY); add_reference(yytext,Image); }
<BODY_BACK>.|\n { position+=yyleng; BEGIN(BODY); }
<ANCHOR>">" { position+=yyleng; BEGIN(INITIAL); }
<ANCHOR>"href"{W}*"="{W}*["']* { position+=yyleng; BEGIN(ANCHOR_HREF); }
<ANCHOR>.|\n { position+=yyleng; }
<ANCHOR_HREF>{F}+ { position+=yyleng; BEGIN(ANCHOR); add_reference(yytext,Link); }
<ANCHOR_HREF>.|\n { position+=yyleng; BEGIN(ANCHOR); }
<LINK>">" { position+=yyleng; BEGIN(INITIAL); }
<LINK>"href"{W}*"="{W}*["']* { position+=yyleng; BEGIN(LINK_HREF); }
<LINK>.|\n { position+=yyleng; }
<LINK_HREF>{F}+ { position+=yyleng; BEGIN(LINK); add_reference(yytext,Link); }
<LINK_HREF>.|\n { position+=yyleng; BEGIN(LINK); }
<FRAME>">" { position+=yyleng; BEGIN(INITIAL); }
<FRAME>"src"{W}*"="{W}*["']* { position+=yyleng; BEGIN(FRAME_SRC); }
<FRAME>.|\n { position+=yyleng; }
<FRAME_SRC>{F}+ { position+=yyleng; BEGIN(FRAME); add_reference(yytext,Frame); }
<FRAME_SRC>.|\n { position+=yyleng; BEGIN(FRAME); }
<META>{W}*"HTTP-EQUIV=\"Refresh\""{W}* { position+=yyleng; BEGIN(META_REFRESH); }
<META>.|\n { position+=yyleng; BEGIN(ANCHOR); }
<META_REFRESH>"URL=" { position+=yyleng; BEGIN(META_REFRESH_URL); }
<META_REFRESH>[^>] { position+=yyleng; }
<META_REFRESH>">" { position+=yyleng; BEGIN(INITIAL); }
<META_REFRESH_URL>{F}+ { position+=yyleng; BEGIN(META_REFRESH);
meta_refresh=(char*)malloc(strlen(yytext)+1); strcpy(meta_refresh,yytext); }
<META_REFRESH_URL>.|\n { position+=yyleng; BEGIN(META_REFRESH); }
<<EOF>> { if(body_end && html_end && (html_end-body_end)<16 && (position-html_end)<16)
body_or_html_end=body_end;
else if(body_end && (position-body_end)<16)
body_or_html_end=body_end;
else if(html_end && (position-html_end)<16)
body_or_html_end=html_end;
else
body_or_html_end=position;
return(EOF); }
%%