/* 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
 * 
 *
 */

#define ERROR_REPLY_CODE (FTPctrl->reply[0] == '5' || FTPctrl->reply[0] == '4')



/* LOGIN */

char
FTP_USER (FTP * FTPctrl, char *username)
{
  char command[256];
  sprintf (command, "USER %s", username);
  if (!FTP_exec_command (FTPctrl, command) || ERROR_REPLY_CODE)
    return FTP_error (FALSE, "USER command failed. ", "", 0);
  return TRUE;
}

char
FTP_PASS (FTP * FTPctrl, char *password)
{
  char command[256];
  sprintf (command, "PASS %s", password);
  if (!FTP_exec_command (FTPctrl, command) || ERROR_REPLY_CODE)
    return FTP_error (FALSE, "PASS command failed. ", "", 0);
  return TRUE;
}


char
FTP_SYST (FTP * FTPctrl)
{
  int host_detected = 0;
  if (!FTP_exec_command (FTPctrl, "SYST") || ERROR_REPLY_CODE)
    return FTP_error (FALSE, "SYST command failed. ", "", 0);

  if (FTPctrl->reply[0] == '2')
    {
      if (strstr (FTPctrl->reply, "SUNOS"))
	host_detected = HOST_SUNOS;

      else if (strstr (FTPctrl->reply, "UNIX"))
	host_detected = HOST_UNIX;

      else if (strstr (FTPctrl->reply, "Windows_NT") || strstr (FTPctrl->reply, "WIN32"))
	host_detected = HOST_WIN_NT;

      else if (strstr (FTPctrl->reply, "VMS"))
	host_detected = HOST_VMS;
    }

  if (FTPctrl->host_type == HOST_AUTODETECT)
    {
      if (!host_detected)
	{
	  FTP_error_msg ("Unable to detect host type.");
	  FTP_error_msg ("Let's say it's UNIX.");
	  FTPctrl->host_type = HOST_UNIX;
	}
      else
	{
	  char msg_buf[256];
	  FTPctrl->host_type = (int) host_detected;
	  sprintf (msg_buf, "Setting host type to %s", host_type_name[host_detected]);
	  FTP_info_msg (msg_buf);
	}
    }

  return TRUE;
}


char
FTP_SET_TYPE (FTP * FTPctrl, char this_type, char *this_type_name)
{
  char command[256];

  sprintf (command, "TYPE %c", this_type);
  if (!FTP_exec_command (FTPctrl, command) || ERROR_REPLY_CODE)
    return FTP_error (FALSE, "Unable to set transfert mode to ", this_type_name, 0);

  switch (this_type)
    {
    case 'A':
      FTPctrl->tmode = TYPE_ASCII;
      break;
    case 'I':
      FTPctrl->tmode = TYPE_IMAGE;
      break;
    case 'L':
      FTPctrl->tmode = TYPE_LOCAL;
      break;
    }

  return TRUE;
}






/* DIRECTORIES OP */

char
FTP_CWD (FTP * FTPctrl, char *path)
{
  char command[256];

  if (!strcmp (path, ".."))
    {
      if (!FTP_exec_command (FTPctrl, "CDUP") || ERROR_REPLY_CODE)
	return FTP_error (FALSE, "CDUP command failed. ", "", 0);
      return TRUE;
    }

  sprintf (command, "CWD %s", path);
  if (!FTP_exec_command (FTPctrl, command))
    return FTP_error (FALSE, "CWD command failed. ", "", 0);

  if (FTPctrl->reply[0] != '5')
    return TRUE;

  if (FTPctrl->reply[1] == '0')
    {
      sprintf (command, "XCWD %s", path);
      if (!FTP_exec_command (FTPctrl, command))
	return FTP_error (FALSE, "XCWD command failed. ", "", 0);
    }

  return (!ERROR_REPLY_CODE);
}


