home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / analg211.zip / alias.c next >
C/C++ Source or Header  |  1997-03-14  |  15KB  |  571 lines

  1. /*** analog 2.1 ***/
  2. /* Please read Readme.html, or http://www.statslab.cam.ac.uk/~sret1/analog/  */
  3.  
  4. /*** alias.c; functions to cope with aliasing, etc. ***/
  5.  
  6. #include "analhea2.h"
  7.  
  8. flag doaliaslist(char *name, struct alias *listhead)
  9. {                     /* do requested aliases on an object */
  10.   struct alias *aliasp;
  11.   int anydone = OFF;
  12.   char *p1, *p2, *c;
  13.   char answer[MAXSTRINGLENGTH];
  14.  
  15.   for (aliasp = listhead; aliasp -> from[0] != '\0' && !anydone;
  16.        aliasp = aliasp -> next) {
  17.     if (wildmatch(name, aliasp -> from, &p1, &p2)) {
  18.       anydone = ON;
  19.       if ((c = strchr(aliasp -> to, '*')) == NULL)
  20.     strcpy(name, aliasp -> to);
  21.       else {
  22.     *c = '\0';
  23.     if ((int)strlen(aliasp -> to) + (p2 - p1) + (int)strlen(c + 1) <
  24.         MAXSTRINGLENGTH) {
  25.       strcpy(answer, aliasp -> to);
  26.       strncat(answer, p1, (size_t)(p2 - p1));
  27.       strcat(answer, c + 1);
  28.       *c = '*';
  29.       strcpy(name, answer);
  30.     }
  31.       }
  32.     }
  33.   }
  34.  
  35.   return(anydone);
  36.  
  37. }
  38.  
  39. #ifndef NODNS
  40. flag dnsresolve(char *hostn)
  41. {  /* assume dnsq and isdigit(hostn[0]) already tested */
  42.   flag done = FALSE;
  43.   extern int debug;
  44. #ifdef MAC
  45.   printf("Lookup for '%s'",hostn);
  46.   done=IpAddr2Name(hostn);
  47.   if (done)
  48.     printf(" gives '%s'.\n",hostn);
  49.   else
  50.     printf(" failed.\n");
  51. #else
  52.   unsigned long addr;
  53.   const char *addrp;
  54.   struct hostent *tempp;
  55.  
  56.   addr = inet_addr(hostn);
  57.   if (addr != INET_ADDR_ERR) {
  58.     addrp = (const char *) &addr;
  59.     tempp = gethostbyaddr(addrp, sizeof(struct in_addr), AF_INET);
  60.     if (tempp != NULL && tempp -> h_name[0] != '\0') {
  61.       if (debug >= 2)
  62.     fprintf(stderr, "D: %s -> %s\n", hostn, tempp -> h_name);
  63.       strncpy(hostn, tempp -> h_name, MAXSTRINGLENGTH - 1);
  64.       hostn[MAXSTRINGLENGTH - 1] = '\0';
  65.       done = TRUE;
  66.     }
  67.     else if (debug >= 2)
  68.       fprintf(stderr, "D: %s -> [unresolvable]\n", hostn);
  69.   }
  70. #endif
  71.   return(done);
  72. }
  73. #endif
  74.  
  75. int doaliashost(char *hostn)
  76. {   /* apply all required aliases to a hostname */
  77.   extern struct alias *hostaliashead;
  78. #ifndef NODNS
  79.   extern flag dnsq;
  80. #endif
  81.  
  82.   int anydone = OFF;
  83.   int i, j;
  84.  
  85.   /* DNS lookup */
  86.  
  87. #ifndef NODNS
  88.   if (dnsq && isdigit(hostn[0]) && isdigit(hostn[strlen(hostn) - 1]))
  89.     /* isdigit(hostn[0]) is quick test to save time before proper test */
  90.     anydone = (dnshashadd(hostn, (char *)NULL, (time_t)(-1)) -> alias != NULL);
  91. #endif
  92.  
  93.   /* remove trailing dots */
  94.  
  95.   j = (int)strlen(hostn);
  96.  
  97.   if (hostn[MAX(j - 1, 0)] == '.') {
  98.     hostn[j - 1] = '\0';
  99.     anydone = ON;
  100.   }
  101.  
  102.   /* convert to lower case */
  103.  
  104.   for (i = j - 1; i >= 0; i--) {
  105.     if (isupper(hostn[i])) {
  106.       hostn[i] = tolower(hostn[i]);
  107.       anydone = ON;
  108.     }
  109.   }
  110.  
  111.   /* alias conversion from configuration file */
  112.  
  113.   if (doaliaslist(hostn, hostaliashead))
  114.     anydone = ON;
  115.  
  116.   return(anydone);
  117.  
  118. }
  119.  
  120. char *reversehostname(char *hostn)
  121. {  /* reverse an internet hostname (cam.ac.uk -> uk.ac.cam). Return a pointer
  122.       to the reversed name, and leave the hostname changed on exit */
  123.  
  124.   char tempstr[MAXSTRINGLENGTH];
  125.   char *tempp;
  126.   int i = 0;
  127.  
  128.   while ((tempp = strrchr(hostn, '.')) != NULL) {
  129.     strcpy(tempstr + i, tempp + 1);
  130.     i = (int)strlen(tempstr);
  131.     tempstr[i] = '.';
  132.     i++;
  133.     *tempp = '\0';
  134.   }
  135.  
  136.   strcpy(tempstr + i, hostn);
  137.  
  138.   return(strcpy(hostn, tempstr));
  139.  
  140. }
  141.  
  142.  
  143. int doaliasfile(char *filename)
  144. {  /* apply all required aliases to a filename */
  145.  
  146.   extern int dirsufflength;
  147.   extern struct alias *filealiashead;
  148.   extern char *dirsuffix;
  149.   extern flag case_insensitive;
  150.  
  151.   int anydone = OFF;
  152.   char *tempp;
  153.   char tempstr[MAXSTRINGLENGTH];
  154.   unsigned int tempint = 0;
  155.  
  156.   /* First, change %7E to ~, etc. */
  157.   tempp = filename;
  158.   while ((tempp = strchr(tempp, '%')) != NULL) {
  159.     if (*(tempp + 1) != '\0' && *(tempp + 2) != '\0')
  160.       sscanf(tempp + 1, "%2x", &tempint);
  161.     if (tempint >= 0x20 && tempint < 0x7F) {
  162.       anydone = ON;
  163.       *tempp = tempint;
  164.       strcpy(tempstr, tempp + 3);
  165.       strcpy(tempp + 1, tempstr);
  166.       /* strcpy(tempp + 1, tempp + 3) may not be safe on all machines
  167.      (overlapping arguments) */
  168.     }
  169.     tempp++;
  170.   }
  171.  
  172.   /* Secondly, convert to lower case if desired */
  173.   /* If contains ?, already done at sscanf time */
  174.  
  175.   if (case_insensitive && strrchr(filename, '?') == NULL)
  176.     if(strtolowerf(filename))
  177.       anydone = ON;
  178.  
  179.   /* Thirdly, if it ends with the DIRSUFFIX (often index.html), strip it */
  180.  
  181.   if (dirsufflength > 0) {
  182.     if ((STREQ(filename + MAX((int)strlen(filename) - dirsufflength, 0),
  183.            dirsuffix)) &&
  184.       *(filename + MAX((int)strlen(filename) - dirsufflength - 1, 0)) == '/') {
  185.       filename[(int)strlen(filename) - dirsufflength] = '\0';
  186.       anydone = ON;
  187.     }
  188.   }
  189.  
  190.   /* Fourthly, // -> /  ;  /./ -> /  ;  /spam/../ -> /  (except  at start) */
  191.   /* We could worry about trailing /. and /.. but they should be 302 redirects
  192.      anyway so shouldn't matter */
  193.   /* NB On our server //Dept/ -> /Dept/, but //~sret1/ doesn't -> /~sret1/
  194.      But that doesn't matter because the latter will be 404 not found, so
  195.      won't ever get this far. Successes will have been interpreted in the
  196.      following way, and that's all we care about. */
  197.   /* NB Used to use 3 strstr()s. But that is very slow if we've got INCLUDEs
  198.      or EXCLUDEs (so have to alias every time). */
  199.  
  200.   tempp = filename;
  201.   while ((tempp = strchr(tempp, '/')) != NULL) {
  202.     if (*(tempp + 1) == '/') {
  203.       if (tempp != filename && *(tempp - 1) == ':')
  204.     tempp++;   /* Don't translate http:// ; just skip to next /  */
  205.       else {
  206.     anydone = ON;
  207.     strcpy(tempstr, tempp + 2);
  208.     strcpy(tempp + 1, tempstr);
  209.       }
  210.     }
  211.     else if (*(tempp + 1) == '.') {
  212.       if (*(tempp + 2) == '/') {
  213.     anydone = ON;
  214.     strcpy(tempstr, tempp + 3);
  215.     strcpy(tempp + 1, tempstr);
  216.       }
  217.       else if (*(tempp + 2) == '.' && *(tempp + 3) == '/') {
  218.     anydone = ON;
  219.     strcpy(tempstr, tempp + 4);
  220.     /* go back to prev slash (but not past // or start of name) */
  221.     if (tempp != filename && *(tempp - 1) != '/')
  222.       while (*(--tempp) != '/' && tempp != filename)
  223.         ;
  224.     strcpy(tempp + 1, tempstr);
  225.     if (tempp == filename)
  226.       *tempp = '/';
  227.       }
  228.       else
  229.     tempp++;
  230.     }
  231.     else
  232.       tempp++;
  233.   }
  234.  
  235.   /* Lastly, alias conversion from config. file */
  236.  
  237.   if (doaliaslist(filename, filealiashead))
  238.     anydone = ON;
  239.  
  240.   return(anydone);
  241.  
  242. }
  243.  
  244. int doaliasref(char *name)
  245. {        /* apply all required aliases to a referrer */
  246.          /* return 1 if any done, -1 if url corrupt or wrong type, 0 o/wise */
  247.  
  248.   extern struct alias *refaliashead;
  249.  
  250.   int anydone = OFF;
  251.   int defaultport = -1;
  252.   int tempint;
  253.   char *tempp, *tempp2;
  254.   char tempstr[MAXSTRINGLENGTH];
  255.   flag tempf;
  256.  
  257.   /* First, strip off #'s */
  258.   if ((tempp = strchr(name, '#')) != NULL) {
  259.     *tempp = '\0';
  260.     anydone = ON;
  261.   }
  262.  
  263.   /* Next, change %7E to ~, etc. */
  264.   tempp = name;
  265.   while ((tempp = strchr(tempp, '%')) != NULL) {
  266.     sscanf(tempp + 1, "%2x", &tempint);
  267.     if (tempint >= 0x20 && tempint < 0x7F) {
  268.       anydone = ON;
  269.       *tempp = tempint;
  270.       strcpy(tempstr, tempp + 3);
  271.       strcpy(tempp + 1, tempstr);
  272.       /* strcpy(tempp + 1, tempp + 3) may not be safe on all machines
  273.      (overlapping arguments) */
  274.     }
  275.     tempp++;
  276.   }
  277.  
  278.   /* Coerce method to lower case */
  279.  
  280.   for (tempp = name; *tempp != ':' && *tempp != '\0'; tempp++)
  281.     if (*tempp != tolower(*tempp)) {
  282.       *tempp = tolower(*tempp);
  283.       anydone = ON;
  284.     }
  285.   if (*tempp != ':')
  286.     return(-1);
  287.  
  288.   /* find out what sort of URL it is */
  289.  
  290.   *tempp = '\0';
  291.   if (STREQ(name, "http"))
  292.     defaultport = 80;
  293.   else if (STREQ(name, "ftp"))
  294.     defaultport = 21;
  295.   else if (STREQ(name, "file"))
  296.     return(-1);
  297.   else if (STREQ(name, "news"))
  298.     defaultport = 0;
  299.   else if (STREQ(name, "gopher"))
  300.     defaultport = 70;
  301.   else if (STREQ(name, "telnet"))
  302.     defaultport = 23;
  303.   else if (STREQ(name, "wais"))
  304.     defaultport = 210;
  305.   else if (STREQ(name, "nntp"))
  306.     defaultport = 119;
  307.   else if (STREQ(name, "prospero"))
  308.     defaultport = 1525;
  309.   else if (STREQ(name, "mailto"))
  310.     defaultport = 0;
  311.   *tempp = ':';
  312.  
  313.   /* Unless "news:" or unknown, check it has the // next and coerce hostname
  314.      to lower case */
  315.   
  316.   if (defaultport > 0) {
  317.     if (*(tempp + 1) != '/' || *(tempp + 2) != '/')
  318.       return(-1);
  319.     else for (tempp += 3; *tempp != '/' && *tempp != ':' && *tempp != '\0';
  320.           tempp++) {
  321.       if (*tempp != tolower(*tempp)) {
  322.     *tempp = tolower(*tempp);
  323.     anydone = ON;
  324.       }
  325.     }
  326.  
  327.     /* strip trailing .'s from hostname */
  328.  
  329.     for (tempp2 = tempp - 1; *tempp2 == '.'; tempp2--)
  330.       ;
  331.     if (tempp2 != tempp - 1) {
  332.       strcpy(tempstr, tempp);
  333.       tempp = tempp2 + 1;
  334.       strcpy(tempp, tempstr);
  335.       anydone = ON;
  336.     }
  337.  
  338.     /* strip leading 0s from port numbers and cross out default port numbers */
  339.  
  340.     if (*tempp == ':') {
  341.       while (*(tempp + 1) == '0') {
  342.     strcpy(tempstr, tempp + 2);
  343.     strcpy(tempp + 1, tempstr);
  344.       }
  345.       if ((tempp2 = strchr(tempp, '/')) != NULL) {
  346.     *tempp2 = '\0';
  347.     tempf = TRUE;
  348.       }
  349.       else
  350.     tempf = FALSE;
  351.       if (defaultport == atoi(tempp + 1)) {
  352.     strcpy(tempstr, "/");
  353.     if (tempf)
  354.       strcat(tempstr, tempp2 + 1);
  355.     strcpy(tempp, tempstr);
  356.     anydone = ON;
  357.       }
  358.       else if (tempf)
  359.     *tempp2 = '/';        /* restore slash */
  360.       else
  361.     strcpy(tempp + strlen(tempp), "/"); /* port but no pathname; + slash */
  362.     }
  363.  
  364.     /* trailing slash on methods without portname or pathname */
  365.  
  366.     else if (*tempp == '\0')
  367.       strcpy(tempp, "/");
  368.   }
  369.  
  370.   /* We probably don't want to change /./ -> / etc. even in http protocol,
  371.      because we don't want to make assumptions about other people's file
  372.      systems. */
  373.  
  374.   /* Finally, alias conversion from config. file */
  375.  
  376.   if(doaliaslist(name, refaliashead))
  377.     anydone = ON;
  378.  
  379.   return(anydone);
  380.  
  381. }
  382.  
  383. int doalias(char *name, char codeletter)
  384. {
  385.   if (codeletter == 'S')
  386.     return(doaliashost(name));
  387.   else if (codeletter == 'r')
  388.     return(doaliasfile(name));
  389.   else /* codeletter == 'f' */
  390.     return(doaliasref(name));
  391. }
  392.     
  393.  
  394. /* Now a function to run through all hosts, files or refs doing all aliases */
  395.  
  396. void allaliases(struct genstruct **objhead, struct genstruct **objhead2,
  397.         size_t hashsize, int *totalobjs, int *totalobjs7,
  398.         int *totalnew7, char code)
  399. {
  400.   int onlist;
  401.   struct genstruct *p, *nextp;
  402.  
  403.   onlist = 0;                      /* the list of items we are on */
  404.   p = objhead[0];                  /* starting at list 0 */
  405.   for ( ; onlist < hashsize; p = nextp)   {  /* run through items */
  406.     if (p -> name == NULL)           /* then finished this list */
  407.       nextp = objhead[++onlist];     /* so start the next list */
  408.     else {
  409.       if (p -> wanted)    /* file the alias if any, else original name */
  410.     hashadd(objhead2, hashsize,
  411.         (p -> alias == NULL)?(p -> name):(p -> alias), p -> reqs,
  412.         p -> bytes, p -> pages, p -> last7 * (1 + p -> pre7),
  413.         totalobjs, totalobjs7, totalnew7, ON, OFF, p -> ispage, p,
  414.         (p -> alias == NULL)?onlist:(-1), code);
  415.       nextp = p -> next;
  416.     }
  417.  
  418.   }   /* end for all items */
  419.  
  420. }
  421.  
  422. int hosttodomcode(char *hostn)
  423. {    /* find the domain code for a certain hostname */
  424.  
  425.   extern struct domain **ohead;
  426.  
  427.   char domainname[MAXSTRINGLENGTH];
  428.   register int i;
  429.  
  430.   int x;
  431.  
  432.   /* first change hostn into a domain */
  433.  
  434.   for (i = (int)strlen(hostn) - 1; hostn[i] != '.' && i > 0; i--)
  435.     ;     /* run back to final '.' (or initial char) */
  436.  
  437.   if (isdigit(hostn[i + 1]))
  438.     return(DOMHASHSIZE - 1);   /* representing numerical hosts */
  439.  
  440.   if (i == 0)
  441.     return(DOMHASHSIZE - 2);   /* representing unknown hosts */
  442.  
  443.   strcpy(domainname, hostn + i + 1);
  444.         
  445.   x = (domainname[0] - 'a') * 52 + (domainname[1] - 'a') * 2 +
  446.     (domainname[2] != '\0');
  447.  
  448.   if (x < 0 || x > DOMHASHSIZE - 3)  /* some funny characters messed it up */
  449.     return(DOMHASHSIZE - 2);
  450.  
  451.   if (ohead[x] -> name == NULL)
  452.     return(DOMHASHSIZE - 2);      /* no domain at that domaincode */
  453.  
  454.   if (!STREQ(ohead[x] -> id, domainname))
  455.     return(DOMHASHSIZE - 2);      /* right code, nevertheless wrong domain */
  456.  
  457.   return(x);
  458.  
  459. }
  460.  
  461. void urltodir(char *filename)
  462. {  /* converts a filename to a dir for a level 'dirlevel' directory report */
  463.  
  464.   extern int dirlevel;
  465.  
  466.   register int i = 0, j;
  467.  
  468.   for (j = 0; j < dirlevel; j++) {
  469.     if (filename[i] == '/')
  470.       i++;
  471.     for ( ; filename[i] != '/' && filename[i] != '\0'; i++)
  472.       ;     /* run through to level'th slash, if any */
  473.   }
  474.   
  475.   if (filename[i] == '\0')   /* not j levels; run back */
  476.     for ( i-- ; filename[i] != '/' && i > 0; i--)
  477.       ;
  478.  
  479.   if (filename[i] != '/')
  480.     strcpy(filename, "[no directory]");
  481.   else {
  482.     filename[i + 1] = '\0';     /* Terminate it straight after the / */
  483.     if (i == 0)
  484.       strcpy(filename, "[root directory]");
  485.   }
  486.  
  487. }
  488.  
  489. char *urltoext(char *filename)
  490. {  /* finds the extension (file type) of a given filename */
  491.  
  492.   char *answer;
  493.   int len;
  494.   char *p;
  495.  
  496.   len = strlen(filename);
  497.   if (len == 0) {
  498.     answer = (char *)xmalloc(14);
  499.     strcpy(answer, "(no extension)");
  500.   }
  501.   else if (filename[len - 1] == '/') {
  502.     answer = (char *)xmalloc(13);
  503.     strcpy(answer, "(directories)");
  504.   }
  505.   else {
  506.     for (p = filename + len - 1; *p != '.' && *p != '/' && p != filename; p--)
  507.       ;   /* run back to the final dot */
  508.     if (*p == '.' && p != filename + len - 1)
  509.       answer = p;
  510.     else {
  511.       answer = (char *)xmalloc(14);      
  512.       strcpy(answer, "(no extension)");
  513.     }
  514.   }
  515.  
  516.   return(answer);
  517. }
  518.  
  519. /* whether a certain string is wanted given a list of includes and excludes */
  520. /* NB Need to make sure aliases have been done before calling this */
  521. /* ispage says whether it's a page if we know, else UNSET */
  522.  
  523. flag included(char *name, flag ispage, struct include *listhead)
  524. {
  525.   extern struct include *ispagehead;
  526.  
  527.   struct include *stringp;
  528.   flag answer;
  529.   char *tempp1, *tempp2;
  530.  
  531.   if (listhead -> in == TRUE)
  532.     answer = FALSE;
  533.   else
  534.     answer = TRUE;
  535.  
  536.   for (stringp = listhead; stringp -> in != UNSET;
  537.        stringp = stringp -> next) {
  538.     if (STREQ(stringp -> name, "pages") && listhead != ispagehead) {
  539.       if (ispage == TRUE ||
  540.       (ispage == UNSET && included(name, UNSET, ispagehead))) {
  541.     if (stringp -> in == TRUE)
  542.       answer = TRUE;
  543.     else
  544.       answer = FALSE;
  545.       }
  546.     }
  547.     else if (wildmatch(name, stringp -> name, &tempp1, &tempp2)) {
  548.       if (stringp -> in == TRUE)
  549.     answer = TRUE;
  550.       else
  551.     answer = FALSE;
  552.     }
  553.   }
  554.  
  555.   return(answer);
  556. }
  557.  
  558. /* use included() to see whether a certain item is wanted */
  559.  
  560. flag itemwanted(char *name, flag ispage, char codeletter)
  561. {
  562.   extern struct include *wantfilehead, *wanthosthead, *wantrefhead;
  563.  
  564.   if (codeletter == 'S')
  565.     return(included(name, ispage, wanthosthead));
  566.   else if (codeletter == 'r')
  567.     return(included(name, ispage, wantfilehead));
  568.   else /* codeletter == 'f' */
  569.     return(included(name, ispage, wantrefhead));
  570. }
  571.