/* IglooFTP - Graphical and User Friendly FTP Client.
 * Copyright (c) 1998-1999 Jean-Marc Jacquet. 
 * All rights reserved.
 * 
 * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE
 *
 * IglooFTP Original Packages, information and support,  
 * can be obtained at :
 *                              http://www.littleigloo.org
 * 
 *
 */


#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <utime.h>

#include "protos.h"
#include "IGLOOftp.h"





/* INITIALISATION */

/*PUBLIC :
 *IGLOO_default_session
 *IGLOO_init_connexion 
 */

void
IGLOO_init_session (FTPsession * that_session)
{
  memset (that_session, 0, sizeof (FTPsession));
  *that_session = user_rc.default_session;

  strcpy (that_session->start_dir, user_rc.default_session.start_dir);
  strcpy (that_session->local_dir, user_rc.default_session.local_dir);

}

void
IGLOO_default_session (void)
{
  IGLOO_init_session (&this_session);
}


static void
IGLOO_init_connexion (void)
{
  memset (&this_connexion, 0, sizeof (this_connexion));
  strcpy (this_connexion.hostname, this_session.hostname);
  this_connexion.port = this_session.port;
  this_connexion.timeout = this_session.timeout;
  this_connexion.dmode = this_session.dmode;

  if ((this_connexion.tmode = this_session.tmode) == TYPE_AUTODETECT)
    this_connexion.tmode = TYPE_IMAGE;


  this_connexion.host_type = this_session.host_type;
  this_connexion.resolve_link = this_session.resolve_link;

  download_stat_timeout = 0;
  anti_idle_timeout = 0;
  want_abort = FALSE;
  DOS_FILESYSTEM = FALSE;
}





/* ABORT AND LOGOFF */

/*PUBLIC
 *IGLOO_abort 
 *IGLOO_logoff 
 *IGLOO_connexion_lost 
 */


void
IGLOO_abort (void)
{
  if (this_connexion.xfer_busy && this_connexion.is_connected && this_connexion.transfert_type == FILE_DOWNLOAD)
    {
      FTP_ABORT (&this_connexion);
    }
  else
    want_abort = TRUE;
}


char
IGLOO_logoff (char CLOSE_ALL)
{

  if (!this_connexion.is_connected)
    {
      error_message ("NOT connected");
      return FALSE;
    }

  anti_idle = FALSE;
  IGLOO_end_idle ();

  if (download_stat_timeout)
    {
      gtk_timeout_remove (download_stat_timeout);
      clear_file_transfert_status ();
    }


  if (!this_connexion.connexion_lost)
    this_connexion.xfer_busy ? FTP_QUIT_WHILE_XFER (&this_connexion) : FTP_QUIT (&this_connexion);
  else
    this_connexion.connexion_lost = NO_MORE_TRUE;


  info_message ("Disconnected.");

  this_connexion.is_connected = FALSE;

  clear_ftplist ();
  menu_set_connect ();
  toolbar_buttons_set_sensitive ();
  bookmark_menu_set_sensitive ();
  set_main_title ();
  active_dir_panel (TRUE);
  //  active_queue (FALSE);

  if (!is_smanager_visible)
    switch_smanager_panel ();
  USER_CONNECT_VIA_SITE_MANAGER = FALSE;


  if (this_connexion.socket)
    close (this_connexion.socket);
  if (this_connexion.data_socket)
    close (this_connexion.data_socket);

  if (user_rc.lastlog_on && CLOSE_ALL)
    close_user_lastlog ();


  PROCESS_EVENTS;

  return TRUE;
}


int
IGLOO_connexion_lost (void)
{
  char msg[256];

  if (this_connexion.connexion_lost != TRUE)
    return 0;
  sprintf (msg, "Lost connexion to %s ", this_connexion.connect_address);
  error_message (msg);

  IGLOO_logoff (TRUE);

  return 0;
}






/* FTP COMMAND */

/* PUBLIC
 * IGLOO_cwd
 * IGLOO_pwd
 */

int
IGLOO_pwd (void)
{
  char *ptr;
  CHECK_CONNEXION;
  if (FTP_PWD (&this_connexion))
    {
      ptr = strrchr (this_connexion.reply, '"');
      *ptr = 0;
      ptr = strchr (this_connexion.reply, '"');
      strcpy (this_session.cwd_dir, ptr + 1);
      update_ftplist (this_session.cwd_dir);
    }
  else
    return 0;

  CHECK_CONNEXION;
  return 1;
}