char
FTP_PWD (FTP * FTPctrl)
{
  if (!FTP_exec_command (FTPctrl, "PWD"))
    return FTP_error (FALSE, "PWD command failed. ", "", 0);

  if (FTPctrl->reply[0] == '5')
    if (!FTP_exec_command (FTPctrl, "XPWD"))
      return FTP_error (FALSE, "XPWD command failed. ", "", 0);

  return (!ERROR_REPLY_CODE);
}


char
FTP_MKD (FTP * FTPctrl, char *path)
{
  char command[256];


  sprintf (command, "MKD %s", path);
  if (!FTP_exec_command (FTPctrl, command))
    return FTP_error (FALSE, "MKD command failed. ", "", 0);

  if (FTPctrl->reply[0] != '5')
    return TRUE;

  if (FTPctrl->reply[1] == '0')
    {
      sprintf (command, "XMKD %s", path);
      if (!FTP_exec_command (FTPctrl, command))
	return FTP_error (FALSE, "XMKD command failed. ", "", 0);
    }

  return (!ERROR_REPLY_CODE);
}


char
FTP_RMD (FTP * FTPctrl, char *path)
{
  char command[256];

  sprintf (command, "RMD %s", path);
  if (!FTP_exec_command (FTPctrl, command))
    return FTP_error (FALSE, "RMD command failed. ", "", 0);

  if (FTPctrl->reply[0] != '5')
    return TRUE;

  if (FTPctrl->reply[1] == '0')
    {
      sprintf (command, "XRMD %s", path);
      if (!FTP_exec_command (FTPctrl, command))
	return FTP_error (FALSE, "XRMD command failed. ", "", 0);
    }

  return (!ERROR_REPLY_CODE);
}






/* FILES OP */

char
FTP_DELETE (FTP * FTPctrl, char *filename)
{
  char command[256];
  sprintf (command, "DELE %s", filename);
  if (!FTP_exec_command (FTPctrl, command) || ERROR_REPLY_CODE)
    return FTP_error (FALSE, "DELE command failed. ", "", 0);
  return TRUE;
}


char
FTP_CHMOD (FTP * FTPctrl, char *filename, char *mode_string)
{
  char command[256];
  sprintf (command, "SITE CHMOD %s %s", mode_string, filename);
  if (!FTP_exec_command (FTPctrl, command) || ERROR_REPLY_CODE)
    return FTP_error (FALSE, "CHMOD command failed. ", "", 0);
  return TRUE;
}


char
FTP_RENAME (FTP * FTPctrl, char *old_name, char *new_name)
{
  char command[256];

  sprintf (command, "RNFR %s", old_name);
  if (!FTP_exec_command (FTPctrl, command) || ERROR_REPLY_CODE)
    return FTP_error (FALSE, "RNFR (rename from) command failed. ", "", 0);

  sprintf (command, "RNTO %s", new_name);
  if (!FTP_exec_command (FTPctrl, command) || ERROR_REPLY_CODE)
    return FTP_error (FALSE, "RNTO (rename to) command failed. ", "", 0);

  return TRUE;
}






/* XFER */

char
FTP_REST (FTP * FTPctrl, long fpos)
{
  char command[256];
  sprintf (command, "REST %ld", fpos);
  if (!FTP_exec_command (FTPctrl, command) || ERROR_REPLY_CODE)
    return FTP_error (FALSE, "REST command failed. ", "", 0);
  return TRUE;
}

long
FTP_SIZE (FTP * FTPctrl, char *filename)
{
  char command[256];
  sprintf (command, "SIZE %s", filename);
  if (!FTP_exec_command (FTPctrl, command) || ERROR_REPLY_CODE)
    return FTP_error (0, "SIZE command failed. ", "", 0);
  return atol (&FTPctrl->reply[4]);
}


