home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Magazine / wwwoffle-2.1.tar.gz / wwwoffle-2.1 / index.c < prev    next >
C/C++ Source or Header  |  1998-02-25  |  41KB  |  1,393 lines

  1. /***************************************
  2.   $Header: /home/amb/wwwoffle/RCS/index.c 2.28 1998/02/25 19:27:40 amb Exp $
  3.  
  4.   WWWOFFLE - World Wide Web Offline Explorer - Version 2.1.
  5.   Generate an index of the web pages that are cached in the system.
  6.   ******************/ /******************
  7.   Written by Andrew M. Bishop
  8.  
  9.   This file Copyright 1997,98 Andrew M. Bishop
  10.   It may be distributed under the GNU Public License, version 2, or
  11.   any higher version.  See section COPYING of the GNU Public license
  12.   for conditions under which this file may be redistributed.
  13.   ***************************************/
  14.  
  15.  
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19.  
  20. #include <time.h>
  21. #include <utime.h>
  22. #include <sys/types.h>
  23. #include <sys/stat.h>
  24. #include <dirent.h>
  25. #include <fcntl.h>
  26. #include <unistd.h>
  27.  
  28. #include "wwwoffle.h"
  29. #include "misc.h"
  30. #include "proto.h"
  31. #include "config.h"
  32. #include "errors.h"
  33.  
  34.  
  35. /*+ A type to contain the information required to sort the files. +*/
  36. typedef struct _FileIndex
  37. {
  38.  char *name;                    /*+ The URL of the file. +*/
  39.  char *type;                    /*+ The type (file extension) of the URL. +*/
  40.  long time;                     /*+ The time of the file (access or modification as appropriate). +*/
  41. }
  42. FileIndex;
  43.  
  44. /*+ The method of sorting used. +*/
  45. static char *sorttype[][2]={{"none"  ,"Unsorted"},
  46.                             {"mtime" ,"Modification Time"},
  47.                             {"atime" ,"Access Time"},
  48.                             {"dated" ,"Date Changed"},
  49.                             {"alpha" ,"Alphabetical"},
  50.                             {"type"  ,"File Type"},
  51.                             {"none"  ,"Unsorted"}};
  52.  
  53. /*+ An enumerated type for the sort modes. +*/
  54. typedef enum _SortMode
  55. {
  56.  None,                          /*+ No sorting, natural order. +*/
  57.  MTime,                         /*+ Sort by modification time +*/
  58.  ATime,                         /*+ Sort by access time. +*/
  59.  Dated,                         /*+ Sort by modification time with separators. +*/
  60.  Alpha,                         /*+ Sort Alphabetically. +*/
  61.  Type,                          /*+ Sort by type (file extension). +*/
  62.  NSortModes                     /*+ The number of sort modes. +*/
  63. }
  64. SortMode;
  65.  
  66.  
  67. /*+ The list of files. +*/
  68. static FileIndex **files=NULL;
  69. static int nfiles=0;
  70.  
  71. /*+ The earliest time that files can appear in the dated list. +*/
  72. static time_t earliest=0;
  73.  
  74. /*+ The current time. +*/
  75. static time_t now;
  76.  
  77. static void IndexRoot(int fd);
  78. static void IndexProtocol(int fd,char *proto,SortMode mode);
  79. static void IndexHost(int fd,char *proto,char *host,SortMode mode);
  80. static void IndexOutgoing(int fd,SortMode mode);
  81. static void IndexMonitor(int fd,SortMode mode);
  82. static void IndexLastTime(int fd,SortMode mode);
  83. static void IndexLatest(int fd,SortMode mode);
  84.  
  85. static void CorrectIndex(int fd,char *path,char *args);
  86. static void IllegalIndex(int fd,char *path,char *args);
  87.  
  88. static void add_dir(char *name,SortMode mode,char *link);
  89. static void add_file(char *name,SortMode mode);
  90.  
  91. static void dated_separator(int fd,int file,int *lastdays,int *lasthours);
  92.  
  93. static int sort_alpha(FileIndex **a,FileIndex **b);
  94. static int sort_type(FileIndex **a,FileIndex **b);
  95. static int sort_time(FileIndex **a,FileIndex **b);
  96.  
  97.  
  98. /*++++++++++++++++++++++++++++++++++++++
  99.   Generate an index of the pages that are in the cache.
  100.  
  101.   int fd The file descriptor to write the output to.
  102.  
  103.   char *url The URL that specifies the path to generate the index for.
  104.   ++++++++++++++++++++++++++++++++++++++*/
  105.  
  106. void IndexPage(int fd,char *path,char *args)
  107. {
  108.  char *head=
  109.  "HTTP/1.0 200 WWWOFFLE Cache Index\r\n"
  110.  "Content-type: text/html\r\n"
  111.  "\r\n"
  112.  "<HTML>\n"
  113.  "<HEAD>\n"
  114.  "<TITLE>WWWOFFLE Index - %s</TITLE>\n"
  115.  "</HEAD>\n"
  116.  "<BODY>\n"
  117.  "<H1 align=center>WWWOFFLE Cache Index</H1>\n";
  118.  char *tail=
  119.  "</BODY>\n"
  120.  "</HTML>\n";
  121.  char *newpath=(char*)malloc(strlen(path)+1);
  122.  char *proto=newpath,*host=NULL;
  123.  SortMode sort=NSortModes;
  124.  Protocol *protocol=NULL;
  125.  int outgoing=0,monitor=0,lasttime=0,latest=0,main=0;
  126.  int i;
  127.  
  128.  now=time(NULL);
  129.  
  130.  strcpy(newpath,path);
  131.  
  132.  if(*newpath && newpath[strlen(newpath)-1]=='/')
  133.     newpath[strlen(newpath)-1]=0;
  134.  
  135.  for(i=0;newpath[i];i++)
  136.     if(newpath[i]=='/')
  137.       {
  138.        newpath[i]=0;
  139.        host=newpath+i+1;
  140.        break;
  141.       }
  142.  
  143.  for(i=0;i<NProtocols;i++)
  144.     if(!strcmp(proto,Protocols[i].name))
  145.        protocol=&Protocols[i];
  146.  
  147.  outgoing=!strcmp(proto,"outgoing");
  148.  monitor =!strcmp(proto,"monitor");
  149.  lasttime=!strcmp(proto,"lasttime");
  150.  latest  =!strcmp(proto,"latest");
  151.  main=(!protocol && !outgoing && !monitor && !lasttime && !latest);
  152.  
  153.  if(args)
  154.     for(sort=0;sort<NSortModes;sort++)
  155.        if(!strcmp(args,sorttype[sort][0]))
  156.           break;
  157.  
  158.  if(host && (strchr(host,'/') || !strcmp(host,"..") || !strcmp(host,".")))
  159.     IllegalIndex(fd,path,args);
  160.  else if(main && *newpath)
  161.     IllegalIndex(fd,path,args);
  162.  else if((outgoing || monitor || lasttime || latest) && host)
  163.     IllegalIndex(fd,path,args);
  164.  else if(sort==NSortModes && (outgoing || monitor || lasttime || protocol))
  165.     CorrectIndex(fd,path,args);
  166.  else
  167.    {
  168.     SortMode mode;
  169.  
  170.     if(main)
  171.        write_formatted(fd,head,"Main Index");
  172.     else if(outgoing)
  173.        write_formatted(fd,head,"Outgoing Requests");
  174.     else if(monitor)
  175.        write_formatted(fd,head,"Monitored Pages");
  176.     else if(lasttime)
  177.        write_formatted(fd,head,"Last Time Online Pages");
  178.     else if(latest)
  179.        write_formatted(fd,head,"Latest Pages");
  180.     else if(protocol && !host)
  181.        write_formatted(fd,head,proto);
  182.     else if(protocol && host)
  183.       {
  184.        char *protohost=(char*)malloc(strlen(proto)+strlen(host)+4);
  185.        sprintf(protohost,"%s://%s",proto,host);
  186.        write_formatted(fd,head,protohost);
  187.        free(protohost);
  188.       }
  189.  
  190.     write_string(fd,"<p align=center>\n");
  191.  
  192.     if(main)
  193.        write_string(fd,"[Main Index]\n");
  194.     else
  195.        write_formatted(fd,"[<a href=\"/index/?%s\">Main Index</a>]\n",sorttype[sort][0]);
  196.  
  197.     write_string(fd,"<br>\n");
  198.  
  199.     if(outgoing)
  200.        write_string(fd,"[Outgoing]\n");
  201.     else
  202.        write_formatted(fd,"[<a href=\"/index/outgoing/?%s\">Outgoing</a>]\n",sorttype[sort][0]);
  203.  
  204.     if(monitor)
  205.        write_string(fd,"[Monitored]\n");
  206.     else
  207.        write_formatted(fd,"[<a href=\"/index/monitor/?%s\">Monitored</a>]\n",sorttype[sort][0]);
  208.  
  209.     if(lasttime)
  210.        write_string(fd,"[Last Time]\n");
  211.     else
  212.        write_formatted(fd,"[<a href=\"/index/lasttime/?%s\">Last Time</a>]\n",sorttype[sort][0]);
  213.  
  214.     if(latest)
  215.        write_string(fd,"[Latest]\n");
  216.     else
  217.        write_formatted(fd,"[<a href=\"/index/latest/?%s\">Latest</a>]\n",sorttype[Dated][0]);
  218.  
  219.     for(i=0;i<NProtocols;i++)
  220.        write_formatted(fd,"[<a href=\"/index/%s/?%s\">%s</a>]\n",Protocols[i].name,sorttype[sort][0],Protocols[i].name);
  221.  
  222.     write_string(fd,"<br>\n");
  223.  
  224.     for(mode=0;mode<NSortModes;mode++)
  225.        if(mode==sort || main)
  226.           write_formatted(fd,"[%s]\n",sorttype[mode][1]);
  227.        else
  228.           write_formatted(fd,"[<a href=\"/index/%s?%s\">%s</a>]\n",path,sorttype[mode][0],sorttype[mode][1]);
  229.  
  230.     write_string(fd,"</p>\n");
  231.     write_string(fd,"<hr>\n");
  232.  
  233.     if(outgoing)
  234.        IndexOutgoing(fd,sort);
  235.     else if(monitor)
  236.        IndexMonitor(fd,sort);
  237.     else if(lasttime)
  238.        IndexLastTime(fd,sort);
  239.     else if(latest)
  240.        IndexLatest(fd,sort);
  241.     else if(protocol && !host)
  242.        IndexProtocol(fd,proto,sort);
  243.     else if(protocol && host)
  244.        IndexHost(fd,proto,host,sort);
  245.     else
  246.        IndexRoot(fd);
  247.  
  248.     write_string(fd,"<hr>\n");
  249.     write_string(fd,"<p align=center>\n");
  250.  
  251.     if(outgoing || monitor || lasttime || latest || (protocol && !host))
  252.        write_formatted(fd,"[<a href=\"/index/?%s\">Back to the Main Index</a>]\n",sorttype[mode][0]);
  253.     else if(protocol && host)
  254.        write_formatted(fd,"[<a href=\"/index/%s/?%s\">Back to the Hosts Index</a>]\n",proto,sorttype[mode][0]);
  255.     else
  256.        write_string(fd,"[<a href=\"/\">Back to the Welcome Page</a>]\n");
  257.  
  258.     write_string(fd,"</p>\n");
  259.  
  260.     write_string(fd,tail);
  261.    }
  262.  
  263.  free(newpath);
  264. }
  265.  
  266.  
  267. /*++++++++++++++++++++++++++++++++++++++
  268.   Index the root of the cache.
  269.  
  270.   int fd The file descriptor to write to.
  271.   ++++++++++++++++++++++++++++++++++++++*/
  272.  
  273. static void IndexRoot(int fd)
  274. {
  275.  char *page=
  276.  "<h2>Main Index</h2>\n"
  277.  "This is the main index page for all of the files in the wwwoffle cache."
  278.  "<h3>New Format Index</h3>\n"
  279.  "The index of the files in the cache has changed in version 2.0 of wwwoffle compared to earlier versions."
  280.  "This is for a number of reasons:\n"
  281.  "<ul>\n"
  282.  "<li>So that the new protocol types can be introduced.\n"
  283.  "<li>To present a consistent interface for all of the index pages (the new buttons bars).\n"
  284.  "<li>To improve the formatting and layout.\n"
  285.  "</ul>\n"
  286.  "It is hoped that this new format is easier to use and makes more sense than the previous version.\n"
  287.  "<h3>First Level Index</h3>\n"
  288.  "This page is the first level index, it is available on the first of the three button bars.\n"
  289.  "<h3>Second Level Indexes</h3>\n"
  290.  "Below the main index there are several second level indexes as shown on the second of the button bars.\n"
  291.  "<br>These indexes are:\n"
  292.  "<dl compact>\n"
  293.  "<dt>Outgoing\n"
  294.  "<dd>The index of the requests that have been made while offline and are waiting to be fetched.\n"
  295.  "<dt>Monitored\n"
  296.  "<dd>The index of the pages that are automatically monitored at fixed intervals.\n"
  297.  "<dt>Last Time\n"
  298.  "<dd>All of the pages from all protocols that were fetched the last time that wwwoffle was online.\n"
  299.  "<dt>Latest\n"
  300.  "<dd>All of the latest pages (from the last %d days) from all protocols.\n"
  301.  "<dt>Protocols (http,ftp etc.)\n"
  302.  "<dd>Each of the protocols that wwwoffle supports has an index showing the hosts that have pages stored.\n"
  303.  "</dl>\n"
  304.  "<h3>Third Level Indexes</h3>\n"
  305.  "Below the protocol indexes there are third level indexes (not shown on the button bars).\n"
  306.  "<br>These indexes are the list of pages from a particular host using a particular protocol.\n"
  307.  "<h3>Sorting</h3>\n"
  308.  "All of the second and third level indexes can be sorted in several ways using the third button bar.\n"
  309.  "<br>These methods are:\n"
  310.  "<dl compact>\n"
  311.  "<dt>Unsorted\n"
  312.  "<dd>No sorting applied, this uses the default directory order.\n"
  313.  "<dt>Modification Time\n"
  314.  "<dd>The time that the page was last modified (most recent first), this could be when it was fetched or refreshed.\n"
  315.  "<dt>Access Time\n"
  316.  "<dd>The time that the page was last accessed (most recent first), this is the time that the page was last viewed (if later than modification time).\n"
  317.  "<dt>Date Changed\n"
  318.  "<dd>The same as for \"Modification Time\", but with separators for every day and a blank line for gaps of an hour or more.\n"
  319.  "<dt>Alphabetical\n"
  320.  "<dd>The pages are sorted into alphabetical order.\n"
  321.  "<dt>File Type\n"
  322.  "<dd>The pages are sorted alphabetically according to the file extension.\n"
  323.  "</dl>\n";
  324.  
  325.  write_formatted(fd,page,IndexLatestDays);
  326. }
  327.  
  328.  
  329. /*++++++++++++++++++++++++++++++++++++++
  330.   Index the hosts for one protocol in the cache.
  331.  
  332.   int fd The file descriptor to write to.
  333.  
  334.   char *proto The protocol to index.
  335.  
  336.   SortMode mode The sort mode to use.
  337.   ++++++++++++++++++++++++++++++++++++++*/
  338.  
  339. static void IndexProtocol(int fd,char *proto,SortMode mode)
  340. {
  341.  DIR *dir;
  342.  struct dirent* ent;
  343.  char ***mirrored;
  344.  int i;
  345.  
  346.  /* Open the spool directory. */
  347.  
  348.  if(chdir(proto))
  349.    {PrintMessage(Warning,"Cannot change to directory '%s' [%!s]; not indexed.",proto);
  350.    write_formatted(fd,"No %s directory.",proto);return;}
  351.  
  352.  dir=opendir(".");
  353.  if(!dir)
  354.    {PrintMessage(Warning,"Cannot open spool directory '%s' [%!s]; index failed.",proto);chdir("..");
  355.    write_formatted(fd,"Unable to open directory %s.",proto);return;}
  356.  
  357.  ent=readdir(dir);  /* skip .  */
  358.  if(!ent)
  359.    {PrintMessage(Warning,"Cannot read spool directory '%s' [%!s]; index failed.",proto);closedir(dir);chdir("..");
  360.    write_formatted(fd,"Unable to read directory %s.",proto);return;}
  361.  ent=readdir(dir);  /* skip .. */
  362.  
  363.  /* Get all of the host sub-directories. */
  364.  
  365.  while((ent=readdir(dir)))
  366.     add_dir(ent->d_name,mode,NULL);
  367.  
  368.  closedir(dir);
  369.  
  370.  /* Get all of the mirrored hosts. */
  371.  
  372.  if((mirrored=ListMirrors(proto)))
  373.    {
  374.     int i;
  375.  
  376.     for(i=0;mirrored[i];i++)
  377.       {
  378.        add_dir(mirrored[i][0],mode,mirrored[i][1]);
  379.        free(mirrored[i][0]);
  380.        free(mirrored[i][1]);
  381.        free(mirrored[i]);
  382.       }
  383.  
  384.     free(mirrored);
  385.    }
  386.  
  387.  chdir("..");
  388.  
  389.  /* Sort the files. */
  390.  
  391.  if(mode==MTime || mode==ATime || mode==Dated)
  392.     qsort(files,nfiles,sizeof(FileIndex*),(int (*)(const void*,const void*))sort_time);
  393.  else if(mode==Alpha || mode==Type)
  394.     qsort(files,nfiles,sizeof(FileIndex*),(int (*)(const void*,const void*))sort_alpha);
  395.  
  396.  /* Output the page. */
  397.  
  398.  write_formatted(fd,"<h2>%s://</h2>\n",proto);
  399.  
  400.  if(nfiles)
  401.    {
  402.     int lastdays=0,lasthours=0;
  403.  
  404.     write_formatted(fd,"<b>%d Hosts</b>\n",nfiles);
  405.     write_string(fd,"<ul>\n");
  406.  
  407.     for(i=0;i<nfiles;i++)
  408.       {
  409.        char *url=(char*)malloc(strlen(proto)+strlen(files[i]->name)+8);
  410.        URL *Url;
  411.  
  412.        strcpy(url,proto);
  413.        strcat(url,"://");
  414.        strcat(url,files[i]->name);
  415.        Url=SplitURL(url);
  416.  
  417.        if(mode==Dated)
  418.           dated_separator(fd,i,&lastdays,&lasthours);
  419.  
  420.        if(ExistsWebpageSpoolFile(Url))
  421.           write_formatted(fd,"<li><a href=\"/index/%s/%s?%s\">%s</a> [<a href=\"%s\">/</a>]\n",
  422.                           proto,files[i]->name,sorttype[mode][0],files[i]->name,
  423.                           Url->link);
  424.        else
  425.           write_formatted(fd,"<li><a href=\"/index/%s/%s?%s\">%s</a>\n",
  426.                           proto,files[i]->name,sorttype[mode][0],files[i]->name);
  427.  
  428.        free(files[i]->name);
  429.        free(files[i]);
  430.        FreeURL(Url);
  431.       }
  432.  
  433.     write_string(fd,"</ul>\n");
  434.    }
  435.  else
  436.     write_string(fd,"<b>No hosts</b>\n");
  437.  
  438.  if(files)
  439.     free(files);
  440.  files=NULL;
  441.  nfiles=0;
  442. }
  443.  
  444.  
  445. /*++++++++++++++++++++++++++++++++++++++
  446.   Create an index of the pages on a host.
  447.  
  448.   int fd The file descriptor to write to.
  449.  
  450.   char *proto The protocol to index.
  451.  
  452.   char *host The name of the subdirectory.
  453.  
  454.   SortMode mode The sort mode to use.
  455.   ++++++++++++++++++++++++++++++++++++++*/
  456.  
  457. static void IndexHost(int fd,char *proto,char *host,SortMode mode)
  458. {
  459.  DIR *dir;
  460.  struct dirent* ent;
  461.  int i;
  462.  char *link_proto=NULL,*link_host=NULL;
  463.  
  464.  /* Write the header. */
  465.  
  466.  write_formatted(fd,"<h2>%s://%s/</h2>\n",proto,host);
  467.  
  468.  if(IsMirrored(proto,host,&link_proto,&link_host))
  469.    {
  470.     write_formatted(fd,"Mirror Link => %s://%s/\n<p>\n",link_proto,link_host);
  471.     proto=link_proto;
  472.     host=link_host;
  473.    }
  474.  
  475.  /* Open the spool subdirectory. */
  476.  
  477.  if(chdir(proto))
  478.    {PrintMessage(Warning,"Cannot change to directory '%s' [%!s]; not indexed.",proto);
  479.    write_formatted(fd,"No %s directory.",proto);return;}
  480.  
  481.  /* Open the spool subdirectory. */
  482.  
  483.  if(chdir(host))
  484.    {PrintMessage(Warning,"Cannot change to directory '%s/%s' [%!s]; not indexed.",proto,host);chdir("..");
  485.    write_formatted(fd,"No %s/%s directory.",proto,host);return;}
  486.  
  487.  dir=opendir(".");
  488.  if(!dir)
  489.    {PrintMessage(Warning,"Cannot open directory '%s/%s' [%!s]; not indexed.",proto,host);chdir("../..");
  490.    write_formatted(fd,"Unable to open directory %s/%s.",proto,host);return;}
  491.  
  492.  ent=readdir(dir);  /* skip .  */
  493.  if(!ent)
  494.    {PrintMessage(Warning,"Cannot read directory '%s/%s' [%!s]; not indexed.",proto,host);closedir(dir);chdir("../..");
  495.    write_formatted(fd,"Unable to read directory %s/%s.",proto,host);return;}
  496.  ent=readdir(dir);  /* skip .. */
  497.  
  498.  /* Add all of the file names. */
  499.  
  500.  while((ent=readdir(dir)))
  501.     add_file(ent->d_name,mode);
  502.  
  503.  closedir(dir);
  504.  
  505.  chdir("../..");
  506.  
  507.  /* Sort the files. */
  508.  
  509.  if(mode==MTime || mode==ATime || mode==Dated)
  510.     qsort(files,nfiles,sizeof(FileIndex*),(int (*)(const void*,const void*))sort_time);
  511.  else if(mode==Alpha)
  512.     qsort(files,nfiles,sizeof(FileIndex*),(int (*)(const void*,const void*))sort_alpha);
  513.  else if(mode==Type)
  514.     qsort(files,nfiles,sizeof(FileIndex*),(int (*)(const void*,const void*))sort_type);
  515.  
  516.  /* Output the page. */
  517.  
  518.  if(nfiles)
  519.    {
  520.     int lastdays=0,lasthours=0;
  521.  
  522.     write_formatted(fd,"<b>%d Pages</b>\n",nfiles);
  523.     write_string(fd,"<ul>\n");
  524.  
  525.     for(i=0;i<nfiles;i++)
  526.       {
  527.        URL *Url=SplitURL(files[i]->name);
  528.        char *encurl=UrlEncode(Url->name);
  529.        char *decurl=UrlDecode(Url->name,0);
  530.  
  531.        if(mode==Dated)
  532.           dated_separator(fd,i,&lastdays,&lasthours);
  533.  
  534.        if(Url->Protocol && Url->args && *Url->args=='!')
  535.           write_formatted(fd,"<li>[<a href=\"/control/delete?url=%s\">Del</a>"
  536.                              "|Refresh:"
  537.                              "Opt|"
  538.                              "Mon]"
  539.                              " <a href=\"%s\">%s</a>\n",
  540.                           encurl,
  541.                           Url->link,decurl);
  542.        else if(Url->Protocol)
  543.           write_formatted(fd,"<li>[<a href=\"/control/delete?url=%s\">Del</a>"
  544.                              "|<a href=\"/refresh/%s/%s\">Refresh</a>:"
  545.                              "<a href=\"/refresh/?%s\">Opt</a>|"
  546.                              "<a href=\"/monitor/?%s\">Mon</a>]"
  547.                              " <a href=\"%s\">%s</a>\n",
  548.                           encurl,
  549.                           Url->proto,Url->hostp,
  550.                           encurl,
  551.                           encurl,
  552.                           Url->link,decurl);
  553.        else
  554.           write_formatted(fd,"<li>[Del"
  555.                              "|Refresh:"
  556.                              "Opt|"
  557.                              "Mon]"
  558.                              " %s\n",
  559.                           decurl);
  560.  
  561.        free(files[i]->name);
  562.        free(files[i]);
  563.        FreeURL(Url);
  564.        free(encurl);
  565.        free(decurl);
  566.       }
  567.  
  568.     write_string(fd,"</ul>\n");
  569.  
  570.     write_formatted(fd,"[<a href=\"/control/delete?url=%s://%s/&all=yes\">Delete ALL Pages</a>]\n",proto,host);
  571.    }
  572.  else
  573.     write_string(fd,"<b>No Pages</b>\n");
  574.  
  575.  if(files)
  576.     free(files);
  577.  files=NULL;
  578.  nfiles=0;
  579. }
  580.  
  581.  
  582. /*++++++++++++++++++++++++++++++++++++++
  583.   Create an index of the requests that are waiting in the outgoing directory.
  584.  
  585.   int fd The file descriptor to write to.
  586.  
  587.   SortMode mode The method to use to sort the names.
  588.   ++++++++++++++++++++++++++++++++++++++*/
  589.  
  590. static void IndexOutgoing(int fd,SortMode mode)
  591. {
  592.  DIR *dir;
  593.  struct dirent* ent;
  594.  int i;
  595.  
  596.  /* Open the outgoing subdirectory. */
  597.  
  598.  if(chdir("outgoing"))
  599.    {PrintMessage(Warning,"Cannot change to directory 'outgoing' [%!s]; not indexed.");
  600.    write_formatted(fd,"No outgoing directory.");return;}
  601.  
  602.  dir=opendir(".");
  603.  if(!dir)
  604.    {PrintMessage(Warning,"Cannot open directory 'outgoing' [%!s]; not indexed.");chdir("..");
  605.    write_formatted(fd,"Unable to open outgoing directory.");return;}
  606.  
  607.  ent=readdir(dir);  /* skip .  */
  608.  if(!ent)
  609.    {PrintMessage(Warning,"Cannot read directory 'outgoing' [%!s]; not indexed.");closedir(dir);chdir("..");
  610.    write_formatted(fd,"Unable to read outgoing directory.");return;}
  611.  ent=readdir(dir);  /* skip .. */
  612.  
  613.  /* Add all of the file names. */
  614.  
  615.  while((ent=readdir(dir)))
  616.     add_file(ent->d_name,mode);
  617.  
  618.  closedir(dir);
  619.  
  620.  chdir("..");
  621.  
  622.  /* Sort the files. */
  623.  
  624.  if(mode==MTime || mode==ATime || mode==Dated)
  625.     qsort(files,nfiles,sizeof(FileIndex*),(int (*)(const void*,const void*))sort_time);
  626.  else if(mode==Alpha)
  627.     qsort(files,nfiles,sizeof(FileIndex*),(int (*)(const void*,const void*))sort_alpha);
  628.  else if(mode==Type)
  629.     qsort(files,nfiles,sizeof(FileIndex*),(int (*)(const void*,const void*))sort_type);
  630.  
  631.  /* Output the page. */
  632.  
  633.  write_string(fd,"<h2>Outgoing Requests</h2>\n");
  634.  
  635.  if(nfiles)
  636.    {
  637.     int lastdays=0,lasthours=0;
  638.  
  639.     write_formatted(fd,"<b>%d Requests</b>\n",nfiles);
  640.     write_string(fd,"<ul>\n");
  641.  
  642.     for(i=0;i<nfiles;i++)
  643.       {
  644.        URL *Url=SplitURL(files[i]->name);
  645.        char *encurl=UrlEncode(Url->name);
  646.        char *decurl=UrlDecode(Url->name,0);
  647.  
  648.        if(mode==Dated)
  649.           dated_separator(fd,i,&lastdays,&lasthours);
  650.  
  651.        if(Url->Protocol && Url->args && *Url->args=='!')
  652.           write_formatted(fd,"<li>[<a href=\"/control/delete?req=%s\">Del</a>"
  653.                              "|Refresh:"
  654.                              "Opt|"
  655.                              "Mon]"
  656.                              " <a href=\"%s\">%s</a>\n",
  657.                           encurl,
  658.                           Url->link,decurl);
  659.        else if(Url->Protocol)
  660.           write_formatted(fd,"<li>[<a href=\"/control/delete?req=%s\">Del</a>"
  661.                              "|Refresh:"
  662.                              "<a href=\"/refresh/?%s\">Opt</a>|"
  663.                              "<a href=\"/monitor/?%s\">Mon</a>]"
  664.                              " <a href=\"%s\">%s</a>\n",
  665.                           encurl,
  666.                           encurl,
  667.                           encurl,
  668.                           Url->link,decurl);
  669.        else
  670.           write_formatted(fd,"<li>[<a href=\"/control/delete?req=%s\">Del</a>"
  671.                              "|Refresh:"
  672.                              "Opt|"
  673.                              "Mon]"
  674.                              " %s\n",
  675.                           encurl,
  676.                           decurl);
  677.  
  678.        free(files[i]->name);
  679.        free(files[i]);
  680.        FreeURL(Url);
  681.        free(encurl);
  682.        free(decurl);
  683.       }
  684.  
  685.     write_string(fd,"</ul>\n");
  686.  
  687.     write_string(fd,"[<a href=\"/control/delete?req=&all=yes\">Delete ALL Requests</a>]\n");
  688.    }
  689.  else
  690.     write_string(fd,"<b>No Requests</b>\n");
  691.  
  692.  write_string(fd,"<p align=center>\n");
  693.  write_string(fd,"[<a href=\"/refresh/\">Specify a Page to Be Requested</a>]\n");
  694.  write_string(fd,"</p>\n");
  695.  
  696.  if(files)
  697.     free(files);
  698.  files=NULL;
  699.  nfiles=0;
  700. }
  701.  
  702.  
  703. /*++++++++++++++++++++++++++++++++++++++
  704.   Create an index of the requests that are in the monitor directory.
  705.  
  706.   int fd The file descriptor to write to.
  707.  
  708.   SortMode mode The method to use to sort the names.
  709.   ++++++++++++++++++++++++++++++++++++++*/
  710.  
  711. static void IndexMonitor(int fd,SortMode mode)
  712. {
  713.  DIR *dir;
  714.  struct dirent* ent;
  715.  int i;
  716.  
  717.  /* Open the monitor subdirectory. */
  718.  
  719.  if(chdir("monitor"))
  720.    {PrintMessage(Warning,"Cannot change to directory 'monitor' [%!s]; not indexed.");
  721.    write_formatted(fd,"No monitor directory.");return;}
  722.  
  723.  dir=opendir(".");
  724.  if(!dir)
  725.    {PrintMessage(Warning,"Cannot open directory 'monitor' [%!s]; not indexed.");chdir("..");
  726.    write_formatted(fd,"Unable to open monitor directory.");return;}
  727.  
  728.  ent=readdir(dir);  /* skip .  */
  729.  if(!ent)
  730.    {PrintMessage(Warning,"Cannot read directory 'monitor' [%!s]; not indexed.");closedir(dir);chdir("..");
  731.    write_formatted(fd,"Unable to read monitor directory.");return;}
  732.  ent=readdir(dir);  /* skip .. */
  733.  
  734.  /* Add all of the file names. */
  735.  
  736.  while((ent=readdir(dir)))
  737.     add_file(ent->d_name,mode);
  738.  
  739.  closedir(dir);
  740.  
  741.  chdir("..");
  742.  
  743.  /* Sort the files. */
  744.  
  745.  if(mode==Dated)
  746.     for(i=0;i<nfiles;i++)
  747.       {
  748.        int mtimedays=(now-files[i]->time+3600)/(24*3600);
  749.  
  750.        files[i]->time+=(24*3600)*MonitorInterval*(mtimedays/MonitorInterval);
  751.       }
  752.  
  753.  if(mode==MTime || mode==ATime || mode==Dated)
  754.     qsort(files,nfiles,sizeof(FileIndex*),(int (*)(const void*,const void*))sort_time);
  755.  else if(mode==Alpha)
  756.     qsort(files,nfiles,sizeof(FileIndex*),(int (*)(const void*,const void*))sort_alpha);
  757.  else if(mode==Type)
  758.     qsort(files,nfiles,sizeof(FileIndex*),(int (*)(const void*,const void*))sort_type);
  759.  
  760.  /* Output the page. */
  761.  
  762.  write_string(fd,"<h2>Monitored Pages</h2>\n");
  763.  write_formatted(fd,"Checked Every %d Days\n<p>\n",MonitorInterval);
  764.  
  765.  if(nfiles)
  766.    {
  767.     int lastdays=0,lasthours=0;
  768.  
  769.     write_formatted(fd,"<b>%d Pages</b>\n",nfiles);
  770.     write_string(fd,"<ul>\n");
  771.  
  772.     for(i=0;i<nfiles;i++)
  773.       {
  774.        URL *Url=SplitURL(files[i]->name);
  775.        char *encurl=UrlEncode(Url->name);
  776.        char *decurl=UrlDecode(Url->name,0);
  777.  
  778.        if(mode==Dated)
  779.           dated_separator(fd,i,&lastdays,&lasthours);
  780.  
  781.        if(Url->Protocol && Url->args && *Url->args=='!')
  782.           write_formatted(fd,"<li>[<a href=\"/control/delete?mon=%s\">Del</a>"
  783.                              "|Refresh:"
  784.                              "Opt|"
  785.                              "Mon]"
  786.                              " <a href=\"%s\">%s</a>\n",
  787.                           encurl,
  788.                           Url->link,decurl);
  789.        else if(Url->Protocol)
  790.           write_formatted(fd,"<li>[<a href=\"/control/delete?mon=%s\">Del</a>"
  791.                              "|<a href=\"/refresh/%s/%s\">Refresh</a>:"
  792.                              "<a href=\"/refresh/?%s\">Opt</a>|"
  793.                              "Mon]"
  794.                              " <a href=\"%s\">%s</a>\n",
  795.                           encurl,
  796.                           Url->proto,Url->hostp,
  797.                           encurl,
  798.                           Url->link,decurl);
  799.        else
  800.           write_formatted(fd,"<li>[<a href=\"/control/delete?mon=%s\">Del</a>"
  801.                              "|Refresh:"
  802.                              "Opt|"
  803.                              "Mon]"
  804.                              " %s\n",
  805.                           encurl,
  806.                           decurl);
  807.  
  808.        free(files[i]->name);
  809.        free(files[i]);
  810.        FreeURL(Url);
  811.        free(encurl);
  812.        free(decurl);
  813.       }
  814.  
  815.     write_string(fd,"</ul>\n");
  816.    }
  817.  else
  818.     write_string(fd,"<b>No Pages</b>\n");
  819.  
  820.  write_string(fd,"<p align=center>\n");
  821.  write_string(fd,"[<a href=\"/monitor/\">Specify a Page to Be Monitored</a>]\n");
  822.  write_string(fd,"</p>\n");
  823.  
  824.  if(files)
  825.     free(files);
  826.  files=NULL;
  827.  nfiles=0;
  828. }
  829.  
  830.  
  831. /*++++++++++++++++++++++++++++++++++++++
  832.   Create an index of the pages that were got last time online.
  833.  
  834.   int fd The file descriptor to write to.
  835.  
  836.   SortMode mode The method to use to sort the names.
  837.   ++++++++++++++++++++++++++++++++++++++*/
  838.  
  839. static void IndexLastTime(int fd,SortMode mode)
  840. {
  841.  DIR *dir;
  842.  struct dirent* ent;
  843.  int i;
  844.  
  845.  /* Open the lasttime subdirectory. */
  846.  
  847.  if(chdir("lasttime"))
  848.    {PrintMessage(Warning,"Cannot change to directory 'lasttime' [%!s]; not indexed.");
  849.    write_formatted(fd,"No lasttime directory.");return;}
  850.  
  851.  dir=opendir(".");
  852.  if(!dir)
  853.    {PrintMessage(Warning,"Cannot open directory 'lasttime' [%!s]; not indexed.");chdir("..");
  854.    write_formatted(fd,"Unable to open lasttime directory.");return;}
  855.  
  856.  ent=readdir(dir);  /* skip .  */
  857.  if(!ent)
  858.    {PrintMessage(Warning,"Cannot read directory 'lasttime' [%!s]; not indexed.");closedir(dir);chdir("..");
  859.    write_formatted(fd,"Unable to read lasttime directory.");return;}
  860.  ent=readdir(dir);  /* skip .. */
  861.  
  862.  /* Add all of the file names. */
  863.  
  864.  while((ent=readdir(dir)))
  865.     add_file(ent->d_name,mode);
  866.  
  867.  closedir(dir);
  868.  
  869.  chdir("..");
  870.  
  871.  /* Sort the files. */
  872.  
  873.  if(mode==MTime || mode==ATime || mode==Dated)
  874.     qsort(files,nfiles,sizeof(FileIndex*),(int (*)(const void*,const void*))sort_time);
  875.  else if(mode==Alpha)
  876.     qsort(files,nfiles,sizeof(FileIndex*),(int (*)(const void*,const void*))sort_alpha);
  877.  else if(mode==Type)
  878.     qsort(files,nfiles,sizeof(FileIndex*),(int (*)(const void*,const void*))sort_type);
  879.  
  880.  /* Output the page. */
  881.  
  882.  write_string(fd,"<h2>Last Time Online Pages</h2>\n");
  883.  
  884.  if(nfiles)
  885.    {
  886.     int lastdays=0,lasthours=0;
  887.  
  888.     write_formatted(fd,"<b>%d Pages</b>\n",nfiles);
  889.     write_string(fd,"<ul>\n");
  890.  
  891.     for(i=0;i<nfiles;i++)
  892.       {
  893.        URL *Url=SplitURL(files[i]->name);
  894.        char *encurl=UrlEncode(Url->name);
  895.        char *decurl=UrlDecode(Url->name,0);
  896.  
  897.        if(mode==Dated)
  898.           dated_separator(fd,i,&lastdays,&lasthours);
  899.  
  900.        if(Url->Protocol && Url->args && *Url->args=='!')
  901.           write_formatted(fd,"<li>[<a href=\"/control/delete?url=%s\">Del</a>"
  902.                              "|Refresh:"
  903.                              "Opt|"
  904.                              "Mon]"
  905.                              " <a href=\"%s\">%s</a>\n",
  906.                           encurl,
  907.                           Url->link,decurl);
  908.        else if(Url->Protocol)
  909.           write_formatted(fd,"<li>[<a href=\"/control/delete?url=%s\">Del</a>"
  910.                              "|<a href=\"/refresh/%s/%s\">Refresh</a>:"
  911.                              "<a href=\"/refresh/?%s\">Opt</a>|"
  912.                              "<a href=\"/monitor/?%s\">Mon</a>]"
  913.                              " <a href=\"%s\">%s</a>\n",
  914.                           encurl,
  915.                           Url->proto,Url->hostp,
  916.                           encurl,
  917.                           encurl,
  918.                           Url->link,decurl);
  919.        else
  920.           write_formatted(fd,"<li>[<a href=\"/control/delete?url=%s\">Del</a>"
  921.                              "|Refresh:"
  922.                              "Opt|"
  923.                              "Mon]"
  924.                              " %s\n",
  925.                           encurl,
  926.                           decurl);
  927.  
  928.        free(files[i]->name);
  929.        free(files[i]);
  930.        FreeURL(Url);
  931.        free(encurl);
  932.        free(decurl);
  933.       }
  934.  
  935.     write_string(fd,"</ul>\n");
  936.    }
  937.  else
  938.     write_string(fd,"<b>No Pages</b>\n");
  939.  
  940.  if(files)
  941.     free(files);
  942.  files=NULL;
  943.  nfiles=0;
  944. }
  945.  
  946.  
  947. /*++++++++++++++++++++++++++++++++++++++
  948.   Create an index of the latest pages.
  949.  
  950.   int fd The file descriptor to write to.
  951.  
  952.   SortMode mode The method to use to sort the names.
  953.   ++++++++++++++++++++++++++++++++++++++*/
  954.  
  955. static void IndexLatest(int fd,SortMode mode)
  956. {
  957.  int i,p;
  958.  
  959.  earliest=now-IndexLatestDays*24*3600;
  960.  
  961.  /* Add all of the files in the sub directories. */
  962.  
  963.  for(p=0;p<NProtocols;p++)
  964.    {
  965.     struct stat buf;
  966.  
  967.     if(!lstat(Protocols[p].name,&buf) && S_ISDIR(buf.st_mode))
  968.       {
  969.        DIR *dir2;
  970.        struct dirent* ent2;
  971.  
  972.        if(chdir(Protocols[p].name))
  973.          {PrintMessage(Warning,"Cannot change to directory '%s' [%!s]; not indexed.",Protocols[p].name);continue;}
  974.  
  975.        /* Open the spool directory. */
  976.  
  977.        dir2=opendir(".");
  978.        if(!dir2)
  979.          {PrintMessage(Warning,"Cannot open directory '%s' [%!s]; not indexed.",Protocols[p].name);chdir("..");continue;}
  980.  
  981.        ent2=readdir(dir2);  /* skip .  */
  982.        if(!ent2)
  983.          {PrintMessage(Warning,"Cannot read directory '%s' [%!s]; index failed.",Protocols[p].name);closedir(dir2);chdir("..");continue;}
  984.        ent2=readdir(dir2);  /* skip .. */
  985.  
  986.        /* Print all of the sub directories. */
  987.  
  988.        while((ent2=readdir(dir2)))
  989.          {
  990.           struct stat buf2;
  991.  
  992.           if(lstat(ent2->d_name,&buf2))
  993.              PrintMessage(Inform,"Cannot stat file '%s' [%!s]; race condition?",ent2->d_name);
  994.           else
  995.              if(S_ISDIR(buf2.st_mode) && buf2.st_mtime>earliest)
  996.                {
  997.                 DIR *dir3;
  998.                 struct dirent* ent3;
  999.                 struct utimbuf utbuf;
  1000.  
  1001.                 if(chdir(ent2->d_name))
  1002.                   {PrintMessage(Warning,"Cannot change to directory '%s/%s' [%!s]; not indexed.",Protocols[p].name,ent2->d_name);continue;}
  1003.  
  1004.                 dir3=opendir(".");
  1005.                 if(!dir3)
  1006.                   {PrintMessage(Warning,"Cannot open directory '%s/%s' [%!s]; not indexed.",Protocols[p].name,ent2->d_name);chdir("..");continue;}
  1007.  
  1008.                 ent3=readdir(dir3);  /* skip .  */
  1009.                 if(!ent3)
  1010.                   {PrintMessage(Warning,"Cannot read directory '%s/%s' [%!s]; not indexed.",Protocols[p].name,ent2->d_name);closedir(dir3);chdir("..");continue;}
  1011.                 ent3=readdir(dir3);  /* skip .. */
  1012.  
  1013.                 while((ent3=readdir(dir3)))
  1014.                    add_file(ent3->d_name,mode);
  1015.  
  1016.                 closedir(dir3);
  1017.                 chdir("..");
  1018.  
  1019.                 utbuf.actime=buf2.st_atime;
  1020.                 utbuf.modtime=buf2.st_mtime;
  1021.                 utime(ent2->d_name,&utbuf);
  1022.                }
  1023.          }
  1024.  
  1025.        closedir(dir2);
  1026.        chdir("..");
  1027.       }
  1028.    }
  1029.  
  1030.  /* Sort the files. */
  1031.  
  1032.  if(mode==MTime || mode==ATime || mode==Dated)
  1033.     qsort(files,nfiles,sizeof(FileIndex*),(int (*)(const void*,const void*))sort_time);
  1034.  else if(mode==Alpha)
  1035.     qsort(files,nfiles,sizeof(FileIndex*),(int (*)(const void*,const void*))sort_alpha);
  1036.  else if(mode==Type)
  1037.     qsort(files,nfiles,sizeof(FileIndex*),(int (*)(const void*,const void*))sort_type);
  1038.  
  1039.  /* Output the page. */
  1040.  
  1041.  write_formatted(fd,"<h2>Latest Pages</h2>\n");
  1042.  write_formatted(fd,"From the last %d Days\n<p>\n",IndexLatestDays);
  1043.  
  1044.  if(nfiles)
  1045.    {
  1046.     int lastdays=0,lasthours=0;
  1047.  
  1048.     write_formatted(fd,"<b>%d Pages</b>\n",nfiles);
  1049.     write_string(fd,"<ul>\n");
  1050.  
  1051.     for(i=0;i<nfiles;i++)
  1052.       {
  1053.        URL *Url=SplitURL(files[i]->name);
  1054.        char *encurl=UrlEncode(Url->name);
  1055.        char *decurl=UrlDecode(Url->name,0);
  1056.  
  1057.        if(mode==Dated)
  1058.           dated_separator(fd,i,&lastdays,&lasthours);
  1059.  
  1060.        if(Url->Protocol && Url->args && *Url->args=='!')
  1061.           write_formatted(fd,"<li>[<a href=\"/control/delete?url=%s\">Del</a>"
  1062.                              "|Refresh:"
  1063.                              "Opt|"
  1064.                              "Mon]"
  1065.                              " <a href=\"%s\">%s</a>\n",
  1066.                           encurl,
  1067.                           Url->link,decurl);
  1068.        else if(Url->Protocol)
  1069.           write_formatted(fd,"<li>[<a href=\"/control/delete?url=%s\">Del</a>"
  1070.                              "|<a href=\"/refresh/%s/%s\">Refresh</a>:"
  1071.                              "<a href=\"/refresh/?%s\">Opt</a>|"
  1072.                              "<a href=\"/monitor/?%s\">Mon</a>]"
  1073.                              " <a href=\"%s\">%s</a>\n",
  1074.                           encurl,
  1075.                           Url->proto,Url->hostp,
  1076.                           encurl,
  1077.                           encurl,
  1078.                           Url->link,decurl);
  1079.        else
  1080.           write_formatted(fd,"<li>[<a href=\"/control/delete?url=%s\">Del</a>"
  1081.                              "|Refresh:"
  1082.                              "Opt|"
  1083.                              "Mon]"
  1084.                              " %s\n",
  1085.                           encurl,
  1086.                           decurl);
  1087.  
  1088.        free(files[i]->name);
  1089.        free(files[i]);
  1090.        FreeURL(Url);
  1091.        free(encurl);
  1092.        free(decurl);
  1093.       }
  1094.  
  1095.     write_string(fd,"</ul>\n");
  1096.    }
  1097.  else
  1098.     write_string(fd,"<b>No Pages</b>\n");
  1099.  
  1100.  if(files)
  1101.     free(files);
  1102.  files=NULL;
  1103.  nfiles=0;
  1104. }
  1105.  
  1106.  
  1107. /*++++++++++++++++++++++++++++++++++++++
  1108.   Redirect the user to the correct index page in case of a bad argument.
  1109.  
  1110.   int fd The file descriptor to write to.
  1111.  
  1112.   char *path The specified path.
  1113.  
  1114.   char *args The specified args.
  1115.   ++++++++++++++++++++++++++++++++++++++*/
  1116.  
  1117. static void CorrectIndex(int fd,char *path,char *args)
  1118. {
  1119.  char *head1=
  1120.  "HTTP/1.0 301 WWWOFFLE Index Incorrect\r\n"
  1121.  "Content-type: text/html\r\n";
  1122.  char *head2=
  1123.  "\r\n"
  1124.  "<HTML>\n"
  1125.  "<HEAD>\n"
  1126.  "<TITLE>WWWOFFLE - Index Incorrect</TITLE>\n"
  1127.  "</HEAD>\n"
  1128.  "<BODY>\n"
  1129.  "<H1 align=center>WWWOFFLE Index Incorrect</H1>\n"
  1130.  "<p align=center>\n"
  1131.  "Your request for the index URL\n"
  1132.  "<br><b><tt>\n";
  1133.  char *middle=
  1134.  "\n"
  1135.  "</tt></b><br>\n"
  1136.  "was incorrect, select the link below for a correct version.\n"
  1137.  "<br>\n";
  1138.  char *tail=
  1139.  "\n"
  1140.  "</BODY>\n"
  1141.  "</HTML>\n";
  1142.  
  1143.  write_string(fd,head1);
  1144.  write_formatted(fd,"Location: http://%s/index/%s?%s\r\n",GetLocalHost(1),path,sorttype[0][0]);
  1145.  write_string(fd,head2);
  1146.  if(args)
  1147.     write_formatted(fd,"/index/%s?%s",path,args);
  1148.  else
  1149.     write_formatted(fd,"/index/%s",path);
  1150.  write_string(fd,middle);
  1151.  write_formatted(fd,"<a href=\"/index/%s?%s\">/index/%s?%s</a>",path,sorttype[0][0],path,sorttype[0][0]);
  1152.  write_string(fd,tail);
  1153. }
  1154.  
  1155.  
  1156. /*++++++++++++++++++++++++++++++++++++++
  1157.   Inform the user that the specified index page is illegal.
  1158.  
  1159.   int fd The file descriptor to write to.
  1160.  
  1161.   char *path The specified path.
  1162.  
  1163.   char *args The specified args.
  1164.   ++++++++++++++++++++++++++++++++++++++*/
  1165.  
  1166. static void IllegalIndex(int fd,char *path,char *args)
  1167. {
  1168.  char *head=
  1169.  "HTTP/1.0 404 WWWOFFLE Illegal Index\r\n"
  1170.  "Content-type: text/html\r\n"
  1171.  "\r\n"
  1172.  "<HTML>\n"
  1173.  "<HEAD>\n"
  1174.  "<TITLE>WWWOFFLE - Illegal Index</TITLE>\n"
  1175.  "</HEAD>\n"
  1176.  "<BODY>\n"
  1177.  "<H1 align=center>WWWOFFLE Illegal Index</H1>\n"
  1178.  "<p align=center>\n"
  1179.  "Your request for the index URL\n"
  1180.  "<br><b><tt>\n";
  1181.  char *tail=
  1182.  "\n"
  1183.  "</tt></b><br>\n"
  1184.  "is illegal, select the link below for the main index.\n"
  1185.  "<br>\n"
  1186.  "<a href=\"/index/\">/index/</a>\n"
  1187.  "</BODY>\n"
  1188.  "</HTML>\n";
  1189.  
  1190.  write_string(fd,head);
  1191.  if(args)
  1192.     write_formatted(fd,"/index/%s?%s",path,args);
  1193.  else
  1194.     write_formatted(fd,"/index/%s",path);
  1195.  write_string(fd,tail);
  1196. }
  1197.  
  1198.  
  1199. /*++++++++++++++++++++++++++++++++++++++
  1200.   Add a directory to the list.
  1201.  
  1202.   char *name The name of the directory.
  1203.  
  1204.   SortMode mode The sort mode.
  1205.  
  1206.   char *link The directory that this is linked to if this is a mirror link.
  1207.   ++++++++++++++++++++++++++++++++++++++*/
  1208.  
  1209. static void add_dir(char *name,SortMode mode,char *link)
  1210. {
  1211.  struct stat buf;
  1212.  
  1213.  if(!link && lstat(name,&buf))
  1214.    {PrintMessage(Inform,"Cannot stat directory '%s' [%!s]; race condition?",name);return;}
  1215.  else if(link && stat(link,&buf))
  1216.    {PrintMessage(Inform,"Cannot stat link '%s' [%!s]; points nowhere?",link);return;}
  1217.  else if(S_ISDIR(buf.st_mode))
  1218.    {
  1219.     if(!(nfiles%16))
  1220.       {
  1221.        if(!files)
  1222.           files=(FileIndex**)malloc(16*sizeof(FileIndex*));
  1223.        else
  1224.           files=(FileIndex**)realloc(files,(nfiles+16)*sizeof(FileIndex*));
  1225.       }
  1226.     files[nfiles]=(FileIndex*)malloc(sizeof(FileIndex));
  1227.  
  1228.     files[nfiles]->name=(char*)malloc(strlen(name)+1);
  1229.     strcpy(files[nfiles]->name,name);
  1230.  
  1231.     files[nfiles]->type="";
  1232.  
  1233.     if(mode==MTime || mode==Dated)
  1234.        files[nfiles]->time=buf.st_mtime;
  1235.     else if(mode==ATime)
  1236.        files[nfiles]->time=buf.st_atime;
  1237.  
  1238.     nfiles++;
  1239.    }
  1240. }
  1241.  
  1242.  
  1243. /*++++++++++++++++++++++++++++++++++++++
  1244.   Add a file to the list.
  1245.  
  1246.   char *name The name of the file.
  1247.  
  1248.   SortMode mode The sort mode.
  1249.   ++++++++++++++++++++++++++++++++++++++*/
  1250.  
  1251. static void add_file(char *name,SortMode mode)
  1252. {
  1253.  char *url=NULL;
  1254.  struct stat buf;
  1255.  
  1256.  url=FileNameToURL(name);
  1257.  
  1258.  if(!url)
  1259.     return;
  1260.  
  1261.  if(lstat(name,&buf))
  1262.    {PrintMessage(Inform,"Cannot stat file '%s' [%!s]; race condition?",name);return;}
  1263.  else if(S_ISREG(buf.st_mode) && (mode!=Dated || buf.st_mtime>earliest))
  1264.    {
  1265.     if(!(nfiles%16))
  1266.       {
  1267.        if(!files)
  1268.           files=(FileIndex**)malloc(16*sizeof(FileIndex*));
  1269.        else
  1270.           files=(FileIndex**)realloc(files,(nfiles+16)*sizeof(FileIndex*));
  1271.       }
  1272.     files[nfiles]=(FileIndex*)malloc(sizeof(FileIndex));
  1273.  
  1274.     files[nfiles]->name=url;
  1275.  
  1276.     if(mode==Type)
  1277.       {
  1278.        char *p;
  1279.  
  1280.        files[nfiles]->type="";
  1281.  
  1282.        p=strchr(files[nfiles]->name,'?');
  1283.        if(!p)
  1284.           p=files[nfiles]->name+strlen(files[nfiles]->name);
  1285.  
  1286.        for(;p>url;p--)
  1287.           if(*p=='.')
  1288.             {files[nfiles]->type=p;break;}
  1289.           else if(*p=='/')
  1290.              break;
  1291.       }
  1292.     else if(mode==MTime || mode==Dated)
  1293.        files[nfiles]->time=buf.st_mtime;
  1294.     else if(mode==ATime)
  1295.        files[nfiles]->time=buf.st_atime;
  1296.  
  1297.     nfiles++;
  1298.    }
  1299. }
  1300.  
  1301.  
  1302. /*++++++++++++++++++++++++++++++++++++++
  1303.   Write out a date separator for the dated format if needed.
  1304.  
  1305.   int fd The file to write to.
  1306.  
  1307.   int file The number of the file in the list.
  1308.  
  1309.   int *lastdays The age of the previous file in days.
  1310.  
  1311.   int *lasthours The age of the previous file in hours.
  1312.   ++++++++++++++++++++++++++++++++++++++*/
  1313.  
  1314. static void dated_separator(int fd,int file,int *lastdays,int *lasthours)
  1315. {
  1316.  int days=(now-files[file]->time)/(24*3600),hours=(now-files[file]->time)/3600;
  1317.  
  1318.  if(*lastdays<days)
  1319.    {
  1320.     write_string(fd,"</ul>\n");
  1321.     for(;*lastdays<days;(*lastdays)++)
  1322.        write_string(fd,"<hr width=\"25%\">\n");
  1323.     write_string(fd,"<ul>\n");
  1324.    }
  1325.  else if(file && *lasthours<(hours-1))
  1326.    {
  1327.     write_string(fd,"</ul>\n");
  1328.     write_string(fd,"<p>\n");
  1329.     write_string(fd,"<ul>\n");
  1330.    }
  1331.  *lasthours=hours;
  1332. }
  1333.  
  1334. /*++++++++++++++++++++++++++++++++++++++
  1335.   Used to sort the files into alphabetical order.
  1336.  
  1337.   int sort_alpha Returns the comparison of the pointers to strings.
  1338.  
  1339.   FileIndex **a The first FileIndex.
  1340.  
  1341.   FileIndex **b The second FileIndex.
  1342.   ++++++++++++++++++++++++++++++++++++++*/
  1343.  
  1344. static int sort_alpha(FileIndex **a,FileIndex **b)
  1345. {
  1346.  char *an=(*a)->name;
  1347.  char *bn=(*b)->name;
  1348.  
  1349.  return(strcmp(an,bn));
  1350. }
  1351.  
  1352.  
  1353. /*++++++++++++++++++++++++++++++++++++++
  1354.   Used to sort the files into type (file extension) order.
  1355.  
  1356.   int sort_type Returns the comparison of the pointers to strings.
  1357.  
  1358.   FileIndex **a The first FileIndex.
  1359.  
  1360.   FileIndex **b The second FileIndex.
  1361.   ++++++++++++++++++++++++++++++++++++++*/
  1362.  
  1363. static int sort_type(FileIndex **a,FileIndex **b)
  1364. {
  1365.  char *an=(*a)->name,*at=(*a)->type;
  1366.  char *bn=(*b)->name,*bt=(*b)->type;
  1367.  int sort1=strcmp(at,bt);
  1368.  
  1369.  if(sort1==0)
  1370.     return(strcmp(an,bn));
  1371.  else
  1372.     return(sort1);
  1373. }
  1374.  
  1375.  
  1376. /*++++++++++++++++++++++++++++++++++++++
  1377.   Used to sort the files into alphabetical order.
  1378.  
  1379.   int sort_time Returns the comparison of the times.
  1380.  
  1381.   FileIndex **a The first FileIndex.
  1382.  
  1383.   FileIndex **b The second FileIndex.
  1384.   ++++++++++++++++++++++++++++++++++++++*/
  1385.  
  1386. static int sort_time(FileIndex **a,FileIndex **b)
  1387. {
  1388.  long at=(*a)->time;
  1389.  long bt=(*b)->time;
  1390.  
  1391.  return(bt-at);
  1392. }
  1393.