int
IGLOO_cwd (char *path)
{
  CHECK_CONNEXION;
  IDLE_END;
  if (FTP_CWD (&this_connexion, path))
    return IGLOO_pwd ();
  CHECK_CONNEXION;
  IDLE_START;
  return 0;
}






/* ANTI IDLE */

/* PUBLIC
 * IGLOO_start_idle
 * IGLOO_end_idle
 * toggle_anti_idle
 * STATIC
 * IGLOO_anti_idle
 */


static gint
IGLOO_anti_idle (gpointer data)
{
  char msg_buf[10];

  sprintf (msg_buf, "Idle (%02i)", next_noop_delay++);
  idle_message (msg_buf);
  if (next_noop_delay > user_rc.idle_delay)
    {
      next_noop_delay = 0;
      CHECK_CONNEXION;
      FTP_NOOP (&this_connexion);
      CHECK_CONNEXION;
    }

  return this_connexion.is_connected;
}


void
IGLOO_start_idle (void)
{
  IGLOO_end_idle ();
  next_noop_delay = 0;
  DEBUG ("IGLOOftp : IDLE_START");
  anti_idle_timeout = gtk_timeout_add (1000, IGLOO_anti_idle, NULL);
}


void
IGLOO_end_idle (void)
{
  DEBUG ("IGLOOftp : IDLE_END");
  if (anti_idle_timeout)
    gtk_timeout_remove (anti_idle_timeout);
  anti_idle_timeout = 0;
  idle_message (" ");
}


void
toggle_anti_idle (GtkWidget * widget)
{
  if (!(anti_idle = GTK_CHECK_MENU_ITEM (widget)->active))
    IGLOO_end_idle ();
  else
    {
      if (!this_connexion.xfer_busy && !this_connexion.command_busy)
	IGLOO_start_idle ();
      idle_message ("Idle (ON)");
    }
}





/* SLEEP functions */
/* STATIC
 * IGLOO_sleep_timeout 
 * IGLOO_sleep 
 */

static gint
IGLOO_sleep_timeout (gpointer data)
{
  return (IS_SLEEPING = FALSE);
}

static void
IGLOO_sleep (int seconds)
{
  IS_SLEEPING = TRUE;
  gtk_timeout_add (1000 * seconds, IGLOO_sleep_timeout, NULL);
  while (IS_SLEEPING && (!want_abort))
    PROCESS_EVENTS;
}









/* CONNEXION */

/* PUBLIC :
 * IGLOO_connect
 * IGLOO_login 
 * IGLOO_reconnect
 * IGLOO_connect_from_site_manager
 * STATIC :
 * IGLOO_connect
 */