char
FTP_LIST (FTP * FTPctrl, char *filename)
{
  char tmp_filename[256];
  char list_command[10];
  int data_socket = FTP_open_data_connection (FTPctrl);
  FILE *local;

  if (FTPctrl->host_type == HOST_VMS)
    strcpy (list_command, "LIST");
  else
    strcpy (list_command, FTPctrl->resolve_link ? "LIST -aL" : "LIST -a");

  FTPctrl->transfert_type = LIST_DOWNLOAD;

  FTP_TYPE_ASCII (FTPctrl);

  tmpnam (tmp_filename);
  if (!FTP_exec_command (FTPctrl, list_command) || ERROR_REPLY_CODE)
    return FTP_error (FALSE, "LIST command failed.", "", data_socket);

  local = fopen (tmp_filename, "w");
  if (!FTP_download (FTPctrl, data_socket, local))
    return FTP_error (FALSE, "Unable to retreive directory listing. ", "", data_socket);

  FTP_format_dir_list (tmp_filename, filename, FTPctrl->host_type);
  unlink (tmp_filename);

  FTP_close_socket (data_socket);
  return TRUE;
}


char
FTP_DOWNLOAD (FTP * FTPctrl, char *remote_filename, FILE * local, long fpos)
{
  char command[256];
  int data_socket;

  if (!(data_socket = FTP_open_data_connection (FTPctrl)))
    return FTP_error (FALSE, "Failed to get a data_socket. ", "", 0);

  if (FTPctrl->can_resume && fpos)
    FTP_REST (FTPctrl, fpos);

  FTPctrl->transfert_type = FILE_DOWNLOAD;

  sprintf (command, "RETR %s", remote_filename);
  if (!FTP_exec_command (FTPctrl, command) || ERROR_REPLY_CODE)
    return FTP_error (FALSE, "RETR command failed. ", "", data_socket);

  if (!FTP_download (FTPctrl, data_socket, local))
    return FTP_error (FALSE, "Incomplete download : ", remote_filename, data_socket);

  return TRUE;
}


char
FTP_UPLOAD (FTP * FTPctrl, char *remote_filename, FILE * local, char append_to_file)
{
  char command[256];
  int data_socket;

  if (!(data_socket = FTP_open_data_connection (FTPctrl)))
    return FTP_error (FALSE, "Failed to get a data_socket. ", "", 0);

  FTPctrl->transfert_type = FILE_UPLOAD;

  sprintf (command, append_to_file ? "APPE %s" : "STOR %s", remote_filename);

  if (!FTP_exec_command (FTPctrl, command) || ERROR_REPLY_CODE)
    return FTP_error (FALSE, append_to_file ? "APPE command failed " : "STOR command failed ", "", data_socket);

  if (!FTP_upload (FTPctrl, data_socket, local))
    return FTP_error (FALSE, "Incomplete upload : ", remote_filename, data_socket);

  return TRUE;
}





/* MISC */

char
FTP_QUIT (FTP * FTPctrl)
{
  if (!FTP_exec_command (FTPctrl, "QUIT"))
    return FTP_error (FALSE, "Can't disconnect. Let say we are.", "", 0);
  FTP_close_session (FTPctrl);
  return TRUE;
}

char
FTP_QUOTE (FTP * FTPctrl, char *command)
{
  if (!FTP_exec_command (FTPctrl, command) || ERROR_REPLY_CODE)
    return FTP_error (FALSE, "Command failed : ", command, 0);
  return TRUE;
}


char
FTP_XFER_QUOTE (FTP * FTPctrl, char *this_command)
{
  FTP this_FTPctrl;
  char error_msg[40];

  printf ("FTP_XFER_QUOTE : %s\n", this_command);
  memcpy (&this_FTPctrl, FTPctrl, sizeof (FTP));
  sprintf (error_msg, "%s command failed", this_command);

  if (!FTP_send_telnet_interrupt (this_FTPctrl.socket))
    return FTP_error (FALSE, error_msg, "", 0);

  if (!FTP_exec_command (&this_FTPctrl, this_command))
    {
      FTPctrl->connexion_lost = this_FTPctrl.connexion_lost;
      return FTP_error (FALSE, error_msg, "", 0);
    }

  return TRUE;
}


/* EOF */
