/*
 * dummied-up type 3 binary packet tosser demo (a "viewer," actually)
 * displays contents of packet ("3PAKT000.000" default) to screen.
 * Public Domain from M. Kimes
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "3binary.h"

#define NUMTYPES 28
char *typenames[] = {"EOP:      ","FROM:     ","TO:       ","SUBJECT:  ",
                     "ID:       ","REF:      ","DATE:     ","ATTRIB:   ",
                     "PASSWORD: ","PRODUCT:  ","ECHO:     ","MSG:      ",
                     "TEXT:     ","ORIG:     ","ORIGID:   ","FONT:     ",
                     "CHARSET:  ","RICH:     ","SUB:      ","GROUP:    ",
                     "ATTACH:   ","DEST:     ","QUOTE:    ","GLOBAL:   ",
                     "ENCRYPT:  ","ADD:      ","DROP:     ","REPORT:   "};


void process_unknown_chunk3(FILE *handle,USHORT type,long chunklen,int *error) {

  /* handle unknown master chunks here */

  printf("\n\n ***Unknown chunk #%d  Len %ld ignored...\n",type,chunklen);
}


void end_3bmsg (void *priv,CHUNK3 *pkt3,CHUNK3 *msg3,CHUNK3 *globals) {

  /* dummy "callback" function; we don't need it for these purposes */
}


void show_text (char *text,SHORT dlen,int trans) {

  register SHORT len = dlen;
  register char *p = text;

  if(trans) {
    while(*p && len) {
      fputc(*p,stdout);
      if(*p == '\r')
        fputc('\n',stdout);
      p++;
      len--;
    }
  }
  else {
    while(len) {
      if(isprint(*p))
        fputc(*p,stdout);
      else
        printf("[%02hX]",*p);
      p++;
      len--;
    }
  }
}


void show_data (char *data,SHORT len,SHORT type) {

  switch(type) {
    case TEXT3:
      fputc('\n',stdout);
      show_text(data,len,1);
      break;

    case ID3:
      printf("%08lx",*(long *)data);
      break;

    case REF3:
      printf("%08lx",*(long *)data);
      show_text(data + 4,len - 4,0);
      break;

    case ENCRYPT3:
    case QUOTE3:
      show_text(data + sizeof(SHORT),*(SHORT *)data,0);
      fputc('\n',stdout);
      show_text(data + (*(SHORT *)data) + sizeof(SHORT) + (*(SHORT *)data %
                sizeof(SHORT)) + sizeof(SHORT), *(SHORT *)data +
                (*(SHORT *)data) + sizeof(SHORT) + (*(SHORT *)data %
                sizeof(SHORT)), 1);
      break;

    case ATTRIB3:
      {
        int x;

        for(x = 0;x < 32;x++)
          fputc((*(long *)data & (1 << x)) ? '+' : '-',stdout);
      }
      break;

    case DATE3:
      if((*(BINDATE3 *)data).year) {
        printf("%4u/%02hu/%02hu %02hu:%02hu:%02hu",
               (*(BINDATE3 *)data).year,(*(BINDATE3 *)data).mon,
               (*(BINDATE3 *)data).mday,(*(BINDATE3 *)data).hour,
               (*(BINDATE3 *)data).min,(*(BINDATE3 *)data).sec);
        if((*(BINDATE3 *)data).gmtoff != -32767)
          printf(" %d",(*(BINDATE3 *)data).gmtoff);
      }
      break;

    default:
      show_text(data,len,0);
      break;
  }
  fflush(stdout);
}


int import_3bmsg (void *dummy,CHUNK3 *pkt3,CHUNK3 *msg3,CHUNK3 *globals,
                  long msglen,int *error) {

  /*
   * this function is called to import/forward the message
   * this version of it just displays the contents of the message
   * doesn't interact with every damned type available (for
   * instance, insists on either a TO chunk (netmail) and/or an ECHO
   * chunk; doesn't allow for GROUP chunk...
   */

  static long      nummsgs = 0L;
  register CHUNK3 *info;

  *error = NOERR3;
  printf("\n\n ***Msg #%ld  Len %ld:\n",++nummsgs,msglen);

  info = globals;
  while(info) {
    fputs("\n **Global ",stdout);
    if(info->type < NUMTYPES)
      fputs(typenames[info->type],stdout);
    else
      printf(" UNKNOWN (%d):  ",info->type);
    if(info->len)
      show_data((char *)info->data,info->len,info->type);
    info = info->next;
  }
  info = msg3;
  while(info) {
    fputs("\n **Msg ",stdout);
    if(info->type < NUMTYPES)
      fputs(typenames[info->type],stdout);
    else
      printf(" UNKNOWN (%d):  ",info->type);
    if(info->len)
      show_data((char *)info->data,info->len,info->type);
    info = info->next;
  }
  fflush(stdout);

  return 0;
}


int check_3bpkthdr (void *dummy,char *fname,CHUNK3 *pkt3,CHUNK3 *globals,
                    long hdrlen,int *error) {

  /*
   * this "callback" function should check packet header and decide
   * if you want to process the packet.  return 0 if so, anything
   * else if not.
   */

  register CHUNK3 *info;

  *error = NOERR3;
  printf("\n\n ***Pkt Hdr  Len %ld:\n",hdrlen);
  info = pkt3;
  while(info) {
    fputs("\n **Pkt ",stdout);
    if(info->type < NUMTYPES)
      fputs(typenames[info->type],stdout);
    else
      printf(" UNKNOWN (%d):  ",info->type);
    if(info->len)
      show_data((char *)info->data,info->len,info->type);
    info = info->next;
  }
  fflush(stdout);

  return 0;
}



int main (int argc,char *argv[]) {

  int   error;
  char *pname = "3PAKT000.000";

  if(argc > 1)
    pname = argv[1];

  printf("\n3VIEWPKT    type 3binary packet viewer example\n");
  printf("\n\n\n ****\"Processed\" %ld msgs\n",
         process_pkt3(NULL,pname,&error));

  if(error != NOERR3) {
    error3(error);
    printf("\nUsage:  3VIEWPKT [3binary packet name, default 3PAKT000.000]\n");
  }

  return error;
}
