/*
    receive.c - Provide everything for receiving files
    Copyright (c) 2006  Joey Schulze <joey@infodrom.org>

    This file is part of the Gerstensaft package.

    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.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*/

#define _GNU_SOURCE

#include "main.h"
#include "receive.h"
#include "msgbox.h"
#include "beer.h"
#include "nls.h"
#include "io.h"
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <sys/wait.h>

struct rfile {
  char *nr;
  char *date;
  char *size;
  char *name;
  char *flags;
};

/*
 27) 1999-12-13 17:49:08         43 kB  martin.jpg (archive)
 */
struct rfile *split_line (char *line, struct rfile *rf)
{
  char *cp, *xp;

  memset (rf, 0, sizeof(struct rfile));

  for (cp=line; *cp && isspace(*cp); cp++);

  /* 27) */
  if ((xp = strchr(cp, ')')) == NULL)
    return NULL;
  if ((rf->nr = (char *)malloc(xp-cp+1)) == NULL)
    return NULL;
  memset (rf->nr, 0, xp-cp+1);
  strncpy (rf->nr, cp, xp-cp);

  /* 1999-12-13 17:49:08 */
  cp = xp+2;
  if ((rf->date = (char *)malloc(20)) == NULL)
    return NULL;
  memset (rf->date, 0, 20);
  strncpy (rf->date, cp, 19);

  /* 43 kB */
  cp += 20;
  for (; *cp && isspace(*cp); cp++);
  for (xp=cp; *xp && isdigit(*xp); xp++);
  if ((rf->size = (char *)malloc(xp-cp+1)) == NULL)
    return NULL;
  memset (rf->size, 0, xp-cp+1);
  strncpy (rf->size, cp, xp-cp);

  for (cp=xp; *cp && isspace(*cp); cp++);
  if (*cp == 'k' && *(cp+1) == 'B')
    cp += 2;

  /* martin.jpg (archive) */
  for (; *cp && isspace(*cp); cp++);
  if ((xp = strrchr(cp, '(')) != NULL) {
    if ((rf->flags = (char *)malloc(strlen(xp))) == NULL)
      return NULL;
    memset (rf->flags, 0, strlen(xp));
    strncpy (rf->flags, xp, strlen(xp)-1);
    *(xp--) = '\0';
    if (isspace(*xp)) *xp = '\0';
  }
  if ((rf->name = (char *)malloc(strlen(cp)+1)) == NULL)
    return NULL;
  memset (rf->name, 0, strlen(cp)+1);
  strncpy (rf->name, cp, strlen(cp));

  return rf;
}