int
IGLOO_connect (void)
{
  int retry_count = user_rc.retry_count;

  DEBUG ("IGLOOftp : IGLOO_connect BEGIN");

  want_abort = FALSE;

  if (this_connexion.is_connected)
    return FALSE;

  IGLOO_init_connexion ();
  info_message ("");


  if (USE_FIREWALL)
    {
      strcpy (this_connexion.hostname, this_session.firewall_hostname);
      this_connexion.port = this_session.firewall_port;
      this_connexion.proxy = this_session.firewall_login_type;
      info_message ("Connecting to Firewall host ...");
    }

  if (!FTP_resolve (&this_connexion))
    {
      char msg_buf[256];
      sprintf (msg_buf, "Can't resolve %s.", this_connexion.hostname);
      error_message (msg_buf);
      return IGLOO_logoff (TRUE);
    }


  while (retry_count-- && !this_connexion.is_connected && !want_abort)
    {
      if (this_connexion.retry_count++)
	{
	  info_message ("");
	  info_message ("");
	}

      this_connexion.connexion_lost = FALSE;
      this_connexion.command_busy = FALSE;

      if (FTP_connect (&this_connexion))
	{
	  if (USE_FIREWALL)
	    {
	      strcpy (this_connexion.hostname, this_session.hostname);
	      this_connexion.port = this_session.port;

	      if (FIREWALL_IS (FIREWALL_TYPE_SOCKSV5))
		{
		  FTP_SOCKSV5_connect (&this_connexion, this_session.firewall_username, this_session.firewall_userpass);
		}
	      else
		{
		  if (this_connexion.reply[0] == '5' || this_connexion.reply[0] == '4')
		    {
		      this_connexion.is_connected = FALSE;
		      error_message ("Access denied.");
		      IGLOO_logoff (FALSE);
		    }

		  if (FIREWALL_IS (FIREWALL_TYPE_SITE) || FIREWALL_IS (FIREWALL_TYPE_OPEN)
		      || FIREWALL_IS (FIREWALL_TYPE_LOGIN_USER_AT_SITE))
		    {
		      info_message ("Logging on Firewall ...");

		      if (this_connexion.reply[0] == '2')
			if (!FTP_USER (&this_connexion, this_session.firewall_username))
			  IGLOO_logoff (FALSE);

		      if (this_connexion.reply[0] == '3')
			if (!FTP_PASS (&this_connexion, this_session.firewall_userpass))
			  IGLOO_logoff (FALSE);
		    }

		  if (this_connexion.reply[0] == '2')
		    {
		      char quote_buf[1024];
		      switch (this_session.firewall_login_type)
			{
			case FIREWALL_TYPE_SITE:
			  sprintf (quote_buf, "SITE %s", this_session.hostname);
			  break;
			case FIREWALL_TYPE_OPEN:
			  sprintf (quote_buf, "OPEN %s", this_session.hostname);
			  break;
			case FIREWALL_TYPE_USER_AT_SITE:
			case FIREWALL_TYPE_LOGIN_USER_AT_SITE:
			  sprintf (quote_buf, "USER %s@%s", this_session.username, this_session.hostname);
			  break;
			}
		      info_message ("Connecting to FTP host ( this can take a while ) ...");
		      if (!FTP_QUOTE (&this_connexion, quote_buf))
			IGLOO_logoff (FALSE);
		    }

		}
	    }


	  if (this_connexion.reply[0] == '5' || this_connexion.reply[0] == '4')
	    if (this_connexion.is_connected)
	      {
		this_connexion.is_connected = FALSE;
		error_message ("Access denied.");
		IGLOO_logoff (FALSE);
	      }

	  if (this_connexion.reply[0] == '2')
	    if (this_connexion.is_connected)
	      if (!FTP_USER (&this_connexion, this_session.username))
		IGLOO_logoff (FALSE);

	  if (this_connexion.reply[0] == '3')
	    if (this_connexion.is_connected)
	      if (!FTP_PASS (&this_connexion, this_session.userpass))
		IGLOO_logoff (FALSE);

	  if (this_connexion.reply[0] == '3')
	    if (this_connexion.is_connected)
	      {
		_HERE ("ACCOUNT");
	      }

	}


      if (!this_connexion.is_connected)
	{
	  char msg_buf[256];
	  sprintf (msg_buf, "Failed to connect on try #%i.", this_connexion.retry_count);
	  error_message (msg_buf);
	  if (retry_count)
	    {
	      sprintf (msg_buf, "Sleeping %i second(s) before next retry ...", user_rc.retry_delay);
	      info_message (msg_buf);
	      IGLOO_sleep (user_rc.retry_delay);
	      PROCESS_EVENTS;
	      if (USE_FIREWALL)
		{
		  strcpy (this_connexion.hostname, this_session.firewall_hostname);
		  this_connexion.port = this_session.firewall_port;
		}
	    }
	  else
	    {
	      error_message ("Maximum retry count reached. RENOUNCING.");
	      return 0;
	    }
	}
    }


  if (want_abort)
    {
      want_abort = FALSE;
      error_message ("Connexion ABORTED by USER.");
      return 0;
    }


  DEBUG ("IGLOOftp : IGLOO_connect END");
  return TRUE;
}





