"""Handle FTP links""" # Copyright (C) 2000,2001 Bastian Kleineidam # # 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 of the License, 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., 675 Mass Ave, Cambridge, MA 02139, USA. import ftplib, i18n from linkcheck import Config, error, extensions, debug from urllib import splitpasswd from ProxyUrlData import ProxyUrlData from HttpUrlData import HttpUrlData from UrlData import ExcList ExcList.extend([ ftplib.error_reply, ftplib.error_temp, ftplib.error_perm, ftplib.error_proto, ]) class FtpUrlData (ProxyUrlData): """ Url link with ftp scheme. """ def checkConnection (self): # proxy support (we support only http) self.setProxy(self.config["proxy"].get(self.scheme)) if self.proxy: http = HttpUrlData(self.urlName, self.recursionLevel, self.config, parentName=self.parentName, baseRef=self.baseRef, line=self.line, column=self.column, name=self.name) http.buildUrl() return http.check() # using no proxy here # get login credentials if self.userinfo: _user, _password = splitpasswd(self.userinfo) else: _user, _password = self.getUserPassword() if _user is None or _password is None: raise error, i18n._("No user or password found") self.login(_user, _password) filename = self.cwd() if filename: self.retrieve(filename) return None def isHtml (self): # guess by extension for ro in extensions.values(): if ro.search(self.url): return 1 return None def parseUrl (self): for key,ro in extensions.items(): if ro.search(self.url): return getattr(self, "parse_"+key)() return None def login (self, _user, _password): """log into ftp server and check the welcome message""" # ready to connect try: self.urlConnection = ftplib.FTP() self.urlConnection.set_debuglevel(debug.DebugLevel) self.urlConnection.connect(self.urlparts[1]) self.urlConnection.login(_user, _password) except EOFError: raise error, i18n._("Remote host has closed connection") if not self.urlConnection.getwelcome(): self.closeConnection() raise error, i18n._("Got no answer from FTP server") # dont set info anymore, this may change every time we logged in #self.setInfo(info) def cwd (self): """change directory to given path""" # leeched from webcheck dirs = self.urlparts[2].split('/') filename = dirs.pop() if len(dirs) and not dirs[0]: del dirs[0] for d in dirs: self.urlConnection.cwd(d) return filename def retrieve (self, filename): """initiate download of given filename""" # it could be a directory if the trailing slash was forgotten try: self.urlConnection.cwd(filename) self.setWarning(i18n._("Missing trailing directory slash in ftp url")) return except ftplib.error_perm: pass self.urlConnection.voidcmd('TYPE I') conn, size = self.urlConnection.ntransfercmd('RETR %s'%filename) if size: self.dlsize = size # dont download data XXX recursion #page = conn.makefile().read(size) #else: # page = conn.makefile().read() def closeConnection (self): try: self.urlConnection.closet() except: pass self.urlConnection = None