# This software and supporting documentation are distributed by
# Institut Federatif de Recherche 49
# CEA/NeuroSpin, Batiment 145,
# 91191 Gif-sur-Yvette cedex
# France
#
# This software is governed by the CeCILL license version 2 under
# French law and abiding by the rules of distribution of free software.
# You can use, modify and/or redistribute the software under the
# terms of the CeCILL license version 2 as circulated by CEA, CNRS
# and INRIA at the following URL "http://www.cecill.info".
#
# As a counterpart to the access to the source code and rights to copy,
# modify and redistribute granted by the license, users are provided only
# with a limited warranty and the software's author, the holder of the
# economic rights, and the successive licensors have only limited
# liability.
#
# In this respect, the user's attention is drawn to the risks associated
# with loading, using, modifying and/or developing or reproducing the
# software by the user in light of its specific status of free software,
# that may mean that it is complicated to manipulate, and that also
# therefore means that it is reserved for developers and experienced
# professionals having in-depth computer knowledge. Users are therefore
# encouraged to load and test the software's suitability as regards their
# requirements in conditions enabling the security of their systems and/or
# data to be ensured and, more generally, to use and operate it in the
# same conditions as regards security.
#
# The fact that you are presently reading this means that you have had
# knowledge of the CeCILL license version 2 and that you accept its terms.
import re
import ftplib
from brainvisa.data import virtualDirectory
class Splitter(object):
re = re.compile('([^ ]*)([ ]*)([^ ]?.*)')
def __init__(self, s):
self.s = s
def get(self):
if self.s:
match = self.re.match(self.s)
if match is None:
raise RuntimeError('No match !')
else:
result = match.group(1, 2)
self.s = match.group(3)
else:
result = None
return result
class EnhancedFTP(object):
class Item(object):
def __init__(self, ftpDirString, parentName):
splitter = Splitter(ftpDirString)
self.flags = splitter.get()[0]
splitter.get()
self.user = splitter.get()[0]
self.group = splitter.get()[0]
self.size = int(splitter.get()[0])
self.date = ' '.join(
(splitter.get()[0], splitter.get()[0], splitter.get()[0]))
if self.flags[0] == 'l':
self.name = splitter.s.split(' -> ')[0]
else:
self.name = splitter.s
self.fullName = parentName + '/' + self.name
self.isDirectory = self.flags[0] == 'd'
class __Reader(object):
def __init__(self, ftp, socket, bufferSize):
self.__ftp = ftp
self.__socket = socket
self.__bufferSize = bufferSize
def __del__(self):
self.close()
def read(self, bufferSize):
result = ''
while len(result) < bufferSize:
data = self.__socket.recv(bufferSize - len(result))
if not data:
break
result += data
return result
def close(self):
if self.__socket is not None:
self.__socket.close()
self.__ftp.voidresp()
self.__socket = None
def __init__(self, host, login, password):
self._ftp = None
self.host = host
self.login = login
self.password = password
def __del__(self):
self._disconnect()
def _connect(self):
if self._ftp is None:
self._ftp = ftplib.FTP(self.host)
# self._ftp.set_pasv( False )
self._ftp.login(self.login, self.password)
def _disconnect(self):
if self._ftp is not None:
self._ftp.quit()
self._ftp = None
def ls(self, directory=None):
self._connect()
if directory is not None:
self._ftp.cwd(directory)
try:
l = self._ftp.nlst()
except ftplib.error_perm as e:
if e.args[0][:3] == '550':
# Error thrown when directory is empty
l = []
else:
raise
return result
def dir(self, directory):
self._connect()
if directory is not None:
self._ftp.cwd(directory)
self._dir = []
self._ftp.dir(self._buildDir)
self._disconnect()
result = self._dir[1:] # Suppress 'total ...' line
del self._dir
return [self.Item(x, directory) for x in result]
def getItem(self, path):
i = path.rfind('/')
parent = path[: i]
me = path[i + 1:]
for item in self.dir(parent):
if item.name == me:
return item
return None
def getReader(self, fileName, bufferSize=None):
self._connect()
self._ftp.voidcmd('TYPE I')
sock = self._ftp.transfercmd('RETR ' + fileName)
return self.__Reader(self._ftp, sock, bufferSize)
# result = sock.makefile( 'rb', bufferSize )
# sock.close()
# self._ftp.voidresp()
# return result
def retrieve(self, fileName, destination, progressFunction=None):
self._connect()
self._output = open(destination, 'wb')
self._progressFunction = progressFunction
self._ftp.retrbinary('RETR ' + fileName, self._download)
self._output.close()
del self._output
del self._progressFunction
def _download(self, data):
self._output.write(data)
self._output.flush()
if self._progressFunction:
self._progressFunction(data)
def _buildDir(self, line):
self._dir.append(line)
[docs]
class FTPDirectory(virtualDirectory.VirtualDirectory):
[docs]
class Item(virtualDirectory.VirtualDirectory.Item):
def __init__(self, s, ftp, path):
virtualDirectory.VirtualDirectory.Item.__init__(self, s)
self.__ftp = ftp
if isinstance(path, EnhancedFTP.Item):
self.__path = path.fullName
self.__item = path
else:
self.__path = str(path)
self.__item = None
def __getItem(self):
if self.__item is None:
self.__item = self.__ftp.getItem(self.__path)
[docs]
def size(self):
self.__getItem()
if self.__item is not None and not self.__item.isDirectory:
return self.__item.size
return None
[docs]
def reader(self):
return self.__ftp.getReader(self.__path)
[docs]
def hasChildren(self):
self.__getItem()
return self.__item.isDirectory
[docs]
def children(self):
result = []
for item in self.__ftp.dir(self.__path):
result.append(
FTPDirectory.Item(self.virtualDirectory, self.__ftp, item))
return result
[docs]
def name(self):
if self.__item is None:
return self.__path[self.__path.rfind('/') + 1:]
return self.__item.name
[docs]
def fullName(self):
if self.virtualDirectory:
return self.virtualDirectory._FTPDirectory__binIdFromPath(self.__path)
return self.__path
[docs]
def parentFullName(self):
index = self.__path.rfind('/')
if index >= 0:
return self.__path[:index]
return ''
def __init__(self, name, server, login, password, baseDirectory='/'):
virtualDirectory.VirtualDirectory.__init__(self)
self.__name = name
self.__ftp = EnhancedFTP(server, login, password)
self.__baseDirectory = baseDirectory
def __pathFromBinId(self, binId):
if binId:
if self.__baseDirectory == '/':
base = ''
else:
base = self.__baseDirectory
if binId[0] == '/':
return base + '/' + binId[1:]
return base + '/' + binId
else:
return self.__baseDirectory
def __binIdFromPath(self, path):
if self.__baseDirectory == '/':
return path[1:]
else:
return path[len(self.__baseDirectory) + 1:]
[docs]
def get(self, binId):
return self.Item(self, self.__ftp, self.__pathFromBinId(binId))
[docs]
def name(self):
return self.__name