int
IGLOO_login (void)
{
#define IGLOO_login_return(a);  CURSOR_MAIN_default ();return (a);

  if (IS_SLEEPING)
    return 0;

  DEBUG ("IGLOOftp : IGLOO_login BEGIN");
  CURSOR_MAIN_busy ();


  if (!(USER_WANT_RECONNECT || USER_CONNECT_VIA_SITE_MANAGER || USER_CONNECT_VIA_URL))
    {
      IGLOO_default_session ();
      if (!can_connect ())
	{
	  error_message ("No FTP host specified.");
	  IGLOO_login_return (0);
	}
      retrieve_local_dir_from_user_profile ();
    }
  USER_WANT_RECONNECT = FALSE;
  USER_CONNECT_VIA_URL = FALSE;

  if (!IGLOO_connect ())
    {
      error_message ("Login failed.");
      IGLOO_login_return (0);
    }

  info_message ("Login successful.");
  update_combo_host_history (this_connexion.hostname);

  RDC_create_site_root ();
  move_welcome_message ();

  if (user_rc.view_host_welcome_message)
    popup_window_host_welcome_message ();

  if (this_session.host_type == HOST_AUTODETECT)
    {
      if (!FTP_SYST (&this_connexion))
	{			/* { } needed by MACRO */
	  IGLOO_login_return (IGLOO_logoff (TRUE));
	}
    }
  else
    {
      char msg_buf[256];
      int index = (char) this_session.host_type;
      sprintf (msg_buf, "Type set to %s by user.", host_type_name[index]);
      info_message (msg_buf);
    }

  this_connexion.can_resume = IGLOO_rest (100);
  IGLOO_rest (0);

  if (is_smanager_visible)
    switch_smanager_panel ();
  reset_ftp_sort_options ();


  if (strlen (this_session.start_dir))
    {
      if (!FTP_CWD (&this_connexion, this_session.start_dir))
	{
	  error_message ("Can't cd to default directory.");
	  error_message ("Trying cd to root directory ...");
	  FTP_CWD (&this_connexion, "/");
	  strcpy (this_session.cwd_dir, "/");
	}
    }

  IGLOO_pwd ();

  if (strlen (this_session.local_dir))
    chdir (this_session.local_dir);
  refresh_dirlist ();


  menu_set_connect ();
  toolbar_buttons_set_sensitive ();
  bookmark_menu_set_sensitive ();
  active_ftp_panel (TRUE);
  active_dir_panel (TRUE);
  set_main_title ();


  if (anti_idle)
    {
      if (!FTP_NOOP (&this_connexion))
	anti_idle = FALSE;
      else
	IGLOO_start_idle ();
    }


  USER_WAS_CONNECTED = TRUE;
  DEBUG ("IGLOOftp : IGLOO_login END");
  IGLOO_login_return (1);
}







void
IGLOO_connect_or_reconnect (void)
{
  if (IS_SLEEPING)
    return;

  if (this_connexion.is_connected)
    {
      if (this_connexion.xfer_busy)
	if (!alert_ok_cancel_modal ("Disconnect", "Transfer in progress !\nDisconnect anyway ?", "Yes"))
	  return;
      IGLOO_logoff (TRUE);

      if (was_connectbar_modified ())
	{
	  IGLOO_login ();
	}
      else
	{
	  strcpy (this_session.start_dir, this_session.cwd_dir);
	  USER_WANT_RECONNECT = TRUE;
	  IGLOO_login ();
	}
    }
  else
    {
      IGLOO_login ();
    }
}


void
IGLOO_load_session_and_connect (void)
{
  DEBUG ("IGLOOftp : IGLOO_spawn_session");
  if (load_session ())
    {
      USER_WANT_RECONNECT = TRUE;
      update_connectbar (&this_session);
      IGLOO_login ();
    }
}


void
IGLOO_connect_from_site_manager (MANAGERsite * this_site)
{
  DEBUG ("IGLOOftp : IGLOO_connect_from_site_manager");


  if (IS_SLEEPING)
    return;

  if (this_connexion.is_connected)
    {
      if (this_connexion.xfer_busy)
	if (!alert_ok_cancel_modal ("Disconnect", "Transfer in progress !\nDisconnect anyway ?", "Yes"))
	  return;
      IGLOO_logoff (TRUE);
    }

  IGLOO_default_session ();

  strcpy (this_session.hostname, this_site->session.hostname);
  strcpy (this_session.username, this_site->session.username);
  strcpy (this_session.userpass, this_site->session.userpass);
  if (strstr (this_session.userpass, SITE_DEFAULT_PASSWORD_TEXT))
    strcpy (this_session.userpass, user_rc.default_session.userpass);
  else if (strstr (this_session.userpass, SITE_ASK_PASSWORD_TEXT))
    {
      char buf[256];
      sprintf (buf, "%s password :", this_session.username);
      strcpy (this_session.userpass, password_entry_dialog_modal ("Enter Password", buf, "Ok", ""));
      if (!strlen (this_session.userpass))
	return;
    }
  else
    MemFrob (this_session.userpass, strlen (this_session.userpass));

  this_session.port = this_site->session.port;

  update_connectbar (&this_session);

  if (!this_site->USE_DEFAULT)
    {
      strcpy (this_session.start_dir, this_site->session.start_dir);
      strcpy (this_session.local_dir, this_site->session.local_dir);
      if (!strlen (this_session.local_dir))
	strcpy (this_session.local_dir, user_rc.default_session.local_dir);
      this_session.host_type = this_site->session.host_type;
      this_session.tmode = this_site->session.tmode;
      this_session.resolve_link = this_site->session.resolve_link;
      this_session.use_RDC = this_site->session.use_RDC;
      this_session.dmode = this_site->session.dmode;

      this_session.uploads_filename = this_site->session.uploads_filename;
      this_session.uploads_perm = this_site->session.uploads_perm;
      this_session.uploads_date = this_site->session.uploads_date;

      this_session.downloads_filename = this_site->session.downloads_filename;
      this_session.downloads_perm = this_site->session.downloads_perm;
      this_session.downloads_date = this_site->session.downloads_date;
    }

  USER_CONNECT_VIA_SITE_MANAGER = TRUE;
  IGLOO_login ();
}



