ftp.nice.ch/pub/next/unix/network/www/analog.NIHS.bs.gnutar.gz#/analog/analform.c

This is analform.c in view mode; [Download] [Up]

/* analform.c 1.9beta -- parse the output of the analog form interface */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* You must change the next line to indicate where the analog program lives */

#define COMMAND "/http/cgi-bin/analog"
#define MAXARGLENGTH (2048)   /* should be plenty */
#define OK (0)
#define ERR (-1)
#define STRLENGTH (64)

typedef int flag;

void unhttp(char *url)     /* converts back all http special characters */
{
  char *tempp;
  char tempstr[MAXARGLENGTH];
  int i;

  /* firstly, change +'s into spaces */

  for (i = strlen(url) - 1; i >= 0; i--) {
    if (url[i] == '+')
      url[i] = ' ';
  }

  /* secondly change %7E to ~, etc. */

  tempp = url;
  while ((tempp = strchr(tempp, '%')) != NULL) {
    sscanf(tempp + 1, "%2x", &i);
    if (i >= 0x20 && i < 0x7F) {
      *tempp = i;
      strcpy(tempstr, tempp + 3);
      strcpy(tempp + 1, tempstr);
      /* strcpy(tempp + 1, tempp + 3) may not be safe on all machines
	 (overlapping arguments) */
    }
    tempp++;
  }

}

void genopts(FILE *thepipe, char name[9], int sortby, char *astr, char *cstr)
{
  fprintf(thepipe, "%sSORTBY ", name);
  if (sortby == 3)
    fprintf(thepipe, "RANDOM\n");
  else if (sortby == 2)
    fprintf(thepipe, "ALPHABETICAL\n");
  else if (sortby == 1)
    fprintf(thepipe, "BYTES\n");
  else
    fprintf(thepipe, "REQUESTS\n");
  if (sortby == 1) {
    if (cstr[0] != '\0')
      fprintf(thepipe, "%sMINBYTES %s\n", name, cstr);
  }
  else {
    if (astr[0] != '\0')
      fprintf(thepipe, "%sMINREQS %s\n", name, astr);
  }
}

