/*
   axgetmail
   (c) 1999 by Radek Burget OK2JBG

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version
   2 of the license, or (at your option) any later version.

   readmsg: read and decode one message to stdout
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <errno.h>
#include "lzhuf.h"
#include "common.h"
#include "readmsg.h"

/* control characters */
#define NUL 0
#define SOH 1
#define STX 2
#define EOT 4

char error_msg[] =
"The BBS refused to forward this message.\n"
"The message is either deleted or you are not allowed to read it.\n";

int errmsg = 0;

/* read and store one message
   return: 0 = OK
           1 = checksum error
           2 = protocol violation
           3 = invalid starting character (msg not present) */
int get_one_message(FILE *fin, unsigned char **buf, int *bsize, char *title)
{
  int eot;
  int hd_length;
  int ch;
  unsigned char c;
  unsigned char ofset[7];
  signed char sum, chksum;
  int flen;
  int i;
  int bpoz;
  int size;

  message(MSG_INFO, "Downloading message\n");

  size = 1;
  *buf = (unsigned char *) malloc(sizeof(unsigned char) * size);
  bpoz = 0;
  
  ch = ffgetc(fin);
  if (ch != SOH)
  {
    /* transfer wasn't started */
    message(MSG_DEBUG, "Invalid starting character (0x%x)\n", ch);
    message(MSG_ERROR, "Message not present or acces denied\n");
    return 3; /* no message */
  }
  hd_length = ffgetc(fin);

  message(MSG_DEBUG, "Transfer started, header length %i\n", hd_length);

  /* read title */
  strcpy(title, "");
  do
  {
    ch = ffgetc(fin);
    c = (unsigned char) ch;
    if (ch != NUL) strncat(title, &c, 1);
  } while (ch != NUL);

  message(MSG_DEBUG, "Title: `%s'\n", title);

  /* read ofset */
  strcpy(ofset, "");
  do
  {
    ch = ffgetc(fin);
    c = (unsigned char) ch;
    if (ch != NUL) strncat(ofset, &c, 1);
  } while (ch != NUL);

  message(MSG_DEBUG, "Offset: `%s'\n", ofset);

  /* read data frames */
  sum = 0;
  eot = 0;
  while (!eot)
  {
    ch = ffgetc(fin);
    if (ch == STX) /* data frame */
    {
      flen = ffgetc(fin);
      if (flen == 0) flen = 256;
      message(MSG_DEBUG, "Data frame, length %i\n", 256);
      if (bpoz+flen >= size) /* buffer exceeded -> expand */
      {
        size += flen;
        *buf = (unsigned char *) realloc(*buf, sizeof(unsigned char) * size);
      }

      for (i=0; i<flen; i++)
      {
        ch = ffgetc(fin);
        (*buf)[bpoz] = (unsigned char) ch; bpoz++;
        sum += ch;
      }
    }
    else if (ch == EOT)/* end of transfer */
    {
      chksum = ffgetc(fin);
      message(MSG_DEBUG, "End of transfer, chksum %i, our %i, result %i\n", chksum, sum, chksum+sum);
      if (chksum + sum != 0 && !(chksum == -128 && sum == -128))
      {
        message(MSG_ERROR, "Message broken : checksum error\n");
        return 1;
      }
      eot = 1;
    }
    else
    {
      message(MSG_DEBUG, "Unexpected character '%c' (0x%x)\n", ch, ch);
      message(MSG_ERROR, "Message broken : protocol violation\n");
      return 2;
    }
  }
  *bsize = bpoz;
  return 0;
}

/* read one msg */
int read_msg(FILE *bbs_stream, char **_buf, int *_len, char *_subj)
{
  unsigned char *buf;
  int bsize;
  char subj[256];
  unsigned long clen;
  int result;

  lzhuf_init(1);
  
  result = get_one_message(bbs_stream, &buf, &bsize, subj);
  if (result == 0) /* all OK */
  {
     clen = ((buf[3]*256 + buf[2])*256 + buf[1])*256 + buf[0];
     message(MSG_DEBUG, "decmpressing message (%li bytes)", clen);
     lzhuf_decode(clen, buf+4, bsize-4);
     *_buf = lzhuf_data();
     *_len = lzhuf_length();
     strcpy(_subj, subj);
     message(MSG_DEBUG, " - done\n");
     errmsg = 0;
  }
  else if (result == 3) /* message not present */
  {
     message(MSG_DEBUG, "Download refused - error output\n");
     *_buf = error_msg;
     *_len = strlen(error_msg);
     strcpy(_subj, "Message is inaccessible");
     errmsg = 1;
  }
  else
  {
    message(MSG_DEBUG, "Download failed - error code %i\n", result);
    return 0;
  }

  return 1;
}

