#!/usr/bin/env python
# Auther : Kong Hyeog Jun <sanzio2001@hanmail.net>
# Copyright (c) 2002, Kong Hyeog Jun. 
# 
# Version : 0.20
# Last Modified  August 22, 2002

from ftplib import FTP
import ftplib
import sys, cmd, string, os,socket
import os.path

class kFTP(cmd.Cmd):

	def __init__(self):
		cmd.Cmd.__init__(self)
		self.prompt = "Remote kFTP>"
		self.ftp = FTP()
		self.file_size = 0		# temp file used for the evaluation of file'size
		self.mode = 0   		# if self.mode is 0, Current location is Remote Server. if 1, Local host 
		print "Welcome to kFTP 0.20!"
		while 1:
			try :
				ServerName = raw_input("Enter Server Name:")
				print "connecting..."
				self.ftp.connect(ServerName)
			except socket.gaierror:
				print "Error : No address associated with Server Name"
				print "Again!"
			except:
				pass
			else:
				break
		print "Connected to %s" % ServerName

		UserID = raw_input("Login Name:")
		if UserID == "": UserID = "anonymous"
		UserPW = raw_input("Password  :")
		if UserPW == "": UserPW = "realuser@host"
		flag = 0
		while 1:
			if flag:
				UserID = raw_input("Login Name:")
				UserPW = raw_input("Password  :")
				flag = 0
			if not flag:
				try:
					self.ftp.login(UserID,UserPW)
				except ftplib.error_perm:
					print "Error : User anonymous login failed."
					print "Again!"
					flag = 1
				else:
					break
				
		print "Login successful. Have fun!"

	def help_size(self):
		print "DESCRIPTION request the size of the file named 'filename' on the server"
		print "SYNOPSIS    size [filename]"
	def do_size(self, tar):
		try :
			resp = self.ftp.sendcmd("TYPE A")
			conn = self.ftp.transfercmd("LIST")
			fd = conn.makefile('rb')
			while 1:
				line = fd.readline()
				if len(line) == 0:
					print "Error : %s not found" % (tar)
					break
				if line[-2:] == "\r\n":
					tmp = line[:-2]
				elif line[-1:] == "\n":
					tmp = line[:-1]
				tmp2 = string.split(tmp, " ")
				for x in tmp2:
					if x == tar: 
						self.file_size = int(tmp2[-5])
						break
				if self.file_size != 0: break
			fd.close()
			conn.close()
			self.ftp.voidresp()
		except:
			self.help_size()

	def ShowDir(self,strarg = None):
		try:
			tmp = self.ftp.sendcmd('PWD')
			tmp = string.split(tmp," ")
			print "Current Directory : "+tmp[1]
		except:
			pass
	def help_get(self):
		print "DESCRIPTION stores a file in binary transfer mode."
		print "SYNOPSIS    get [filename]"
	def do_get(self, tar):
		try:
			self.do_size(tar)
			self.ftp.voidcmd("TYPE I")
			conn = self.ftp.transfercmd("RETR "+tar) 
			f = file(tar,"w")
			flen = 0
			while 1:
				block = conn.recv(8192)
				if len(block) == 0:
					break
				flen = flen + len(block)
				f.write(block)
				print "\r downloading :%10dB/%sB %d%%" % (flen , self.file_size,int((flen/float(self.file_size))*100)),
			print "\r Downloaded  :%10dB/%sB" % (flen, self.file_size)
			conn.close()
			self.ftp.voidresp()
			self.file_size = 0
		except:
			self.help_get()

	def help_put(self):
		print "DESCRIPTION retrieve a file in binary mode."
		print "SYNOPSIS    put [filename]"
	def do_put(self,tar):
		try:
			self.file_size = os.path.getsize(tar)
			self.ftp.voidcmd("TYPE I")
			conn = self.ftp.transfercmd("STOR "+tar) 
			f = file(tar,"r")
			flen = 0
			while 1:
				block = f.read(8192)
				if len(block) == 0:
					break
				flen = flen + len(block)
				conn.sendall(block)
				print "\r Uploading :%10dB/%sB %d%%" % (flen , self.file_size,int((flen/float(self.file_size))*100)),
			print "\r Uploaded  :%10dB/%sB" % (flen, self.file_size)
			conn.close()
			self.ftp.voidresp()
			self.file_size()
		except:
			self.help_put()
		
	def help_ls(self):
		print "DESCRIPTION show the list of files and directories on the currrent working directory "
		print "SYNOPSIS    ls"
	def do_ls(self,strarg = None):
		try:
			if not self.mode:
				self.ftp.retrlines('LIST')
				self.ShowDir(self)
			elif self.mode:
				os.system("ls")
		except:
			self.help_ls()
	
	def help_cd(self):
		print "DESCRIPTION change the current working directory to path"
		print "SYNOPSIS    cd [pathname]"		
	def do_cd(self,path):
		try:
			if not self.mode:
				self.ftp.cwd(path)
				self.ShowDir(self)
			elif self.mode:
				os.chdir(path)
		except:
			self.help_cd()

	def help_mkdir(self):
		print "DESCRIPTION create a new directory named path ."
		print "SYNOPSIS    mkdir [dirname]"		
	def do_mkdir(self, path):
		try:
			if not self.mode:
				self.ftp.mkd(path)
				print "MKDIR success!"
				self.ShowDir(self)
			elif self.mode:
				os.mkdir(path)
		except:
			self.help_mkdir()

	def help_rmdir(self):
		print "DESCRIPTION remove the directory named path ."
		print "SYNOPSIS    rmdir [dirname]"	
	def do_rmdir(self, path):
		try:
			if not self.mode:
				self.ftp.rmd(path)
				print "RMDIR success!"
				self.ShowDir(self)
			elif self.mode:
				os.rmdir(path)
		except:
			self.help_rmdir()
	
	def help_rm(self):
		print "DESCRIPTION remove the file named filename."
		print "SYNOPSIS    rm [filename]"			
	def do_rm(self, fn):
		try:
			if not self.mode:
				self.ftp.delete(fn)
				print "RM sucess!"
				self.ShowDir(self)
			elif self.mode:
				os.remove(fn)
		except:
			self.help_rm()

	def help_mv(self):
		print "DESCRIPTION rename file fromname to toname"
		print "SYNOPSIS    mv [fromname] [toname]"
	def do_mv(self,fns):
		try:
			if not self.mode:
				files = string.split(fns," ")
				self.ftp.rename(files[0],files[1])
				print "MV sucess!"
				self.ShowDir(self)
			elif self.mode:
				files = string.split(fns, " ")
				os.rename(files[0], files[1])
		except:
			self.help_mv()

	def help_nlst(self):
		pass
	def do_nlst(self,strang= None):
		self.ftp.nlst()

	def help_lcd(self):
		print "DESCRIPTION show the current directory on local host."
		print "SYNOPSIS    lcd"
	def do_lcd(self, strarg = None):
		print "Locol Current Directory is "+ os.getcwd()

	def do_about(self, strang = None):
		print "###############################################################"
		print "#               kFTP - Simple FTP Client Program              #"
		print "# ------------------------------------------------------------#"
		print "#   Program Name  : kFTP                                      #"
		print "#   Version       : 0.20                                      #" 
		print "#   Auther        : Kong Hyeog Jun  <sanzio2001@hanmail.net>  #"
		print "#   If any bug, please send mail me bug report.               #"
		print "#   Enjoy python!                                             #" 
		print "###############################################################"
	
	def help_sys(self,strang=None):
		print "DESCRIPTION Execute the system command named comm."
		print "SYNOPSIS    sys [system command]"	
	def do_sys(self,comm):
		try:
			if self.mode:
				os.system(comm)
			else:
				pass
		except:
			self.help_sys()

	def do_local(self,strang= None):
		self.mode = 1
		self.prompt = "Local kFTP>"
	def do_remote(self,strang = None):
		self.mode = 0
		self.prompt = "Remote kFTP>"

	def help_bye(self):
		print "DESCRIPTION terminates kFTP."
		print "SYNOPSIS    bye"			
	def do_bye(self,strarg = None):
		self.ftp.quit()
		print "See ya again!"
		sys.exit()	
