[Zope-dev] Urgent code-review: code works on win2k, fails on Linux

Thomas Weholt thomas@cintra.no
Fri, 27 Oct 2000 09:19:02 +0200


I try to extend the ftp-server ( and http-server, but that works fine ) in 
Medusa/Zope to fit into a project I'm working on. The following script 
works fine under Windows2k, but it fails under Linux giving me a 
IOException when it tries to open the file I try to upload for writing. A 
ftp-client says the current working directory is "/" after login, which the 
user off course doesn't have write-access to, but I cannot seem to get the 
ftp-server to start in the right folder. I don't even know if that's the 
real problem ...

What I need is a ftp-server that receives files of a specific type ( based 
on extension) in a specific folder built from FTP_FOLDER + username. That's 
it. No listing of files, no making of folders, removing etc. It's suppose 
to plug  right into Zope or Medusa and so far everything works great, but 
only on Windows, and the final product must run on Linux.

Sorry for posting something this big, but I'm desperate.

Thanks.

Best regards,
Thomas Weholt

----- script begins ---------

# Standard modules
import sys, os, sha
sys.path.insert(0, /usr/local/Zope/ZServer/medusa/')
# Medusa modules
import asyncore, http_server, ftp_server, filesys, resolver, logger
# my/hs-modules
import my_handler

# Settings
HTTP_PORT = 1900
FTP_PORT = 1921
IP_ADDRESS = 'localhost'
INCOMING_ROOT = '/home/'
LOG_FILE = 'log.txt'
users = {'thomas':'5f50a84c1fa3bcff146405017f36aec1a10a9e38'}
fs = filesys.os_filesystem ('.')
lg = logger.file_logger (LOG_FILE)

class my_ftp_channel(ftp_server.ftp_channel):
     """A custized ftp_channel for my ftp server"""
     def __init__(self, server, conn, addr):
         ftp_server.ftp_channel.__init__(self, server, conn, addr)
         self.answer = "000 You're not allowed to do that"
     def cmd_stor (self, line, mode='wb'):
         if len (line) < 2:
             self.command_not_understood (string.join (line))
         else:
             if self.restart_position:
                 restart_position = 0
                 self.respond ('553 restart on STOR not yet supported')
                 return
             file = line[1]
             # todo: handle that type flag
             try:
                 if not os.path.splitext(file)[1] in ['.jgz','jix']:
                     self.respond("000 Cannot store that file")
                     return
             except IndexError:
                 self.respond("000 Wrong fileformat.")
                 return

             try:
                 fd = self.open (file, mode)
             except IOError, why:
                 self.respond ('553 could not open file for writing: %s' % 
(repr(why)))
                 return
             self.respond (
                 '150 Opening %s connection for %s' % (
                     self.type_map[self.current_mode],
                     file
                     )
                 )
             self.make_recv_channel (fd)
     def log (self, message):
         self.server.logger.log ( self.addr[0], '%d %s' % (self.addr[1], 
message))

     # Commands that are not allowed
     def cmd_help (self, line):
         self.respond("000 No help is available. This is an automated 
service.")
         return
     def cmd_appe (self, line):
         self.respond(self.answer)
         return
     def cmd_mkd (self, line):
         self.respond(self.answer)
         return
     def cmd_rmd (self, line):
         self.respond(self.answer)
         return
     def cmd_cwd (self, line):
         self.respond(self.answer)
         return
     def cmd_cdup (self, line):
         self.respond(self.answer)
         return
     def cdup (self, line):
         self.respond(self.answer)
         return

class my_authorizer:
     def authorize (self, channel, username, password):
         pwd = sha.new(password)
         if users.has_key(username) and users[username] == pwd.hexdigest():
             channel.read_only = 0
             fs = filesys.os_filesystem (INCOMING_ROOT + username + os.sep)
             return 1, 'Login successful.', fs
         else:
             return 0, 'Login failed.', None
     def __repr__ (self):
         return '<my User Authorizer>'

fp = ftp_server.ftp_server (my_authorizer(), ip=IP_ADDRESS, port=FTP_PORT, 
logger_object=lg)
fp.ftp_channel_class = my_ftp_channel
dh = my_handler.default_handler(fs)
hs = http_server.http_server (IP_ADDRESS, port=HTTP_PORT)
hs.install_handler (dh)
asyncore.loop()