/*
Copyright (C) Rafal Metkowski
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.
*/
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/time.h>
#include <signal.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/telnet.h>
#include <netdb.h>
#include <pwd.h>
#include <dirent.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include <fnmatch.h>
#include <forms.h>
#include "fd_xftp.h"
#define ASCII 0
#define BIN 1
#define LOCAL 0
#define REMOTE 1
#define BY_NAME 1
#define BY_SIZE 2
#define BUF_SIZE 32767
#define HIST_SIZE 15
#define MAXLINE 512
#define CANCEL 0
#define OVERWRITE 1
#define RESUME_TRANSF 2
#define N_FORMS 17
FD_fd_main *fm;
FD_fd_conn_par *fcp;
FD_fd_bookmarks *fb;
FD_fd_options *fo;
FD_fd_options_net *fon;
FD_fd_options_fonts *fof;
FD_fd_options_files *fofl;
FD_fd_options_colors *foc;
FD_fd_about *fa;
FD_fd_download *fd;
FD_fd_download_question *fdq;
FD_fd_input *fi;
FD_fd_question *fq;
FD_fd_message *fmsg;
FD_fd_remote_view *frv;
FD_fd_local_view *flv;
FD_fd_colors *fc;
struct dir_item {
char *file_name;
char *link_name;
char *path;
long mode;
long file_size;
time_t modif_time;
struct dir_item *next;
int selected;
} **local_files = NULL, **remote_files = NULL, *buffer_list = NULL;
struct hist_item {
char *address;
char *user_name;
char *pass_unenc;
char *local_dir;
char *remote_dir;
int anonym_login;
struct hist_item *next;
} *hist_first = NULL, *hist_last = NULL;
struct addr_item {
char *address;
char *dir;
struct addr_item *next;
} *bookm_first = NULL, *bookm_last = NULL;
struct dir_buf_item {
char *dir_path;
struct dir_item **dir;
int dir_len;
int top;
struct dir_buf_item *next;
} *dir_buf = NULL, *cur_dir = NULL;
char *user_name = NULL, *pass_enc = NULL, *pass_unenc = NULL, *address = NULL;
char *remote_dir_path_inp = NULL, *local_dir_path_inp = NULL, e_mail[81] = "";
char *remote_dir_path = NULL, *home_dir, *opt_file_name, *hist_file_name;
char *log_file_name, *addr_file_name, *std_bookm_file, dir_col[10],
lnk_col[10], exe_col[10], other_col[10];
int con_opened = 0, busy = 0, aborted = 0, anonym_login = 0, con_canceled = 0;
int type = BIN, cur_type = ASCII, font_size = 10, br_fsize = 10, port = 21;
int sock_servPI, sock_userDTP, sock_servDTP;
int n_local = 0, n_remote = 0, n_buffer = 0, n_hist = 0, sort_key_local = BY_NAME,
sort_key_remote = BY_NAME;
int ninteract = 0, show_hidden_local = 1, show_hidden_remote = 1, sys_unix,
passive = 0, f_fold_hidden = 0;
int minx = 670, miny = 400;
struct sockaddr_in serverPI, userDTP;
FL_FORM *forms[N_FORMS];
FILE *flog;
int send_command(const char *command, const char *arg, char **pReply);
int get_reply(char **pReply);
int data_command(const char *command, const char *arg);
void cb_close(FL_OBJECT * ob, long arg);
void cb_remote_view_ok(FL_OBJECT * ob, long arg);
char *get_cwdir();
void sort(struct dir_item **ppFiles, int iFiles, int key);
void read_bookmarks(const char *bookm_file);
void write_bookmarks();
void read_hist();
FL_CALLBACKPTR cb_old_local, cb_old_remote, cb_old_buffer;
char *
cut(const char *fn)
{
char *cutted;
cutted = malloc(25);
strncpy(cutted, fn, 20);
cutted[20] = '\0';
if (strlen(fn) > 20)
memset(cutted + 17, '.', 3);
return cutted;
}
char *
resolve_link(const char *full_name)
{
char *resolved, *pc1;
resolved = malloc(strlen(full_name) + 1);
strcpy(resolved, full_name);
pc1 = strstr(resolved, "->");
if (pc1 == NULL) {
free(resolved);
return NULL;
}
*--pc1 = '\0';
return resolved;
}
void center_downl()
{
int x, y;
x = fm->fd_main->x + (fm->fd_main->w - fd->fd_download->w) / 2;
y = fm->fd_main->y + (fm->fd_main->h - fd->fd_download->h) / 2;
fl_set_form_position(fd->fd_download, x, y);
}
int prehndl_local(FL_OBJECT * ob, int event, FL_Coord mx, FL_Coord my, int key, void *xev)
{
if (event == FL_MOTION || event == FL_MOUSE)
fl_set_browser_topline(fm->br_local_size, fl_get_browser_topline(ob));
return 0;
}
int prehndl_local_size(FL_OBJECT * ob, int event, FL_Coord mx, FL_Coord my, int key, void *xev)
{
if (event == FL_MOTION || event == FL_MOUSE)
fl_set_browser_topline(fm->br_local, fl_get_browser_topline(ob));
return 0;
}
int prehndl_remote(FL_OBJECT * ob, int event, FL_Coord mx, FL_Coord my, int key, void *xev)
{
if (event == FL_MOTION || event == FL_MOUSE)
fl_set_browser_topline(fm->br_remote_size, fl_get_browser_topline(ob));
return 0;
}
int prehndl_remote_size(FL_OBJECT * ob, int event, FL_Coord mx, FL_Coord my, int key, void *xev)
{
if (event == FL_MOTION || event == FL_MOUSE)
fl_set_browser_topline(fm->br_remote, fl_get_browser_topline(ob));
return 0;
}
void cb_vscroll_local(FL_OBJECT * ob, long arg)
{
int i;
cb_old_local(ob, arg);
i = fl_get_browser_topline(fm->br_local_size);
fl_set_browser_topline(fm->br_local, i);
}
void cb_vscroll_remote(FL_OBJECT * ob, long arg)
{
int i;
cb_old_remote(ob, arg);
i = fl_get_browser_topline(fm->br_remote_size);
fl_set_browser_topline(fm->br_remote, i);
}
void
add_to_log (const char *line)
{
if (!ninteract)
fl_addto_browser (fm->br_log, line);
if (flog != NULL)
fprintf (flog, "%s\n", line);
}
void add_to_log_err(const char *func)
{
const char *estr = strerror(errno);
if (!ninteract) {
fl_addto_browser_chars(fm->br_log, func);
fl_addto_browser_chars(fm->br_log, ":");
fl_addto_browser_chars(fm->br_log, estr);
}
if (flog != NULL) {
fprintf(flog, "%s:", func);
fprintf(flog, "%s\n", estr);
}
}
void check_forms()
{
if (!ninteract)
fl_check_forms();
}
int cmp_name(const void *p1, const void *p2)
{
struct dir_item *pF1 = *((struct dir_item **) p1);
struct dir_item *pF2 = *((struct dir_item **) p2);
if (S_ISDIR(pF1->mode) && !S_ISDIR(pF2->mode))
return -1;
if (S_ISDIR(pF2->mode) && !S_ISDIR(pF1->mode))
return 1;
if (S_ISLNK(pF1->mode) && !S_ISLNK(pF2->mode))
return -1;
if (S_ISLNK(pF2->mode) && !S_ISLNK(pF1->mode))
return 1;
if (strcmp(pF1->file_name, "..") == 0)
return -1;
if (strcmp(pF2->file_name, "..") == 0)
return 1;
return strcmp(pF1->file_name, pF2->file_name);
}
int cmp_size(const void *p1, const void *p2)
{
struct dir_item *pF1 = *((struct dir_item **) p1);
struct dir_item *pF2 = *((struct dir_item **) p2);
if (S_ISDIR(pF1->mode) && !S_ISDIR(pF2->mode))
return -1;
if (S_ISDIR(pF2->mode) && !S_ISDIR(pF1->mode))
return 1;
if (S_ISLNK(pF1->mode) && !S_ISLNK(pF2->mode))
return -1;
if (S_ISLNK(pF2->mode) && !S_ISLNK(pF1->mode))
return 1;
if (strcmp(pF1->file_name, "..") == 0)
return -1;
if (strcmp(pF2->file_name, "..") == 0)
return 1;
if (S_ISLNK(pF1->mode) || S_ISDIR(pF1->mode))
return strcmp(pF1->file_name, pF2->file_name);
return pF1->file_size - pF2->file_size;
}
void activate_form(FL_FORM * form)
{
FL_OBJECT *p1;
if (ninteract)
return;
p1 = form->first;
fl_freeze_form(form);
while (1) {
if (p1->objclass == FL_BUTTON || p1->objclass == FL_TEXT || p1->objclass == FL_CHECKBUTTON)
fl_set_object_lcol(p1, FL_BLACK);
if (p1 == form->last)
break;
p1 = p1->next;
}
if (!con_opened || busy) {
fl_set_object_lcol(fm->remote_btns, FL_INACTIVE);
fl_set_object_lcol(fm->br_remote, FL_INACTIVE);
fl_set_object_lcol(fm->br_remote_size, FL_INACTIVE);
}
if (busy)
fl_set_object_lcol(fm->local_btns, FL_INACTIVE);
fl_unfreeze_form(form);
fl_activate_form(form);
}
void deactivate_form(FL_FORM * form)
{
FL_OBJECT *p1;
if (ninteract)
return;
p1 = form->first;
fl_deactivate_form(form);
fl_freeze_form(form);
while (1) {
if (p1->objclass == FL_BUTTON || p1->objclass == FL_TEXT)
fl_set_object_lcol(p1, FL_INACTIVE);
if (p1 == form->last)
break;
p1 = p1->next;
}
fl_unfreeze_form(form);
}
void activate_object(FL_OBJECT * ob)
{
fl_set_object_lcol(ob, FL_BLACK);
fl_activate_object(ob);
}
void deactivate_object(FL_OBJECT * ob)
{
fl_set_object_lcol(ob, FL_INACTIVE);
fl_deactivate_object(ob);
}
void adjust_path(FL_OBJECT * f_txt, char *path)
{
int i, path_len, x, y, w, h;
char *pc1, *ad_path;
fl_get_object_geometry(f_txt, &x, &y, &w, &h);
w -= 10;
pc1 = path;
path_len = strlen(path);
for (i = path_len; i > 0; i--) {
if (fl_get_string_width(1, font_size, pc1, i) <= w) {
ad_path = malloc(strlen(path) + 1);
strcpy(ad_path, pc1);
if (i != path_len)
memset(ad_path, '.', 3);
break;
}
pc1++;
}
fl_set_object_label(f_txt, ad_path);
free(ad_path);
}
void add_to_history()
{
char *hist_line;
const char *a = fl_get_input(fcp->address);
const char *r = fl_get_input(fcp->remote_dir);
int i, nh, repeated = 0;
struct hist_item *pHist_it, *pPrev_it = NULL;
FILE *f_history;
read_hist();
pHist_it = hist_first;
for (i = 1; pHist_it != NULL; i++) {
if (strcmp(pHist_it->address, a) == 0 && strcmp(pHist_it->remote_dir, r) == 0) {
repeated = 1;
break;
}
pPrev_it = pHist_it;
pHist_it = pHist_it->next;
}
if (repeated) {
if (!ninteract)
fl_delete_browser_line(fcp->br_history, i);
if (pPrev_it != NULL) {
pPrev_it->next = pHist_it->next;
pHist_it->next = hist_first;
hist_first = pHist_it;
free(hist_first->user_name);
free(hist_first->pass_unenc);
free(hist_first->local_dir);
}
} else {
pHist_it = malloc(sizeof(struct hist_item));
pHist_it->next = hist_first;
hist_first = pHist_it;
pHist_it->remote_dir = malloc(strlen(r) + 1);
strcpy(pHist_it->remote_dir, r);
pHist_it->address = malloc(strlen(a) + 1);
strcpy(pHist_it->address, a);
n_hist++;
}
hist_line = malloc(strlen(a) + strlen(r) + 5);
sprintf(hist_line, "%s %s", a, r);
if (!ninteract)
fl_insert_browser_line(fcp->br_history, 1, hist_line);
free(hist_line);
pHist_it->user_name = malloc(strlen(user_name) + 1);
strcpy(pHist_it->user_name, user_name);
pHist_it->pass_unenc = malloc(strlen(pass_unenc) + 1);
strcpy(pHist_it->pass_unenc, pass_unenc);
pHist_it->local_dir = malloc(strlen(local_dir_path_inp) + 1);
strcpy(pHist_it->local_dir, local_dir_path_inp);
pHist_it->anonym_login = anonym_login;
if ((f_history = fopen(hist_file_name, "w")) != NULL) {
nh = n_hist > HIST_SIZE ? HIST_SIZE : n_hist;
fprintf(f_history, "%d\n", nh);
pHist_it = hist_first;
for (i = 0; i < nh; i++) {
fprintf(f_history, "%s\n", pHist_it->address);
fprintf(f_history, "%s\n", pHist_it->user_name);
fprintf(f_history, "%s\n", pHist_it->pass_unenc);
fprintf(f_history, "%s\n", pHist_it->local_dir);
fprintf(f_history, "%s\n", pHist_it->remote_dir);
fprintf(f_history, "%d\n", pHist_it->anonym_login);
pHist_it = pHist_it->next;
}
fclose(f_history);
}
}
void add_file_to_list(struct dir_item **lf, char *fn, long fs, time_t mt, long mode, char *path)
{
struct dir_item *pDir_it, *last_file;
pDir_it = malloc(sizeof(struct dir_item));
pDir_it->next = *lf;
last_file = pDir_it;
last_file->file_name = malloc(strlen(fn) + 1);
strcpy(last_file->file_name, fn);
last_file->link_name = resolve_link(fn);
last_file->file_size = fs;
last_file->modif_time = mt;
last_file->mode = mode;
last_file->selected = 0;
if (path != NULL) {
last_file->path = malloc(strlen(path) + 1);
strcpy(last_file->path, path);
} else
last_file->path = NULL;
*lf = last_file;
}
struct dir_item **
put_files_into_array(struct dir_item *last_file, int iFiles)
{
int i;
struct dir_item **ppDir_it, **ppFiles;
ppFiles = malloc(iFiles * sizeof(struct dir_item *));
ppDir_it = ppFiles + iFiles;
for (i = 0; i < iFiles; i++) {
*--ppDir_it = last_file;
last_file = last_file->next;
}
return ppFiles;
}
void remove_file_from_array(struct dir_item ***pppFiles, int *piFiles, int iFileno)
{
int i;
struct dir_item **ppF1, **ppF2, **ppNew_files;
ppNew_files = malloc(--*piFiles * sizeof(struct dir_item *));
ppF1 = *pppFiles;
ppF2 = ppNew_files;
for (i = 0; i < *piFiles; i++) {
if (i == iFileno)
ppF1++;
*(ppF2++) = *(ppF1++);
}
free(*pppFiles);
*pppFiles = ppNew_files;
}
void add_file_to_array(struct dir_item ***pppFiles, int *piFiles,
const char *fn, long fs, time_t mt, long mode)
{
int i;
struct dir_item **ppF1, **ppF2, **ppNewfiles, *pNew_file;
ppNewfiles = malloc((*piFiles + 1) * sizeof(struct dir_item *));
ppF1 = *pppFiles;
ppF2 = ppNewfiles;
for (i = 0; i < *piFiles; i++)
*(ppF2++) = *(ppF1++);
pNew_file = malloc(sizeof(struct dir_item));
pNew_file->file_name = malloc(strlen(fn) + 1);
strcpy(pNew_file->file_name, fn);
pNew_file->path = NULL;
pNew_file->link_name = resolve_link(fn);
pNew_file->file_size = fs;
pNew_file->modif_time = mt;
pNew_file->mode = mode;
pNew_file->selected = 0;
*ppF2 = pNew_file;
free(*pppFiles);
*pppFiles = ppNewfiles;
(*piFiles)++;
}
void put_files_into_browser(FL_OBJECT * browser, FL_OBJECT * browser_size,
struct dir_item **ppFiles, int iFiles, int sort_key)
{
int i, j;
char *file_name, file_size[30];
fl_clear_browser(browser);
fl_clear_browser(browser_size);
fl_freeze_form(fm->fd_main);
sort(ppFiles, iFiles, sort_key);
for (i = 0; i < iFiles; i++) {
file_name = malloc(strlen((*ppFiles)->file_name) + 9);
switch ((*ppFiles)->mode & S_IFMT) {
case S_IFDIR:
strcpy(file_name, dir_col);
sprintf(file_size, "%s@rDIR", dir_col);
break;
case S_IFLNK:
strcpy(file_name, lnk_col);
sprintf(file_size, "%s@rLNK", lnk_col);
break;
default:
if ((*ppFiles)->mode & S_IXUSR)
strcpy(file_name, exe_col);
else
strcpy(file_name, other_col);
if ((*ppFiles)->file_size < (long) 1024)
sprintf(file_size, "%s@r%li", file_name, (long) (*ppFiles)->file_size);
else
sprintf(file_size, "%s@r%li k", file_name, (long) (*ppFiles)->file_size >> 10);
}
strcat(file_name, "@n");
if (*(*ppFiles)->file_name == '@')
strcat(file_name, "@");
strcat(file_name, (*ppFiles)->file_name);
fl_add_browser_line(browser, file_name);
fl_add_browser_line(browser_size, file_size);
if ((*ppFiles)->selected) {
j = fl_get_browser_maxline(browser);
fl_select_browser_line(browser, j);
fl_select_browser_line(browser_size, j);
}
free(file_name);
ppFiles++;
}
fl_unfreeze_form(fm->fd_main);
}
void read_local_dir()
{
struct stat stbuf;
char *local_dir_path;
int i;
DIR *pDir;
struct dirent *dir_ent;
struct dir_item **ppDir_it, *last_file = NULL;
fl_clear_browser(fm->br_local);
fl_clear_browser(fm->br_local_size);
ppDir_it = local_files;
for (i = 0; i < n_local; i++) {
free((*ppDir_it)->file_name);
free((*ppDir_it)->path);
free(*(ppDir_it++));
}
free(local_files);
n_local = 0;
if ((local_dir_path = get_cwdir()) == NULL) {
local_dir_path = malloc(2);
strcpy(local_dir_path, ".");
}
adjust_path(fm->txt_local_dir, local_dir_path);
if ((pDir = opendir(local_dir_path)) != NULL)
while ((dir_ent = readdir(pDir))) {
lstat(dir_ent->d_name, &stbuf);
if (strcmp(dir_ent->d_name, ".") == 0 || strcmp(dir_ent->d_name, "..") == 0)
continue;
if (dir_ent->d_name[0] == '.' && !show_hidden_local)
continue;
add_file_to_list(&last_file, dir_ent->d_name, stbuf.st_size, stbuf.st_mtime, stbuf.st_mode, NULL);
n_local++;
}
add_file_to_list(&last_file, "..", -1, -1, S_IFDIR, NULL);
n_local++;
local_files = put_files_into_array(last_file, n_local);
put_files_into_browser(fm->br_local, fm->br_local_size, local_files, n_local, sort_key_local);
free(local_dir_path);
}
struct dir_buf_item *
read_rdir_to_mem(int rescan)
{
int i, bytes_received, iLink, found = 0, length;
long size, mode;
char c1, read_line[512], *pc1, *pc2, *bgn, *end, *pwd_reply, *rdp;
struct dir_item *last_file = NULL, **ppFiles;
struct dir_buf_item *pDbi = dir_buf;
if (send_command("PWD", NULL, &pwd_reply) == 257) {
bgn = strchr(pwd_reply, '"');
end = strrchr(pwd_reply, '"');
if (bgn != NULL && end != NULL && bgn != end) {
i = end - bgn;
rdp = malloc(i);
strncpy(rdp, ++bgn, --i);
rdp[i] = '\0';
}
while (pDbi != NULL) {
if (strcmp(pDbi->dir_path, rdp) == 0) {
found = 1;
break;
}
pDbi = pDbi->next;
}
if (found && !rescan)
return pDbi;
} else {
rdp = malloc(2);
strcpy(rdp, ".");
}
length = 0;
if (cur_type != ASCII && send_command("TYPE A", NULL, NULL) == 200)
cur_type = ASCII;
if (data_command("LIST", NULL) != 150)
goto read_err;
while (1) {
for (bytes_received = 0;; bytes_received++) {
while ((i = read(sock_servDTP, &c1, 1)) < 0) {
if (!con_opened)
goto read_err;
if (errno != EAGAIN) {
add_to_log_err("read");
goto read_err;
}
fl_check_forms();
}
if (c1 == '\n')
break;
read_line[bytes_received] = c1;
}
if (i == 0)
break;
if (read_line[bytes_received - 1] == '\r')
bytes_received--;
read_line[bytes_received] = '\0';
iLink = 1;
if (strpbrk(read_line, "dlspbc-") != read_line)
continue;
switch (*read_line) {
case 'l':
iLink = 3;
mode = S_IFLNK;
break;
case 'd':
mode = S_IFDIR;
break;
default:
if (read_line[3] == 'x')
mode = S_IXUSR;
else
mode = 0;
}
pc1 = read_line;
for (i = 0; i < 4; i++) {
pc2 = pc1;
while (*pc1 != ' ' && *pc1 != '\0')
pc1++;
while (*pc1 == ' ' && *pc1 != '\0')
pc1++;
}
if (!isdigit(*pc1))
pc1 = pc2;
size = atol(pc1);
for (i = 0; i < 4; i++) {
pc2 = pc1;
while (*pc1 != ' ' && *pc1 != '\0')
pc1++;
while (*pc1 == ' ' && *pc1 != '\0')
pc1++;
}
if (pc1[0] == '.' && !show_hidden_remote)
continue;
if (strcmp(pc1, ".") == 0 || strcmp(pc1, "..") == 0)
continue;
add_file_to_list(&last_file, pc1, size, 0, mode, NULL);
length++;
}
add_file_to_list(&last_file, "..", -1, -1, S_IFDIR, NULL);
length++;
ppFiles = put_files_into_array(last_file, length);
get_reply(NULL);
if (found) {
free(pDbi->dir);
pDbi->dir_len = length;
pDbi->dir = ppFiles;
} else {
pDbi = malloc(sizeof(struct dir_buf_item));
pDbi->dir_path = malloc(strlen(rdp) + 1);
strcpy(pDbi->dir_path, rdp);
pDbi->dir_len = length;
pDbi->dir = ppFiles;
pDbi->next = dir_buf;
pDbi->top = 1;
dir_buf = pDbi;
}
close(sock_servDTP);
close(sock_userDTP);
return pDbi;
read_err:
close(sock_servDTP);
close(sock_userDTP);
return NULL;
}
int read_remote_dir(int rescan)
{
struct dir_buf_item *pDbi;
int i;
fl_clear_browser(fm->br_remote);
fl_clear_browser(fm->br_remote_size);
if (cur_dir != NULL) {
cur_dir->dir_len = n_remote;
cur_dir->dir = remote_files;
for (i = 0; i < n_remote; i++)
remote_files[i]->selected = 0;
}
pDbi = read_rdir_to_mem(rescan);
if (pDbi == NULL)
return -1;
free(remote_dir_path);
remote_dir_path = malloc(strlen(pDbi->dir_path) + 1);
strcpy(remote_dir_path, pDbi->dir_path);
adjust_path(fm->txt_remote_dir, remote_dir_path);
remote_files = pDbi->dir;
n_remote = pDbi->dir_len;
put_files_into_browser(fm->br_remote, fm->br_remote_size, remote_files, n_remote, sort_key_remote);
fl_set_browser_topline(fm->br_remote, pDbi->top);
fl_set_browser_topline(fm->br_remote_size, pDbi->top);
cur_dir = pDbi;
return 1;
}
void create_forms()
{
fm = create_form_fd_main();
fcp = create_form_fd_conn_par();
fb = create_form_fd_bookmarks();
fo = create_form_fd_options();
fon = create_form_fd_options_net();
fof = create_form_fd_options_fonts();
fofl = create_form_fd_options_files();
foc = create_form_fd_options_colors();
fa = create_form_fd_about();
fd = create_form_fd_download();
fdq = create_form_fd_download_question();
fi = create_form_fd_input();
fq = create_form_fd_question();
fmsg = create_form_fd_message();
frv = create_form_fd_remote_view();
flv = create_form_fd_local_view();
fc = create_form_fd_colors();
forms[0] = fm->fd_main;
forms[1] = fcp->fd_conn_par;
forms[2] = fo->fd_options;
forms[3] = fon->fd_options_net;
forms[4] = fof->fd_options_fonts;
forms[5] = fa->fd_about;
forms[6] = fd->fd_download;
forms[7] = fdq->fd_download_question;
forms[8] = fi->fd_input;
forms[9] = fq->fd_question;
forms[10] = fmsg->fd_message;
forms[11] = frv->fd_remote_view;
forms[12] = flv->fd_local_view;
forms[13] = fofl->fd_options_files;
forms[14] = fb->fd_bookmarks;
forms[15] = foc->fd_options_colors;
forms[16] = fc->fd_colors;
}
void change_font_s(int form_no)
{
FL_OBJECT *p1;
double k;
fl_freeze_form(forms[form_no]);
p1 = forms[form_no]->first;
while (1) {
fl_set_object_lsize(p1, font_size);
if (p1->objclass == FL_BROWSER)
fl_set_browser_fontsize(p1, br_fsize);
if (p1 == forms[form_no]->last)
break;
p1 = p1->next;
}
k = fl_adjust_form_size(forms[form_no]);
if (form_no == 0) {
minx = (double)minx * k;
miny = (double)miny * k;
fl_set_form_minsize(forms[form_no], minx, miny);
}
fl_set_form_size(forms[form_no], forms[form_no]->w + 1, forms[form_no]->h + 1);
fl_unfreeze_form(forms[form_no]);
}
void change_font_size()
{
int i;
for (i = 0; i < N_FORMS; i++)
if (i != 2) /* without this exception aplication dumps core */
change_font_s (i);
}
void sort(struct dir_item **ppFiles, int iFiles, int sort_key)
{
if (sort_key == BY_NAME)
qsort(ppFiles, iFiles, sizeof(struct dir_item *), cmp_name);
else
qsort(ppFiles, iFiles, sizeof(struct dir_item *), cmp_size);
}
int send_com_no_reply(const char *command, const char *arg, int flags, int crlf)
{
char line_to_send[strlen(command) + (arg != NULL ? strlen(arg) : 0) + 10];
if (crlf) {
if (arg != NULL)
sprintf(line_to_send, "%s %s\r\n", command, arg);
else
sprintf(line_to_send, "%s\r\n", command);
} else
sprintf(line_to_send, "%s", command);
while (send(sock_servPI, line_to_send, strlen(line_to_send), flags) < 0) {
if (!con_opened)
return -1;
if (errno != EWOULDBLOCK) {
add_to_log_err("send");
return -1;
}
check_forms();
}
if (crlf) {
if (arg != NULL) {
sprintf(line_to_send, "%s %s", command, (strncmp(command, "PASS", 4) || anonym_login) ? arg : "XXXX");
add_to_log(line_to_send);
} else
add_to_log(command);
}
return 0;
}
int send_command(const char *command, const char *arg, char **pReply)
{
if (send_com_no_reply(command, arg, 0, 1) < 0)
return -1;
return (get_reply(pReply));
}
int get_reply(char **pReply)
{
char reply[256], rb[5], c1;
int i = 1, j, multi = 0;
while (1) {
for (j = 0; i > 0; j++) {
while ((i = read(sock_servPI, &c1, 1)) < 0) {
if (!con_opened)
return -1;
if (errno != EAGAIN) {
add_to_log_err("read");
return -1;
}
check_forms();
}
if (c1 == '\n')
break;
reply[j] = c1;
}
if (i == 0)
break;
reply[j - 1] = '\0';
add_to_log(reply);
if (pReply != NULL) {
*pReply = malloc(strlen(reply) + 1);
strcpy(*pReply, reply);
}
if (reply[3] == '-') {
multi = 1;
strncpy(rb, reply, 3);
rb[3] = ' ';
rb[4] = '\0';
}
if (!multi || strncmp(reply, rb, 4) == 0)
break;
reply[3] = ' ';
}
return atoi(reply);
}
int open_ftp_connection()
{
struct hostent *h_ent = NULL;
int i, on = 1;
char *status;
fl_set_object_label(fm->txt_status, "Looking up for host");
memset(&serverPI.sin_addr, 0, sizeof(serverPI.sin_addr));
serverPI.sin_port = htons(port);
if ((h_ent = gethostbyname(address)) == NULL) {
add_to_log_err("gethostbyname");
goto op_err;
}
serverPI.sin_family = h_ent->h_addrtype;
serverPI.sin_addr = *((struct in_addr *) *(h_ent->h_addr_list));
if ((sock_servPI = socket(serverPI.sin_family, SOCK_STREAM, 0)) < 0) {
add_to_log_err("socket");
goto op_err;
}
if (fcntl(sock_servPI, F_SETFL, O_NONBLOCK) < 0) {
add_to_log_err("fcntl");
goto op_err;
}
status = malloc(strlen(address) + 15);
sprintf(status, "Connecting to %s", address);
fl_set_object_label(fm->txt_status, status);
while (connect(sock_servPI, (struct sockaddr *) &serverPI, sizeof(serverPI)) < 0) {
if (con_canceled)
return -1;
if (errno == EISCONN)
break;
if (errno == EINPROGRESS || errno == EAGAIN || errno == EALREADY) {
check_forms();
continue;
}
if (*++h_ent->h_addr_list != NULL)
serverPI.sin_addr = *((struct in_addr *) *(h_ent->h_addr_list));
else {
add_to_log_err("connect");
goto op_err;
}
}
i = sizeof(struct sockaddr_in);
if (getsockname(sock_servPI, (struct sockaddr *) &userDTP, &i) < 0) {
add_to_log_err("getsockname");
close(sock_servPI);
goto op_err;
}
setsockopt(sock_servPI, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on));
return 1;
op_err:
fl_set_object_label(fm->txt_status, strerror(errno));
return -1;
}
int data_command2(const char *command1, const char *arg1,
const char *command2, const char *arg2)
{
struct sockaddr_in serverDTP;
char port_command[50];
char *a, *p, *pasv_reply = NULL, *pc1;
int i, rp, ai[6];
unsigned char ac[6];
if ((sock_userDTP = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
add_to_log_err("socket");
return -1;
}
if (passive) {
if (send_command("PASV", NULL, &pasv_reply) != 227) {
free(pasv_reply);
return -1;
}
pc1 = pasv_reply + 3;
while (*pc1 != '\0' && !isdigit(*pc1))
pc1++;
if (*pc1 == '\0') {
free(pasv_reply);
return -1;
}
sscanf(pc1, "%d,%d,%d,%d,%d,%d", &ai[0], &ai[1], &ai[2], &ai[3], &ai[4], &ai[5]);
for (i = 0; i < 6; i++)
ac[i] = (unsigned char) ai[i];
memcpy(&serverDTP.sin_addr, &ac[0], 4);
memcpy(&serverDTP.sin_port, &ac[4], 2);
serverDTP.sin_family = AF_INET;
if ((sock_servDTP = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
add_to_log_err("socket");
return -1;
}
if (!ninteract)
if (fcntl(sock_servDTP, F_SETFL, O_NONBLOCK) < 0) {
add_to_log_err("fcntl");
return -1;
}
while (connect(sock_servDTP, (struct sockaddr *) &serverDTP, sizeof(serverDTP)) < 0) {
if (!con_opened)
return -1;
if (errno == EISCONN)
break;
if (errno == EINPROGRESS || errno == EAGAIN || errno == EALREADY) {
check_forms();
continue;
}
add_to_log_err("connect");
return -1;
}
free(pasv_reply);
if (command1 != NULL && send_command(command1, arg1, NULL) >= 400)
return -1;
rp = send_command(command2, arg2, NULL);
return rp;
} else {
if (!ninteract)
if (fcntl(sock_userDTP, F_SETFL, O_NONBLOCK) < 0) {
add_to_log_err("fcntl");
return -1;
}
userDTP.sin_port = 0;
if (bind(sock_userDTP, (struct sockaddr *) &userDTP, sizeof(userDTP)) < 0) {
add_to_log_err("bind");
return -1;
}
i = sizeof(struct sockaddr_in);
if (getsockname(sock_userDTP, (struct sockaddr *) &userDTP, &i) < 0) {
add_to_log_err("getsockname");
return -1;
}
if (listen(sock_userDTP, 5) < 0) {
add_to_log_err("listen");
return -1;
}
a = (char *) &userDTP.sin_addr;
p = (char *) &userDTP.sin_port;
#define UC(x) (((int) x) & 0xff)
sprintf(port_command, "PORT %d,%d,%d,%d,%d,%d", UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
if (send_command(port_command, NULL, NULL) != 200)
return -1;
if (command1 != NULL && send_command(command1, arg1, NULL) >= 400)
return -1;
rp = send_command(command2, arg2, NULL);
if (rp >= 300)
return rp;
i = sizeof(serverDTP);
while ((sock_servDTP = accept(sock_userDTP, (struct sockaddr *) &serverDTP, &i)) < 0) {
if (errno != EWOULDBLOCK) {
add_to_log_err("accept");
return -1;
}
if (!con_opened)
return -1;
check_forms();
}
return rp;
}
}
int data_command(const char *command, const char *arg)
{
return data_command2(NULL, NULL, command, arg);
}
void download(struct dir_item **ppFiles_to_download, int n_files)
{
int mode, bytes_received, i, j, bytes_wrote, dest_file, action[n_files],
flags;
long bytes_transm, elapsed_time, estimated_time;
float transfer_rate;
char tmp_str[150], receive_buf[BUF_SIZE], *pc1, *pc2, *rfn, *lfn;
char *cfile_name, *full_fname, *file_name;
struct dir_item *pFile;
struct stat stbuf;
struct timeval start_time, cur_time;
FL_OBJECT *ob;
for (j = 0; j < n_files; j++) {
if (S_ISLNK(ppFiles_to_download[j]->mode))
file_name = ppFiles_to_download[j]->link_name;
else
file_name = ppFiles_to_download[j]->file_name;
if (lstat(file_name, &stbuf) == 0) {
deactivate_form(fm->fd_main);
if (stbuf.st_size < ppFiles_to_download[j]->file_size && type == BIN)
sprintf(tmp_str, "Local file %s exists\nand is shorter than remote file!", cfile_name = cut(ppFiles_to_download[j]->file_name));
else {
deactivate_object(fdq->resume_transf);
sprintf(tmp_str, "Local file %s exists!", cfile_name = cut(file_name));
}
free(cfile_name);
fl_show_form(fdq->fd_download_question, FL_PLACE_MOUSE, FL_TRANSIENT, "");
fl_set_object_label(fdq->txt, tmp_str);
ob = fl_do_forms();
if (ob == fdq->cancel)
action[j] = CANCEL;
if (ob == fdq->overwrite)
action[j] = OVERWRITE;
if (ob == fdq->resume_transf)
action[j] = RESUME_TRANSF;
if (fdq->resume_transf->active <= 0)
activate_object(fdq->resume_transf);
fl_hide_form(fdq->fd_download_question);
activate_form(fm->fd_main);
} else
action[j] = OVERWRITE;
}
deactivate_form(fm->fd_main);
fl_show_form(fd->fd_download, FL_PLACE_GEOMETRY, FL_TRANSIENT, "Xrmftp: download");
center_downl();
for (j = 0; j < n_files && !aborted; j++) {
pFile = ppFiles_to_download[j];
if (S_ISLNK(pFile->mode))
file_name = pFile->link_name;
else
file_name = pFile->file_name;
if (action[j] == CANCEL)
continue;
if ((pFile->mode & S_IXUSR) == S_IXUSR)
mode = 0777;
else
mode = 0666;
if (pFile->path != NULL) {
full_fname = malloc(strlen(pFile->path) + strlen(file_name) + 4);
sprintf(full_fname, "%s/%s", pFile->path, file_name);
rfn = full_fname;
} else {
full_fname = NULL;
rfn = file_name;
}
lfn = file_name;
if (!ninteract) {
if (action[j] == OVERWRITE) {
flags = O_CREAT | O_WRONLY | O_TRUNC;
fl_set_object_label(fmsg->txt, "Can not create file !");
} else {
flags = O_APPEND | O_WRONLY;
fl_set_object_label(fmsg->txt, "Can not open file !");
}
fl_set_slider_bounds(fd->sl_time, 0, (double) (pFile->file_size));
fl_set_slider_value(fd->sl_time, 0);
cfile_name = cut(rfn);
fl_set_object_label(fd->txt_file_name, cfile_name);
free(cfile_name);
fl_set_object_label(fd->txt_transm, "0");
if (pFile->file_size < 1024)
sprintf(tmp_str, "%li", pFile->file_size);
else
sprintf(tmp_str, "%li k", pFile->file_size >> 10);
fl_set_object_label(fd->txt_total, tmp_str);
fl_set_object_label(fd->txt_transfer_rate, "");
fl_set_object_label(fd->txt_elapsed_time, "");
fl_set_object_label(fd->txt_estimated_time, "");
fl_check_forms();
}
if (type != cur_type && send_command("TYPE", type == ASCII ? "A" : "I", NULL) == 200)
cur_type = type;
if (action[j] == RESUME_TRANSF) {
lstat(lfn, &stbuf);
bytes_transm = stbuf.st_size;
sprintf(tmp_str, "%li", stbuf.st_size);
if (data_command2("REST", tmp_str, "RETR", rfn) != 150)
goto download_err;
} else {
bytes_transm = 0;
if (data_command("RETR", rfn) != 150)
goto download_err;
}
if ((dest_file = open(lfn, flags, mode)) < 0) {
if (!ninteract) {
deactivate_form(fm->fd_main);
fl_show_form(fmsg->fd_message, FL_PLACE_MOUSE, FL_TRANSIENT, "");
fl_do_forms();
fl_hide_form(fmsg->fd_message);
activate_form(fm->fd_main);
}
return;
}
if (!ninteract) {
}
gettimeofday(&start_time, NULL);
while (1) {
while ((bytes_received = read(sock_servDTP, receive_buf, BUF_SIZE)) < 0) {
if (errno != EAGAIN) {
add_to_log_err("read");
goto download_err1;
}
check_forms();
if (aborted)
goto download_err1;
}
if (bytes_received == 0)
break;
if (aborted)
goto download_err1;
pc1 = pc2 = receive_buf;
bytes_wrote = bytes_received;
if (type == ASCII) {
bytes_wrote = 0;
for (i = 0; i < bytes_received; i++) {
if (*pc1 != '\r') {
*(pc2++) = *pc1;
bytes_wrote++;
}
pc1++;
}
}
if (sys_unix)
bytes_transm += bytes_wrote;
else
bytes_transm += bytes_received;
check_forms();
write(dest_file, receive_buf, bytes_wrote);
gettimeofday(&cur_time, NULL);
elapsed_time = cur_time.tv_sec - start_time.tv_sec;
if (!ninteract) {
if (elapsed_time != 0) {
transfer_rate = (float) bytes_transm / (float) elapsed_time;
estimated_time = pFile->file_size / transfer_rate;
sprintf(tmp_str, "%.2f kbytes/sec.", transfer_rate / 1024);
fl_set_object_label(fd->txt_transfer_rate, tmp_str);
sprintf(tmp_str, "%li sec.", elapsed_time);
fl_set_object_label(fd->txt_elapsed_time, tmp_str);
sprintf(tmp_str, "%li sec.", estimated_time);
fl_set_object_label(fd->txt_estimated_time, tmp_str);
}
if (bytes_transm < 1024)
sprintf(tmp_str, "%li", bytes_transm);
else
sprintf(tmp_str, "%li k", bytes_transm >> 10);
fl_set_object_label(fd->txt_transm, tmp_str);
fl_set_slider_value(fd->sl_time, bytes_transm);
}
}
download_err1:
close(sock_servDTP);
close(sock_userDTP);
if (aborted)
get_reply(NULL);
get_reply(NULL);
download_err:
close(dest_file);
free(full_fname);
}
if (aborted)
aborted = 0;
if (ninteract) {
if (flog != NULL)
fclose(flog);
exit(0);
}
else {
fl_hide_form(fd->fd_download);
activate_form(fm->fd_main);
}
}
void upload(struct dir_item **ppFiles_to_upload, int n_files, int recurs)
{
int bytes_read, i, j, bytes_to_sent, bytes_sent, bs, src_file, action[n_files], fexists;
long bytes_transm, elapsed_time, estimated_time;
double transfer_rate;
char tmp_str[150], send_buf[2 * BUF_SIZE], read_buf[BUF_SIZE], *pc1,
*pc2, *rfn, *lfn;
char *cfile_name, *file_name;
struct dir_item *pFile, *pDest_file;
struct timeval start_time, cur_time;
FL_OBJECT *ob;
for (j = 0; j < n_files; j++) {
file_name = ppFiles_to_upload[j]->file_name;
fexists = 0;
if (!recurs) {
for (i = 0; i < n_remote; i++)
if (strcmp(file_name, remote_files[i]->file_name) == 0) {
fexists = 1;
pDest_file = remote_files[i];
break;
}
}
if (fexists) {
deactivate_form(fm->fd_main);
if (pDest_file->file_size < ppFiles_to_upload[j]->file_size && type == BIN)
sprintf(tmp_str, "Remote file %s exists\nand is shorter than local file!", cfile_name = cut(ppFiles_to_upload[j]->file_name));
else {
deactivate_object(fdq->resume_transf);
sprintf(tmp_str, "Remote file %s exists!", cfile_name = cut(file_name));
}
free(cfile_name);
fl_show_form(fdq->fd_download_question, FL_PLACE_MOUSE, FL_TRANSIENT, "");
fl_set_object_label(fdq->txt, tmp_str);
ob = fl_do_forms();
if (ob == fdq->cancel)
action[j] = CANCEL;
if (ob == fdq->overwrite)
action[j] = OVERWRITE;
if (ob == fdq->resume_transf)
action[j] = RESUME_TRANSF;
if (fdq->resume_transf->active <= 0)
activate_object(fdq->resume_transf);
fl_hide_form(fdq->fd_download_question);
activate_form(fm->fd_main);
} else
action[j] = OVERWRITE;
}
for (j = 0; j < n_files && !aborted; j++) {
pFile = ppFiles_to_upload[j];
file_name = pFile->file_name;
if (action[j] == CANCEL)
continue;
lfn = file_name;
rfn = file_name;
if ((src_file = open(lfn, O_RDONLY)) < 0) {
if (!ninteract) {
deactivate_form(fm->fd_main);
fl_set_object_label(fmsg->txt, "Can not open file !");
fl_show_form(fmsg->fd_message, FL_PLACE_MOUSE, FL_TRANSIENT, "");
fl_do_forms();
fl_hide_form(fmsg->fd_message);
activate_form(fm->fd_main);
}
return;
}
deactivate_form(fm->fd_main);
if (type != cur_type && send_command("TYPE", type == ASCII ? "A" : "I", NULL) == 200)
cur_type = type;
if (action[j] == RESUME_TRANSF) {
bytes_transm = pDest_file->file_size;
if (data_command("APPE", rfn) != 150)
goto upload_err;
} else {
bytes_transm = 0;
if (data_command("STOR", rfn) != 150)
goto upload_err;
}
if (!ninteract) {
fl_set_slider_bounds(fd->sl_time, 0, (double) (pFile->file_size));
fl_set_slider_value(fd->sl_time, bytes_transm);
cfile_name = cut(rfn);
fl_set_object_label(fd->txt_file_name, cfile_name);
free(cfile_name);
fl_set_object_label(fd->txt_transm, "0");
if (pFile->file_size < 1024)
sprintf(tmp_str, "%li", pFile->file_size);
else
sprintf(tmp_str, "%li k", pFile->file_size >> 10);
fl_set_object_label(fd->txt_total, tmp_str);
center_downl();
fl_show_form(fd->fd_download, FL_PLACE_GEOMETRY, FL_TRANSIENT, "");
fl_check_forms();
}
lseek(src_file, bytes_transm, SEEK_SET);
gettimeofday(&start_time, NULL);
while (1) {
bytes_read = read(src_file, read_buf, BUF_SIZE);
if (bytes_read == 0)
break;
pc1 = read_buf;
pc2 = send_buf;
bytes_to_sent = bytes_read;
if (type == ASCII) {
bytes_to_sent = 0;
for (i = 0; i < bytes_read; i++) {
if (*pc1 == '\n') {
*(pc2++) = '\r';
bytes_to_sent++;
}
*(pc2++) = *(pc1++);
bytes_to_sent++;
}
pc2 = send_buf;
} else
pc2 = read_buf;
if (aborted)
break;
bytes_sent = 0;
while ((bs = write(sock_servDTP, pc2 + bytes_sent, bytes_to_sent - bytes_sent)) < 0 || bytes_sent < bytes_to_sent) {
if (bs > 0)
bytes_sent += bs;
if (errno != EAGAIN && errno !=0) {
add_to_log_err("write");
perror("write");
printf("E %d %d %d\n", errno, bytes_sent, bytes_to_sent);
goto upload_err1;
}
check_forms();
}
if (sys_unix)
bytes_transm += bytes_sent;
else
bytes_transm += bytes_read;
check_forms();
gettimeofday(&cur_time, NULL);
elapsed_time = cur_time.tv_sec - start_time.tv_sec;
if (!ninteract) {
if (elapsed_time != 0) {
transfer_rate = (float) bytes_transm / (float) elapsed_time;
estimated_time = pFile->file_size / transfer_rate;
sprintf(tmp_str, "%.2f kbytes/sec.", transfer_rate / 1024);
fl_set_object_label(fd->txt_transfer_rate, tmp_str);
sprintf(tmp_str, "%li", elapsed_time);
fl_set_object_label(fd->txt_elapsed_time, tmp_str);
sprintf(tmp_str, "%li", estimated_time);
fl_set_object_label(fd->txt_estimated_time, tmp_str);
}
if (bytes_transm < 1024)
sprintf(tmp_str, "%li", bytes_transm);
else
sprintf(tmp_str, "%li k", bytes_transm >> 10);
fl_set_object_label(fd->txt_transm, tmp_str);
fl_set_slider_value(fd->sl_time, bytes_transm);
}
}
upload_err1:
close(sock_servDTP);
close(sock_userDTP);
if (aborted)
get_reply(NULL);
get_reply(NULL);
if (!ninteract)
fl_hide_form(fd->fd_download);
upload_err:
close(src_file);
activate_form(fm->fd_main);
}
if (aborted)
aborted = 0;
if (ninteract) {
if (flog != NULL)
fclose(flog);
exit(0);
}
}
/* fd_main callbacks : */
void cb_close(FL_OBJECT * ob, long arg)
{
int i;
struct dir_item **ppDir_it;
struct dir_buf_item *pDbi;
con_canceled = 1;
if (!con_opened) {
con_opened = 0;
return;
}
send_com_no_reply("QUIT", NULL, 0, 1);
fl_set_form_title(fm->fd_main, "Xrmftp");
close(sock_servPI);
add_to_history();
if (cur_dir != NULL) {
cur_dir->dir_len = n_remote;
cur_dir->dir = remote_files;
}
while (dir_buf != NULL) {
ppDir_it = dir_buf->dir;
for (i = 0; i < dir_buf->dir_len; i++) {
free((*ppDir_it)->file_name);
free((*ppDir_it)->link_name);
free((*ppDir_it)->path);
free(*(ppDir_it++));
}
free(dir_buf->dir);
free(dir_buf->dir_path);
pDbi = dir_buf;
dir_buf = dir_buf->next;
free(pDbi);
}
cur_dir = NULL;
fl_clear_browser(fm->br_remote);
fl_clear_browser(fm->br_remote_size);
fl_set_object_label(fm->txt_remote_dir, "");
deactivate_object(fm->remote_btns);
deactivate_object(fm->br_remote);
deactivate_object(fm->br_remote_size);
fl_set_object_label(fm->con_close, "Connect");
fl_set_object_callback(fm->con_close, cb_connect, 0);
con_opened = 0;
}
void cb_connect(FL_OBJECT * ob, long arg)
{
int x, y;
if (fcp->br_history->visible)
cb_history(ob, 0);
x = fm->fd_main->x + (fm->fd_main->w - fcp->fd_conn_par->w) / 2;
y = fm->fd_main->y + (fm->fd_main->h - fcp->fd_conn_par->h) / 2;
fl_set_form_position(fcp->fd_conn_par, x, y);
fl_show_form(fcp->fd_conn_par, FL_PLACE_GEOMETRY, FL_TRANSIENT, "");
deactivate_form(fm->fd_main);
fl_set_focus_object(fcp->fd_conn_par, fcp->address);
}
void cb_about(FL_OBJECT * ob, long arg)
{
deactivate_form(fm->fd_main);
fl_show_form(fa->fd_about, FL_PLACE_MOUSE, FL_TRANSIENT, "");
}
void cb_exit(FL_OBJECT * ob, long arg)
{
struct hist_item *pHist_it;
if (con_opened) {
send_com_no_reply("QUIT", NULL, 0, 1);
add_to_history();
close(sock_servPI);
}
fl_finish();
while (hist_first != NULL) {
free(hist_first->address);
free(hist_first->user_name);
free(hist_first->pass_unenc);
free(hist_first->local_dir);
free(hist_first->remote_dir);
pHist_it = hist_first->next;
free(hist_first);
hist_first = pHist_it;
}
free(home_dir);
free(opt_file_name);
free(hist_file_name);
free(log_file_name);
free(address);
free(user_name);
free(pass_enc);
free(pass_unenc);
free(local_dir_path_inp);
free(remote_dir_path_inp);
if (flog != NULL)
fclose(flog);
exit(0);
}
void cb_type(FL_OBJECT * ob, long arg)
{
if (ob == fm->binary)
type = BIN;
else
type = ASCII;
}
void clear_buffer()
{
struct dir_item *pDir_it = buffer_list;
while (buffer_list != NULL) {
pDir_it = buffer_list->next;
free(buffer_list);
buffer_list = pDir_it;
}
fl_clear_browser(fm->br_buffer_name);
fl_set_object_label(fm->txt_buffer, "");
n_buffer = 0;
}
void download_dir(const char *dir, const char *old_dir, const char *old_ldir)
{
struct dir_item **ppFiles_to_download, **ppFiles;
struct dir_buf_item *pDbi;
int i, j = 0;
char *crd;
send_command("CWD", dir, NULL);
if ((pDbi = read_rdir_to_mem(0)) == NULL) {
send_command("CWD", old_dir, NULL);
return;
}
if (mkdir(dir, 0777) < 0 || chdir(dir) < 0) {
send_command("CWD", old_dir, NULL);
return;
}
crd = get_cwdir();
ppFiles = pDbi->dir;
ppFiles_to_download = malloc(pDbi->dir_len * sizeof(struct dir_item *));
for (i = 0; i < pDbi->dir_len; i++)
if (!S_ISDIR(ppFiles[i]->mode))
ppFiles_to_download[j++] = ppFiles[i];
if (j)
download(ppFiles_to_download, j);
free(ppFiles_to_download);
for (i = 0; i < pDbi->dir_len; i++) {
if (S_ISDIR(ppFiles[i]->mode) && strcmp(ppFiles[i]->file_name, ".."))
download_dir(ppFiles[i]->file_name, pDbi->dir_path, crd);
}
free(crd);
chdir(old_ldir);
send_command("CWD", old_dir, NULL);
}
void cb_download_buffer(FL_OBJECT * ob, long arg)
{
int i, j = 0;
struct dir_item *apFiles_to_download[n_buffer], *pDir_it = buffer_list;
char *crd = get_cwdir();
for (i = 0; i < n_buffer; i++) {
if (!S_ISDIR(pDir_it->mode))
apFiles_to_download[j++] = pDir_it;
pDir_it = pDir_it->next;
}
if (j)
download(apFiles_to_download, j);
pDir_it = buffer_list;
for (i = 0; i < n_buffer; i++) {
if (S_ISDIR(pDir_it->mode) && strcmp(pDir_it->file_name, ".."))
{
send_command("CWD", pDir_it->path, NULL);
download_dir(pDir_it->file_name, pDir_it->path, crd);
send_command("CWD", remote_dir_path, NULL);
}
pDir_it = pDir_it->next;
}
free(crd);
clear_buffer();
read_local_dir();
}
void rem_from_buf(int line)
{
int i;
struct dir_item *pDir_it = buffer_list, *pDir_it1;
fl_delete_browser_line(fm->br_buffer_name, line);
if (line == n_buffer) {
buffer_list = buffer_list->next;
free(pDir_it->file_name);
free(pDir_it->link_name);
free(pDir_it->path);
free(pDir_it);
n_buffer--;
return;
}
for (i = n_buffer; i > line + 1; i--)
pDir_it = pDir_it->next;
pDir_it1 = pDir_it->next;
pDir_it->next = pDir_it1->next;
free(pDir_it1->file_name);
free(pDir_it->link_name);
free(pDir_it1->path);
free(pDir_it1);
n_buffer--;
}
void cb_rem_from_buf(FL_OBJECT * ob, long arg)
{
int i;
fl_freeze_form(fm->fd_main);
for (i = n_buffer; i > 0; i--)
if (fl_isselected_browser_line(fm->br_buffer_name, i))
rem_from_buf(i);
fl_set_object_label(fm->txt_buffer, "");
fl_unfreeze_form(fm->fd_main);
}
void cb_br_local(FL_OBJECT * ob, long arg)
{
int i = fl_get_browser(ob);
if (i > 0) {
local_files[i - 1]->selected = 1;
if (ob == fm->br_local)
fl_select_browser_line(fm->br_local_size, i);
else
fl_select_browser_line(fm->br_local, i);
return;
}
if (i < 0) {
local_files[-i - 1]->selected = 0;
if (ob == fm->br_local)
fl_deselect_browser_line(fm->br_local_size, -i);
else
fl_deselect_browser_line(fm->br_local, -i);
}
}
void cb_br_remote(FL_OBJECT * ob, long arg)
{
int i = fl_get_browser(ob);
if (i > 0) {
remote_files[i - 1]->selected = 1;
if (ob == fm->br_remote)
fl_select_browser_line(fm->br_remote_size, i);
else
fl_select_browser_line(fm->br_remote, i);
return;
}
if (i < 0) {
remote_files[-i - 1]->selected = 0;
if (ob == fm->br_remote)
fl_deselect_browser_line(fm->br_remote_size, -i);
else
fl_deselect_browser_line(fm->br_remote, -i);
}
}
void cb_br_buffer(FL_OBJECT * ob, long arg)
{
int i = fl_get_browser(ob), j;
struct dir_item *pDir_it = buffer_list;
if (i > 0) {
for (j = i; j < n_buffer; j++)
pDir_it = pDir_it->next;
adjust_path(fm->txt_buffer, pDir_it->path);
} else
fl_set_object_label(fm->txt_buffer, "");
}
void cb2_br_local(FL_OBJECT * ob, long arg)
{
int line;
struct dir_item *pDir_it;
if (fl_get_browser_maxline(ob) == 0)
return;
line = abs(fl_get_browser(ob));
pDir_it = local_files[line - 1];
if (S_ISDIR(pDir_it->mode) || S_ISLNK(pDir_it->mode)) {
if (chdir(pDir_it->file_name) == 0)
read_local_dir();
}
}
void cb_updir_local(FL_OBJECT * ob, long arg)
{
if (arg) {
if (chdir("/") == 0)
read_local_dir();
return;
}
if (chdir("..") == 0)
read_local_dir();
}
void cb_updir_remote(FL_OBJECT * ob, long arg)
{
if (arg) {
if (send_command("CWD", "/", NULL) == 250)
read_remote_dir(0);
return;
}
if (send_command("CWD", "..", NULL) == 250)
read_remote_dir(0);
}
void cb2_br_remote(FL_OBJECT * ob, long arg)
{
int line;
struct dir_item *pDir_it;
cur_dir->top = fl_get_browser_topline(fm->br_remote);
if (fl_get_browser_maxline(ob) == 0)
return;
line = abs(fl_get_browser(ob));
pDir_it = remote_files[line - 1];
if (S_ISDIR(pDir_it->mode)) {
deactivate_object(fm->remote_btns);
deactivate_object(fm->br_remote);
deactivate_object(fm->br_remote_size);
if (send_command("CWD", pDir_it->file_name, NULL) == 250)
read_remote_dir(0);
activate_object(fm->remote_btns);
activate_object(fm->br_remote);
activate_object(fm->br_remote_size);
}
if (S_ISLNK(pDir_it->mode)) {
deactivate_object(fm->remote_btns);
deactivate_object(fm->br_remote);
deactivate_object(fm->br_remote_size);
if (send_command("CWD", pDir_it->link_name, NULL) == 250)
read_remote_dir(0);
activate_object(fm->remote_btns);
activate_object(fm->br_remote);
activate_object(fm->br_remote_size);
}
}
void upload_dir(const char *dir)
{
struct dir_item *pFile_to_upload = malloc(sizeof(struct dir_item));
struct dirent *dir_ent;
struct stat stbuf;
DIR *pDir;
if (chdir(dir) < 0)
return;
if (send_command("MKD", dir, NULL) != 257) {
chdir("..");
return;
}
if (send_command("CWD", dir, NULL) != 250) {
chdir("..");
return;
}
if ((pDir = opendir(".")) == NULL) {
chdir("..");
send_command("CWD", "..", NULL);
return;
}
while ((dir_ent = readdir(pDir))) {
lstat(dir_ent->d_name, &stbuf);
if (strcmp(dir_ent->d_name, ".") == 0 || strcmp(dir_ent->d_name, "..") == 0)
continue;
if (dir_ent->d_name[0] == '.' && !show_hidden_local)
continue;
if (!S_ISDIR(stbuf.st_mode)) {
pFile_to_upload->file_name = dir_ent->d_name;
pFile_to_upload->file_size = stbuf.st_size;
pFile_to_upload->mode = stbuf.st_mode;
upload(&pFile_to_upload, 1, 1);
} else
upload_dir(dir_ent->d_name);
}
chdir("..");
read_rdir_to_mem(0);
send_command("CWD", "..", NULL);
free(pFile_to_upload);
}
void cb_upload(FL_OBJECT * ob, long arg)
{
int i, j = 0;
struct dir_item *apFiles_to_upload[n_local];
for (i = 1; i <= n_local; i++)
if (fl_isselected_browser_line(fm->br_local, i) && !S_ISDIR(local_files[i - 1]->mode))
apFiles_to_upload[j++] = local_files[i - 1];
if (j)
upload(apFiles_to_upload, j, 0);
for (i = 1; i <= n_local; i++)
if (fl_isselected_browser_line(fm->br_local, i) && S_ISDIR(local_files[i - 1]->mode)
&& strcmp(local_files[i - 1]->file_name, ".."))
upload_dir(local_files[i - 1]->file_name);
fl_deselect_browser(fm->br_local);
fl_deselect_browser(fm->br_local_size);
read_remote_dir(1);
}
void cb_download(FL_OBJECT * ob, long arg)
{
int i, j = 0;
struct dir_item *apFiles_to_download[n_remote];
char *crd = get_cwdir();
for (i = 1; i <= n_remote; i++)
if (fl_isselected_browser_line(fm->br_remote, i) && !S_ISDIR(remote_files[i - 1]->mode))
apFiles_to_download[j++] = remote_files[i - 1];
if (j)
download(apFiles_to_download, j);
for (i = 1; i <= n_remote; i++)
if (fl_isselected_browser_line(fm->br_remote, i)) {
if (S_ISDIR(remote_files[i - 1]->mode) && strcmp(remote_files[i - 1]->file_name, ".."))
download_dir(remote_files[i - 1]->file_name, remote_dir_path, crd);
}
fl_deselect_browser(fm->br_remote);
fl_deselect_browser(fm->br_remote_size);
read_local_dir();
}
void cb_to_buffer(FL_OBJECT * ob, long arg)
{
int n_lines, i, repeated;
struct dir_item *pDir_it;
n_lines = fl_get_browser_maxline(fm->br_remote);
for (i = 2; i <= n_lines; i++)
if (fl_isselected_browser_line(fm->br_remote, i)) {
repeated = 0;
pDir_it = buffer_list;
while (pDir_it != NULL) {
if (strcmp(remote_files[i - 1]->file_name, pDir_it->file_name) == 0) {
repeated = 1;
break;
}
pDir_it = pDir_it->next;
}
if (!repeated) {
add_file_to_list(&buffer_list, remote_files[i - 1]->file_name, remote_files[i - 1]->file_size,
remote_files[i - 1]->modif_time, remote_files[i - 1]->mode, remote_dir_path);
fl_add_browser_line(fm->br_buffer_name, fl_get_browser_line(fm->br_remote, i));
n_buffer++;
}
}
fl_deselect_browser(fm->br_remote);
fl_deselect_browser(fm->br_remote_size);
}
int rmdir_rec(const char *dir_name)
{
struct stat stbuf;
DIR *pDir;
struct dirent *dir_ent;
char *old_dir;
if ((old_dir = get_cwdir()) == NULL) {
free(old_dir);
return -1;
}
chdir(dir_name);
if ((pDir = opendir(".")) == NULL) {
return -1;
free(old_dir);
}
while ((dir_ent = readdir(pDir))) {
lstat(dir_ent->d_name, &stbuf);
if (strcmp(dir_ent->d_name, ".") == 0 || strcmp(dir_ent->d_name, "..") == 0)
continue;
if (S_ISDIR(stbuf.st_mode)) {
if (rmdir(dir_ent->d_name) < 0 && (errno == ENOTEMPTY || errno == EEXIST))
rmdir_rec(dir_ent->d_name);
} else
remove(dir_ent->d_name);
}
chdir(old_dir);
free(old_dir);
return rmdir(dir_name);
}
void remove_dirs(int *selected, int n_sel, struct dir_item ***pppFiles,
int *pn_files, int place)
{
int i, success;
char label[150], *file_name, *cfile_name;
if (n_sel == 1) {
file_name = (*pppFiles)[selected[0]]->file_name;
sprintf(label, "Remove directory %s ?", cfile_name = cut(file_name));
free(cfile_name);
} else
sprintf(label, "Remove %d directories ?", n_sel);
fl_set_object_label(fq->txt_question, label);
deactivate_form(fm->fd_main);
fl_show_form(fq->fd_question, FL_PLACE_GEOMETRY, FL_TRANSIENT, "");
if (fl_do_forms() == fq->yes)
for (i = n_sel; i > 0;) {
success = 0;
i--;
file_name = (*pppFiles)[selected[i]]->file_name;
if (place == LOCAL) {
if (rmdir(file_name) == 0)
success = 1;
else if (errno == ENOTEMPTY || errno == EEXIST) {
sprintf(label, "Directory %s is not empty.\nDelete it recursively ?", cfile_name = cut(file_name));
free(cfile_name);
fl_set_object_label(fq->txt_question, label);
if (fl_do_forms() == fq->yes)
if (rmdir_rec(file_name) == 0);
success = 1;
}
} else if (send_command("RMD", file_name, NULL) == 250)
success = 1;
if (success)
remove_file_from_array(pppFiles, pn_files, selected[i]);
}
activate_form(fm->fd_main);
fl_hide_form(fq->fd_question);
}
void remove_files(int *selected, int n_sel, struct dir_item ***pppFiles,
int *pn_files, int place)
{
int i, success;
char label[50], *file_name, *cfile_name;
if (n_sel == 1) {
file_name = (*pppFiles)[selected[0]]->file_name;
sprintf(label, "Remove file %s ?", cfile_name = cut(file_name));
free(cfile_name);
} else
sprintf(label, "Remove %d files ?", n_sel);
fl_set_object_label(fq->txt_question, label);
deactivate_form(fm->fd_main);
fl_show_form(fq->fd_question, FL_PLACE_GEOMETRY, FL_TRANSIENT, "");
if (fl_do_forms() == fq->yes)
for (i = n_sel; i > 0;) {
success = 0;
i--;
if (place == REMOTE && S_ISLNK((*pppFiles)[selected[i]]->mode))
file_name = (*pppFiles)[selected[i]]->link_name;
else
file_name = (*pppFiles)[selected[i]]->file_name;
if (place == LOCAL) {
if (remove(file_name) == 0)
success = 1;
} else if (send_command("DELE", file_name, NULL) == 250)
success = 1;
if (success)
remove_file_from_array(pppFiles, pn_files, selected[i]);
}
activate_form(fm->fd_main);
fl_hide_form(fq->fd_question);
}
void rename_files(int *selected, int n_sel, struct dir_item **ppFiles,
int place)
{
int i, success;
const char *new_name;
char label[50], *cfile_name, *file_name;
FL_OBJECT *ret_object;
for (i = 0; i < n_sel; i++) {
if (place == REMOTE && S_ISLNK(ppFiles[selected[i]]->mode))
file_name = ppFiles[selected[i]]->link_name;
else
file_name = ppFiles[selected[i]]->file_name;
fl_set_input(fi->input, "");
sprintf(label, "Rename/move file %s to", cfile_name = cut(file_name));
fl_set_object_label(fi->txt_input, label);
free(cfile_name);
deactivate_form(fm->fd_main);
fl_show_form(fi->fd_input, FL_PLACE_GEOMETRY, FL_TRANSIENT, "");
ret_object = fl_do_forms();
success = 0;
if ((ret_object == fi->ok || ret_object == fi->input) && *(new_name = fl_get_input(fi->input)) != '\0')
if (place == LOCAL) {
if (rename(file_name, new_name) == 0)
success = 1;
} else if (send_command("RNFR", file_name, NULL) == 350 && send_command("RNTO", new_name, NULL) == 250)
success = 1;
if (success) {
free(file_name);
file_name = malloc(strlen(new_name) + 1);
strcpy(file_name, new_name);
ppFiles[selected[i]]->file_name = file_name;
}
fl_hide_form(fi->fd_input);
activate_form(fm->fd_main);
if (ret_object == fi->cancel)
break;
}
}
void cb_btn_local(FL_OBJECT * ob, long arg)
{
int n_sel = 0, x, y, i, *selected;
const char *dir;
char *cfile_name, *file_name, *cdir;
FL_OBJECT *ret_ob;
fl_set_input(fi->input, "");
x = fm->fd_main->x + 5;
y = fm->fd_main->y + fm->br_local->y + fm->br_local->h + 4;
fl_set_form_position(fq->fd_question, x, y);
fl_set_form_position(fi->fd_input, x, y);
if (arg < 3) {
if (arg == 2) {
fl_set_input(fi->input, cdir = get_cwdir());
fl_set_input_selected(fi->input, 1);
free(cdir);
}
fl_set_object_label(fi->txt_input, "Enter directory name:");
fl_show_form(fi->fd_input, FL_PLACE_GEOMETRY, FL_TRANSIENT, "");
deactivate_form(fm->fd_main);
ret_ob = fl_do_forms();
activate_form(fm->fd_main);
fl_hide_form(fi->fd_input);
if (ret_ob == fi->cancel)
return;
dir = fl_get_input(fi->input);
}
switch (arg) {
case 1:
if (mkdir(dir, 0777) == 0) {
add_file_to_array(&local_files, &n_local, dir, 0, 0, S_IFDIR);
put_files_into_browser(fm->br_local, fm->br_local_size, local_files, n_local, sort_key_local);
}
break;
case 2:
if (chdir(dir) == 0)
read_local_dir();
break;
case 3:
selected = malloc(n_local * sizeof(int));
for (i = 1; i <= n_local; i++)
if (fl_isselected_browser_line(fm->br_local, i))
selected[n_sel++] = i - 1;
if (n_sel) {
rename_files(selected, n_sel, local_files, LOCAL);
put_files_into_browser(fm->br_local, fm->br_local_size, local_files, n_local, sort_key_local);
}
free(selected);
break;
case 4:
selected = malloc(n_local * sizeof(int));
for (i = 1; i <= n_local; i++)
if (fl_isselected_browser_line(fm->br_local, i) && S_ISDIR(local_files[i - 1]->mode))
selected[n_sel++] = i - 1;
if (n_sel) {
remove_dirs(selected, n_sel, &local_files, &n_local, LOCAL);
put_files_into_browser(fm->br_local, fm->br_local_size, local_files, n_local, sort_key_local);
}
free(selected);
break;
case 5:
selected = malloc(n_local * sizeof(int));
for (i = 1; i <= n_local; i++)
if (fl_isselected_browser_line(fm->br_local, i) && !S_ISDIR(local_files[i - 1]->mode))
selected[n_sel++] = i - 1;
if (n_sel) {
remove_files(selected, n_sel, &local_files, &n_local, LOCAL);
put_files_into_browser(fm->br_local, fm->br_local_size, local_files, n_local, sort_key_local);
}
free(selected);
break;
case 6:
fl_clear_browser(flv->br_view);
for (i = 1; i <= n_local; i++)
if (fl_isselected_browser_line(fm->br_local, i)) {
file_name = local_files[i - 1]->file_name;
fl_set_object_label(flv->txt_file_name, cfile_name = cut(file_name));
free(cfile_name);
fl_load_browser(flv->br_view, file_name);
fl_show_form(flv->fd_local_view, FL_PLACE_MOUSE, FL_TRANSIENT, "");
break;
}
break;
case 7:
read_local_dir();
}
}
void cb_btn_remote(FL_OBJECT * ob, long arg)
{
int n_lines, x, y, i, *selected, n_sel = 0;
const char *dir;
FL_OBJECT *ret_ob;
n_lines = fl_get_browser_maxline(fm->br_remote);
fl_set_input(fi->input, "");
x = fm->fd_main->x + fm->txt_remote_dir->x + (fm->txt_remote_dir->w +
-fq->fd_question->w) / 2;
y = fm->fd_main->y + fm->br_remote->y + fm->br_remote->h + 4;
fl_set_form_position(fq->fd_question, x, y);
x = fm->fd_main->x + fm->txt_remote_dir->x + (fm->txt_remote_dir->w +
-fi->fd_input->w) / 2;
y = fm->fd_main->y + fm->br_remote->y + fm->br_remote->h + 4;
fl_set_form_position(fi->fd_input, x, y);
if (arg < 3) {
if (arg == 2) {
fl_set_input(fi->input, remote_dir_path);
fl_set_input_selected(fi->input, 1);
}
fl_set_object_label(fi->txt_input, "Enter directory name:");
fl_show_form(fi->fd_input, FL_PLACE_GEOMETRY, FL_TRANSIENT, "");
deactivate_form(fm->fd_main);
ret_ob = fl_do_forms();
activate_form(fm->fd_main);
fl_hide_form(fi->fd_input);
if (ret_ob == fi->cancel)
return;
dir = fl_get_input(fi->input);
}
deactivate_object(fm->remote_btns);
deactivate_object(fm->br_remote);
deactivate_object(fm->br_remote_size);
switch (arg) {
case 1:
if (send_command("MKD", dir, NULL) == 257) {
add_file_to_array(&remote_files, &n_remote, dir, 0, 0, S_IFDIR);
put_files_into_browser(fm->br_remote, fm->br_remote_size, remote_files, n_remote, sort_key_remote);
}
break;
case 2:
if (send_command("CWD", dir, NULL) == 250)
read_remote_dir(0);
break;
case 3:
selected = malloc(n_remote * sizeof(int));
for (i = 1; i <= n_remote; i++)
if (fl_isselected_browser_line(fm->br_remote, i))
selected[n_sel++] = i - 1;
if (n_sel) {
rename_files(selected, n_sel, remote_files, REMOTE);
put_files_into_browser(fm->br_remote, fm->br_remote_size, remote_files, n_remote, sort_key_remote);
}
free(selected);
break;
case 4:
selected = malloc(n_remote * sizeof(int));
for (i = 1; i <= n_remote; i++)
if (fl_isselected_browser_line(fm->br_remote, i) && S_ISDIR(remote_files[i - 1]->mode))
selected[n_sel++] = i - 1;
if (n_sel) {
remove_dirs(selected, n_sel, &remote_files, &n_remote, REMOTE);
put_files_into_browser(fm->br_remote, fm->br_remote_size, remote_files, n_remote, sort_key_remote);
}
free(selected);
break;
case 5:
selected = malloc(n_remote * sizeof(int));
for (i = 1; i <= n_remote; i++)
if (fl_isselected_browser_line(fm->br_remote, i) && !S_ISDIR(remote_files[i - 1]->mode))
selected[n_sel++] = i - 1;
if (n_sel) {
remove_files(selected, n_sel, &remote_files, &n_remote, REMOTE);
put_files_into_browser(fm->br_remote, fm->br_remote_size, remote_files, n_remote, sort_key_remote);
}
free(selected);
break;
case 7:
read_remote_dir(1);
break;
}
activate_object(fm->remote_btns);
activate_object(fm->br_remote);
activate_object(fm->br_remote_size);
}
void cb_sort(FL_OBJECT * ob, long arg)
{
if (arg < 3) {
sort_key_local = arg;
put_files_into_browser(fm->br_local, fm->br_local_size, local_files, n_local, arg);
} else {
sort_key_remote = arg - 2;
put_files_into_browser(fm->br_remote, fm->br_remote_size, remote_files, n_remote, arg - 2);
}
}
void cb_remote_view(FL_OBJECT * ob, long arg)
{
int bytes_received, bytes_wrote, i;
long bytes_transm, file_size;
char *pc1, *pc2, fsize[25], receive_buf[BUF_SIZE + 1], *file_name,
*cfile_name;
for (i = 1; !fl_isselected_browser_line(fm->br_remote, i) ||
S_ISDIR(remote_files[i - 1]->mode); i++)
if (i > n_remote)
return;
fl_clear_browser(frv->br_view);
fl_set_object_label(frv->btn_ok_cnc, "Cancel");
fl_set_object_callback(frv->btn_ok_cnc, cb_dwnld_cancel, 0);
if (S_ISLNK(remote_files[i - 1]->mode))
file_name = remote_files[i - 1]->link_name;
else
file_name = remote_files[i - 1]->file_name;
file_size = remote_files[i - 1]->file_size;
fl_set_object_label(frv->txt_transm, "0");
if (file_size < 1024)
sprintf(fsize, "%li", file_size);
else
sprintf(fsize, "%li k", file_size >> 10);
fl_set_object_label(frv->txt_total, fsize);
fl_set_object_color(frv->sl_time, FL_COL1, FL_GREEN);
fl_set_slider_bounds(frv->sl_time, 0, (double) (file_size));
fl_set_slider_value(frv->sl_time, 0);
fl_set_object_label(frv->txt_file_name, cfile_name = cut(file_name));
free(cfile_name);
busy = 1;
deactivate_object(fm->local_btns);
deactivate_object(fm->remote_btns);
deactivate_object(fm->br_remote);
deactivate_object(fm->br_remote_size);
if (cur_type != ASCII && send_command("TYPE", "A", NULL) == 200)
cur_type = ASCII;
if (data_command("RETR", file_name) != 150) {
activate_form(fm->fd_main);
goto view_err;
}
deactivate_form(fm->fd_main);
fl_show_form(frv->fd_remote_view, FL_PLACE_MOUSE, FL_TRANSIENT, "");
fl_check_forms();
bytes_transm = 0;
while (1) {
while ((bytes_received = read(sock_servDTP, receive_buf, BUF_SIZE)) < 0) {
if (errno != EAGAIN) {
add_to_log_err("read");
goto view_err1;
}
fl_check_forms();
if (aborted)
goto view_err1;
}
if (bytes_received == 0)
break;
if (aborted)
goto view_err1;
pc1 = pc2 = receive_buf;
bytes_wrote = 0;
for (i = 0; i < bytes_received; i++) {
if (*pc1 != '\r') {
*(pc2++) = *pc1;
bytes_wrote++;
}
pc1++;
}
receive_buf[bytes_wrote] = '\0';
if (sys_unix)
bytes_transm += bytes_wrote;
else
bytes_transm += bytes_received;
fl_check_forms();
for (i = 0; receive_buf[i] != '\n'; i++);
receive_buf[i] = '\0';
fl_addto_browser_chars(frv->br_view, receive_buf);
fl_add_browser_line(frv->br_view, receive_buf + i + 1);
if (bytes_transm < 1024)
sprintf(fsize, "%li", bytes_transm);
else
sprintf(fsize, "%li k", bytes_transm >> 10);
fl_set_object_label(frv->txt_transm, fsize);
fl_set_slider_value(frv->sl_time, bytes_transm);
}
view_err1:
close(sock_servDTP);
close(sock_userDTP);
if (aborted)
get_reply(NULL);
get_reply(NULL);
fl_set_object_color(frv->sl_time, FL_COL1, FL_INACTIVE);
fl_set_object_label(frv->btn_ok_cnc, "OK");
fl_set_object_callback(frv->btn_ok_cnc, cb_remote_view_ok, 0);
goto view_end;
view_err:
close(sock_userDTP);
busy = 0;
activate_object(fm->local_btns);
activate_object(fm->remote_btns);
activate_object(fm->br_remote);
activate_object(fm->br_remote_size);
view_end:
if (aborted) {
aborted = 0;
fl_hide_form(frv->fd_remote_view);
activate_form(fm->fd_main);
busy = 0;
activate_object(fm->local_btns);
activate_object(fm->remote_btns);
activate_object(fm->br_remote);
activate_object(fm->br_remote_size);
}
}
void cb_select(FL_OBJECT * ob, long arg)
{
int i, x, y, lmax = fl_get_browser_maxline(fm->br_local);
int rmax = fl_get_browser_maxline(fm->br_remote);
int bmax = fl_get_browser_maxline(fm->br_buffer_name);
const char *pattern;
FL_OBJECT *ret_ob;
fl_freeze_form(fm->fd_main);
switch (arg) {
case 1:
for (i = 1; i <= lmax; i++) {
fl_select_browser_line(fm->br_local, i);
fl_select_browser_line(fm->br_local_size, i);
}
break;
case 2:
fl_deselect_browser(fm->br_local);
fl_deselect_browser(fm->br_local_size);
break;
case 3:
fl_set_input(fi->input, "");
x = fm->fd_main->x + 5;
y = fm->fd_main->y + fm->br_local->y + fm->br_local->h + 4;
fl_set_form_position(fi->fd_input, x, y);
fl_set_object_label(fi->txt_input, "Enter pattern:");
fl_show_form(fi->fd_input, FL_PLACE_GEOMETRY, FL_TRANSIENT, "");
deactivate_form(fm->fd_main);
ret_ob = fl_do_forms();
activate_form(fm->fd_main);
fl_hide_form(fi->fd_input);
if (ret_ob == fi->cancel) {
fl_unfreeze_form(fm->fd_main);
return;
}
pattern = fl_get_input(fi->input);
for (i = 1; i <= lmax; i++)
if (fnmatch(pattern, local_files[i - 1]->file_name, 0) == 0) {
fl_select_browser_line(fm->br_local, i);
fl_select_browser_line(fm->br_local_size, i);
}
break;
case 4:
for (i = 1; i <= rmax; i++) {
fl_select_browser_line(fm->br_remote, i);
fl_select_browser_line(fm->br_remote_size, i);
}
break;
case 5:
fl_deselect_browser(fm->br_remote);
fl_deselect_browser(fm->br_remote_size);
break;
case 6:
fl_set_input(fi->input, "");
x = fm->fd_main->x + fm->txt_remote_dir->x + (fm->txt_remote_dir->w +
-fi->fd_input->w) / 2;
y = fm->fd_main->y + fm->br_remote->y + fm->br_remote->h + 4;
fl_set_form_position(fi->fd_input, x, y);
fl_set_object_label(fi->txt_input, "Enter pattern:");
fl_show_form(fi->fd_input, FL_PLACE_GEOMETRY, FL_TRANSIENT, "");
deactivate_form(fm->fd_main);
ret_ob = fl_do_forms();
activate_form(fm->fd_main);
fl_hide_form(fi->fd_input);
if (ret_ob == fi->cancel) {
fl_unfreeze_form(fm->fd_main);
return;
}
pattern = fl_get_input(fi->input);
for (i = 1; i <= rmax; i++)
if (fnmatch(pattern, remote_files[i - 1]->file_name, 0) == 0) {
fl_select_browser_line(fm->br_remote, i);
fl_select_browser_line(fm->br_remote_size, i);
}
break;
case 7:
for (i = 1; i <= bmax; i++)
fl_select_browser_line(fm->br_buffer_name, i);
break;
case 8:
fl_deselect_browser(fm->br_buffer_name);
}
fl_unfreeze_form(fm->fd_main);
}
/* fd_download callbacks: */
void cb_dwnld_cancel(FL_OBJECT * ob, long arg)
{
char send_buf[20];
if (aborted)
return;
sprintf(send_buf, "%c%c%c", IAC, IP, IAC);
send_com_no_reply(send_buf, NULL, 0, 0);
sprintf(send_buf, "%c", DM);
send_com_no_reply(send_buf, NULL, MSG_OOB, 0);
sprintf(send_buf, "ABOR");
send_com_no_reply(send_buf, NULL, 0, 1);
aborted = 1;
}
void cb_detach(FL_OBJECT * ob, long arg)
{
ninteract = 1;
if (fcntl(sock_servPI, F_SETFL, fcntl(sock_servPI, F_GETFL) & ~O_NONBLOCK) < 0) {
add_to_log_err("fcntl");
exit(1);
}
fcntl(sock_servDTP, F_SETFL, fcntl(sock_servPI, F_GETFL) & ~O_NONBLOCK);
fl_finish();
}
/* fd_conn_par callbacks: */
void cb_anonymous(FL_OBJECT * ob, long arg)
{
if (fcp->br_history->visible)
cb_history(ob, 0);
if (fl_get_button(ob)) {
fl_set_input(fcp->user_name, "anonymous");
fl_set_input(fcp->pass_unenc, e_mail ? e_mail : "");
fl_show_object(fcp->pass_unenc);
if (fcp->pass_enc->focus)
fl_set_focus_object(fcp->fd_conn_par, fcp->pass_unenc);
fl_hide_object(fcp->pass_enc);
} else {
fl_set_input(fcp->pass_enc, "");
fl_show_object(fcp->pass_enc);
if (fcp->pass_unenc->focus)
fl_set_focus_object(fcp->fd_conn_par, fcp->pass_enc);
fl_hide_object(fcp->pass_unenc);
}
}
void cb_ok(FL_OBJECT * ob, long arg)
{
const char *input;
char *title, *syst_reply;
char *password;
int i;
free(address);
free(user_name);
free(pass_enc);
free(pass_unenc);
free(local_dir_path_inp);
free(remote_dir_path_inp);
fl_set_object_label(fm->con_close, "Close");
fl_set_object_callback(fm->con_close, cb_close, 0);
anonym_login = fl_get_button(fcp->anonymous);
fl_clear_browser(fm->br_log);
input = fl_get_input(fcp->address);
address = malloc(strlen(input) + 1);
strcpy(address, input);
input = fl_get_input(fcp->user_name);
user_name = malloc(strlen(input) + 1);
strcpy(user_name, input);
if (anonym_login) {
input = fl_get_input(fcp->pass_unenc);
pass_unenc = malloc(strlen(input) + 1);
strcpy(pass_unenc, input);
*(pass_enc = malloc(1)) = '\0';
} else {
input = fl_get_input(fcp->pass_enc);
pass_enc = malloc(strlen(input) + 1);
strcpy(pass_enc, input);
*(pass_unenc = malloc(1)) = '\0';
}
input = fl_get_input(fcp->local_dir);
local_dir_path_inp = malloc(strlen(input) + 1);
strcpy(local_dir_path_inp, input);
chdir(local_dir_path_inp);
input = fl_get_input(fcp->remote_dir);
remote_dir_path_inp = malloc(strlen(input) + 1);
strcpy(remote_dir_path_inp, input);
busy = 1;
deactivate_object(fm->local_btns);
activate_form(fm->fd_main);
fl_hide_form(fcp->fd_conn_par);
XFlush(fl_get_display());
read_local_dir();
con_canceled = 0;
add_to_history();
if (open_ftp_connection() < 0)
goto err_ok1;
con_opened = 1;
cur_type = ASCII;
if (get_reply(NULL) != 220)
goto err_ok;
if ((i = send_command("USER", user_name, NULL)) != 331 && i != 230)
goto err_ok;
if (i == 331) {
password = anonym_login ? pass_unenc : pass_enc;
i = send_command("PASS", strcmp(password, "") ? password : " ", NULL);
switch (i) {
case 230:
break;
case 332:
if (send_command("ACCT", e_mail, NULL) == 230)
break;
default:
goto err_ok;
}
}
send_command("SYST", NULL, &syst_reply);
if (strstr(syst_reply, "UNIX") != NULL)
sys_unix = 1;
else
sys_unix = 0;
if (*remote_dir_path_inp != '\0')
send_command("CWD", remote_dir_path_inp, NULL);
read_remote_dir(1);
title = malloc(strlen(address) + 20);
sprintf(title, "Xrmftp : %s", address);
fl_set_form_title(fm->fd_main, title);
fl_set_object_label(fm->txt_status, "");
activate_object(fm->remote_btns);
activate_object(fm->local_btns);
activate_object(fm->br_remote);
activate_object(fm->br_remote_size);
busy = 0;
free(title);
return;
err_ok:
send_com_no_reply("QUIT", NULL, 0, 1);
close(sock_servPI);
err_ok1:
activate_object(fm->local_btns);
con_opened = 0;
fl_set_form_title(fm->fd_main, "");
fl_set_object_label(fm->txt_status, "");
fl_set_object_label(fm->con_close, "Connect");
fl_set_object_callback(fm->con_close, cb_connect, 0);
}
void cb_cancel(FL_OBJECT * ob, long arg)
{
activate_form(fm->fd_main);
fl_hide_form(fcp->fd_conn_par);
}
void cb_options(FL_OBJECT * ob, long arg)
{
char input[20], *pc1;
if (arg == 1) {
if (fcp->br_history->visible)
cb_history(ob, 0);
fo->fd_options->u_vdata = fcp->fd_conn_par;
if (f_fold_hidden) {
fl_addto_tabfolder(fo->fld_options, "Files", fofl->fd_options_files);
f_fold_hidden = 0;
}
} else {
fo->fd_options->u_vdata = fm->fd_main;
if (!f_fold_hidden) {
if (fl_get_folder(fo->fld_options) == fofl->fd_options_files)
fl_set_folder_bynumber(fo->fld_options, 1);
fl_delete_folder(fo->fld_options, fofl->fd_options_files);
f_fold_hidden = 1;
}
}
sprintf(input, "%d", port);
fl_set_input(fon->port, input);
fl_set_input(fon->e_mail, e_mail);
pc1 = strrchr(std_bookm_file, '/');
fl_set_input(fofl->bookm_file, pc1 == NULL ? std_bookm_file : ++pc1);
fl_set_choice(fof->font_txt, (font_size - 8) / 2);
fl_set_choice(fof->font_br, (br_fsize - 8) / 2);
fl_set_button(fofl->btn_show_hidden_local, show_hidden_local);
fl_set_button(fofl->btn_show_hidden_remote, show_hidden_remote);
fl_set_button(fon->btn_passive, passive);
deactivate_form(fo->fd_options->u_vdata);
fl_show_form(fo->fd_options, FL_PLACE_MOUSE, FL_TRANSIENT, "");
}
void cb_history(FL_OBJECT * ob, long arg)
{
int i;
fl_freeze_form(fcp->fd_conn_par);
i = fl_get_button(fcp->anonymous);
fl_set_focus_object(fcp->fd_conn_par, fcp->address);
if (fcp->br_history->visible) {
fl_hide_object(fcp->br_history);
fl_show_object(fcp->user_name);
fl_show_object(fcp->local_dir);
fl_show_object(fcp->remote_dir);
fl_show_object(i ? fcp->pass_unenc : fcp->pass_enc);
} else {
fl_show_object(fcp->br_history);
fl_hide_object(fcp->user_name);
fl_hide_object(fcp->local_dir);
fl_hide_object(fcp->remote_dir);
fl_hide_object(i ? fcp->pass_unenc : fcp->pass_enc);
}
fl_unfreeze_form(fcp->fd_conn_par);
}
void cb_bookm(FL_OBJECT * ob, long arg)
{
if (strcmp(addr_file_name, std_bookm_file))
deactivate_object(fb->btn_delete);
read_bookmarks(addr_file_name);
if (fcp->br_history->visible)
cb_history(ob, 0);
fl_show_form(fb->fd_bookmarks, FL_PLACE_MOUSE, FL_TRANSIENT, "");
deactivate_form(fcp->fd_conn_par);
}
void cb_load(FL_OBJECT * ob, long arg)
{
const char *selected_file, *pc1;
deactivate_form(fcp->fd_conn_par);
fl_set_fselector_fontsize(font_size);
pc1 = strrchr(std_bookm_file, '/');
selected_file = fl_show_fselector("Filename to load bookmarks from", home_dir, "*.html", pc1 == NULL ? std_bookm_file : ++pc1);
if (selected_file != NULL) {
free(addr_file_name);
addr_file_name = malloc(strlen(selected_file) + 1);
strcpy(addr_file_name, selected_file);
}
activate_form(fcp->fd_conn_par);
}
void cb_add(FL_OBJECT * ob, long arg)
{
const char *addr, *dir;
struct addr_item *pAd_it;
read_bookmarks(std_bookm_file);
pAd_it = bookm_first;
addr = fl_get_input(fcp->address);
dir = fl_get_input(fcp->remote_dir);
while (pAd_it != NULL) {
if (strcmp(addr, pAd_it->address) == 0 && strcmp(dir, pAd_it->dir) == 0)
return;
pAd_it = pAd_it->next;
}
pAd_it = malloc(sizeof(struct addr_item));
pAd_it->next = NULL;
if (bookm_last != NULL)
bookm_last->next = pAd_it;
bookm_last = pAd_it;
if (bookm_first == NULL)
bookm_first = pAd_it;
pAd_it->address = malloc(strlen(addr) + 1);
pAd_it->dir = malloc(strlen(dir) + 1);
strcpy(pAd_it->address, addr);
strcpy(pAd_it->dir, dir);
fl_add_browser_line(fb->br_bookmarks, addr);
fl_addto_browser_chars(fb->br_bookmarks, dir);
write_bookmarks();
read_bookmarks(addr_file_name);
}
void cb_br_hist(FL_OBJECT * ob, long arg)
{
int i;
struct hist_item *pHist_it;
i = fl_get_browser(ob);
fl_hide_object(fcp->br_history);
pHist_it = hist_first;
for (; i > 1; i--)
pHist_it = pHist_it->next;
fl_set_button(fcp->anonymous, pHist_it->anonym_login);
cb_anonymous(fcp->anonymous, 0);
fl_set_input(fcp->address, pHist_it->address);
fl_set_input(fcp->user_name, pHist_it->user_name);
fl_set_input(fcp->pass_unenc, pHist_it->pass_unenc);
fl_set_input(fcp->local_dir, pHist_it->local_dir);
fl_set_input(fcp->remote_dir, pHist_it->remote_dir);
fl_show_object(fcp->user_name);
fl_show_object(fcp->local_dir);
fl_show_object(fcp->remote_dir);
fl_show_object(pHist_it->anonym_login ? fcp->pass_unenc : fcp->pass_enc);
}
/* fd_bookmarks callbacks */
void cb_bm_cancel(FL_OBJECT * ob, long arg)
{
if (strcmp(addr_file_name, std_bookm_file))
activate_object(fb->btn_delete);
fl_hide_form(fb->fd_bookmarks);
activate_form(fcp->fd_conn_par);
}
void cb_bm_delete(FL_OBJECT * ob, long arg)
{
int i;
struct addr_item *pAd_it, *pPrev_it = NULL, *pNext_it;
pAd_it = bookm_first;
for (i = 1; i <= fl_get_browser_maxline(fb->br_bookmarks);) {
if (fl_isselected_browser_line(fb->br_bookmarks, i)) {
fl_delete_browser_line(fb->br_bookmarks, i);
pNext_it = pAd_it->next;
if (pNext_it == NULL)
bookm_last = pPrev_it;
if (pPrev_it != NULL)
pPrev_it->next = pAd_it->next;
else
bookm_first = pAd_it->next;
free(pAd_it->address);
free(pAd_it->dir);
free(pAd_it);
pAd_it = pNext_it;
} else {
pPrev_it = pAd_it;
pAd_it = pAd_it->next;
i++;
}
}
write_bookmarks();
}
void cb2_br_bookmarks(FL_OBJECT * ob, long arg)
{
int i;
struct addr_item *pAd_it = bookm_first;
i = abs(fl_get_browser(ob));
for (; i > 1; i--)
pAd_it = pAd_it->next;
fl_set_input(fcp->address, pAd_it->address);
fl_set_input(fcp->remote_dir, pAd_it->dir);
if (strcmp(addr_file_name, std_bookm_file))
activate_object(fb->btn_delete);
fl_hide_form(fb->fd_bookmarks);
activate_form(fcp->fd_conn_par);
}
void cb_bm_ok(FL_OBJECT * ob, long arg)
{
int i, m;
struct addr_item *pAd_it = bookm_first;
m = fl_get_browser_maxline(fb->br_bookmarks);
for (i = 1; !fl_isselected_browser_line(fb->br_bookmarks, i); i++)
if (i > m)
return;
for (; i > 1; i--)
pAd_it = pAd_it->next;
fl_set_input(fcp->address, pAd_it->address);
fl_set_input(fcp->remote_dir, pAd_it->dir);
if (strcmp(addr_file_name, std_bookm_file))
activate_object(fb->btn_delete);
fl_hide_form(fb->fd_bookmarks);
activate_form(fcp->fd_conn_par);
}
/* fd_options callbacks */
void cb_op_ok(FL_OBJECT * ob, long arg)
{
int tsize, bsize, r, g, b;
const char *input;
FILE *f_options;
fl_redraw_form(fm->fd_main);
activate_form(fo->fd_options->u_vdata);
fl_hide_form(fo->fd_options);
tsize = atoi(fl_get_choice_text(fof->font_txt));
bsize = atoi(fl_get_choice_text(fof->font_br));
if (tsize != font_size || bsize != br_fsize) {
br_fsize = bsize;
font_size = tsize;
change_font_size();
}
port = atoi(fl_get_input(fon->port));
input = fl_get_input(fon->e_mail);
strcpy(e_mail, input);
input = fl_get_input(fofl->bookm_file);
free(std_bookm_file);
std_bookm_file = malloc(strlen(input) + strlen(home_dir) + 2);
sprintf(std_bookm_file, "%s%s", home_dir, input);
free(addr_file_name);
addr_file_name = malloc(strlen(std_bookm_file) + 1);
strcpy(addr_file_name, std_bookm_file);
read_bookmarks(std_bookm_file);
show_hidden_local = fl_get_button(fofl->btn_show_hidden_local);
show_hidden_remote = fl_get_button(fofl->btn_show_hidden_remote);
passive = fl_get_button(fon->btn_passive);
if ((f_options = fopen(opt_file_name, "w")) == NULL) {
fl_set_object_label(fmsg->txt, "Can not save options file !");
deactivate_form(fo->fd_options);
fl_show_form(fmsg->fd_message, FL_PLACE_MOUSE, FL_TRANSIENT, "");
fl_do_forms();
fl_hide_form(fmsg->fd_message);
activate_form(fo->fd_options);
return;
}
fprintf(f_options, "%s\n", e_mail);
fprintf(f_options, "%d\n", font_size);
fprintf(f_options, "%d\n", br_fsize);
fprintf(f_options, "%d\n", show_hidden_local);
fprintf(f_options, "%d\n", show_hidden_remote);
fprintf(f_options, "%d\n", passive);
fprintf(f_options, "%s\n", input);
fl_getmcolor(FL_FREE_COL1, &r, &g, &b);
fprintf(f_options, "%d,%d,%d\n", r, g, b);
fl_getmcolor(FL_FREE_COL1 + 1, &r, &g, &b);
fprintf(f_options, "%d,%d,%d\n", r, g, b);
fl_getmcolor(FL_FREE_COL1 + 2, &r, &g, &b);
fprintf(f_options, "%d,%d,%d\n", r, g, b);
fl_getmcolor(FL_FREE_COL1 + 3, &r, &g, &b);
fprintf(f_options, "%d,%d,%d\n", r, g, b);
fl_getmcolor(FL_FREE_COL1 + 4, &r, &g, &b);
fprintf(f_options, "%d,%d,%d\n", r, g, b);
fl_getmcolor(FL_FREE_COL1 + 5, &r, &g, &b);
fprintf(f_options, "%d,%d,%d\n", r, g, b);
fclose(f_options);
}
void cb_op_cancel(FL_OBJECT * ob, long arg)
{
fl_hide_form(fo->fd_options);
fl_redraw_form(fm->fd_main);
activate_form(fo->fd_options->u_vdata);
}
void cb_chg_col(FL_OBJECT * ob, long arg)
{
int r, g, b;
int *rgb = malloc(3 * sizeof(int));
char label[30];
fc->txt_col->u_ldata = arg;
deactivate_form(fo->fd_options);
fl_set_object_lcol(fc->txt_col, FL_FREE_COL1 + arg);
fl_set_object_lcol(fc->txt_col_sel, FL_FREE_COL1 + arg);
switch (arg) {
case 0:
strcpy(label, "");
break;
case 1:
strcpy(label, "");
break;
case 2:
strcpy(label, "Directories");
break;
case 3:
strcpy(label, "Links");
break;
case 4:
strcpy(label, "Executable files");
break;
case 5:
strcpy(label, "Other files");
}
fl_set_object_label(fc->txt_col, label);
fl_set_object_label(fc->txt_col_sel, label);
fl_getmcolor(FL_FREE_COL1 + arg, &r, &g, &b);
rgb[0] = r;
rgb[1] = g;
rgb[2] = b;
fc->txt_col->u_vdata = rgb;
fl_set_slider_value(fc->sld_red, r);
fl_set_slider_value(fc->sld_green, g);
fl_set_slider_value(fc->sld_blue, b);
fl_show_form(fc->fd_colors, FL_PLACE_MOUSE, FL_TRANSIENT, "");
}
void cb_col_ok(FL_OBJECT * ob, long arg)
{
int i, no = fc->txt_col->u_ldata;
fl_hide_form(fc->fd_colors);
if (no == 0)
for (i = 0; i < 6; i++)
fl_redraw_object(foc->btn_col[i]);
else
fl_redraw_object(foc->btn_col[no]);
activate_form(fo->fd_options);
}
void cb_col_cancel(FL_OBJECT * ob, long arg)
{
int *rgb;
activate_form(fo->fd_options);
fl_hide_form(fc->fd_colors);
rgb = fc->txt_col->u_vdata;
fl_mapcolor(FL_FREE_COL1 + fc->txt_col->u_ldata, rgb[0], rgb[1], rgb[2]);
free(rgb);
}
void cb_sld_col(FL_OBJECT * ob, long arg)
{
int r, g, b;
FL_COLOR col_ind = FL_FREE_COL1 + fc->txt_col->u_ldata;
r = fl_get_slider_value(fc->sld_red);
g = fl_get_slider_value(fc->sld_green);
b = fl_get_slider_value(fc->sld_blue);
fl_mapcolor(col_ind, r, g, b);
fl_redraw_object(fc->txt_col);
fl_redraw_object(fc->txt_col_sel);
}
/* fd_remote_view callback */
void cb_remote_view_ok(FL_OBJECT * ob, long arg)
{
fl_hide_form(frv->fd_remote_view);
busy = 0;
activate_object(fm->local_btns);
activate_object(fm->remote_btns);
activate_object(fm->br_remote);
activate_object(fm->br_remote_size);
activate_form(fm->fd_main);
}
/* fd_local_view callback */
void cb_local_view_ok(FL_OBJECT * ob, long arg)
{
fl_hide_form(flv->fd_local_view);
}
/* fd_about callback */
void cb_about_ok(FL_OBJECT * ob, long arg)
{
activate_form(fm->fd_main);
fl_hide_form(fa->fd_about);
}
/*************/
char *
get_cwdir()
{
int i = 50;
char *wd;
i = 50;
wd = malloc(i);
while (getcwd(wd, i) == NULL) {
if (errno == EACCES) {
free(wd);
wd = NULL;
return wd;
}
if (errno != ERANGE) {
perror("getcwd error");
exit(1);
}
free(wd);
wd = malloc(i += 10);
}
return wd;
}
char *
get_home_dir()
{
struct passwd *pw_ent;
char *h_dir;
if ((pw_ent = getpwuid(getuid()))) {
h_dir = malloc(strlen(pw_ent->pw_dir) + 3);
strcpy(h_dir, pw_ent->pw_dir);
strcat(h_dir, "/");
return h_dir;
}
return NULL;
}
void read_bookmarks(const char *bookm_file)
{
int bf, bytes_read;
char read_buf[BUF_SIZE + 1], *full_addr, buf[BUF_SIZE + 1], *pc1,
*pc2;
struct addr_item *pAd_it;
fl_clear_browser(fb->br_bookmarks);
bookm_last = NULL;
while (bookm_first != NULL) {
free(bookm_first->address);
free(bookm_first->dir);
pAd_it = bookm_first->next;
free(bookm_first);
bookm_first = pAd_it;
}
if ((bf = open(bookm_file, O_RDONLY)) >= 0) {
while ((bytes_read = read(bf, read_buf, BUF_SIZE)) != 0) {
read_buf[bytes_read] = '\0';
pc1 = read_buf;
while ((pc1 = strstr(pc1, "<A HREF=")) != NULL) {
pc1 += 8;
if (*pc1 == '"')
pc1++;
if (strncmp(pc1, "ftp://", 6))
continue;
pAd_it = malloc(sizeof(struct addr_item));
pAd_it->next = NULL;
if (bookm_last != NULL)
bookm_last->next = pAd_it;
bookm_last = pAd_it;
if (bookm_first == NULL)
bookm_first = pAd_it;
pc1 += 6;
while (*pc1 == ' ')
pc1++;
pc2 = pc1;
while (*pc2 != '>' && *pc2 != '/' && *pc2 != ' ' && *pc1 != '\0')
pc2++;
if (*(pc2 - 1) == '"')
pc2--;
pAd_it->address = malloc(pc2 - pc1 + 1);
strncpy(pAd_it->address, pc1, pc2 - pc1);
pAd_it->address[pc2 - pc1] = '\0';
if (*pc2 == '>' || *pc2 == ' ') {
pAd_it->dir = malloc(1);
*pAd_it->dir = '\0';
pc1 = pc2;
} else {
buf[0] = '\0';
pc1 = pc2;
while (*pc1 != '>' && *pc1 != ' ' && *pc1 != '\0')
pc1++;
if (*pc1 == '\0') {
strcpy(buf, pc2);
if ((bytes_read = read(bf, read_buf, BUF_SIZE)) == 0) {
close(bf);
return;
}
read_buf[bytes_read] = '\0';
pc2 = read_buf;
if ((pc1 = strchr(pc2, ' ')) == NULL && (pc1 = strchr(pc2, '>')) == NULL)
return;
}
if (*(pc1 - 1) == '"')
pc1--;
*pc1 = '\0';
strcat(buf, pc2);
pAd_it->dir = malloc(strlen(buf) + 1);
strcpy(pAd_it->dir, buf);
pc1++;
}
}
}
close(bf);
pAd_it = bookm_first;
while (pAd_it != NULL) {
full_addr = malloc(strlen(pAd_it->address) + strlen(pAd_it->dir) + 2);
sprintf(full_addr, "%s%s", pAd_it->address, pAd_it->dir);
fl_add_browser_line(fb->br_bookmarks, full_addr);
free(full_addr);
pAd_it = pAd_it->next;
}
}
}
void write_bookmarks()
{
struct addr_item *pAd_it;
int i = 0;
FILE *fbm;
pAd_it = bookm_first;
if ((fbm = fopen(std_bookm_file, "w")) != NULL) {
fprintf(fbm, "<HTML>\n");
fprintf(fbm, "<HEAD>\n");
fprintf(fbm, "<TITLE>Xrmtfp bookmarks</TITLE>\n");
fprintf(fbm, "</HEAD>\n");
fprintf(fbm, "<BODY>\n");
while (pAd_it != NULL) {
fprintf(fbm, "%d <A HREF=\"ftp://%s%s\">%s%s</A><BR>\n", ++i, pAd_it->address, pAd_it->dir, pAd_it->address, pAd_it->dir);
pAd_it = pAd_it->next;
}
fprintf(fbm, "</BODY>\n");
fprintf(fbm, "</HTML>\n");
}
fclose(fbm);
}
char *
read_hist_field(FILE * fh)
{
char rl[MAXLINE], *fld;
fgets(rl, MAXLINE, fh);
rl[strlen(rl) - 1] = '\0';
fld = malloc(strlen(rl) + 1);
strcpy(fld, rl);
return fld;
}
void read_hist()
{
FILE *f_history;
int i;
struct hist_item *pHist_it;
char rl[10];
hist_last = NULL;
while (hist_first != NULL) {
free(hist_first->address);
free(hist_first->user_name);
free(hist_first->pass_unenc);
free(hist_first->local_dir);
free(hist_first->remote_dir);
pHist_it = hist_first->next;
free(hist_first);
hist_first = pHist_it;
}
if ((f_history = fopen(hist_file_name, "r+")) != NULL) {
fgets(rl, MAXLINE, f_history);
n_hist = atoi(rl);
if (n_hist > HIST_SIZE)
n_hist = HIST_SIZE;
for (i = 0; i < n_hist; i++) {
pHist_it = malloc(sizeof(struct hist_item));
pHist_it->address = read_hist_field(f_history);
pHist_it->user_name = read_hist_field(f_history);
pHist_it->pass_unenc = read_hist_field(f_history);
pHist_it->local_dir = read_hist_field(f_history);
pHist_it->remote_dir = read_hist_field(f_history);
fgets(rl, MAXLINE, f_history);
pHist_it->anonym_login = atoi(rl);
pHist_it->next = NULL;
if (hist_last != NULL)
hist_last->next = pHist_it;
hist_last = pHist_it;
if (hist_first == NULL)
hist_first = pHist_it;
}
fl_clear_browser(fcp->br_history);
pHist_it = hist_first;
while (pHist_it != NULL) {
fl_add_browser_line(fcp->br_history, pHist_it->address);
fl_addto_browser_chars(fcp->br_history, " ");
fl_addto_browser_chars(fcp->br_history, pHist_it->remote_dir);
pHist_it = pHist_it->next;
}
fclose(f_history);
return;
}
}
int read_op(FILE * f_options, int *pOp)
{
char op_line[MAXLINE];
if (fgets(op_line, MAXLINE - 1, f_options) == NULL)
return -1;
op_line[strlen(op_line) - 1] = '\0';
*pOp = atoi(op_line);
return 1;
}
void read_init_files()
{
FILE *f_options;
char op_line[MAXLINE];
int r, g, b;
if ((f_options = fopen(opt_file_name, "r")) != NULL) {
fgets(e_mail, 80, f_options);
e_mail[strlen(e_mail) - 1] = '\0';
if (read_op(f_options, &font_size) < 0)
font_size = 10;
else if (font_size < 10 || font_size > 14)
font_size = 10;
if (read_op(f_options, &br_fsize) < 0)
br_fsize = 10;
else if (br_fsize < 10 || br_fsize > 14)
br_fsize = 10;
if (read_op(f_options, &show_hidden_local) < 0)
show_hidden_local = 1;
if (read_op(f_options, &show_hidden_remote) < 0)
show_hidden_remote = 1;
if (read_op(f_options, &passive) < 0)
passive = 1;
if (fgets(op_line, 80, f_options) != NULL) {
op_line[strlen(op_line) - 1] = '\0';
free(std_bookm_file);
std_bookm_file = malloc(strlen(home_dir) + strlen(op_line) + 2);
sprintf(std_bookm_file, "%s%s", home_dir, op_line);
addr_file_name = malloc(strlen(std_bookm_file) + 1);
strcpy(addr_file_name, std_bookm_file);
if (fscanf(f_options, "%d,%d,%d\n", &r, &g, &b) == 3)
fl_mapcolor(FL_FREE_COL1, r, g, b);
if (fscanf(f_options, "%d,%d,%d\n", &r, &g, &b) == 3)
fl_mapcolor(FL_FREE_COL1 + 1, r, g, b);
if (fscanf(f_options, "%d,%d,%d\n", &r, &g, &b) == 3)
fl_mapcolor(FL_FREE_COL1 + 2, r, g, b);
if (fscanf(f_options, "%d,%d,%d\n", &r, &g, &b) == 3)
fl_mapcolor(FL_FREE_COL1 + 3, r, g, b);
if (fscanf(f_options, "%d,%d,%d\n", &r, &g, &b) == 3)
fl_mapcolor(FL_FREE_COL1 + 4, r, g, b);
if (fscanf(f_options, "%d,%d,%d\n", &r, &g, &b) == 3)
fl_mapcolor(FL_FREE_COL1 + 5, r, g, b);
}
fclose(f_options);
}
read_hist();
if (hist_first != NULL) {
fl_set_input(fcp->address, hist_first->address);
fl_set_input(fcp->user_name, hist_first->user_name);
fl_set_input(fcp->pass_unenc, hist_first->pass_unenc);
fl_set_input(fcp->local_dir, hist_first->local_dir);
fl_set_input(fcp->remote_dir, hist_first->remote_dir);
}
read_bookmarks(addr_file_name);
flog = fopen(log_file_name, "w");
}
int main(int argc, char *argv[])
{
FL_OBJECT *vscroll_local, *vscroll_remote, *ob;
FL_IOPT options;
int x, y, r, g, b, i;
home_dir = get_home_dir();
addr_file_name = malloc(strlen(home_dir) + 30);
std_bookm_file = malloc(strlen(home_dir) + 30);
opt_file_name = malloc(strlen(home_dir) + 30);
hist_file_name = malloc(strlen(home_dir) + 30);
log_file_name = malloc(strlen(home_dir) + 30);
strcpy(addr_file_name, home_dir);
strcpy(opt_file_name, home_dir);
strcpy(hist_file_name, home_dir);
strcpy(log_file_name, home_dir);
strcat(addr_file_name, "ftp_bookmarks.html");
strcat(opt_file_name, ".Xrmftp_options");
strcat(hist_file_name, ".Xrmftp_history");
strcat(log_file_name, ".Xrmftp_log");
strcpy(std_bookm_file, addr_file_name);
*(address = malloc(1)) = '\0';
*(user_name = malloc(1)) = '\0';
*(pass_enc = malloc(1)) = '\0';
*(pass_unenc = malloc(1)) = '\0';
*(local_dir_path_inp = malloc(1)) = '\0';
*(remote_dir_path_inp = malloc(1)) = '\0';
*(remote_dir_path = malloc(1)) = '\0';
options.borderWidth = -1;
fl_set_defaults(FL_PDBorderWidth, &options);
fl_initialize(&argc, argv, "", 0, 0);
create_forms();
sprintf(dir_col, "@C%d", FL_FREE_COL1 + 2);
sprintf(lnk_col, "@C%d", FL_FREE_COL1 + 3);
sprintf(exe_col, "@C%d", FL_FREE_COL1 + 4);
sprintf(other_col, "@C%d", FL_FREE_COL1 + 5);
fl_getmcolor(FL_COL1, &r, &g, &b);
fl_mapcolor(FL_FREE_COL1, r, g, b);
fl_getmcolor(FL_YELLOW, &r, &g, &b);
fl_mapcolor(FL_FREE_COL1 + 1, r, g, b);
fl_getmcolor(FL_BLUE, &r, &g, &b);
fl_mapcolor(FL_FREE_COL1 + 2, r, g, b);
fl_getmcolor(FL_GREEN, &r, &g, &b);
fl_mapcolor(FL_FREE_COL1 + 3, r, g, b);
fl_getmcolor(FL_RED, &r, &g, &b);
fl_mapcolor(FL_FREE_COL1 + 4, r, g, b);
fl_getmcolor(FL_BLACK, &r, &g, &b);
fl_mapcolor(FL_FREE_COL1 + 5, r, g, b);
fl_set_object_color(fc->txt_col, FL_FREE_COL1, FL_INACTIVE_COL);
fl_set_object_color(fc->txt_col_sel, FL_FREE_COL1 + 1, FL_INACTIVE_COL);
read_init_files();
ob = fm->fd_main->first;
while (1) {
if (ob->objclass == FL_BROWSER)
fl_set_object_color(ob, FL_FREE_COL1, FL_FREE_COL1 + 1);
if (ob == fm->fd_main->last)
break;
ob = ob->next;
}
for (i = 2; i < 6; i++) {
fl_set_object_color(foc->btn_col[i], FL_FREE_COL1, FL_FREE_COL1);
fl_set_object_lcol(foc->btn_col[i], FL_FREE_COL1 + i);
}
fl_set_object_lcol(fm->br_log, FL_FREE_COL1 + 5);
signal(SIGPIPE, SIG_IGN);
fl_set_button(fofl->btn_show_hidden_local, show_hidden_local);
fl_set_button(fofl->btn_show_hidden_remote, show_hidden_remote);
fl_set_button(fon->btn_passive, passive);
change_font_size();
fl_deactivate_object(fd->sl_time);
fl_deactivate_object(frv->sl_time);
fl_hide_object(fcp->pass_unenc);
fl_hide_object(fcp->br_history);
fl_set_input_maxchars(fon->e_mail, 80);
fl_addto_tabfolder(fo->fld_options, "Network", fon->fd_options_net);
fl_addto_tabfolder(fo->fld_options, "Fonts", fof->fd_options_fonts);
fl_addto_tabfolder(fo->fld_options, "Colors", foc->fd_options_colors);
fl_addto_tabfolder(fo->fld_options, "Files", fofl->fd_options_files);
fl_set_object_prehandler(fm->br_local_size, prehndl_local_size);
fl_set_object_prehandler(fm->br_local, prehndl_local);
fl_set_object_prehandler(fm->br_remote_size, prehndl_remote_size);
fl_set_object_prehandler(fm->br_remote, prehndl_remote);
vscroll_local = fl_get_object_component(fm->br_local_size, FL_SCROLLBAR, FL_VERT_THIN_SCROLLBAR, 0);
vscroll_remote = fl_get_object_component(fm->br_remote_size, FL_SCROLLBAR, FL_VERT_THIN_SCROLLBAR, 0);
cb_old_local = fl_set_object_callback(vscroll_local, cb_vscroll_local, 0);
cb_old_remote = fl_set_object_callback(vscroll_remote, cb_vscroll_remote, 0);
fl_set_browser_vscrollbar(fm->br_local, FL_OFF);
fl_set_browser_hscrollbar(fm->br_local, FL_ON);
fl_set_browser_hscrollbar(fm->br_local_size, FL_ON);
fl_set_browser_scrollbarsize(fm->br_local, 15, 15);
fl_set_browser_scrollbarsize(fm->br_local_size, 15, 15);
fl_set_browser_dblclick_callback(fm->br_local, cb2_br_local, 0);
fl_set_browser_dblclick_callback(fm->br_local_size, cb2_br_local, 0);
fl_set_browser_dblclick_callback(fb->br_bookmarks, cb2_br_bookmarks, 0);
fl_set_browser_vscrollbar(fm->br_remote, FL_OFF);
fl_set_browser_hscrollbar(fm->br_remote, FL_ON);
fl_set_browser_hscrollbar(fm->br_remote_size, FL_ON);
fl_set_browser_scrollbarsize(fm->br_remote, 15, 15);
fl_set_browser_scrollbarsize(fm->br_remote_size, 15, 15);
fl_set_browser_dblclick_callback(fm->br_remote, cb2_br_remote, 0);
fl_set_browser_dblclick_callback(fm->br_remote_size, cb2_br_remote, 0);
fl_set_browser_hscrollbar(fm->br_buffer_name, FL_ON);
fl_set_browser_scrollbarsize(fm->br_buffer_name, 15, 15);
fl_set_browser_scrollbarsize(fm->br_log, 15, 15);
fl_set_browser_scrollbarsize(fcp->br_history, 15, 15);
fl_set_browser_scrollbarsize(fb->br_bookmarks, 15, 15);
fl_set_choice(fof->font_txt, (font_size - 8) / 2);
fl_set_choice(fof->font_br, (br_fsize - 8) / 2);
deactivate_object(fm->remote_btns);
deactivate_object(fm->br_remote);
deactivate_object(fm->br_remote_size);
fl_set_form_minsize(fm->fd_main, minx, miny);
fl_show_form (fm->fd_main, FL_PLACE_FREE, FL_FULLBORDER, "Xrmftp");
deactivate_form(fm->fd_main);
x = fm->fd_main->x + (fm->fd_main->w - fcp->fd_conn_par->w) / 2;
y = fm->fd_main->y + (fm->fd_main->h - fcp->fd_conn_par->h) / 2;
fl_set_form_position(fcp->fd_conn_par, x, y);
fl_show_form(fcp->fd_conn_par, FL_PLACE_GEOMETRY, FL_TRANSIENT, "");
XFlush(fl_get_display());
read_local_dir();
while (1)
fl_check_forms();
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1