void
IGLOO_connect_from_URL (char *this_url)
{
  char this_port[256];
  char this_file[256];
  char this_type[256];
  char VALID_URL = FALSE;

  DEBUG ("IGLOOftp : IGLOO_connect_from_URL");

  if (IS_SLEEPING)
    return;

  if (this_connexion.is_connected)
    {
      if (this_connexion.xfer_busy)
	if (!alert_ok_cancel_modal ("Disconnect", "Transfer in progress !\nDisconnect anyway ?", "Yes"))
	  {
	    g_free (this_url);
	    return;
	  }
      IGLOO_logoff (TRUE);
    }

  MEM0 (this_port);
  MEM0 (this_file);
  MEM0 (this_type);

  IGLOO_default_session ();
  MEM0 (this_session.username);
  MEM0 (this_session.userpass);

  VALID_URL =
    parse_ftp_url (this_url, this_session.username, this_session.userpass, this_session.hostname, this_port, this_session.start_dir, this_file, this_type);
  g_free (this_url);

  if (!VALID_URL
      || !strlen (this_session.hostname))
    {
      alert_ok ("Error", "Not a valid FTP URL.", "Ok");
    }
  else
    {
      this_session.port = strlen (this_port) ? atoi (this_port) : 21;
      update_connectbar (&this_session);
      getcwd (this_session.local_dir, sizeof (this_session.local_dir));
      USER_CONNECT_VIA_URL = TRUE;
      IGLOO_login ();
    }
}

/* TRANSFERT */

/*PUBLIC:
 *IGLOO_download 
 *IGLOO_upload
 *STATIC:
 *IGLOO_set_type
 */


static int
IGLOO_set_type (char *filename)
{
  CHECK_CONNEXION;
  switch (this_session.tmode)
    {
    case TYPE_AUTODETECT:
      {
	char msg_buf[1024];
	char *dup_ptr = strdup (filename + 1);
	char *ptr;
	char set_ascii = TRUE;

	sprintf (msg_buf, "Detecting %s TYPE ...", filename);
	info_message (msg_buf);

	ptr = strrchr (dup_ptr, '.');
	if (ptr == NULL)
	  {
	    free (dup_ptr);
	    ptr = strdup (filename);
	    strupr (ptr);
	    if (strstr (ptr, "README") == NULL)
	      if (strstr (ptr, "MESSAGE") == NULL)
		set_ascii = FALSE;
	    free (ptr);
	  }
	else
	  {
	    set_ascii = is_text_ext (ptr);
	    free (dup_ptr);
	  }
	set_ascii ? FTP_TYPE_ASCII (&this_connexion) : FTP_TYPE_IMAGE (&this_connexion);
      }
      break;

    case TYPE_ASCII:
      FTP_TYPE_ASCII (&this_connexion);
      break;
    case TYPE_IMAGE:
      FTP_TYPE_IMAGE (&this_connexion);
      break;
    case TYPE_LOCAL:
      FTP_TYPE_LOCAL (&this_connexion);
      break;
    }
  CHECK_CONNEXION;
  return 1;
}




int
IGLOO_download_from (char *src_filename, char *dest_filename, char *filesize, char *filedate, char *fileperm)

