/***************************************************************************/
/* */
/* Fast Webpage Exchanger - an FTP client for updating webpages */
/* Copyright (C) 1999-2000 Yuuki NINOMIYA <gm@debian.or.jp> */
/* */
/* 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, or (at your option) */
/* any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the */
/* Free Software Foundation, Inc., 59 Temple Place - Suite 330, */
/* Boston, MA 02111-1307, USA. */
/* */
/***************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/stat.h>
#include "intl.h"
#include "ftplib.h"
#include "strlib.h"
#include "variable.h"
#include "proto.h"
static int total_sent_file;
static int total_removed_file;
/* --------------------------------------------------
NAME ftp_main
FUNCTION main loop of sending
INPUT argc ... argument counter
argv ... argument vector
max_hosts ... maximum hosts in the configuration file
OUTPUT none
-------------------------------------------------- */
void ftp_main(int argc,char *argv[],int max_hosts)
{
int i;
char *temp;
FtpInit();
for(i=0;i<argc-1;i++){
host_number=argv_to_host_num(argv[i+1]);
if(argc-1>1){
put_mes(PROCESS,0,cfgSectionNumberToName(host_number),NULL);
}
if(ftp_connect_init()==-1){
log_flush();
continue;
}
total_sent_file=total_removed_file=0;
ftp_recursive_search();
put_mes(LEAVE,0,dest_dir[host_number],NULL);
temp=str_dup_printf(_("Complete: sent %d file(s), removed %d file(s)"),total_sent_file,total_removed_file);
log_write(temp);
free(temp);
ftp_disconnect();
if(!opt_test){
save_cache();
}
}
}
/* --------------------------------------------------
NAME argv_to_host_num
FUNCTION conver the argument(name or number) to host number
INPUT arg ... argument
OUTPUT host number
-------------------------------------------------- */
int argv_to_host_num(char *arg)
{
int num;
num=atoi(arg)-1;
if(num==-1){
num=cfgSectionNameToNumber(arg);
if(num==-1){
fprintf(stderr,_("Specified host (section) name `%s' is undefined.\n"),arg);
exit(1);
}
}else{
if(cfgSectionNumberToName(num)==NULL){
fprintf(stderr,_("Specified host (section) number `%s' is undefined.\n"),arg);
exit(1);
}
}
if(strcasecmp("default",cfgSectionNumberToName(num))==0){
fprintf(stderr,_("Cannot specify a default configuration.\n"));
exit(1);
}
return(num);
}
/* --------------------------------------------------
NAME ftp_connect_init
FUNCTION connect and login
OUTPUT 0 ... success
-1 ... fail
-------------------------------------------------- */
int ftp_connect_init(void)
{
char *temp;
log_init();
put_mes(CONNECT,0,host_name[host_number],NULL);
if(ftp_connect()==-1){
return(-1);
}
if(ftp_login()==-1){
return(-1);
}
load_cache();
current_dir[LOCAL]=NULL;
if(src_dir[host_number]==NULL){
fprintf(stderr,_("The source directory (SrcDir) is not configured.\n"));
exit(1);
}
change_dir(src_dir[host_number],LOCAL);
current_dir[REMOTE]=NULL;
if(dest_dir[host_number]==NULL){
fprintf(stderr,_("The destination directory (DestDir) is not configured.\n"));
exit(1);
}
change_dir(dest_dir[host_number],REMOTE);
if(chdir_at_connection[host_number]){
if(!is_cache_existent){
temp=str_dup(dest_dir[host_number]);
if(strcmp(temp,"/")!=0){
temp[strlen(temp)-1]='\0';
}
if(FtpChdir(temp,ftp_buf)==0){
if(FtpMkdir(temp,ftp_buf)==1){
put_mes(MKDIR,0,dest_dir[host_number],NULL);
}
FtpChdir(temp,ftp_buf);
}
free(temp);
}else{
change_dir_actually(REMOTE);
}
}
put_mes(ENTER,0,dest_dir[host_number],NULL);
return(0);
}
/* --------------------------------------------------
NAME ftp_connect
FUNCTION connect the host
OUTPUT 0 ... success
-1 ... fail
-------------------------------------------------- */
int ftp_connect(void)
{
char *temp;
if(host_name[host_number]==NULL){
fprintf(stderr,_("The host name is not configured.\n"));
exit(1);
}
if(!FtpConnect(host_name[host_number],&ftp_buf)){
fprintf(stderr,_("Cannot connect host `%s'.\n\n"),host_name[host_number]);
temp=str_dup_printf(_("Connection failed: %s (%s)"),host_name[host_number],cfgSectionNumberToName(host_number));
log_write(temp);
free(temp);
return(-1);
}
temp=str_dup_printf(_("Connected: %s (%s)"),host_name[host_number],cfgSectionNumberToName(host_number));
log_write(temp);
free(temp);
return(0);
}
/* --------------------------------------------------
NAME ftp_disconnect
FUNCTION disconnect the host
OUTPUT none
-------------------------------------------------- */
void ftp_disconnect(void)
{
char *temp;
put_mes(DISCONNECT,0,host_name[host_number],NULL);
if(!cfg_silent[host_number] && !opt_silent){
printf("\n");
}
FtpQuit(ftp_buf);
free(current_dir[LOCAL]);
free(current_dir[REMOTE]);
temp=str_dup_printf(_("Disconnected: %s (%s)"),host_name[host_number],cfgSectionNumberToName(host_number));
log_write(temp);
free(temp);
log_flush();
}
/* --------------------------------------------------
NAME ftp_login
FUNCTION login to the host
OUTPUT 0 ... success
-1 ... fail
-------------------------------------------------- */
int ftp_login(void)
{
if(login_name[host_number]==NULL){
fprintf(stderr,_("The login name is not configured.\n"));
exit(1);
}
if(password[host_number]==NULL){
/* Changed by Waleed Kadous <waleed@cse.unsw.edu.au> to ask
for a password if none is given in the weexrc file */
fprintf(stderr,_("No password specified in configuration file for `%s'. Asking ...\n"),host_name[host_number]);
password[host_number]=str_dup(getpass(_("Password:")));
}
if(!FtpLogin(login_name[host_number],password[host_number],ftp_buf)){
char *temp;
fprintf(stderr,_("Login failed. Check your ID and password.\n\n"));
temp=str_dup_printf(_("Login failed: %s (%s)"),host_name[host_number],cfgSectionNumberToName(host_number));
log_write(temp);
free(temp);
return(-1);
}
if(authorization_name[host_number]){
while(!FtpAuthorize(authorization_name[host_number], ftp_buf)){
fprintf(stderr,_("Authorization failed; try again\n\n"));
}
}
return(0);
}
/* --------------------------------------------------
NAME change_dir
FUNCTION change the current working directory
INPUT path ... change to path
side ... LOCAL or REMOTE
OUTPUT none
-------------------------------------------------- */
void change_dir(char *path,LocalOrRemote side)
{
if(current_dir[side]==NULL){
current_dir[side]=str_dup(path);
}else{
current_dir[side]=str_realloc(current_dir[side],strlen(current_dir[side])+strlen(path)+2);
strcat(current_dir[side],path);
strcat(current_dir[side],"/");
}
if(side==LOCAL){
change_dir_actually(LOCAL);
}
}
/* --------------------------------------------------
NAME up_dir
FUNCTION change the current working directory to the parent one
INPUT side ... LOCAL or REMOTE
OUTPUT none
-------------------------------------------------- */
void up_dir(LocalOrRemote side)
{
*strrchr(current_dir[side],'/')='\0';
*(strrchr(current_dir[side],'/')+1)='\0';
current_dir[side]=str_realloc(current_dir[side],strlen(current_dir[side])+1);
if(side==LOCAL){
change_dir_actually(LOCAL);
}
}
void change_dir_actually(LocalOrRemote side)
{
char *temp;
temp=str_dup(current_dir[side]);
if(strcmp(temp,"/")!=0){
temp[strlen(temp)-1]='\0';
}
if((side==LOCAL && chdir(temp)==-1) || (side==REMOTE && FtpChdir(temp,ftp_buf)==0)){
free(temp);
fprintf(stderr,_("Cannot change %s current working directory to `%s'.\n"),side==LOCAL ? _("local") : _("remote"),current_dir[side]);
temp=str_dup_printf(_("Changing %s current working directory failed: %s"),side==LOCAL ? _("local") : _("remote"),current_dir[side]);
log_write(temp);
free(temp);
ftp_disconnect();
exit(1);
}
free(temp);
}
/* --------------------------------------------------
NAME ftp_recursive_search
FUNCTION search files and directories recursively
OUTPUT none
-------------------------------------------------- */
void ftp_recursive_search(void)
{
static int dir_nest=1;
FileData *local_data=NULL;
FileData *remote_data=NULL;
int max_local_file;
int max_remote_file;
char *file_name;
int remote_num;
int trans_mode;
int i,j;
int opt_silent_bak;
char *temp;
char *put_temp;
char *mode_temp=NULL;
int dir_sent_file=0;
int dir_removed_file=0;
max_local_file=get_local_file_data(&local_data);
max_remote_file=get_remote_file_data_from_cache(&remote_data);
for(i=0;i<max_local_file;i++){
if(conv_to_lower[host_number]){
file_name=str_tolower(local_data[i].name);
}else{
file_name=local_data[i].name;
}
remote_num=get_equivalent_remote_number(file_name,max_remote_file,remote_data);
DebugPrint((stderr,"remote_num of `%s' is %d\n",file_name,remote_num));
if(local_data[i].isdir){
change_dir(file_name,LOCAL);
ftp_enter(file_name,(remote_num==-1) ? 0 : remote_data[remote_num].isdir,dir_nest,remote_num,&dir_removed_file);
dir_nest++;
ftp_recursive_search();
dir_nest--;
put_mes(LEAVE,dir_nest,current_dir[REMOTE],NULL);
up_dir(LOCAL);
up_dir(REMOTE);
if(conv_to_lower[host_number]){
free(file_name);
}
continue;
}else if(remote_num!=-1 && remote_data[remote_num].isdir){
remove_remote_dir(file_name,dir_nest,&dir_removed_file);
}
if(opt_force || cfg_force[host_number] || remote_num==-1 ||
remote_data[remote_num].isdir ||
local_data[i].date>remote_data[remote_num].date ||
(local_data[i].date==remote_data[remote_num].date &&
local_data[i].time>remote_data[remote_num].time)){
if(!overwrite_ok[host_number] && !rename_ok[host_number]){
ftp_remove(file_name,dir_nest,&dir_removed_file);
}
if(is_ascii_file(file_name)){
trans_mode=FTPLIB_ASCII;
if(conv_to_lower[host_number] && strcmp(local_data[i].name,file_name)!=0){
put_mes(ASCII_LOWER_SEND,dir_nest,local_data[i].name,file_name,NULL);
}else{
put_mes(ASCII_SEND,dir_nest,file_name,NULL);
}
}else{
trans_mode=FTPLIB_IMAGE;
if(conv_to_lower[host_number] && strcmp(local_data[i].name,file_name)!=0){
put_mes(BINARY_LOWER_SEND,dir_nest,local_data[i].name,file_name,NULL);
}else{
put_mes(BINARY_SEND,dir_nest,file_name,NULL);
}
}
if(!opt_test){
int success = 0;
opt_silent_bak=opt_silent;
if(cfg_silent[host_number]){
opt_silent=1;
}
if (rename_ok[host_number]) {
put_temp=str_concat(current_dir[REMOTE],"weex.tmp",NULL);
} else {
put_temp=str_concat(current_dir[REMOTE],file_name,NULL);
}
for(j=0;;j++){
if(FtpPut(local_data[i].name,put_temp,trans_mode,ftp_buf)==1){
if(log_detail_level[host_number]>=3){
temp=str_dup_printf(_("Sent: %s%s"),current_dir[REMOTE],file_name);
log_write(temp);
free(temp);
}
dir_sent_file++;
update_cache(file_name,local_data[i].date,local_data[i].time);
if(is_change_permission_dir()){
mode_temp=str_dup(change_permission[host_number]);
}else if(is_preserve_permission_dir()){
struct stat local_file_stat;
stat(file_name,&local_file_stat);
mode_temp=str_dup_printf("%o",local_file_stat.st_mode & 0777);
}
if(is_preserve_permission_dir() || is_change_permission_dir()){
put_mes(CHMOD,dir_nest,file_name,NULL);
if(FtpChmod(put_temp,mode_temp,ftp_buf)==0){
fprintf(stderr,_("Cannot change the access permissions of `%s%s' to `%s'.\n"),current_dir[REMOTE],file_name,change_permission[host_number]);
temp=str_dup_printf(_("Changing the access permissions failed: %s%s"),current_dir[REMOTE],file_name);
log_write(temp);
free(temp);
}
free(mode_temp);
}
success = 1;
break;
}
if(j>=max_retry_to_send[host_number]){
fprintf(stderr,_("Cannot send file `%s%s'.\n"),current_dir[REMOTE],file_name);
temp=str_dup_printf(_("Sending failed: %s%s"),current_dir[REMOTE],file_name);
log_write(temp);
free(temp);
break;
}
temp=str_dup_printf(_("Retry to send: %s%s"),current_dir[REMOTE],file_name);
log_write(temp);
free(temp);
fprintf(stderr,_("Retrying...\n"));
}
if (success && rename_ok[host_number]) {
char *put_temp2;
if(!overwrite_ok[host_number]){
ftp_remove(file_name,dir_nest,&dir_removed_file);
}
put_temp2 = str_concat(current_dir[REMOTE],file_name,NULL);
if (!FtpRename(put_temp, put_temp2, ftp_buf)) {
fprintf(stderr,_("Cannot rename temporary file to `%s%s'.\n"),current_dir[REMOTE],file_name);
temp=str_dup_printf(_("Sending failed: %s%s"),current_dir[REMOTE],file_name);
log_write(temp);
free(temp);
}
free(put_temp2);
}
free(put_temp);
opt_silent=opt_silent_bak;
}
}
if(conv_to_lower[host_number]){
free(file_name);
}
}
remove_files_on_remote_only(max_local_file,max_remote_file,local_data,remote_data,dir_nest,&dir_removed_file);
free_file_data(local_data,max_local_file);
free_file_data(remote_data,max_remote_file);
total_sent_file+=dir_sent_file;
total_removed_file+=dir_removed_file;
if(log_detail_level[host_number]>=2){
temp=str_dup_printf(_("%s : sent %d file(s), removed %d file(s)"),current_dir[REMOTE],dir_sent_file,dir_removed_file);
log_write(temp);
free(temp);
}
}
/* --------------------------------------------------
NAME remove_files_on_remote_only
FUNCTION remove the files on the remote side only
INPUT max_local_file .... the maximum number of local files
max_remote_file ... the maximum number of remote files
local_data .... local file data
remote_data ... remote file data
dir_nest ...... nest level of directory
dir_removed_file ... the number of removed files in the directory
OUTPUT none
-------------------------------------------------- */
void remove_files_on_remote_only(int max_local_file,int max_remote_file,FileData *local_data,FileData *remote_data,int dir_nest,int *dir_removed_file)
{
int i;
int local_num;
char *file_name;
for(i=0;i<max_remote_file;i++){
file_name=remote_data[i].name;
local_num=get_equivalent_local_number(file_name,max_local_file,local_data);
if(local_num==-1){
if(remote_data[i].isdir){
remove_remote_dir(file_name,dir_nest,dir_removed_file);
}else{
ftp_remove(file_name,dir_nest,dir_removed_file);
}
}
}
}
/* --------------------------------------------------
NAME get_equivalent_remote_number
FUNCTION get remote file number equivalent to local one
INPUT local_name ... file name of the local file
max_remote_file ... the maximum number of remote files
remote_data ... remote file data
OUTPUT remote file number equivalent to local one
return -1 if no equivalent file
-------------------------------------------------- */
int get_equivalent_remote_number(char *local_name,int max_remote_file,FileData *remote_data)
{
int i;
for(i=0;i<max_remote_file;i++){
if(strcmp(local_name,remote_data[i].name)==0){
return(i);
}
}
return(-1);
}
/* --------------------------------------------------
NAME get_equivalent_local_number
FUNCTION get local file number equivalent to remote one
INPUT remote_name ... file name of the remote file
max_local_file ... the maximum number of local files
local_data ... local file data
OUTPUT local file number equivalent to remote one
return -1 if no equivalent file
-------------------------------------------------- */
int get_equivalent_local_number(char *remote_name,int max_local_file,FileData *local_data)
{
int i;
for(i=0;i<max_local_file;i++){
if(conv_to_lower[host_number]){
if(strcasecmp(remote_name,local_data[i].name)==0){
return(i);
}
}else{
if(strcmp(remote_name,local_data[i].name)==0){
return(i);
}
}
}
return(-1);
}
/* --------------------------------------------------
NAME ftp_enter
FUNCTION enter the directory in remote
INPUT dir_name ....... name of entered directory
remote_isdir ... whether equivalent remote file is directory
dir_level ...... nest level of directory
remote_num ..... equivalent remote file number
dir_removed_file ... the number of removed files in the directory
OUTPUT none
-------------------------------------------------- */
void ftp_enter(char *dir_name,int remote_isdir,int dir_nest,int remote_num,int *dir_removed_file)
{
if(remote_num==-1){
put_mes(MKDIR,dir_nest,current_dir[REMOTE],dir_name,"/",NULL);
DebugPrint((stderr,"FtpMkdir: %s(remote_num==-1)\n",dir_name));
ftp_mkdir(dir_name);
}else if(!remote_isdir){
ftp_remove(dir_name,dir_nest,dir_removed_file);
put_mes(MKDIR,dir_nest,current_dir[REMOTE],dir_name,"/",NULL);
DebugPrint((stderr,"FtpMkdir: %s(remote_num!=-1 and !isdir)\n",dir_name));
ftp_mkdir(dir_name);
}
put_mes(ENTER,dir_nest,current_dir[REMOTE],dir_name,"/",NULL);
update_cache(dir_name,99999999,999999);
change_dir(dir_name,REMOTE);
}
/* --------------------------------------------------
NAME ftp_remove
FUNCTION remove the remote file
INPUT file_name ....... remote file that you want to remove
dir_nest ........ nest level of directory
dir_removed_file ... the number of removed files in the directory
OUTPUT none
-------------------------------------------------- */
void ftp_remove(char *file_name,int dir_nest,int *dir_removed_file)
{
char *temp;
char *del_temp;
if(is_keep_remote_dir()){
return;
}
put_mes(REMOVE,dir_nest,file_name,NULL);
if(opt_test){
return;
}
del_temp=str_concat(current_dir[REMOTE],file_name,NULL);
if(FtpDelete(del_temp,ftp_buf)==0){
fprintf(stderr,_("Cannot remove remote file `%s%s'.\n"),current_dir[REMOTE],file_name);
temp=str_dup_printf(_("Removing failed: %s%s"),current_dir[REMOTE],file_name);
log_write(temp);
free(temp);
}else{
if(log_detail_level[host_number]>=3){
temp=str_dup_printf(_("Removed: %s%s"),current_dir[REMOTE],file_name);
log_write(temp);
free(temp);
}
(*dir_removed_file)++;
del_cache(file_name);
}
free(del_temp);
}
/* --------------------------------------------------
NAME remove_remote_dir
FUNCTION remove the remote directory recursively
INPUT dir_name ... name of the remote directory that you want to remove
dir_nest ... nest level of directory
dir_removed_file ... the number of removed files in the directory
OUTPUT none
-------------------------------------------------- */
void remove_remote_dir(char *dir_name,int dir_nest,int *dir_removed_file)
{
FileData *remote_data=NULL;
int max_remote_file;
char *file_name;
int i;
char *rm_temp;
put_mes(ENTER,dir_nest,current_dir[REMOTE],dir_name,"/",NULL);
change_dir(dir_name,REMOTE);
if(is_keep_remote_dir()){
put_mes(LEAVE,dir_nest,current_dir[REMOTE],NULL);
up_dir(REMOTE);
return;
}
dir_nest++;
max_remote_file=get_remote_file_data_from_cache(&remote_data);
for(i=0;i<max_remote_file;i++){
file_name=remote_data[i].name;
if(remote_data[i].isdir){
remove_remote_dir(file_name,dir_nest,dir_removed_file);
}else{
ftp_remove(file_name,dir_nest,dir_removed_file);
}
}
dir_nest--;
put_mes(LEAVE,dir_nest,current_dir[REMOTE],NULL);
up_dir(REMOTE);
put_mes(REMOVE,dir_nest,current_dir[REMOTE],dir_name,"/",NULL);
if(opt_test){
return;
}
if(!is_cache_existent){
change_dir_actually(REMOTE);
}
rm_temp=str_concat(current_dir[REMOTE],dir_name,NULL);
if(FtpRmdir(rm_temp,ftp_buf)==0){
char *temp;
fprintf(stderr,_("Cannot remove remote directory `%s%s/'.\n"),current_dir[REMOTE],dir_name);
temp=str_dup_printf(_("Removing failed: %s%s/"),current_dir[REMOTE],dir_name);
log_write(temp);
free(temp);
}else{
del_cache(dir_name);
del_cache_dir(dir_name);
}
free(rm_temp);
}
/* --------------------------------------------------
NAME ftp_mkdir
FUNCTION make the directory
INPUT dir_name ... name of directory that you want to create
OUTPUT none
-------------------------------------------------- */
void ftp_mkdir(char *dir_name)
{
char *temp;
if(opt_test){
return;
}
temp=str_concat(current_dir[REMOTE],dir_name,NULL);
if(FtpMkdir(temp,ftp_buf)==0){
free(temp);
fprintf(stderr,_("Cannot make remote directory `%s%s/'.\n"),current_dir[REMOTE],dir_name);
temp=str_dup_printf(_("Making directory failed: %s%s/"),current_dir[REMOTE],dir_name);
log_write(temp);
free(temp);
ftp_disconnect();
exit(1);
}
free(temp);
}
syntax highlighted by Code2HTML, v. 0.9.1