From a97e726622fee2a89ef265c7fdaeb37a82c7ce16 Mon Sep 17 00:00:00 2001 From: Fabio Erculiani Date: Sun, 10 May 2009 16:29:30 +0200 Subject: [PATCH] entropy.transceivers: implement support for FtpInterface.get_file_md5 in FtpServerHandler The aim is to make php handlers not always required when there is a FTP server that supports "SITE MD5" commands (like proftpd with mod_md5). This commit makes FtpServerHandler able to handle such feature and avoid using any other external hook. If server support is found, this verification is enough. If support is broken, FtpServerHandler will try to fallback to previously supported features, if enabled (use_handlers variable). Moreover, FtpServerHandler now makes use of entropy.tools.is_valid_md5 instead of just checking if provided strings are long 32 chars. --- libraries/entropy/transceivers.py | 81 ++++++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 7 deletions(-) diff --git a/libraries/entropy/transceivers.py b/libraries/entropy/transceivers.py index dc970341a..b63e3b81f 100644 --- a/libraries/entropy/transceivers.py +++ b/libraries/entropy/transceivers.py @@ -1111,7 +1111,8 @@ class FtpServerHandler: self.critical_files = critical_files self.handlers_data = handlers_data.copy() - def handler_verify_upload(self, local_filepath, uri, counter, maxcount, tries): + def handler_verify_upload(self, local_filepath, uri, counter, maxcount, + tries, remote_md5 = None): crippled_uri = self.entropyTools.extract_ftp_host_from_uri(uri) @@ -1130,6 +1131,68 @@ class FtpServerHandler: back = True ) + valid_remote_md5 = True + # if remote server supports MD5 commands, remote_md5 is filled + if isinstance(remote_md5, basestring): + valid_md5 = self.entropyTools.is_valid_md5(remote_md5) + ckres = False + if valid_md5: # seems valid + ckres = self.entropyTools.compare_md5(local_filepath, + remote_md5) + if ckres: + self.Entropy.updateProgress( + "[%s|#%s|(%s/%s)] %s: %s: %s" % ( + blue(crippled_uri), + darkgreen(str(tries)), + blue(str(counter)), + bold(str(maxcount)), + blue(_("digest verification")), + os.path.basename(local_filepath), + darkgreen(_("so far, so good!")), + ), + importance = 0, + type = "info", + header = red(" @@ ") + ) + return True + # ouch! + elif not valid_md5: + # mmmh... malformed md5, try with handlers + self.Entropy.updateProgress( + "[%s|#%s|(%s/%s)] %s: %s: %s" % ( + blue(crippled_uri), + darkgreen(str(tries)), + blue(str(counter)), + bold(str(maxcount)), + blue(_("digest verification")), + os.path.basename(local_filepath), + bold(_("malformed md5 provided to function")), + ), + importance = 0, + type = "warning", + header = brown(" @@ ") + ) + else: # it's really bad! + self.Entropy.updateProgress( + "[%s|#%s|(%s/%s)] %s: %s: %s" % ( + blue(crippled_uri), + darkgreen(str(tries)), + blue(str(counter)), + bold(str(maxcount)), + blue(_("digest verification")), + os.path.basename(local_filepath), + bold(_("remote md5 is invalid")), + ), + importance = 0, + type = "warning", + header = brown(" @@ ") + ) + valid_remote_md5 = False + + if not self.use_handlers: + # handlers usage is disabled + return valid_remote_md5 # always valid + checksum = self.Entropy.get_remote_package_checksum( self.repo, os.path.basename(local_filepath), @@ -1150,8 +1213,8 @@ class FtpServerHandler: type = "info", header = red(" @@ ") ) - return True - elif isinstance(checksum,bool) and not checksum: + return valid_remote_md5 + elif isinstance(checksum, bool) and not checksum: self.Entropy.updateProgress( "[%s|#%s|(%s/%s)] %s: %s: %s" % ( blue(crippled_uri), @@ -1167,7 +1230,7 @@ class FtpServerHandler: header = brown(" @@ ") ) return False - elif len(checksum) == 32: + elif self.entropyTools.is_valid_md5(checksum): # valid? checking ckres = self.entropyTools.compare_md5(local_filepath,checksum) if ckres: @@ -1217,7 +1280,7 @@ class FtpServerHandler: type = "warning", header = brown(" @@ ") ) - return True + return valid_remote_md5 def go(self): @@ -1306,8 +1369,12 @@ class FtpServerHandler: header = red(" @@ ") ) rc = syncer(*myargs) - if rc and self.use_handlers and not self.download: - rc = self.handler_verify_upload(mypath, uri, counter, maxcount, tries) + if rc and not self.download: + # try with "SITE MD5 command first" + # proftpd's mod_md5 supports it + remote_md5 = ftp.get_file_md5(os.path.basename(mypath)) + rc = self.handler_verify_upload(mypath, uri, + counter, maxcount, tries, remote_md5 = remote_md5) if rc: self.Entropy.updateProgress( "[%s|#%s|(%s/%s)] %s %s: %s" % (