home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Magazine / wwwoffle-2.1.tar.gz / wwwoffle-2.1 / misc.c < prev    next >
C/C++ Source or Header  |  1998-02-21  |  14KB  |  609 lines

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