#<----------------------------------- the special commands executed on local host --------------------># 
	def do_getcwd(self,strang = None): # Return a string representing the current working directory
		if self.mode:
			os.getcwd()
		
	def do_chroot(self,path): # Change the root directory of the current process to path
		if self.mode:
			os.chroot(path)
	def do_chmod(self,argv): # Change the mode of path to the numeric mode.
		if self.mode:
			argv = string.split(argv," ")
			os.chmod(argv[0], argv[1])
	def do_chown(self, argv): #Change the owner and group id of path to the numberic uid and gid
		if self.mode:
			argv = string.split(argv," ")
			os.chown(argv[0],argv[1],argv[2])
	def do_mkdirs(self, paths): # Recursive directory creation function
		if self.mode:
			os.makedirs(paths)
	def do_rmdirs(self, paths): #Recursive directory removal function
		if self.mode:
			os.removedirs(paths)
#<------------------------------------------------------------------------------------------------------>#
	def do_help(self,strang = None):
		print "###################################################################################"
		print "#                               kFTP COMMAND LIST                                 #"
		print "# --------------------------------------------------------------------------------#"
		print "# local        : change working host to local host                                #"
		print "# remote       : change working host to remote host                               #"
		print "# put [file]   : upload a file                                                    #"
		print "# get [file]   : download a file                                                  #"
		print "# cd  [path]   : change the current working directory to path                     #" 
		print "# ls           : show the list of files and directories on the currrent directory #"
		print "# lcd          : show the current working directory on local host.                #"
		print "# mkdir [path] : create a new directory named path                                #"
		print "# rmdir [path] : remove the directory named path                                  #"
		print "# rm           : remove the file named filename                                   #"
		print "# mv [frn][ton]: rename 'frn' to ton                                              #"
		print "# sys [command]: execute an arbitrary system command on a local host.             #"
		print "# bye          : terminates kFTP                                                  #"
		print "# about        : show info about kFTP                                             #"
		print "###################################################################################"
		
if __name__ == "__main__":
	start = kFTP()
	start.cmdloop()
	
