/*
 *  Program to extract URL's from AWeb cache data file
 */

#include <sys/types.h>
#include <stdio.h>
#include <ctype.h>

#define getl_be(a) (  ((u_long)(((u_char *)(a))[3]))        \
                    + ((u_long)(((u_char *)(a))[2]) << 8)   \
                    + ((u_long)(((u_char *)(a))[1]) << 16)  \
                    + ((u_long)(((u_char *)(a))[0]) << 24))

FILE *f1_p;
char *blkbuf;

static const char PROGVER[] =
  "\0$VER: urla V1.00 ** (c) Jul 99 ** frans";

static const char USAGE[] =
  "usage: urla [aweb_history_filename]";

void cleanup(void)
{
  if (f1_p)
    fclose(f1_p);
  if (blkbuf)
    free(blkbuf);
}

void shutdown(char *msg, ...)
{
  vprintf(msg, (void *)(&msg + 1));
  exit(0);
}

void usage(void)
{
  shutdown("%s\n\n%s\n\n", PROGVER + 7, USAGE);
}

void *xalloc(long len)
{
  char *p;
  if ((p = (char *)malloc(len)) == 0)
    shutdown("out of memory\n");
  return (void *)p;
}

char *ultoa_f(
  unsigned long n,char *buf,int radix,int len,char pre)
{
  char *p = (buf += len);
  *buf = 0;
  do
  {
    *--buf ="0123456789ABCDEF"[n % radix];
  } while((--len) && (n /= radix));
  while(len--)
    *--buf = pre;
  return p;
}

hexdump(char *buf, long address, long len)
{
  long c, cnt = 0;
  char obuf[80], *op1, *op2;

  while (len != 0)
  {
    if ((cnt & 15) == 0)
    {
      op1 = ultoa_f(address, obuf, 16, 6, '0');
      *op1++ = ':';
      op2 = obuf + 44;
    }
    c = (*buf++) & 0xFF;
    if ((cnt & 3) == 0)
      *op1++ = ' ';
    op1 = ultoa_f(c, op1, 16, 2, '0');
    *op2++ = (c > 31 && c < 127) ? c : '.';
    *op2 = 0;
    cnt++;
    address++;
    len--;
    if ((cnt & 15) == 0 || len == 0)
    {
      while (op1 - obuf < 44)
        *op1++ = ' ';
      printf("%ls\n", obuf);
    }
  }
  return cnt;
}

char *getnum(char *s, long *np)
{
  long n, h, sign = 1;
  char c;
  while (*s == ' ' || *s == '\t')
    s++;
  if (*s == '-')
    s++, sign = -1;
  n = 0;
  if (*s == '$' || (*s == '0' && *++s == 'x'))
  {
    s++;
    while (isxdigit(*s))
    {
      c = *s++;
      h = ((c < 58) ? c - 48 : ((c < 96) ? c - 55 : c - 87));
      n = (n << 4) + h;
    }
  }
  else
  {
    while (isdigit(*s))
    {
      h = *s++ - 48;
      n = n * 10 + h;
    }
  }
  *np = n * sign;
  return s;
}

int main(int argc, char **argv)
{
  int     i, quiet_f, verbose_f;
  long    f1_len, len, ulen;
  char    *f1_name, *p;
  u_long  second, third;

  f1_p     = 0;
  blkbuf   = 0;
  f1_name  = 0;

  quiet_f  = verbose_f = 0;

  atexit(cleanup);

  for (i = 1; i < argc; i++)
  {
    if (*(p = argv[i]) == '-')
    {
      switch (*++p)
      {
      case 'v':
        verbose_f = 1;
        if (*++p == 'v')
          verbose_f = 2;
        break;
      case 'q':
        quiet_f = 1;
        if (*++p == 'q')
          quiet_f = 2;
        break;
      default:
        usage();
      }
    }
    else if (f1_name == 0)
      f1_name = p;
    else
      usage();
  }
  if (f1_name == 0)
    f1_name = "AWCR";

  if (!quiet_f)
    printf("%s\n\n", PROGVER + 7);

  if ((f1_p = fopen(f1_name, "rb")) == 0)
    shutdown("Couldn't open input file %s\n", f1_name);

  fseek(f1_p, 0L, 2);
  f1_len = ftell(f1_p);
  fseek(f1_p, 0L, 0);

  if ((len = f1_len) != 0)
    blkbuf = xalloc(f1_len);

  if (fread(blkbuf, f1_len, 1, f1_p) != 1)
    shutdown("read error\n");

  /*
   *  now whole file is in buffer so scan it
   */

  p = blkbuf; p += 4;

  second = getl_be(p); p += 4;
  third  = getl_be(p); p += 4;

  while (p - blkbuf < len)
  {
    u_long tag, flen;

    tag  = getl_be(p); p += 4;

    p += 12;

    flen = getl_be(p); p += 4;

    ulen = getl_be(p); p += 4; ulen &= 0xFFFF;

    while (*p++ != 0) ;

    while (ulen && *p != 0)
    {
      printf("%c", *p++); ulen--;
    }
    printf("\n");

    while (ulen--)
      p++;
  }

  exit(0);
}
