document.c
上传用户:seven77cht
上传日期:2007-01-04
资源大小:486k
文件大小:7k
源码类别:

浏览器

开发平台:

Unix_Linux

  1. /***************************************
  2.   $Header: /home/amb/wwwoffle/RCS/document.c 1.12 1999/08/29 10:01:46 amb Exp $
  3.   WWWOFFLE - World Wide Web Offline Explorer - Version 2.5.
  4.   Document parsing functions.
  5.   ******************/ /******************
  6.   Written by Andrew M. Bishop
  7.   This file Copyright 1998,99 Andrew M. Bishop
  8.   It may be distributed under the GNU Public License, version 2, or
  9.   any higher version.  See section COPYING of the GNU Public license
  10.   for conditions under which this file may be redistributed.
  11.   ***************************************/
  12. #include <string.h>
  13. #include <stdlib.h>
  14. #include <ctype.h>
  15. #include "wwwoffle.h"
  16. #include "document.h"
  17. #include "errors.h"
  18. #include "proto.h"
  19. #include "misc.h"
  20. #include "config.h"
  21. /*+ The list of references. +*/
  22. static char **references[NRefTypes];
  23. /*+ The number of references. +*/
  24. static int nreferences[NRefTypes];
  25. /*+ The base URL from which references are related. +*/
  26. static URL *baseUrl;
  27. static DocType GetDocumentType(char *mimetype);
  28. static char *GetMIMEType(int fd, URL *Url);
  29. /*++++++++++++++++++++++++++++++++++++++
  30.   Parse a document.
  31.   DocType ParseDocument Return 1 if there was anything that could be parsed.
  32.   int fd The file descriptor to read the document from.
  33.   URL *Url The URL of the document.
  34.   ++++++++++++++++++++++++++++++++++++++*/
  35. DocType ParseDocument(int fd,URL *Url)
  36. {
  37.  char *mimetype;
  38.  DocType doctype=DocUnknown;
  39.  baseUrl=Url;
  40.  if((mimetype = GetMIMEType(fd,Url)) != NULL)
  41.     doctype = GetDocumentType(mimetype);
  42.  /* Check the file extension if we don't yet know the DocType. */
  43.  if(doctype==DocUnknown)
  44.    {
  45.     /* Get MIME-Type from extension. */
  46.     mimetype = WhatMIMEType(Url->path);
  47.     doctype =  GetDocumentType(mimetype);
  48.    }
  49.  /* Parse the document if we do know the DocType. */
  50.  if(doctype!=DocUnknown)
  51.    {
  52.     PrintMessage(Debug,"Parsing document of MIME Type '%s'.",mimetype);
  53.     /* Free previous references. */
  54.     ResetReferences();
  55.     if(doctype==DocHTML)
  56.        ParseHTML(fd,Url);
  57.     else if(doctype==DocJavaClass)
  58.        InspectJavaClass(fd,Url);
  59.     else if(doctype==DocXML)
  60.        ParseXML(fd,Url);
  61.     else if(doctype==DocVRML)
  62.        ParseVRML(fd,Url);
  63.     /* Put a trailing NULL on the references. */
  64.  
  65.     FinishReferences();
  66.    }
  67.  return(doctype);
  68. }
  69. static struct {
  70.   char *mimetype;
  71.   DocType doctype;
  72. } docTypeList[] = {
  73. {"text/html",DocHTML},
  74. {"application/java",DocJavaClass},
  75. {"text/xml",DocXML},
  76. {"application/xml",DocXML},
  77. {"x-world/x-vrml",DocVRML},
  78. {"model/vrml",DocVRML},
  79. {"",},
  80. };
  81. /*++++++++++++++++++++++++++++++++++++++
  82.   Decide the current document type based on the mime type.
  83.   DocType GetDocumentType Returns the document type.
  84.   char *mimetype The mime type to be tested.
  85.   ++++++++++++++++++++++++++++++++++++++*/
  86. DocType GetDocumentType(char *mimetype)
  87. {
  88.  int i;
  89.  for(i = 0; i < sizeof(docTypeList)/sizeof(docTypeList[0]); i++)
  90.     if(!strcmp(mimetype,docTypeList[i].mimetype))
  91.        return(docTypeList[i].doctype);
  92.  return(DocUnknown);
  93. }
  94. /*++++++++++++++++++++++++++++++++++++++
  95.   Decide the mime type of a document based on the header.
  96.   char *GetMIMEType Returns the mime type.
  97.   int fd The file descriptor to read the header from.
  98.   URL *Url The URL we are looking at.
  99.   ++++++++++++++++++++++++++++++++++++++*/
  100. char *GetMIMEType(int fd, URL *Url)
  101. {
  102.  Header *doc_header;
  103.  char *contenttype,*mimetype=NULL;
  104.  /* Get the header and examine it. */
  105.  ParseReply(fd,Url,&doc_header);
  106.  contenttype=GetHeader(doc_header,"Content-Type",NULL);
  107.  if(contenttype)
  108.    {
  109.     char *p;
  110.     mimetype=(char*)malloc(strlen(contenttype)+1);
  111.     strcpy(mimetype,contenttype);
  112.     p=mimetype;
  113.     while(*p && !isspace(*p) && *p!=';')
  114.        p++;
  115.     *p=0;
  116.    }
  117.  FreeHeader(doc_header);
  118.  
  119.  return(mimetype);
  120. }
  121.  
  122. /*++++++++++++++++++++++++++++++++++++++
  123.   A function to add a reference to a list.
  124.   char* name The name to add.
  125.   RefType type The type of reference.
  126.   ++++++++++++++++++++++++++++++++++++++*/
  127. void AddReference(char* name,RefType type)
  128. {
  129.  /* Check for badly formatted URLs */
  130.  if(name)
  131.    {
  132.     char *p=name+strlen(name)-1;
  133.     int onlychars=1;
  134.     while(*name && isspace(*name))
  135.        name++;
  136.     while(p>name && isspace(*p))
  137.        *p--=0;
  138.     for(p=name;*p;p++)
  139.        if(isspace(*p))
  140.           return;
  141.        else if(*p=='#')
  142.          {
  143.           *p=0;
  144.           break;
  145.          }
  146.        else if(*p==':' && onlychars)
  147.          {
  148.           int i;
  149.           for(i=0;i<NProtocols;i++)
  150.              if(!strncmp(Protocols[i].name,name,p-name))
  151.                 break;
  152.           if(i && i==NProtocols)
  153.              return;
  154.          }
  155.        else if(onlychars && !isalpha(*p))
  156.           onlychars=0;
  157.     if(!*name)
  158.        return;
  159.    }
  160.  /* Add it to the list. */
  161.  if(name || references[type])
  162.    {
  163.     if(nreferences[type]==0)
  164.        references[type]=(char**)malloc(16*sizeof(char*));
  165.     else if((nreferences[type]%16)==0)
  166.        references[type]=(char**)realloc(references[type],(nreferences[type]+16)*sizeof(char*));
  167.     if(name)
  168.       {
  169.        references[type][nreferences[type]]=(char*)malloc(strlen(name)+1);
  170.        strcpy(references[type][nreferences[type]],name);
  171.       }
  172.     else
  173.        references[type][nreferences[type]]=NULL;
  174.     nreferences[type]++;
  175.    }
  176. }
  177. /*++++++++++++++++++++++++++++++++++++++
  178.   Finish the list of references and set the base URL if changed.
  179.   ++++++++++++++++++++++++++++++++++++++*/
  180. void FinishReferences(void)
  181. {
  182.  RefType i;
  183.  for(i=0;i<NRefTypes;i++)
  184.     AddReference(NULL,i);
  185. }
  186. /*++++++++++++++++++++++++++++++++++++++
  187.   Set another base URL.
  188.   URL *Url The new base URL.
  189.   ++++++++++++++++++++++++++++++++++++++*/
  190. void SetBaseURL(URL *Url)
  191. {
  192.  if(Url)
  193.     baseUrl=Url;
  194. }
  195. /*++++++++++++++++++++++++++++++++++++++
  196.   Get a list of the references of the specified type.
  197.   char **GetReferences Returns the list of URLs.
  198.   RefType type The type of list that is required.
  199.   ++++++++++++++++++++++++++++++++++++++*/
  200. char **GetReferences(RefType type)
  201. {
  202.  int i,j;
  203.  if(!references[type])
  204.     return(NULL);
  205.  /* canonicalise the links */
  206.  for(i=0;references[type][i];i++)
  207.    {
  208.     char *new=LinkURL(baseUrl,references[type][i]);
  209.     if(new!=references[type][i])
  210.       {
  211.        free(references[type][i]);
  212.        references[type][i]=new;
  213.       }
  214.    }
  215.  /* remove the duplicates */
  216.  for(i=0;references[type][i];i++)
  217.    {
  218.     for(j=i+1;references[type][j];j++)
  219.        if(!strcmp(references[type][i],references[type][j]))
  220.           break;
  221.     if(references[type][j])
  222.       {
  223.        free(references[type][j]);
  224.        do
  225.          {
  226.           references[type][j]=references[type][j+1];
  227.          }
  228.        while(references[type][j++]);
  229.        i--;
  230.        nreferences[type]--;
  231.       }
  232.    }
  233.  return(references[type]);
  234. }
  235. /*++++++++++++++++++++++++++++++++++++++
  236.   Reset all of the reference lists.
  237.   ++++++++++++++++++++++++++++++++++++++*/
  238. void ResetReferences(void)
  239. {
  240.  static int first=1;
  241.  RefType i;
  242.  for(i=0;i<NRefTypes;i++)
  243.    {
  244.     if(!first && references[i])
  245.       {
  246.        int j;
  247.        for(j=0;references[i][j];j++)
  248.           free(references[i][j]);
  249.        free(references[i]);
  250.       }
  251.     references[i]=NULL;
  252.     nreferences[i]=0;
  253.    }
  254.  first=0;
  255. }