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

浏览器

开发平台:

Unix_Linux

  1. /***************************************
  2.   $Header: /home/amb/wwwoffle/RCS/misc.c 2.40 2000/02/20 09:44:01 amb Exp $
  3.   WWWOFFLE - World Wide Web Offline Explorer - Version 2.5d.
  4.   Miscellaneous HTTP / HTML functions.
  5.   ******************/ /******************
  6.   Written by Andrew M. Bishop
  7.   This file Copyright 1997,98,99,2000 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 <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <ctype.h>
  16. #include <time.h>
  17. #include <sys/time.h>
  18. #include <sys/types.h>
  19. #include <fcntl.h>
  20. #include <unistd.h>
  21. #include <errno.h>
  22. #include "misc.h"
  23. #include "errors.h"
  24. #include "proto.h"
  25. #include "config.h"
  26. #include "md5.h"
  27. /*++++++++++++++++++++++++++++++++++++++
  28.   Split a URL into a protocol, hostname, path name and an argument list.
  29.   URL *SplitURL Returns a URL structure containing the information.
  30.   char *url The name of the url to split.
  31.   ++++++++++++++++++++++++++++++++++++++*/
  32. URL *SplitURL(char *url)
  33. {
  34.  URL *Url=(URL*)malloc(sizeof(URL));
  35.  char *copyurl,*mallocurl=malloc(strlen(url)+2);
  36.  int i=0,n=0;
  37.  char *colon,*slash,*at,*ques,*temppath,root[2];
  38.  copyurl=mallocurl;
  39.  strcpy(copyurl,url);
  40.  /* Protocol */
  41.  colon=strchr(copyurl,':');
  42.  slash=strchr(copyurl,'/');
  43.  at   =strchr(copyurl,'@');
  44.  if(slash==copyurl)                     /* /dir/... (local) */
  45.    {
  46.     Url->proto=(char*)malloc(5);
  47.     strcpy(Url->proto,"http");
  48.    }
  49.  else if(colon && slash && (colon+1)==slash) /* http://... */
  50.    {
  51.     *colon=0;
  52.     Url->proto=(char*)malloc(colon-copyurl+1);
  53.     strcpy(Url->proto,copyurl);
  54.     copyurl=slash+1;
  55.     if(*copyurl=='/')
  56.        copyurl++;
  57.     colon=strchr(copyurl,':');
  58.     slash=strchr(copyurl,'/');
  59.    }
  60.  else if(colon && !isdigit(*(colon+1)) &&
  61.          (!slash || colon<slash) &&
  62.          (!at || (slash && at>slash)))  /* http:www.foo.com/...[:@]... */
  63.    {
  64.     *colon=0;
  65.     Url->proto=(char*)malloc(colon-copyurl+1);
  66.     strcpy(Url->proto,copyurl);
  67.     copyurl=colon+1;
  68.     colon=strchr(copyurl,':');
  69.    }
  70.  else                                   /* www.foo.com:80/... */
  71.    {
  72.     Url->proto=(char*)malloc(5);
  73.     strcpy(Url->proto,"http");
  74.    }
  75.  for(i=0;Url->proto[i];i++)
  76.     Url->proto[i]=tolower(Url->proto[i]);
  77.  Url->Protocol=NULL;
  78.  for(i=0;i<NProtocols;i++)
  79.     if(!strcmp(Protocols[i].name,Url->proto))
  80.        Url->Protocol=&Protocols[i];
  81.  /* Password */
  82.  if(at && at>copyurl && (!slash || slash>at))
  83.    {
  84.     if(colon && at>colon)               /* user:pass@www.foo.com...[/]... */
  85.       {
  86.        *colon=0;
  87.        Url->user=URLDecode(copyurl,0);
  88.        copyurl=colon+1;
  89.        *at=0;
  90.        Url->pass=URLDecode(copyurl,0);
  91.        copyurl=at+1;
  92.       }
  93.     else                               /* user@www.foo.com...[:/]... */
  94.       {
  95.        *at=0;
  96.        Url->user=URLDecode(copyurl,0);
  97.        copyurl=at+1;
  98.        Url->pass=NULL;
  99.       }
  100.    }
  101.  else
  102.    {
  103.     if(at==copyurl)             /* @www.foo.com... */
  104.        copyurl++;
  105.     Url->user=NULL;
  106.     Url->pass=NULL;
  107.    }
  108.  /* Arguments */
  109.  ques=strchr(copyurl,'?');
  110.  if(ques)                       /* ../path?... */
  111.    {
  112.     *ques++=0;
  113.     Url->args=(char*)malloc(strlen(ques)+1);
  114.     strcpy(Url->args,ques);
  115.    }
  116.  else
  117.     Url->args=NULL;
  118.  /* Hostname */
  119.  if(*copyurl=='/')              /* /path/... (local) */
  120.    {
  121.     Url->host=GetLocalHost(1);
  122.     Url->local=1;
  123.    }
  124.  else                           /* www.foo.com... */
  125.    {
  126.     Url->host=copyurl;
  127.     Url->local=0;
  128.     if(slash && (!ques || slash<ques)) /* www.foo.com/...[?]... */
  129.        copyurl=slash;
  130.     else                        /* www.foo.com[?]... */
  131.       {root[0]='/';root[1]=0;copyurl=root;}
  132.    }
  133.  /* Pathname */
  134.  temppath=URLDecode(copyurl,0);
  135.  Url->path=URLEncode(temppath);
  136.  free(temppath);
  137.  /* Hostname (cont) */
  138.  if(!Url->local)
  139.    {
  140.     *copyurl=0;
  141.     copyurl=Url->host;
  142.     Url->host=(char*)malloc(strlen(copyurl)+1);
  143.     strcpy(Url->host,copyurl);
  144.    }
  145.  for(i=0;Url->host[i] && Url->host[i]!=':';i++)
  146.     Url->host[i]=tolower(Url->host[i]);
  147.  if(Url->host[i]==':')
  148.     if(atoi(&Url->host[i+1])==(Url->Protocol?Url->Protocol->defport:80))
  149.        Url->host[i]=0;
  150.  if(!Url->local && IsLocalHost(Url->host,1) && Url->Protocol && Url->Protocol==&Protocols[0])
  151.    {
  152.     free(Url->host);
  153.     Url->host=GetLocalHost(1);
  154.     Url->local=1;
  155.    }
  156.  /* Canonicalise the URL. */
  157.  Url->name=(char*)malloc(strlen(Url->proto)+strlen(Url->host)+strlen(Url->path)+(Url->args?strlen(Url->args):1)+8);
  158.  strcpy(Url->name,Url->proto);
  159.  n=strlen(Url->proto);
  160.  strcpy(Url->name+n,"://");
  161.  n+=3;
  162.  Url->hostp=Url->name+n;
  163.  strcpy(Url->name+n,Url->host);
  164.  n+=strlen(Url->host);
  165.  Url->pathp=Url->name+n;
  166.  strcpy(Url->name+n,Url->path);
  167.  n+=strlen(Url->path);
  168.  if(Url->args && *Url->args)
  169.    {
  170.     strcpy(Url->name+n,"?");
  171.     strcpy(Url->name+n+1,Url->args);
  172.    }
  173.  if(Url->user)
  174.    {
  175.     Url->file=(char*)malloc(strlen(Url->proto)+strlen(Url->hostp)+strlen(Url->user)+(Url->pass?strlen(Url->pass):0)+8);
  176.     n=Url->hostp-Url->name;
  177.     strncpy(Url->file,Url->name,n);
  178.     strcpy(Url->file+n,Url->user);
  179.     n+=strlen(Url->user);
  180.     if(Url->pass)
  181.       {
  182.        strcpy(Url->file+n,":");
  183.        strcpy(Url->file+n+1,Url->pass);
  184.        n+=strlen(Url->pass)+1;
  185.       }
  186.     strcpy(Url->file+n,"@");
  187.     strcpy(Url->file+n+1,Url->hostp);
  188.    }
  189.  else
  190.     Url->file=Url->name;
  191.  if(Url->Protocol && !Url->Protocol->proxyable)
  192.    {
  193.     char *localhost=GetLocalHost(1);
  194.     Url->link=(char*)malloc(strlen(Url->name)+strlen(localhost)+8);
  195.     sprintf(Url->link,"http://%s/%s/%s",localhost,Url->proto,Url->hostp);
  196.    }
  197.  else
  198.     Url->link=Url->name;
  199.  Url->dir=Url->host;
  200. #if defined(__CYGWIN__)
  201.  if(strchr(Url->host,':'))
  202.    {
  203.     char *colon=strchr(Url->host,':');
  204.     Url->dir=(char*)malloc(strlen(Url->host));
  205.     strcpy(Url->dir,Url->host);
  206.     Url->dir[colon-Url->host]='!';
  207.    }
  208. #endif
  209.  /* end */
  210.  free(mallocurl);
  211.  return(Url);
  212. }
  213. /*++++++++++++++++++++++++++++++++++++++
  214.   Add a password to an existing URL.
  215.   URL *Url The URL to add the username and password to.
  216.   char *user The username.
  217.   char *pass The password.
  218.   ++++++++++++++++++++++++++++++++++++++*/
  219. void AddURLPassword(URL *Url,char *user,char *pass)
  220. {
  221.  int n;
  222.  Url->user=(char*)malloc(strlen(user)+1);
  223.  strcpy(Url->user,user);
  224.  if(pass)
  225.    {
  226.     Url->pass=(char*)malloc(strlen(pass)+1);
  227.     strcpy(Url->pass,pass);
  228.    }
  229.  Url->file=(char*)malloc(strlen(Url->name)+strlen(Url->user)+(Url->pass?strlen(Url->pass):0)+8);
  230.  n=Url->hostp-Url->name;
  231.  strncpy(Url->file,Url->name,n);
  232.  strcpy(Url->file+n,Url->user);
  233.  n+=strlen(Url->user);
  234.  if(Url->pass)
  235.    {
  236.     strcpy(Url->file+n,":");
  237.     strcpy(Url->file+n+1,Url->pass);
  238.     n+=strlen(Url->pass)+1;
  239.    }
  240.  strcpy(Url->file+n,"@");
  241.  strcpy(Url->file+n+1,Url->hostp);
  242. }
  243. /*++++++++++++++++++++++++++++++++++++++
  244.   Free the memory in a URL.
  245.   URL *Url The URL to free.
  246.   ++++++++++++++++++++++++++++++++++++++*/
  247. void FreeURL(URL *Url)
  248. {
  249.  if(Url->name!=Url->link)
  250.     free(Url->link);
  251.  if(Url->name!=Url->file)
  252.     free(Url->file);
  253.  if(Url->dir!=Url->host)
  254.     free(Url->dir);
  255.  free(Url->name);
  256.  if(Url->proto) free(Url->proto);
  257.  if(Url->host)  free(Url->host);
  258.  if(Url->path)  free(Url->path);
  259.  if(Url->args)  free(Url->args);
  260.  if(Url->user)  free(Url->user);
  261.  if(Url->pass)  free(Url->pass);
  262.  free(Url);
  263. }
  264. /*++++++++++++++++++++++++++++++++++++++
  265.   Convert a url reference from a page to an absolute one.
  266.   char *LinkURL Return the linked to URL or the original link if unchanged.
  267.   URL *Url The page that we are looking at.
  268.   char *link The link from the page.
  269.   ++++++++++++++++++++++++++++++++++++++*/
  270. char *LinkURL(URL *Url,char *link)
  271. {
  272.  char *new=link;
  273.  char *colon=strchr(link,':');
  274.  char *slash=strchr(link,'/');
  275.  if(colon && slash && colon<slash)
  276.     ;
  277.  else if(!*link)
  278.    {
  279.     new=(char*)malloc(strlen(Url->name));
  280.     strcpy(link,Url->name);
  281.    }
  282.  else
  283.    {
  284.     if(*link=='/')
  285.       {
  286.        new=(char*)malloc(strlen(Url->proto)+strlen(Url->host)+strlen(link)+8);
  287.        sprintf(new,"%s://%s%s",Url->proto,Url->host,link);
  288.       }
  289.     else
  290.       {
  291.        int j;
  292.        char *path=(char*)malloc(strlen(Url->path)+strlen(link)+2);
  293.        strcpy(path,Url->path);
  294.        for(j=strlen(path);j>0;j--)
  295.           if(path[j]=='/')
  296.              break;
  297.        path[j]=0;
  298.        strcat(path,"/");
  299.        strcat(path,link);
  300.        CanonicaliseName(path);
  301.        new=(char*)malloc(strlen(Url->proto)+strlen(Url->host)+strlen(path)+8);
  302.        sprintf(new,"%s://%s%s",Url->proto,Url->host,path);
  303.        free(path);
  304.       }
  305.    }
  306.  return(new);
  307. }
  308. /*++++++++++++++++++++++++++++++++++++++
  309.   Canonicalise a file name by removing '/../', '/./' and '//' references.
  310.   char *CanonicaliseName Returns the argument modified.
  311.   char *name The original name
  312.   ++++++++++++++++++++++++++++++++++++++*/
  313. char *CanonicaliseName(char *name)
  314. {
  315.  char *match,*name2;
  316.  match=name;
  317.  while((match=strstr(match,"/./")) || !strncmp(match=name,"./",2))
  318.    {
  319.     char *prev=match, *next=match+2;
  320.     while((*prev++=*next++));
  321.    }
  322.  match=name;
  323.  while((match=strstr(match,"//")))
  324.    {
  325.     char *prev=match, *next=match+1;
  326.     while((*prev++=*next++));
  327.    }
  328.  match=name2=name;
  329.  while((match=strstr(match,"/../")))
  330.    {
  331.     char *prev=match, *next=match+4;
  332.     if((prev-name2)==2 && !strncmp(name2,"../",3))
  333.       {name2+=3;match++;continue;}
  334.     while(prev>name2 && *--prev!='/');
  335.     match=prev;
  336.     if(*prev=='/')prev++;
  337.     while((*prev++=*next++));
  338.    }
  339.  match=&name[strlen(name)-2];
  340.  if(match>=name && !strcmp(match,"/."))
  341.     *match=0;
  342.  match=&name[strlen(name)-3];
  343.  if(match>=name && !strcmp(match,"/.."))
  344.     if(match==name)
  345.        *++match=0;
  346.     else
  347.        while(match>name && *--match!='/')
  348.           *match=0;
  349. #if 0 /* as used in cxref */
  350.  match=&name[strlen(name)-1];
  351.  if(match>name && !strcmp(match,"/"))
  352.     *match=0;
  353.  if(!*name)
  354.     *name='.',*(name+1)=0;
  355. #else /* as used in wwwoffle */
  356.  if(!*name || !strncmp(name,"../",3))
  357.     *name='/',*(name+1)=0;
  358. #endif
  359.  return(name);
  360. }
  361. /*++++++++++++++++++++++++++++++++++++++
  362.   Decode a string that has been UrlEncoded.
  363.   char *URLDecode Returns a malloced copy of the decoded string.
  364.   const char *str The string to be decoded.
  365.   int isform Set to true if the string being decoded is from a form.
  366.   ++++++++++++++++++++++++++++++++++++++*/
  367. char *URLDecode(const char *str, int isform)
  368. {
  369.  int i,j;
  370.  char *copy=(char*)malloc(strlen(str)+1);
  371.  for(i=0,j=0;str[i];i++)
  372.     if(str[i]=='+' && isform)
  373.        copy[j++]=' ';
  374.     else if(str[i]=='%')
  375.       {
  376.        unsigned int val=0;
  377.        i++;
  378.        if(str[i]>='a') val=str[i]-'a'+10;
  379.        else if(str[i]>='A') val=str[i]-'A'+10;
  380.        else val=str[i]-'0';
  381.        val*=16;
  382.        i++;
  383.        if(str[i]>='a') val+=str[i]-'a'+10;
  384.        else if(str[i]>='A') val+=str[i]-'A'+10;
  385.        else val+=str[i]-'0';
  386.        copy[j++]=val;
  387.       }
  388.     else
  389.        copy[j++]=str[i];
  390.  copy[j]=0;
  391.  return(copy);
  392. }
  393. /*++++++++++++++++++++++++++++++++++++++
  394.   Decode a URL argument string that has been UrlEncoded.
  395.   char *URLDecodeArgs Returns a malloced copy of the decoded string.
  396.   const char *str The string to be decoded.
  397.   ++++++++++++++++++++++++++++++++++++++*/
  398. char *URLDecodeArgs(const char *str)
  399. {
  400.  int i,j;
  401.  char *copy=(char*)malloc(strlen(str)+1);
  402.  for(i=0,j=0;str[i];i++)
  403.     if(str[i]=='%')
  404.       {
  405.        unsigned int val=0;
  406.        i++;
  407.        if(str[i]>='a') val=str[i]-'a'+10;
  408.        else if(str[i]>='A') val=str[i]-'A'+10;
  409.        else val=str[i]-'0';
  410.        val*=16;
  411.        i++;
  412.        if(str[i]>='a') val+=str[i]-'a'+10;
  413.        else if(str[i]>='A') val+=str[i]-'A'+10;
  414.        else val+=str[i]-'0';
  415.        if(val=='&' || val=='=')
  416.           copy[j++]=str[i];
  417.        else
  418.           copy[j++]=val;
  419.       }
  420.     else
  421.        copy[j++]=str[i];
  422.  copy[j]=0;
  423.  return(copy);
  424. }
  425. /*++++++++++++++++++++++++++++++++++++++
  426.   Encode a string using the UrlEncode method as used with the POST method.
  427.   char *URLEncode Returns a malloced copy of the encoded string.
  428.   const char *str The string to be encoded.
  429.   ++++++++++++++++++++++++++++++++++++++*/
  430. char *URLEncode(const char *str)
  431. {
  432.  int i,j;
  433.  char *copy=(char*)malloc(3*strlen(str)+1);
  434.  for(i=0,j=0;str[i];i++)
  435.     if(isalpha(str[i]) ||
  436.        isdigit(str[i]) ||
  437.        str[i]=='/' || str[i]=='?' || str[i]=='@' || str[i]=='=' ||
  438.        str[i]=='$' || str[i]=='-' || str[i]=='_' || str[i]=='.' || str[i]=='+' || str[i]=='!' ||
  439.        str[i]=='*' || str[i]=='(' || str[i]==')' || str[i]==',' || str[i]==''')
  440.        copy[j++]=str[i];
  441.     else
  442.       {
  443.        unsigned int val=str[i];
  444.        copy[j]='%';
  445.        if(val%16>9)
  446.           copy[j+2]=val%16+'A'-10;
  447.        else
  448.           copy[j+2]=val%16+'0';
  449.        val/=16;
  450.        if(val%16>9)
  451.           copy[j+1]=val%16+'A'-10;
  452.        else
  453.           copy[j+1]=val%16+'0';
  454.        j+=3;
  455.       }
  456.  copy[j]=0;
  457.  return(copy);
  458. }
  459. /*++++++++++++++++++++++++++++++++++++++
  460.   Encode a string using the UrlEncode method as used for passwords in URLs.
  461.   char *URLEncodePassword Returns a malloced copy of the encoded string.
  462.   const char *str The string to be encoded.
  463.   ++++++++++++++++++++++++++++++++++++++*/
  464. char *URLEncodePassword(const char *str)
  465. {
  466.  int i,j;
  467.  char *copy=(char*)malloc(3*strlen(str)+1);
  468.  for(i=0,j=0;str[i];i++)
  469.     if(isalpha(str[i]) ||
  470.        isdigit(str[i]) ||
  471.        str[i]=='?' || str[i]==':' || str[i]=='=' ||
  472.        str[i]=='$' || str[i]=='-' || str[i]=='_' || str[i]=='.' || str[i]=='+' || str[i]=='!' ||
  473.        str[i]=='*' || str[i]=='(' || str[i]==')' || str[i]==',' || str[i]==''')
  474.        copy[j++]=str[i];
  475.     else
  476.       {
  477.        unsigned int val=str[i];
  478.        copy[j]='%';
  479.        if(val%16>9)
  480.           copy[j+2]=val%16+'A'-10;
  481.        else
  482.           copy[j+2]=val%16+'0';
  483.        val/=16;
  484.        if(val%16>9)
  485.           copy[j+1]=val%16+'A'-10;
  486.        else
  487.           copy[j+1]=val%16+'0';
  488.        j+=3;
  489.       }
  490.  copy[j]=0;
  491.  return(copy);
  492. }
  493. /*++++++++++++++++++++++++++++++++++++++
  494.   Generate a hash value for a string.
  495.   char *MakeHash Returns a string that can be used as the hashed string.
  496.   const char *args The arguments.
  497.   ++++++++++++++++++++++++++++++++++++++*/
  498. char *MakeHash(const char *args)
  499. {
  500.  char md5[17];
  501.  char *hash,*p;
  502.  struct MD5Context ctx;
  503.  /* Initialize the computation context.  */
  504.  MD5Init (&ctx);
  505.  /* Process whole buffer but last len % 64 bytes.  */
  506.  MD5Update (&ctx, args, strlen(args));
  507.  /* Put result in desired memory area.  */
  508.  MD5Final (md5, &ctx);
  509.  md5[17]=0;
  510.  hash=Base64Encode(md5,16);
  511.  for(p=hash;*p;p++)
  512.     if(*p=='/')
  513.        *p='-';
  514.     else if(*p=='=')
  515.        *p=0;
  516.  return(hash);
  517. }
  518. /*++++++++++++++++++++++++++++++++++++++
  519.   Convert the time into an RFC 822 compliant date.
  520.   char *RFC822Date Returns a pointer to a fixed string containing the date.
  521.   long t The time.
  522.   int utc Set to true to get Universal Time, else localtime.
  523.   ++++++++++++++++++++++++++++++++++++++*/
  524. char *RFC822Date(long t,int utc)
  525. {
  526.  static char *week[7]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
  527.  static char *month[12]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
  528.  static char value[2][32];
  529.  static int which=0;
  530.  struct tm *tim;
  531.  if(utc)
  532.     tim=gmtime(&t);
  533.  else
  534.    {
  535.     tim=localtime(&t);
  536.     if(tim->tm_isdst<0)
  537.       {tim=gmtime(&t);utc=1;}
  538.    }
  539.  which^=1;
  540.  /* Sun, 06 Nov 1994 08:49:37 GMT    ; RFC 822, updated by RFC 1123 */
  541.  sprintf(value[which],"%3s, %02d %3s %4d %02d:%02d:%02d %s",
  542.          week[tim->tm_wday],
  543.          tim->tm_mday,
  544.          month[tim->tm_mon],
  545.          tim->tm_year+1900,
  546.          tim->tm_hour,
  547.          tim->tm_min,
  548.          tim->tm_sec,
  549. #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
  550.          utc?"GMT":tim->tm_zone
  551. #elif defined(__CYGWIN__)
  552.          utc?"GMT":_tzname[tim->tm_isdst>0]
  553. #else
  554.          utc?"GMT":tzname[tim->tm_isdst>0]
  555. #endif
  556.          );
  557.  return(value[which]);
  558. }
  559. /*++++++++++++++++++++++++++++++++++++++
  560.   Convert a string representing a date into a time.
  561.   long DateToTimeT Returns the time.
  562.   const char *date The date string.
  563.   ++++++++++++++++++++++++++++++++++++++*/
  564. long DateToTimeT(const char *date)
  565. {
  566.  static char *month[12]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
  567.  int  year,day,hour,min,sec;
  568.  char monthstr[16];
  569.  long retval=0;
  570.  if(sscanf(date,"%*s %d %s %d %d:%d:%d",&day,monthstr,&year,&hour,&min,&sec)==6 ||
  571.     sscanf(date,"%*s %d-%3s-%d %d:%d:%d",&day,monthstr,&year,&hour,&min,&sec)==6 ||
  572.     sscanf(date,"%*s %3s %d %d:%d:%d %d",monthstr,&day,&hour,&min,&sec,&year)==6)
  573.    {
  574.     struct tm tim;
  575.     int mon;
  576.     for(mon=0;mon<12;mon++)
  577.        if(!strcmp(monthstr,month[mon]))
  578.           break;
  579.     tim.tm_sec=sec;
  580.     tim.tm_min=min;
  581.     tim.tm_hour=hour;
  582.     tim.tm_mday=day;
  583.     tim.tm_mon=mon;
  584.     if(year<38)
  585.        tim.tm_year=year+100;
  586.     else if(year<100)
  587.        tim.tm_year=year;
  588.     else
  589.        tim.tm_year=year-1900;
  590.     tim.tm_isdst=0;
  591.     retval=mktime(&tim);
  592.     if(retval==-1)
  593.        retval=0;
  594.    }
  595.  else if(sscanf(date,"%ld %1s",&retval,monthstr)==1)
  596.     ;
  597.  return(retval);
  598. }
  599. /*+ The conversion from a 6 bit value to an ASCII character. +*/
  600. static char base64[64]={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
  601.                         'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
  602.                         'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
  603.                         'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'};
  604. /*++++++++++++++++++++++++++++++++++++++
  605.   Decode a base 64 string.
  606.   char *Base64Decode Return a malloced string containing the decoded version.
  607.   const char *str The string to be decoded.
  608.   int *l Returns the length of the decoded string.
  609.   ++++++++++++++++++++++++++++++++++++++*/
  610. char *Base64Decode(const char *str,int *l)
  611. {
  612.  int le=strlen(str);
  613.  char *decoded=(char*)malloc(le+1);
  614.  int i,j,k;
  615.  while(str[le-1]=='=')
  616.     le--;
  617.  *l=3*(le/4)+(le%4)-1+!(le%4);
  618.  for(j=0;j<le;j++)
  619.     for(k=0;k<64;k++)
  620.        if(base64[k]==str[j])
  621.          {decoded[j]=k;break;}
  622.  for(i=j=0;j<(le+4);i+=3,j+=4)
  623.    {
  624.     unsigned long s=0;
  625.     for(k=0;k<4;k++)
  626.        if((j+k)<le)
  627.           s|=((unsigned long)decoded[j+k]&0xff)<<(18-6*k);
  628.     for(k=0;k<3;k++)
  629.        if((i+k)<*l)
  630.           decoded[i+k]=(char)((s>>(16-8*k))&0xff);
  631.    }
  632.  decoded[*l]=0;
  633.  return(decoded);
  634. }
  635. /*++++++++++++++++++++++++++++++++++++++
  636.   Encode a string into base 64.
  637.   char *Base64Encode Return a malloced string containing the encoded version.
  638.   const char *str The string to be encoded.
  639.   int l The length of the string to be encoded.
  640.   ++++++++++++++++++++++++++++++++++++++*/
  641. char *Base64Encode(const char *str,int l)
  642. {
  643.  int le=4*(l/3)+(l%3)+!!(l%3);
  644.  char *encoded=(char*)malloc(4*(le/4)+4*!!(le%4)+1);
  645.  int i,j,k;
  646.  for(i=j=0;i<(l+3);i+=3,j+=4)
  647.    {
  648.     unsigned long s=0;
  649.     for(k=0;k<3;k++)
  650.        if((i+k)<l)
  651.           s|=((unsigned long)str[i+k]&0xff)<<(16-8*k);
  652.     for(k=0;k<4;k++)
  653.        if((j+k)<le)
  654.           encoded[j+k]=(char)((s>>(18-6*k))&0x3f);
  655.    }
  656.  for(j=0;j<le;j++)
  657.     encoded[j]=base64[(int)encoded[j]];
  658.  for(;j%4;j++)
  659.     encoded[j]='=';
  660.  encoded[j]=0;
  661.  return(encoded);
  662. }
  663. /*++++++++++++++++++++++++++++++++++++++
  664.   Make the input string safe to output as HTML ( not < > & " ).
  665.   char* HTMLString Returns a safe HTML string.
  666.   const char* c A non-safe HTML string.
  667.   ++++++++++++++++++++++++++++++++++++++*/
  668. char* HTMLString(const char* c)
  669. {
  670.  int i=0,j=0,len=256-5;              /* 5 is the longest possible inserted amount */
  671.  char* ret=(char*)malloc(257);
  672.  do
  673.    {
  674.     for(;j<len && c[i];i++)
  675.        switch(c[i])
  676.          {
  677.          case '<':
  678.           ret[j++]='&';
  679.           ret[j++]='l';
  680.           ret[j++]='t';
  681.           ret[j++]=';';
  682.           break;
  683.          case '>':
  684.           ret[j++]='&';
  685.           ret[j++]='g';
  686.           ret[j++]='t';
  687.           ret[j++]=';';
  688.           break;
  689.          case '"':
  690.           ret[j++]='&';
  691.           ret[j++]='q';
  692.           ret[j++]='u';
  693.           ret[j++]='o';
  694.           ret[j++]='t';
  695.           ret[j++]=';';
  696.           break;
  697.          case '&':
  698.           ret[j++]='&';
  699.           ret[j++]='a';
  700.           ret[j++]='m';
  701.           ret[j++]='p';
  702.           ret[j++]=';';
  703.           break;
  704.          default:
  705.           ret[j++]=c[i];
  706.          }
  707.     if(c[i])                 /* Not finished */
  708.       {
  709.        ret=(char*)realloc((void*)ret,len+256+5);
  710.        len+=256;
  711.       }
  712.    }
  713.  while(c[i]);
  714.  ret[j]=0;
  715.  return(ret);
  716. }