diff --git a/src/calibre/__init__.py b/src/calibre/__init__.py index f747c756f3..bae748eacd 100644 --- a/src/calibre/__init__.py +++ b/src/calibre/__init__.py @@ -1,7 +1,7 @@ ''' E-book management software''' __license__ = 'GPL v3' __copyright__ = '2008, Kovid Goyal ' -__version__ = '0.4.65' +__version__ = '0.4.66' __docformat__ = "epytext" __author__ = "Kovid Goyal " __appname__ = 'calibre' diff --git a/src/calibre/gui2/dialogs/user_profiles.py b/src/calibre/gui2/dialogs/user_profiles.py index 9976d2180c..09c4c971bf 100644 --- a/src/calibre/gui2/dialogs/user_profiles.py +++ b/src/calibre/gui2/dialogs/user_profiles.py @@ -186,7 +186,6 @@ class %(classname)s(%(base_class)s): files = choose_files(self, 'recipe loader dialog', _('Choose a recipe file'), filters=[(_('Recipes'), '*.py')], all_files=False, select_only_single_file=True) if files: file = files[0] - raise Exception('a') try: src = open(file, 'rb').read().decode('utf-8') title = compile_recipe(src).title diff --git a/src/calibre/utils/sftp.py b/src/calibre/utils/sftp.py new file mode 100644 index 0000000000..49613991b3 --- /dev/null +++ b/src/calibre/utils/sftp.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python +__license__ = 'GPL v3' +__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net' +__docformat__ = 'restructuredtext en' + +''' +Create a file handle to a remote file over the sftp protocol. +''' + +import sys, socket, getpass +from urlparse import urlparse +from binascii import hexlify + +import paramiko + +def agent_auth(transport, username): + """ + Attempt to authenticate to the given transport using any of the private + keys available from an SSH agent. + """ + + agent = paramiko.Agent() + agent_keys = agent.get_keys() + if len(agent_keys) == 0: + return + + for key in agent_keys: + print 'Trying ssh-agent key %s' % hexlify(key.get_fingerprint()), + try: + transport.auth_publickey(username, key) + print '... success!' + return True + except paramiko.SSHException: + print '... failed.' + return False + +def portable_getpass(username, hostname, retry): + return getpass.getpass('%sPlease enter the password for %s on %s: '%( + 'Incorrect password. ' if retry else '', username, hostname)) + +def password_auth(transport, username, hostname, getpw=portable_getpass): + for i in range(3): + pw = getpw(username, hostname, i>0) + transport.auth_password(username, pw) + if transport.is_authenticated(): + return True + return False + + +def connect_to_url(url, getpw=portable_getpass, mode='r+', bufsize=-1): + protocol, host, path = urlparse(url)[:3] + if protocol != 'sftp': + raise ValueError(_('URL must have the scheme sftp')) + try: + username, host = host.split('@') + except: + raise ValueError(_('host must be of the form user@hostname')) + port = 22 + if ':' in host: + host, port = host.split(':') + port = int(port) + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((host, port)) + t = paramiko.Transport(sock) + try: + t.start_client() + except: + raise Exception(_('Failed to negotiate SSH session: ') + str(t.get_exception())) + if not agent_auth(t, username): + if not password_auth(t, username, host, getpw): + raise ValueError(_('Failed to authenticate with server: %s'%url)) + sftp = paramiko.SFTPClient.from_transport(t) + return sftp, sftp.open(path, mode=mode, bufsize=bufsize) + + +def main(args=sys.argv): + f = connect_to_url(args[1])[-1] + print f.read() + f.seek(0, 2) + print f.tell() + f.close() + return 0 + +if __name__ == '__main__': + sys.exit(main()) \ No newline at end of file