{
  FILE *local = NULL;
  long resume_offset = 0;
  struct stat stat_buf;
  char *this_dest_filename = g_strdup (dest_filename);
#define IGLOO_download_return(a);  g_free(this_dest_filename);CURSOR_default ();return (a);

  DEBUG ("IGLOOftp : IGLOO_download BEGIN");

  CURSOR_busy ();

  switch (this_session.downloads_filename)
    {
    case XFER_FILENAME_UPPER:
      strupr (this_dest_filename);
      break;
    case XFER_FILENAME_LOWER:
      strlwr (this_dest_filename);
      break;
    default:
      break;
    }


  if ((!access (this_dest_filename, F_OK)) && (!xfer_overwrite))
    {
      char local_fileinfo[100];
      char remote_fileinfo[100];
      struct tm *timeptr;
      char time_buf[20];
      int DUP_action;

      if (xfer_skip)
	{
	  IGLOO_download_return (1);
	}

      stat (this_dest_filename, &stat_buf);
      timeptr = localtime (&stat_buf.st_ctime);
      strftime (time_buf, sizeof (time_buf), "%D %H:%M ", timeptr);
      sprintf (local_fileinfo, "%ld bytes, %s", stat_buf.st_size, time_buf);
      sprintf (remote_fileinfo, "%s bytes, %s", filesize, filedate);


      if (xfer_resume)
	DUP_action = DUP_resume;
      else
	DUP_action = duplicate_dialog ("Duplicate File", "Resume", this_dest_filename,
				       local_fileinfo, remote_fileinfo, (char) (atol (filesize) != stat_buf.st_size));
      switch (DUP_action)
	{
	case DUP_abort:
	  xfer_abort = TRUE;
	  IGLOO_download_return (1);

	case DUP_skip_all:
	  xfer_skip = TRUE;
	case DUP_skip:
	  IGLOO_download_return (1);

	case DUP_resume:
	  resume_offset = stat_buf.st_size;
	  local = fopen (this_dest_filename, "a+");
	  break;

	case DUP_rename:
	  {
	    char buf[256];
	    strcpy (buf, entry_dialog_modal ("Rename Duplicate File", "Rename file to :", "Rename", this_dest_filename));
	    if (strlen (buf))
	      local = fopen (buf, "w");
	    else
	      {
		IGLOO_download_return (0);
	      }
	  }
	  break;

	case DUP_overwrite_all:
	  xfer_overwrite = TRUE;
	case DUP_overwrite:
	default:
	  local = fopen (this_dest_filename, "w");
	  break;
	}
    }
  else
    local = fopen (this_dest_filename, "w");

  if (!local)
    {
      char msg_buf[1024];
      sprintf (msg_buf, "Can't open %s", this_dest_filename);
      error_message (msg_buf);
      IGLOO_download_return (2);
    }


  IGLOO_set_type (src_filename);


  init_file_transfert_status (src_filename, atol (filesize), resume_offset, DOWNLOAD_XPM);
  this_connexion.xfered_bytes = 0;

  download_stat_timeout = gtk_timeout_add (500, update_file_transfert_status, NULL);

  FTP_DOWNLOAD (&this_connexion, strdup (src_filename), local, resume_offset);
  CHECK_CONNEXION;

  update_file_transfert_status (NULL);
  gtk_timeout_remove (download_stat_timeout);
  clear_file_transfert_status ();

  stat (this_dest_filename, &stat_buf);
  if (!stat_buf.st_size)
    {
      unlink (this_dest_filename);
      IGLOO_download_return (2);
    }


  if (this_session.downloads_date)
    if (filedate != NULL)
      {
	const char *format = REMOTE_DATE_FORMAT;
	struct tm remote_date;
	struct utimbuf buf;
	memset (&remote_date, 0, sizeof (struct tm));
	strptime (filedate, format, &remote_date);
	buf.actime = mktime (&remote_date);
	buf.modtime = mktime (&remote_date);
	utime (this_dest_filename, &buf);
      }

  if (this_session.downloads_perm)
    if (fileperm != NULL)
      {
	char buf_mode[5];
	static long int this_chmod_mode = 644;
	StrNumMode (buf_mode, fileperm);
	this_chmod_mode = strtol (buf_mode, NULL, 8);
	chmod (this_dest_filename, this_chmod_mode);
      }


  DEBUG ("IGLOOftp : IGLOO_download END");

  IGLOO_download_return (1);
}




