#
# ftp_update.py Version 1.1
#
# Copyright by Michael Neumann; 30.1.1999
# neumann@s-direktnet.de
# http://www.s-direktnet.de/homepages/neumann/index.htm
#
# Python ist kostenlos unter http://www.python.org erhältlich.
#
# Dieses Programm stellt Änderungen in einem speziellen Verzeichnis fest, und
# aktualisiert ein Verzeichnis auf einem FTP-Server dementsprechend, daß beide
# den gleichen Inhalt haben.
# Wenn Sie beispielsweise Ihre Homepage in einem Verzeichnis auf ihrem Computer
# editieren und möchten, daß im Internet dasselbe zu sehen ist, können Sie einfach
# dieses Programm dafür benutzen.
#
Aufruf = """
1.) python.exe ftp_update.py -n filename
Erzeugt ein neues Projekt . Sie werden automatisch
aufgefordert, bestimmte Angaben zu machen.
2.) python.exe ftp_update.py filename
Die Aktualisierung des FTP-Servers wird durch die Angaben des
Projekts durchgeführt.
3.) python.exe ftp_update.py -nof filename
Diese Option wird benötigt wenn sich schon etwas auf dem FTP-Server
befindet, und somit COMPUTER-Ordner und FTP-Server übereinstimmen.
Es wird nur das Projekt aktualisiert und nichts übertragen."""
ProjektDateiAufbau = """
Computer-Dir
Ftp-Dir
LogFile
Host
User
Passwd
Account
Data
"""
# eingebundene Module
import os, sys, string
from ftplib import FTP
on = 1
off = 0
################################################################################################
# generiert eine CRC-Prüfsumme der übergebenen Datei
################################################################################################
def crc(path):
import sys, zlib
buffer_size = 1024
f=open(path,'rb')
fbuf = f.read(buffer_size)
crc_val = zlib.crc32(fbuf)
while len(fbuf)>0:
fbuf = f.read(buffer_size)
crc_val = zlib.crc32(fbuf,crc_val)
f.close
return crc_val
################################################################################################
# File-Funktionen
################################################################################################
def writeln(fileptr, text):
fileptr.write(text+'\n')
def readln(fileptr):
return fileptr.readline()[:-1]
################################################################################################
# Utilities für den FTP-Zugriff
################################################################################################
ftp_handle = 0 # das erzeugte FTP-Objekt
ftp_level = 0 # gibt die Höhe des Pfades an
def connect(host, user, passwd, acct):
"Nimmt Verbindung mit dem FTP-Server auf"
global ftp_handle
ftp_level = 0
ftp_handle = FTP(host,user,passwd,acct)
def disconnect():
"Trennt Verbindung mit dem FTP-Server (nicht aber telefon!)"
global ftp_handle
ftp_handle.quit()
def create_dir(name):
"erzeugt z.B. bei a\\b\\c\\ oder a\\b\\c\\x das verzeichnis c"
"kann nur immer das letzte erzeugen, nicht mehrere auf einmal"
global ftp_handle
ftp_handle.mkd(_beforedir(name))
def delete_dir(name):
"wie create_dir nur das es das verzeichnis löscht"
global ftp_handle
ftp_handle.rmd(_beforedir(name))
def copy_file(file,name):
"file stellt den kompletten filenamen dar, name ist der name auf dem server mit verz"
global ftp_handle
name = _todir(name)
f=open(file,'rb')
ftp_handle.storbinary('STOR '+name, f, 1024)
f.close()
def delete_file(name):
"löscht name auf dem server"
global ftp_handle
name = _todir(name)
ftp_handle.sendcmd('DELE '+name)
def _cd(dir):
"wechselt das Remote-Verzeichnis (nur ein Verzeichnis aufeinmal)"
global ftp_level, ftp_handle
if dir=='..': ftp_level = ftp_level - 1
else: ftp_level = ftp_level + 1
ftp_handle.cwd(dir)
def _home():
"kehrt ins Home-Remote-Verzeichnis zurück"
global ftp_level
while ftp_level>0: _cd('..')
def _todir(dir):
"wechselt in ein beliebiges Remote-Verzeichnis, Verzeichnis muß mit \\ enden"
"es kann auch ein filename mit angegeben werden! z.B. a\\b wechselt in a, wie a\\"
_home()
a = string.split(dir,'\\')
for i in a[:-1]: _cd(i)
return a[-1]
def _beforedir(dir):
"fast wie _todir nur ein verzeichnis weniger"
"gibt das verzeichnis danach an"
_home()
a = string.split(dir,'\\')
for i in a[:-2]: _cd(i)
return a[-2]
################################################################################################
# Utilities für Listen (kürzesten String bzw. längsten aus einer Liste finden)
################################################################################################
def find_shortest(a):
"sucht den kürzesten String aus der Liste 'a' heraus und gibt ihn zurück"
if len(a)==0: return ''
shortest = a[0]
for i in a:
if len(i)<len(shortest): shortest = i
return shortest
def find_shortest2(a):
"sucht den kürzesten String aus der doppel-Liste 'a' heraus und gibt ihn zurück"
if len(a)==0: return ['',0]
shortest = a[0][0]
ptr = a[0]
for i in a:
if len(i[0])<len(shortest):
shortest = i[0]
ptr = i
return [shortest,ptr]
def find_longest(a):
"sucht den längsten String aus der Liste 'a' heraus und gibt ihn zurück"
if len(a)==0: return ''
longest = a[0]
for i in a:
if len(i)>len(longest): longest = i
return longest
def find_longest2(a):
"sucht den längsten String aus der doppel-Liste 'a' heraus und gibt ihn zurück"
if len(a)==0: return ['',0]
longest = a[0][0]
ptr = a[0]
for i in a:
if len(i[0])>len(longest):
longest = i[0]
ptr = i
return [longest,ptr]
################################################################################################
################################################################################################
def ende():
raw_input("Ende ")
sys.exit()
# Option -n
def new_project(filename):
print "Verzeichnisse enden mit \\ !"
f = open(filename,"w")
a = raw_input("Computer-Verzeichnis: ")
writeln(f,a)
a = raw_input("FTP-Verzeichnis: ")
writeln(f,a)
a = raw_input("Logfile: ")
writeln(f,a)
print "Bei folgende Angaben wenn nicht zutreffend bitte nichts eingeben"
a = raw_input("Host: ")
writeln(f,a)
a = raw_input("User: ")
writeln(f,a)
a = raw_input("Passwort: ")
writeln(f,a)
a = raw_input("Account: ")
writeln(f,a)
f.close()
#
# Listen
#
COMPdirList=[]
COMPfileList=[]
FTPdirList=[]
FTPfileList=[]
# enthält später das aktuelle Projektfile und wird dann nach erfolgreicher FTP-Übertragung
# geschrieben
changed_proj=[]
def check_dirs(srcdir, path):
global changed_proj,COMPdirList,COMPfileList
l = os.listdir(srcdir+path)
for i in l:
if os.path.isdir(srcdir+path+i):
print srcdir+path+i+'\\'
changed_proj.append(path+i+'\\')
COMPdirList.append(path+i+'\\')
check_dirs(srcdir,path+i+'\\')
else:
print srcdir+path+i
changed_proj.append(path+i)
crcsum = crc(srcdir+path+i)
changed_proj.append(str(crcsum))
COMPfileList.append([path+i,crcsum])
def update(filename,ftp):
global COMPdirList, COMPfileList, FTPdirList, FTPfileList, changed_proj
f = open(filename,'r') # Projektdatei öffnen
computer_dir = readln(f)
ftp_dir = readln(f)
logfile = readln(f)
host = readln(f)
user = readln(f)
passwd = readln(f)
account = readln(f)
readln(f) # leerzeile
#
# die Daten des Projektfiles werden ausgelesen
#
ln = readln(f)
while len(ln)!=0:
# 'ln' ist ein Verzeichnis
if ln[-1]=='\\': FTPdirList.append(ln)
# 'ln' ist eine Datei
else: FTPfileList.append([ln,int(readln(f))])
ln=readln(f)
f.close()
#
# das Computer-Verzeichnis wird auf Veränderungen geprüft und das
# aktualisierte Projekt in changed_proj gespeichert.
#
changed_proj.append(computer_dir)
changed_proj.append(ftp_dir)
changed_proj.append(logfile)
changed_proj.append(host)
changed_proj.append(user)
changed_proj.append(passwd)
changed_proj.append(account)
changed_proj.append("")
check_dirs(computer_dir,'')
#
# nun werden alle gleichen Einträge gelöscht
#
## Zuerst Files
for i in FTPfileList[:]:
try:
COMPfileList.remove(i)
FTPfileList.remove(i)
except ValueError: pass
for i in COMPfileList[:]:
try:
FTPfileList.remove(i)
COMPfileList.remove(i)
except ValueError: pass
## Jetzt die Directories
for i in FTPdirList[:]:
try:
COMPdirList.remove(i)
FTPdirList.remove(i)
except ValueError: pass
for i in COMPdirList[:]:
try:
FTPdirList.remove(i)
COMPdirList.remove(i)
except ValueError: pass
######################################################################
# hier wird nun der FTP-Server upgedatet
#
# 1.) Files vom FTP-Server löschen
# 2.) Directories vom FTP-Server löschen
# 3.) Directories auf dem FTP-Server erstellen
# 4.) Files auf den FTP-Server kopieren
#
######################################################################
f=open(logfile,'w')
print ''
if len(COMPdirList)==0 and len(COMPfileList)==0 and len(FTPdirList)==0 and len(FTPfileList)==0:
print 'Nothing to change'
writeln(f,'Nothing to change')
f.close()
ende()
try:
if ftp==on:
connect(host, user, passwd, account)
print 'Connected...'
writeln(f,'Connected...')
# 1.) Files vom FTP-Server löschen
a = find_longest2(FTPfileList)
while a[0]!='':
# a[0] löschen
print 'delete_file '+ftp_dir + a[0]
writeln(f,'delete_file '+ftp_dir+a[0])
try:
if ftp==on: delete_file(ftp_dir+a[0])
except:
print 'could not delete file <'+ftp_dir + a[0] +'>'
writeln(f,'could not delete file <'+ftp_dir + a[0] +'>')
FTPfileList.remove(a[1])
a = find_longest2(FTPfileList)
# 2.) Directories vom FTP-Server löschen
a = find_longest(FTPdirList)
while a!='':
print 'delete_dir '+ftp_dir+a
writeln(f,'delete_dir '+ftp_dir+a)
try:
if ftp==on: delete_dir(ftp_dir+a)
except:
print 'could not delete directory <'+ftp_dir + a +'>'
writeln(f,'could not delete directory <'+ftp_dir + a +'>')
FTPdirList.remove(a)
a = find_longest(FTPdirList)
# 3.) Directories auf dem FTP-Server erstellen
a = find_shortest(COMPdirList)
while a!='':
print 'create_dir '+ftp_dir+a
writeln(f,'create_dir '+ftp_dir+a)
try:
if ftp==on: create_dir(ftp_dir+a)
except:
print 'could not create directory <'+ftp_dir + a +'>'
writeln(f,'could not create directory <'+ftp_dir + a +'>')
COMPdirList.remove(a)
a = find_shortest(COMPdirList)
# 4.) Files auf den FTP-Server kopieren
a = find_shortest2(COMPfileList)
while a[0]!='':
print 'copy_file '+computer_dir+a[0]+' -> '+ftp_dir + a[0]
writeln(f,'copy_file '+computer_dir+a[0]+' -> '+ftp_dir + a[0])
try:
if ftp==on: copy_file(computer_dir+a[0],ftp_dir+a[0])
except:
print 'could not copy file '+computer_dir+a[0]+' -> '+ftp_dir + a[0]
writeln(f,'could not copy file '+computer_dir+a[0]+' -> '+ftp_dir + a[0])
COMPfileList.remove(a[1])
a = find_shortest2(COMPfileList)
if ftp==on:
disconnect()
print 'Disconnected'
writeln(f,'Disconnected')
print 'Bitte Ihre Telefonverbindung trennen, wenn das nicht automatisch geht'
f.close()
except:
print 'Ein Fehler ist aufgetreten! Die Projektdatei wurde nicht upgedated!'
print 'Computer und FTP-Server können unterschiedliche Inhalte haben!'
f.close()
ende()
f = open(filename,"w")
for i in changed_proj:
writeln(f,i)
print '--- Success ---'
ende()
#### main ####
if len(sys.argv)==3:
if sys.argv[1] == '-n':
new_project(sys.argv[2])
ende()
elif sys.argv[1] == '-nof':
update(sys.argv[2],off)
ende()
else:
print "!!!! Falscher Parameter !!!!"
print
print Aufruf
ende()
elif len(sys.argv)==2:
update(sys.argv[1],on)
ende()
else:
print "!!!! Falsche Anzahl an Parametern !!!!"
print
print Aufruf
ende()
#################################################################################
# Copyright (c) 1999 by Michael Neumann
#################################################################################