/*****************************************************************************/
/*  ftp.h - include file for the whole ftp program                           */
/*  Copyright (C) 1998 Brian Masney <masneyb@newwave.net>                    */
/*                                                                           */
/*  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., 675 Mass Ave, Cambridge, MA 02139, USA.                */
/*****************************************************************************/

#ifndef __FTP_H
#define __FTP_H
#include <pthread.h>
#include <gtk/gtk.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <ctype.h>
#include <pwd.h>
#include <sys/types.h>

#define BASE_CONF_DIR		"~/.gftp"
#define CONFIG_FILE		BASE_CONF_DIR "/gftprc"
#define FTP_ASCII               0
#define FTP_BINARY              1
#define MAXSTR			255
#define LOG_SEND		1
#define LOG_RECV		2
#define LOG_MISC		3
#define ANON_LOGIN		"anonymous"

struct ftp_file_data {
   /* File information */
   char file[MAXSTR], user[9], group[9], attribs[11], dt[15], strsize[20];
   unsigned long size, /* File size */
                 startsize; /* String to display in the listbox to the user
                               in the size column */
   int restart, /* When transferring files, if the file exists on the local 
                   computer, do you want to resume the transfer (1) or just
                   overwrite the file (0). */
       /* The next 3 are for figuring out what icon to associate with the file
          in the listbox */
       isdir, /* Is it a directory? */
       isexe, /* Is it executable? */
       islink; /* Is it a symlink? */
   struct ftp_file_data *next; /* Our next file */
};

/* This structure will be contained in the ftp_window_data structure below.
   This should contain all of the information that will be needed about a 
   remote site. This structure will also be contained inside the 
   ftp_transfer_data structure for the multiple downloads. */
   
struct ftp_host_data {
   int type, /* Download type: FTP_BINARY, FTP_ASCII */
       totalfiles, /* How many files are here */
       sockfd; /* Our socket descriptor */
   char host[MAXSTR], /* Current host (if any) connected to */
        user[MAXSTR], /* Our username */
        passwd[MAXSTR], /* Our password */
        dir[MAXSTR]; /* Our current directory */
   long port; /* Current port (if any) we are connected on */
   struct ftp_file_data *files, /* All of the files in the current directory */
                        *last; /* This is the last file. This makes it easier
                                  for adding files to the end of the list */
};

/* There will be 2 of these created...one for the local side and one for the 
   remote side. When all of the callbacks are created, the proper structure
   will be passed to the function */
   
struct ftp_window_data {
   GtkWidget *diredit, /* Edit box for the user to enter a directory */
             *hoststxt, /* Show which directory we're in */
             *listbox, /* Our listbox showing the files */
             *logwdw, /* The text widget for logging */
             *dlwdw; /* The list widget for showing our downloads */
   int local, /* -1 = Not Connected, 0 = Remote, 1 = Local */
       totalitems,  /* How many items are in our list */
       numselected, /* How many items are selected in the list */
       sortcol, /* Which column we are sorting by */
       sortasds, /* Sorting ascending or descending */
       *items; /* A list containing a 1 and 0 for each item in the list 
                  showing whether it is selecteded or not */
   struct ftp_host_data *host; /* The host that we are connected to */
};         

/* This will be the structure used for each thread in transfering files */