void parse_receive (void *data)
{
  FILE *rec;
  char line[100];
  char *cp;
  char *input;
  char *sender = NULL;
  struct rfile *jewels = NULL;
  char **clp;
  gint pos;
  GdkColor background;
  GdkColormap *colormap;

  if ((rec = popen ("receive -l 2> /dev/null", "r")) == NULL)
    return;

  memset (line, 0, sizeof(line));

  if ((clp = (char **)malloc(sizeof(char *)*7)) == NULL) {
    perror ("malloc");
    return;
  }
  clp[0] = NULL;

  gtk_clist_freeze (GTK_CLIST(((struct s_main_data *)data)->receiver));
  gtk_clist_clear (GTK_CLIST(((struct s_main_data *)data)->receiver));

  while (line[0] == '\0' && (cp = fgets(line, sizeof(line), rec))) {
    if (line[0] == '\n')
      line[0] = '\0';
    else if (line[0] == '-') {
      while (line[strlen(line)-1] != '\n' && (cp = fgets(line, sizeof(line), rec)));
      line[0] = '\0';
    } else if (!strncmp(line, "Files in spool directory", 24))
      line[0] = '\0';

    if (line[0] == '\0')
      continue;

    if (line[strlen(line)-1] == '\n') {
      line[strlen(line)-1] = '\0';
      input = line;
    } else {
      if ((input = (char *)malloc(strlen(line)+1)) == NULL) {
	perror ("malloc");
	return;
      }
      memset (input, 0, strlen(line)+1);
      strcpy (input, line);
      while (line[strlen(line)-1] != '\n' && (cp = fgets(line, sizeof(line), rec))) {
	if ((input = (char *)realloc(input, strlen(cp)+strlen(line)+1)) == NULL) {
	  perror ("malloc");
	  free (input);
	  return;
	}
	strcat (input, line);
      }
      input[strlen(input)-1] = '\0';
    }
    if (!strncasecmp (input, "From ", 5)) {
      if (sender) free (sender);
      if ((sender = (char *)malloc(strlen(input)-5+1)) == NULL) {
	perror ("malloc");
	if (strlen(input) >= sizeof(line))
	  free (input);
	return;
      }
      strcpy (sender, input+5);
#ifdef DEBUG
      printf ("new sender: %s\n", sender);
#endif
    } else if (!strncmp(input, "     \"", 6)) {
      if (input[strlen(input)-1] == '"') {
	cp = NULL;
	gtk_clist_get_text (GTK_CLIST(((struct s_main_data *)data)->receiver), pos, 6, &cp);
	if (!cp)
	  if ((cp = (char *)malloc(strlen(input)-6)) != NULL) {
	    snprintf (cp, strlen(input)-6, input+6);
	    gtk_clist_set_text (GTK_CLIST(((struct s_main_data *)data)->receiver), pos, 6, cp);
	  }
      }
    } else {
      if (!jewels)
	if ((jewels = (struct rfile *)malloc(sizeof(struct rfile))) == NULL) {
	  perror ("malloc");
	  if (strlen(input) >= sizeof(line))
	    free (input);
	}
      if ((jewels = split_line (input, jewels)) != NULL) {
	clp[1] = jewels->name;
	if ((cp = (char *)malloc(11)) == NULL) {
	  perror ("malloc");
	  if (strlen(input) >= sizeof(line))
	    free (input);
	}
	strncpy(cp, jewels->date, 10);
	*(cp+10) = '\0';
	clp[2] = cp;
	clp[3] = jewels->size;
	clp[4] = jewels->nr;
	clp[5] = strdup (sender);
	clp[6] = NULL;
	pos = gtk_clist_append (GTK_CLIST(((struct s_main_data *)data)->receiver), clp);

	background.red = background.green = background.blue =  ~0;
	colormap = gdk_colormap_get_system();
	gdk_color_alloc (colormap, &background);

	gtk_clist_set_background (GTK_CLIST(((struct s_main_data *)data)->receiver), pos, &background);
	if (jewels->flags && strstr(jewels->flags, "archive"))
	  gtk_clist_set_pixmap (GTK_CLIST(((struct s_main_data *)data)->receiver), pos, 0, dir_pixmap, dir_mask);
	else
	  gtk_clist_set_pixmap (GTK_CLIST(((struct s_main_data *)data)->receiver), pos, 0, doc_pixmap, doc_mask);

	free (jewels->date);
	if (jewels->flags) free (jewels->flags);
      }
    }

    if (strlen(input) >= sizeof(line))
      free (input);
    line[0] = '\0';
  }
  gtk_clist_thaw (GTK_CLIST(((struct s_main_data *)data)->receiver));
  if (jewels) free (jewels);
  pclose (rec);
}

int receive_file (char *nr, const char *dir, char *fname)
{
  char *cmd;
  char *msg;
  int ret;

#ifdef DEBUG
  printf ("receive_file (%s, %s, %s)\n", nr, dir, fname);
#endif

  if (chdir(dir))
    return 0;

  if (exists (dir, fname)) {
    if (asprintf (&msg, _("A file named '%s' already exists. "
			  "Do you want to replace it with the file you are receiving?"),
		  fname) != -1) {
      if (okbox(_("File exists"), msg) != GTK_RESPONSE_OK) {
	free (msg);
	return 0;
      } else
	free (msg);
    }
  }

  if (asprintf (&cmd, "receive -q%s -n %s 2> /dev/null", (config.keep?" -k":""), nr) == -1)
    return 0;

#ifdef DEBUG
  printf ("%s\n", cmd);
#endif

  ret = system (cmd);
  if (ret == -1) {
    perror ("system");
    free (cmd);
    return 0;
  } else if (WEXITSTATUS(ret)) {
    if (asprintf (&msg, _("%s terminated with exit code %d."),
		  "receive", WEXITSTATUS(ret)) != -1) {
      msgbox (_("Error condition"), msg);
      free (msg);
    }
    free (cmd);
    return 0;
  }

  free (cmd);

  return 1;
}