int main()
{
  extern void exit();

  /* the input */
  char *argstring;
  char *nextarg;
  char *nextval;

  /* the variables that can be read in */
  int xq = 0, mq = 0, Wq = 0, dq = 0, Dq = 0, hq = 0, oq = 0, Sq = 0;
  int iq = 0, rq = 0, fq = 0, bq = 0, Bq = 0, cq = 0, eq = 0, Hq = 0;
  char mg = '\0', Wg = '\0', dg = '\0', Dg = '\0', hg = '\0', Hg = '\0';
  int os, Ss, is, rs, fs, Bs, bs;
  int ou = 0;
  char oa[STRLENGTH], Sa[STRLENGTH], ia[STRLENGTH], ra[STRLENGTH];
  char fa[STRLENGTH], Ba[STRLENGTH], ba[STRLENGTH];
  char oc[STRLENGTH], Sc[STRLENGTH], ic[STRLENGTH], rc[STRLENGTH];
  char fc[STRLENGTH], Bc[STRLENGTH], bc[STRLENGTH];
  int dirlevel;
  char reqtype, reqlinks;
  char *from = NULL, *to = NULL;
  char *fonly = NULL, *fign = NULL;
  char *honly = NULL, *hign = NULL;
  char *org = NULL, *home = NULL;
  char *logfile, *reflog, *browlog, *errlog, *cachefile;
  char *TZ = NULL;
  char TZenv[STRLENGTH];

  FILE *thepipe;
  int ret;

  oa[0] = '\0';
  Sa[0] = '\0';
  ia[0] = '\0';
  ra[0] = '\0';
  fa[0] = '\0';
  ba[0] = '\0';
  Ba[0] = '\0';
  oc[0] = '\0';
  Sc[0] = '\0';
  ic[0] = '\0';
  rc[0] = '\0';
  fc[0] = '\0';
  bc[0] = '\0';
  Bc[0] = '\0';

  if ((argstring = getenv("QUERY_STRING")) == NULL) {
    printf("Content-type: text/plain\n\n");
    printf("Error: cannot find environment variable QUERY_STRING\n");
    exit(ERR);
  }

  unhttp(argstring);

  nextarg = strtok(argstring, "&");

  while (nextarg != NULL) {
    nextval = strchr(nextarg, '=') + 1;
    if (nextval[0] != '\0') {
      switch(nextarg[0]) {
      case 'b':
	switch(nextarg[1]) {
	case 'a':
	  strcpy(ba, nextval);
	  break;
	case 'b':
	  strcpy(ba, "-");
	  strcat(ba, nextval);
	  break;
	case 'c':
	  strcpy(bc, nextval);
	  break;
	case 'd':
	  strcpy(bc, "-");
	  strcat(bc, nextval);
	  break;
	case 'q':
	  bq = atoi(nextval);
	  break;
	case 's':
	  bs = atoi(nextval);
	  break;
	}
	break;
      case 'B':
	switch(nextarg[1]) {
	case 'a':
	  strcpy(Ba, nextval);
	  break;
	case 'b':
	  strcpy(ba, "-");
	  strcat(ba, nextval);
	  break;
	case 'c':
	  strcpy(Bc, nextval);
	  break;
	case 'd':
	  strcpy(Bc, "-");
	  strcat(Bc, nextval);
	  break;
	case 'q':
	  Bq = atoi(nextval);
	  break;
	case 's':
	  Bs = atoi(nextval);
	  break;
	}
	break;
      case 'c':
	cq = atoi(nextval);
	break;
      case 'd':
	switch(nextarg[1]) {
	case 'g':
	  dg = nextval[0];
	  break;
	case 'q':
	  dq = 1;
	  break;
	}
	break;
      case 'D':
	switch(nextarg[1]) {
	case 'g':
	  Dg = nextval[0];
	  break;
	case 'q':
	  Dq = 1;
	  break;
	}
	break;
      case 'e':
	eq = atoi(nextval);
	break;
      case 'f':
	switch(nextarg[1]) {
	case 'a':
	  strcpy(fa, nextval);
	  break;
	case 'b':
	  strcpy(fa, "-");
	  strcat(fa, nextval);
	  break;
	case 'c':
	  strcpy(fc, nextval);
	  break;
	case 'd':
	  strcpy(fc, "-");
	  strcat(fc, nextval);
	  break;
	case 'i':
	  fign = nextval;
	  break;
	case 'q':
	  fq = atoi(nextval);
	  break;
	case 'r':
	  from = nextval;
	  break;
	case 's':
	  fs = atoi(nextval);
	  break;
	case 'y':
	  fonly = nextval;
	  break;
	}
	break;
      case 'h':
	switch(nextarg[1]) {
	case 'g':
	  hg = nextval[0];
	  break;
	case 'i':
	  hign = nextval;
	  break;
	case 'o':
	  home = nextval;
	  break;
	case 'q':
	  hq = 1;
	  break;
	case 'y':
	  honly = nextval;
	  break;
	}
	break;
      case 'H':
	switch(nextarg[1]) {
	case 'g':
	  Hg = nextval[0];
	  break;
	case 'q':
	  Hq = atoi(nextval);
	  break;
	}
	break;
      case 'i':
	switch(nextarg[1]) {
	case 'a':
	  strcpy(ia, nextval);
	  break;
	case 'b':
	  strcpy(ia, "-");
	  strcat(ia, nextval);
	  break;
	case 'c':
	  strcpy(ic, nextval);
	  break;
	case 'd':
	  strcpy(ic, "-");
	  strcat(ic, nextval);
	  break;
	case 'e':
	  dirlevel = atoi(nextval);
	  break;
	case 'q':
	  iq = atoi(nextval);
	  break;
	case 's':
	  is = atoi(nextval);
	  break;
	}
	break;
      case 'l':
	switch(nextarg[1]) {
	case 'b':
	  browlog = nextval;
	  break;
	case 'c':
	  cachefile = nextval;
	  break;
	case 'e':
	  errlog = nextval;
	  break;
	case 'f':
	  reflog = nextval;
	  break;
	case 'o':
	  logfile = nextval;
	  break;
	}
	break;
      case 'm':
	switch(nextarg[1]) {
	case 'g':
	  mg = nextval[0];
	  break;
	case 'q':
	  mq = 1;
	  break;
	}
	break;
      case 'o':
	switch(nextarg[1]) {
	case 'a':
	  strcpy(oa, nextval);
	  break;
	case 'b':
	  strcpy(oa, "-");
	  strcat(oa, nextval);
	  break;
	case 'c':
	  strcpy(oc, nextval);
	  break;
	case 'd':
	  strcpy(oc, "-");
	  strcat(oc, nextval);
	  break;
	case 'q':
	  oq = atoi(nextval);
	  break;
	case 'r':
	  org = nextval;
	  break;
	case 's':
	  os = atoi(nextval);
	  break;
	case 'u':
	  ou = atoi(nextval);
	  break;
	}
	break;
      case 'r':
	switch(nextarg[1]) {
	case 'a':
	  strcpy(ra, nextval);
	  break;
	case 'b':
	  strcpy(ra, "-");
	  strcat(ra, nextval);
	  break;
	case 'c':
	  strcpy(rc, nextval);
	  break;
	case 'd':
	  strcpy(rc, "-");
	  strcat(rc, nextval);
	  break;
	case 'l':
	  reqlinks = nextval[0];
	  break;
	case 'q':
	  rq = atoi(nextval);
	  break;
	case 's':
	  rs = atoi(nextval);
	  break;
	case 't':
	  reqtype = nextval[0];
	  break;
	}
	break;
      case 'S':
	switch(nextarg[1]) {
	case 'a':
	  strcpy(Sa, nextval);
	  break;
	case 'b':
	  strcpy(Sa, "-");
	  strcat(Sa, nextval);
	  break;
	case 'c':
	  strcpy(Sc, nextval);
	  break;
	case 'd':
	  strcpy(Sc, "-");
	  strcat(Sc, nextval);
	  break;
	case 'q':
	  Sq = atoi(nextval);
	  break;
	case 's':
	  Ss = atoi(nextval);
	  break;
	}
	break;
      case 't':
	to = nextval;
	break;
      case 'T':
	TZ = nextval;
	break;
      case 'W':
	switch(nextarg[1]) {
	case 'g':
	  Wg = nextval[0];
	  break;
	case 'q':
	  Wq = 1;
	  break;
	}
	break;
      case 'x':
	xq = 1;
	break;
      }
    }
    nextarg = strtok((char *)NULL, "&");
  }

  /* OK, so we've read everything in, now send it to the program */
  
  if (TZ != NULL) {
    strcpy(TZenv, "TZ=");
    strcat(TZenv, TZ);
    putenv(TZenv);
  }

  if ((thepipe = popen(COMMAND " +g-", "w")) == NULL) {
    printf("Content-type: text/plain\n\n");
    printf("Error: cannot start analog program at %s\n", COMMAND);
  }

  else {
    printf("Content-type: text/html\n\n");
    fflush(stdout);

    fprintf(thepipe, "OUTFILE stdout\n");

    if (xq < 2)
      fprintf(thepipe, "GENERAL %s\n", xq?"ON":"OFF");
    if (mq < 2)
      fprintf(thepipe, "MONTHLY %s\n", mq?"ON":"OFF");
    if (Wq < 2)
      fprintf(thepipe, "WEEKLY %s\n", Wq?"ON":"OFF");
    if (dq < 2)
      fprintf(thepipe, "DAILY %s\n", dq?"ON":"OFF");
    if (Dq < 2)
      fprintf(thepipe, "FULLDAILY %s\n", Dq?"ON":"OFF");
    if (hq < 2)
      fprintf(thepipe, "HOURLY %s\n", hq?"ON":"OFF");
    if (Hq < 2)
      fprintf(thepipe, "FULLHOURLY %s\n", Hq?"ON":"OFF");
    if (oq < 2)
      fprintf(thepipe, "DOMAIN %s\n", oq?"ON":"OFF");
    if (Sq < 2)
      fprintf(thepipe, "FULLHOSTS %s\n", Sq?"ON":"OFF");
    if (iq < 2)
      fprintf(thepipe, "DIRECTORY %s\n", iq?"ON":"OFF");
    if (rq < 2)
      fprintf(thepipe, "REQUEST %s\n", rq?"ON":"OFF");
    if (bq < 2)
      fprintf(thepipe, "BROWSER %s\n", bq?"ON":"OFF");
    if (Bq < 2)
      fprintf(thepipe, "FULLBROWSER %s\n", Bq?"ON":"OFF");
    if (cq < 2)
      fprintf(thepipe, "STATUS %s\n", bq?"ON":"OFF");
    if (eq < 2)
      fprintf(thepipe, "ERROR %s\n", bq?"ON":"OFF");
    if (fq < 2)
      fprintf(thepipe, "REFERER %s\n", bq?"ON":"OFF");

    if (mq && mg != '\0')
      fprintf(thepipe, "MONTHGRAPH %c", mg);
    if (Wq && Wg != '\0')
      fprintf(thepipe, "WEEKGRAPH %c", Wg);
    if (hq && hg != '\0')
      fprintf(thepipe, "HOURGRAPH %c", hg);
    if (Hq && Hg != '\0')
      fprintf(thepipe, "FULLHOURGRAPH %c", Hg);
    if (dq && dg != '\0')
      fprintf(thepipe, "DAYGRAPH %c", dg);
    if (Dq && Dg != '\0')
      fprintf(thepipe, "FULLDAYGRAPH %c", Dg);

    if (oq)
      genopts(thepipe, "DOM", os, oa, oc);
    if (Sq)
      genopts(thepipe, "HOST", Ss, Sa, Sc);
    if (iq) {
      genopts(thepipe, "DIR", is, ia, ic);
      fprintf(thepipe, "DIRLEVEL %d\n", dirlevel);
    }
    if (rq) {
      genopts(thepipe, "REQ", rs, ra, rc);
      fprintf(thepipe, "REQTYPE %s\n", reqtype=='f'?"ALL":"PAGES");
      fprintf(thepipe, "PAGELINKS %s\n", reqlinks=='f'?"ALL":(reqlinks=='p'?"ON":"OFF"));
    }
    if (bq)
      genopts(thepipe, "BROW", bs, ba, bc);
    if (Bq)
      genopts(thepipe, "FULLBROW", Bs, Ba, Bc);
    if (fq)
      genopts(thepipe, "REF", fs, fa, fc);

    fprintf(thepipe, "OUTPUT %s\n", ou?"ASCII":"HTML");

    if (from != NULL)
      fprintf(thepipe, "FROM %s\n", from);
    if (to != NULL)
      fprintf(thepipe, "TO %s\n", to);
    if (org != NULL)
      fprintf(thepipe, "HOSTNAME \"%s\"\n", org);
    if (home != NULL)
      fprintf(thepipe, "HOSTURL %s\n", home);
    else
      fprintf(thepipe, "HOSTURL -\n");
    
    /* That just leaves the only's and ignore's and logfiles, which are a bit
       more complicated as we have to parse them still. Recycle 'nextarg'. */

    nextarg = strtok(fonly, " ,");   /* split at spaces and commas */
    while (nextarg != NULL) {
      fprintf(thepipe, "FILEINCLUDE %s\n", nextarg);
      nextarg = strtok((char *)NULL, " ,");
    }

    nextarg = strtok(fign, " ,");
    while (nextarg != NULL) {
      fprintf(thepipe, "FILEEXCLUDE %s\n", nextarg);
      nextarg = strtok((char *)NULL, " ,");
    }

    nextarg = strtok(honly, " ,");
    while (nextarg != NULL) {
      fprintf(thepipe, "HOSTINCLUDE %s\n", nextarg);
      nextarg = strtok((char *)NULL, " ,");
    }

    nextarg = strtok(hign, " ,");
    while (nextarg != NULL) {
      fprintf(thepipe, "HOSTEXCLUDE %s\n", nextarg);
      nextarg = strtok((char *)NULL, " ,");
    }

    nextarg = strtok(browlog, " ,");
    while (nextarg != NULL) {
      fprintf(thepipe, "BROWLOG %s\n", nextarg);
      nextarg = strtok((char *)NULL, " ,");
    }

    nextarg = strtok(errlog, " ,");
    while (nextarg != NULL) {
      fprintf(thepipe, "ERRLOG %s\n", nextarg);
      nextarg = strtok((char *)NULL, " ,");
    }

    nextarg = strtok(reflog, " ,");
    while (nextarg != NULL) {
      fprintf(thepipe, "REFLOG %s\n", nextarg);
      nextarg = strtok((char *)NULL, " ,");
    }

    nextarg = strtok(logfile, " ,");
    while (nextarg != NULL) {
      fprintf(thepipe, "LOGFILE %s\n", nextarg);
      nextarg = strtok((char *)NULL, " ,");
    }

    nextarg = strtok(cachefile, " ,");
    while (nextarg != NULL) {
      fprintf(thepipe, "CACHEFILE %s\n", nextarg);
      nextarg = strtok((char *)NULL, " ,");
    }

  }

  fflush(thepipe);
  ret = pclose(thepipe);
  if (ret != 0) {
    printf("Analog failed to run or returned an error code.\n");
    printf("Maybe your server's error log will give a clue why.\n");
  }
  fflush(stdout);
  exit(ret);

}
extern int putenv(char *newval)
{
    extern char **environ;

    static int firstTime = 1;
    char **ep;
    char *cp;
    int esiz;
    char *np;

    if (!(np = strchr(newval, '=')))
	return 1;
    *np = '\0';

    /* look it up */
    for (ep=environ ; *ep ; ep++)
    {
	/* this should always be true... */
	if (cp = strchr(*ep, '='))
	{
	    *cp = '\0';
	    if (!strcmp(*ep, newval))
	    {
		/* got it! */
		*cp = '=';
		break;
	    }
	    *cp = '=';
	}
	else
	{
	    *np = '=';
	    return 1;
	}
    }

    *np = '=';
    if (*ep)
    {
	/* the string was already there: just replace it with the new one */
	*ep = newval;
	return 0;
    }

    /* expand environ by one */
    for (esiz=2, ep=environ ; *ep ; ep++)
	esiz++;
    if (firstTime)
    {
	char **epp;
	char **newenv;
	if (!(newenv = malloc(esiz * sizeof(char *))))
	    return 1;
   
	for (ep=environ, epp=newenv ; *ep ;)
	    *epp++ = *ep++;
	*epp++ = newval;
	*epp = (char *) 0;
	environ = newenv;
    }
    else
    {
	if (!(environ = realloc(environ, esiz * sizeof(char *))))
	    return 1;
	environ[esiz - 2] = newval;
	environ[esiz - 1] = (char *) 0;
	firstTime = 0;
    }

    return 0;
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.