struct ftp_transfer_data {
   struct ftp_window_data *wdata,
                          *otherwdata;
   struct ftp_host_data *hdata; /* The host that we are connecting to */
   struct ftp_file_data *curfle; /* The current file that we are transferring */
   char dest[MAXSTR], /* Destination local directory */
        progressstr[MAXSTR]; /* String to be displayed in the listbox under
                                the progress column */
   int doall, /* For the Resume all/Overwrite all buttons */
       op, /* If the file exists, will we resume the transfer (1) or
              just overwrite it (0). */
       direction, /* Are we downloading (1) or uploading (0) */
       cancel, /* If this is true, then terminate the download. This will
                  be set by the main thread when the user selects it */
       action, /* This will be a message to the main thread. If this is > 0,
                  then we will have to add an entry to the download listbox
                  for this thread. After it creates it, it will move it to 0.
                  If action < 0, it will delete the entry from the listbox 
                  and destroy all data structures related to it */
       created, /* This will be set when an entry is made in the listbox for
                   this file transfer. You could have a case where you a file
                   is transferred really fast, and a entry is never made, but
                   then the update function gets called, and it sees to erase
                   the item. */
       selected; /* Whether this item is selected in the listbox or not */
   struct ftp_transfer_data *next;
   unsigned long cursize, /* The size of the current file being transferred */ 
                 curtrans, /* How much of the file we actually transferred */
                 startsize; /* The size that we started the transfer at. This
                               is used for resuming interrupted transfers */
   time_t starttime; /* The time that we started the transfer */
};

/* This will be for queueing messages to the logging window. This will be
   used for the threads, since gtk is not thread safe, we cannot update the
   display inside the threads */
   
struct ftp_log_queue {
   char msg[MAXSTR]; /* Our message */
   int type; /* Logging type. LOG_MISC, LOG_SEND, or LOG_RECV */
   struct ftp_log_queue *next;
};

/* This will be passed to some of the initialization routines so it can 
   initialize both of the windows */
   
struct ftp_both_windows {
   struct ftp_window_data *window1, /* Local window */
                          *window2; /* Remote window */
};

/* For registering file formats */

struct pix_ext {
   char ext[20], /* The file extension to register */
        filename[MAXSTR]; /* The xpm file to display */
   int stlen; /* How long is the file extension. */
   GdkPixmap *pixmap; /* Our pixmap */
   GdkBitmap *mask; /* Mask for the pixmap */
   struct pix_ext *next; /* Next file extension */
};

/* These next two are for the connection manager */

struct conn_hosts { /* This will be a host underneath a category */
   char hostdescr[MAXSTR], /* Our host description to be shown in the combo box */
        hostname[MAXSTR], /* Our actual internet hostname */
        dir[MAXSTR], /* Initial directory */
        user[MAXSTR], /* Username to log in as */
        pass[MAXSTR], /* Our password */
        port[6]; /* Port to connect to */
   struct conn_hosts *next; /* Next host in this category */
};

struct conn_categories { /* Each category will have one of these nodes */
   char name[MAXSTR]; /* Our category name */
   struct conn_hosts *hosts; /* Our hosts underneath this category */
   struct conn_categories *next; /* Our next category */
};

/* connect_dialog.c */
void connect_dialog(GtkWidget *widget, struct ftp_window_data *wdata);

/* delete_dialog.c */
void delete_dialog(GtkWidget *widget, gpointer data);
int ftp_rmdir(struct ftp_window_data *wdata, struct ftp_host_data *hdata, char *dir);
int ftp_rmfile(struct ftp_window_data *wdata, struct ftp_host_data *hdata, char *file);

/* file_transfer.c */
void retrCB(GtkWidget *widget, struct ftp_both_windows *windows);
void putCB(GtkWidget *widget, struct ftp_both_windows *windows);

/* ftp.c */
int ftp_connect(struct ftp_window_data *wdata, struct ftp_host_data *hdata, struct ftp_transfer_data *tdata);
int ftp_init_data_conn(struct ftp_window_data *wdata, struct ftp_host_data *hdata);
int ftp_disconnect(struct ftp_window_data *wdata, struct ftp_host_data *hdata, int log);
int ftp_list_files(struct ftp_window_data *wdata, struct ftp_host_data *hdata);
char *ftp_pwd(struct ftp_window_data *wdata, struct ftp_host_data *hdata, char *dir, int len, int log);
int ftp_read_line(int sockfd, char *buf, int size);
char ftp_sendcommand(int log, struct ftp_window_data *wdata, struct ftp_host_data *hdata, char *destbuf, size_t destlen, char *command, ...);
char ftp_read_response(int log, struct ftp_window_data *wdata, struct ftp_host_data *hdata, char *buf, size_t len);
int ftp_chdir(struct ftp_window_data *wdata, struct ftp_host_data *hdata, char *newdir);