int
IGLOO_upload_from (char *src_filename, char *dest_filename, char *filesize, char *filedate, char *fileperm)
{
  FILE *local = NULL;
  long resume_offset = 0;
  FILEINFO remote_file_info;
  char *this_dest_filename = g_strdup (dest_filename);
#define IGLOO_upload_return(a);  g_free(this_dest_filename);CURSOR_default ();return (a);


  DEBUG ("IGLOOftp : IGLOO_upload BEGIN");

  CURSOR_busy ();

  if ((local = fopen (src_filename, "r")) == NULL)
    {
      char msg_buf[1024];
      sprintf (msg_buf, "Can't open %s for reading", src_filename);
      error_message (msg_buf);
      IGLOO_upload_return (2);
    }

  IGLOO_set_type (src_filename);	/* Must know to determine resume_offset for ASCII transfert */

  switch (this_session.uploads_filename)
    {
    case XFER_FILENAME_UPPER:
      strupr (this_dest_filename);
      break;
    case XFER_FILENAME_LOWER:
      strlwr (this_dest_filename);
      break;
    default:
      break;
    }

  if (remote_get_fileinfo (this_dest_filename, &remote_file_info) && (!xfer_overwrite))
    {
      char local_fileinfo[100];
      char remote_fileinfo[100];
      struct tm *timeptr;
      char time_buf[20];
      struct stat stat_buf;
      int DUP_action;

      if (xfer_skip)
	{
	  fclose (local);
	  IGLOO_upload_return (1);
	}

      stat (src_filename, &stat_buf);
      timeptr = localtime (&stat_buf.st_ctime);
      strftime (time_buf, sizeof (time_buf), "%D %H:%M ", timeptr);
      sprintf (local_fileinfo, "%ld bytes, %s", stat_buf.st_size, time_buf);
      sprintf (remote_fileinfo, "%ld bytes, %s", remote_file_info.filesize, remote_file_info.filedate);

      if (xfer_resume)
	DUP_action = DUP_append;
      else
	DUP_action = duplicate_dialog ("Duplicate File", "Append", this_dest_filename, local_fileinfo, remote_fileinfo, TRUE);

      switch (DUP_action)
	{
	case DUP_abort:
	  xfer_abort = TRUE;
	  fclose (local);
	  IGLOO_upload_return (1);

	case DUP_skip_all:
	  xfer_skip = TRUE;
	case DUP_skip:
	  fclose (local);
	  IGLOO_upload_return (1);

	case DUP_append:
	  if (this_connexion.tmode != TYPE_ASCII)
	    resume_offset = remote_file_info.filesize;
	  else
	    {
	      FTP_TYPE_IMAGE (&this_connexion);
	      resume_offset = FTP_SIZE (&this_connexion, this_dest_filename);	// if 0 (unsucessful FTP_SIZE) => overwrite

	      FTP_TYPE_ASCII (&this_connexion);
	      CHECK_CONNEXION;
	    }
	  fseek (local, resume_offset, SEEK_SET);
	  break;
/*
   case DUP_rename:
   {
   char buf[256];
   strcpy (buf, entry_dialog_modal ("Rename Duplicate File", "Rename file to :", "Rename", this_dest_filename));
   if (strlen (buf))
   local = fopen (buf, "w");
   else
   return 0;
   }
   break;
 */
	case DUP_overwrite_all:
	  xfer_overwrite = TRUE;
	case DUP_overwrite:
	default:
	  break;
	}
    }

  init_file_transfert_status (src_filename, atol (filesize), resume_offset, UPLOAD_XPM);
  this_connexion.xfered_bytes = 0;

  download_stat_timeout = gtk_timeout_add (500, update_file_transfert_status, NULL);

  FTP_UPLOAD (&this_connexion, strdup (this_dest_filename), local, (char) (resume_offset > 0));
  CHECK_CONNEXION;

  if (this_session.uploads_date)
    if (filedate != NULL)
      {
	struct utimbuf buf;
	buf.actime = time (NULL);
	buf.modtime = time (NULL);
	utime (src_filename, &buf);
      }

  if (this_session.uploads_perm)
    if (fileperm != NULL)
      {
	char buf_mode[5];
	StrNumMode (buf_mode, fileperm);
	IGLOO_chmod (this_dest_filename, buf_mode);
	CHECK_CONNEXION;
      }

  update_file_transfert_status (NULL);
  gtk_timeout_remove (download_stat_timeout);
  clear_file_transfert_status ();

  DEBUG ("IGLOOftp : IGLOO_upload END");

  IGLOO_upload_return (1);
}


/*EOF */