/* gtp.c */
void init_gftp(int argc, char *argv[], struct ftp_both_windows *windows, GtkWidget *parent);
void usage(void);
GtkWidget *CreateFTPWindows(GtkWidget *ui, struct ftp_both_windows *windows);
GtkWidget *CreateFTPWindow(GtkWidget *parent, struct ftp_window_data *wdata);
void sortrows(GtkCList *clist, gint column, gpointer data);
void delete_ftp_file_info(struct ftp_window_data *wdata);
void queue_log(int type, char *format, ...);
void ftp_log(int type, char *format, ...);
void update_ftp_info(struct ftp_window_data *wdata);
void change_ascii(GtkWidget *widget, struct ftp_window_data *wdata);
void change_binary(GtkWidget *widget, struct ftp_window_data *wdata);
void selectrow(GtkCList *clist, gint row, gint column, GdkEventButton *event, gpointer data);
void unselectrow(GtkCList *clist, gint row, gint column, GdkEventButton *event, gpointer data);
void selectall(GtkWidget *widget, struct ftp_window_data *wdata);
void deselectall(GtkWidget *widget, struct ftp_window_data *wdata);
void list_dblclick(GtkWidget *widget, GdkEventButton *event, gpointer data);
void chdirfunc(GtkWidget *widget, struct ftp_window_data *wdata);
void chdiredit(GtkWidget *widget, struct ftp_window_data *wdata);
void refresh(GtkWidget *widget, struct ftp_window_data *wdata);
void exitCB(GtkWidget *widget, gpointer data);
void disconnect(GtkWidget *widget, struct ftp_window_data *wdata);
void savelog(GtkWidget *widget, gpointer data);
void dosavelog(GtkWidget *widget, GtkFileSelection *fs);
void savelog_destroy(GtkWidget *widget, GtkWidget *dialog);
void clearlog(GtkWidget *widget, gpointer data);
void fix_display(void);
gint update_downloads(gpointer data);
void selectdl(GtkCList *clist, gint row, gint column, GdkEventButton *event, gpointer data);
void unselectdl(GtkCList *clist, gint row, gint column, GdkEventButton *event, gpointer data);
void stop_transfer(GtkWidget *widget, gpointer data);
int compare_hdata_structs(struct ftp_host_data *hdata1, struct ftp_host_data *hdata2);

/* misc.c */
void *mymalloc(size_t size);
void *myrealloc(void *ptr, size_t size);
char *insert_commas(unsigned long number, char *dest, int size);
void add_local_files(struct ftp_window_data *win);
void add_file_listbox(struct ftp_window_data *wdata, struct ftp_file_data *fle);
long file_countlf(FILE *filefd, long endpos);
char *alltrim(char *str);
int ftp_parse_file_listing(struct ftp_file_data *fle, char *str);
void read_config_file(void);
void write_config_file(void);
int expand_path(char *src, char *dest, size_t size);
int parse_args(char *str, int numargs, int lineno, char *first, ...);
GtkWidget *MakeEditDialog(GtkWidget **dialog, char *diagtxt, char *infotxt,
   char *oktxt, void (*okfunc)(), void *okptr,
   char *canceltxt, void (*cancelfunc)(), void *cancelptr);
GtkWidget *MakeYesNoDialog(GtkWidget **dialog, char *diagtxt, char *infotxt,
   int num, ...);

/* mkdir_dialog.c */
void mkdir_dialog(GtkWidget *widget, gpointer data);
int ftp_mkdir(struct ftp_window_data *wdata, struct ftp_host_data *hdata, char *newdir);

/* rename_dialog.c */
void rename_dialog(GtkWidget *widget, gpointer data);
int ftp_rename(struct ftp_window_data *wdata, struct ftp_host_data *hdata, char *from, char *to);

#endif
