def _purge_cache(cls, *refs): folders = [] for orig_ref in refs: ref = cls._copy_reference_without_username(orig_ref) if cls.debug: dprint("Removing cache for %s" % ref) if ref in cls.remap301: del cls.remap301[ref] if ref in cls.response_cache: status, responses = cls.response_cache[ref] path_found, response = cls._get_response_from_ref(ref, responses) try: if response["getcontenttype"] == "httpd/unix-directory": if cls.debug: dprint("Found folder %s" % ref) folders.append(ref) except KeyError: pass del cls.response_cache[ref] # Remove all the cached data for anything contained in any folders that # have been removed. for folder in folders: if cls.debug: dprint("Checking folder %s" % folder) folder_url = unicode(folder) keys = cls.response_cache.keys() for ref in keys: if cls.debug: dprint("Checking cache %s" % str(ref)) ref_url = unicode(ref) if ref_url.startswith(folder_url): if cls.debug: dprint("Removing cache hit %s for deleted folder: %s" % (ref_url, folder_url)) del cls.response_cache[ref]
def get_transport(transport_key): try: t = paramiko.Transport(transport_key) except Exception, e: import traceback dprint("".join(traceback.format_exc())) raise utils.NetworkError("Failed opening %s:%s -- %s" % (transport_key[0], transport_key[1], str(e)))
def _purge_cache(cls, *refs): folders = [] for orig_ref in refs: ref = cls._copy_reference_without_username(orig_ref) if cls.debug: dprint("Removing cache for %s" % ref) if ref in cls.remap301: del cls.remap301[ref] if ref in cls.response_cache: status, responses = cls.response_cache[ref] path_found, response = cls._get_response_from_ref( ref, responses) try: if response['getcontenttype'] == "httpd/unix-directory": if cls.debug: dprint("Found folder %s" % ref) folders.append(ref) except KeyError: pass del cls.response_cache[ref] # Remove all the cached data for anything contained in any folders that # have been removed. for folder in folders: if cls.debug: dprint("Checking folder %s" % folder) folder_url = unicode(folder) keys = cls.response_cache.keys() for ref in keys: if cls.debug: dprint("Checking cache %s" % str(ref)) ref_url = unicode(ref) if ref_url.startswith(folder_url): if cls.debug: dprint("Removing cache hit %s for deleted folder: %s" % (ref_url, folder_url)) del cls.response_cache[ref]
def open(cls, ref, mode=None): ref, client = cls._get_client(ref) body = client.get(str(ref.path)) if client.response.status == 200: if cls.debug: dprint("%s: %s" % (str(ref), body)) if mode == WRITE: # write truncates fh = cls.temp_file_class(ref, cls._save_file, "") elif mode == APPEND: fh = cls.temp_file_class(ref, cls._save_file, body) fh.seek(len(body)) elif mode == READ_WRITE: # Open for read/write but don't position at end of file, i.e. "r+b" fh = cls.temp_file_class(ref, cls._save_file, body) else: fh = cls.temp_file_class(ref, None, body) return fh else: if cls.debug: dprint("%s: %s" % (str(ref), client.response.status)) raise OSError( "[Errno %d] %s: '%s'" % ( client.response.status, BaseHTTPServer.BaseHTTPRequestHandler.responses[client.response.status][0], ref, ) )
def move(cls, source, target): if cls.is_file(target): raise OSError("[Errno 20] Not a directory: '%s'" % target) ref, client = cls._get_client(source) responses = client.move(source, target) if cls.debug: dprint(client.response.status) cls._purge_cache(source, target)
def remove(cls, ref): if not cls.exists(ref): raise OSError("[Errno 17] File exists: '%s'" % ref) newref, client = cls._get_client(ref) path = str(newref.path) responses = client.delete(path) if cls.debug: dprint(client.response.status) cls._purge_cache(ref, newref)
def get_names(cls, ref): if not cls.exists(ref): raise OSError("[Errno 2] No such file or directory: '%s'" % ref) if not cls.is_folder(ref): raise OSError("[Errno 20] Not a directory: '%s'" % ref) client = cls._get_client(ref) filenames = client.listdir(str(ref.path)) if cls.debug: dprint(filenames) return filenames
def make_folder(cls, ref): if cls.exists(ref): if cls.is_folder(ref): return raise OSError("[Errno 20] Not a directory: '%s'" % ref) parent = utils.get_dirname(ref) if not cls.exists(parent): raise OSError("[Errno 2] No such file or directory: '%s'" % parent) if not cls.is_folder(parent): raise OSError("[Errno 20] Not a directory: '%s'" % parent) client = cls._get_client(ref) path = str(ref.path) if cls.debug: dprint(path) client.mkdir(path)
def _propfind(cls, ref): ref, client = cls._get_client(ref) if ref in cls.response_cache: status, responses = cls.response_cache[ref] if cls.debug: dprint("response_cache hit: %s" % str(ref)) else: if cls.debug: dprint("response_cache miss: %s" % str(ref)) path = str(ref.path) responses = client.propfind(path, depth=1) if client.response.status == 301: #if cls.debug: dprint(client.response.status) #if cls.debug: dprint(pp.pformat(responses)) #if cls.debug: dprint(client.response.body) match = cls.re301.search(client.response.body) if match: newpath = match.group(1) responses = client.propfind(newpath, depth=1) cls.remap301[ref] = get_reference(newpath) status = client.response.status if cls.debug: dprint("response_cache miss: storing status=%s, response=%s" % (status, responses)) if responses is not None: if cls.debug: dprint(ref) newref = cls._copy_reference_without_username(ref) cls.response_cache[newref] = (status, responses) return ref, status, responses
def _propfind(cls, ref): ref, client = cls._get_client(ref) if ref in cls.response_cache: status, responses = cls.response_cache[ref] if cls.debug: dprint("response_cache hit: %s" % str(ref)) else: if cls.debug: dprint("response_cache miss: %s" % str(ref)) path = str(ref.path) responses = client.propfind(path, depth=1) if client.response.status == 301: # if cls.debug: dprint(client.response.status) # if cls.debug: dprint(pp.pformat(responses)) # if cls.debug: dprint(client.response.body) match = cls.re301.search(client.response.body) if match: newpath = match.group(1) responses = client.propfind(newpath, depth=1) cls.remap301[ref] = get_reference(newpath) status = client.response.status if cls.debug: dprint("response_cache miss: storing status=%s, response=%s" % (status, responses)) if responses is not None: if cls.debug: dprint(ref) newref = cls._copy_reference_without_username(ref) cls.response_cache[newref] = (status, responses) return ref, status, responses
def make_folder(cls, ref): if cls.exists(ref): if cls.is_folder(ref): return raise OSError("[Errno 20] Not a directory: '%s'" % ref) parent = utils.get_dirname(ref) if not cls.is_folder(parent): raise OSError("[Errno 20] Not a directory: '%s'" % parent) ref, client = cls._get_client(ref) path = str(ref.path) if cls.debug: dprint(path) responses = client.mkcol(path) # It's also possible (but not required) the parent could be cached, so # clean out its cache as well if cls.debug: dprint(parent) cls._purge_cache(parent)
def open(cls, ref, mode=None): ref, client = cls._get_client(ref) body = client.get(str(ref.path)) if client.response.status == 200: if cls.debug: dprint("%s: %s" % (str(ref), body)) if mode == WRITE: # write truncates fh = cls.temp_file_class(ref, cls._save_file, "") elif mode == APPEND: fh = cls.temp_file_class(ref, cls._save_file, body) fh.seek(len(body)) elif mode == READ_WRITE: # Open for read/write but don't position at end of file, i.e. "r+b" fh = cls.temp_file_class(ref, cls._save_file, body) else: fh = cls.temp_file_class(ref, None, body) return fh else: if cls.debug: dprint("%s: %s" % (str(ref), client.response.status)) raise OSError( "[Errno %d] %s: '%s'" % (client.response.status, BaseHTTPServer.BaseHTTPRequestHandler. responses[client.response.status][0], ref))
def _get_client(cls, ref): client = None newref = cls._copy_root_reference_without_username(ref) if newref in cls.connection_cache: client = cls.connection_cache[newref] if cls.debug: dprint("Found cached sftp connection: %s" % client) transport = client.get_channel().get_transport() if not transport.is_active(): dprint("Cached channel closed. Opening new connection for %s" % ref) client = None if client is None: client = cls._get_sftp(ref) if cls.debug: dprint("Creating sftp connection: %s" % client) cls.connection_cache[newref] = client return client
def _password_auth(cls, transport_key, username, passwd): while True: if cls.debug: dprint("username=%s, passwd=%s" % (username, passwd)) if not passwd: if transport_key in cls.credentials: username, passwd = cls.credentials[transport_key] if cls.debug: dprint("Found cached credentials for %s" % str(transport_key)) else: callback = utils.get_authentication_callback() username, passwd = callback(transport_key[0], "sftp", None, username) if cls.debug: dprint("User entered credentials: username=%s, passwd=%s" % (username, passwd)) if username and passwd: try: t = get_transport(transport_key) t.auth_password(username=username, password=passwd) if cls.debug: dprint("Authenticated for user %s" % username) cls.credentials[transport_key] = (username, passwd) return t except paramiko.AuthenticationException: import traceback error = traceback.format_exc() dprint(error) pass if cls.debug: dprint("Failed password for user %s" % username) if transport_key in cls.credentials: del cls.credentials[transport_key] passwd = ""
def _stat(cls, ref): client = cls._get_client(ref) attrs = client.stat(str(ref.path)) if cls.debug: dprint("%s: %s" % (ref, repr(attrs))) return attrs
def _private_key_auth(cls, transport_key, username): """Attempt to authenticate to the given transport using the private keys available from the user's home directory """ callback = utils.get_authentication_callback() t = get_transport(transport_key) if not username: username = getpass.getuser() if not t.is_authenticated(): agent = paramiko.Agent() agent_keys = agent.get_keys() if len(agent_keys) > 0: for key in agent_keys: if cls.debug: dprint('Trying ssh-agent key %s' % hexlify(key.get_fingerprint())) try: t.auth_publickey(username, key) if cls.debug: dprint('... success!') break except paramiko.SSHException: if not t.is_active(): t = get_transport(transport_key) if not t.is_authenticated(): path = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa') if os.path.exists(path): if cls.debug: dprint("Trying RSA private key") try: key = paramiko.RSAKey.from_private_key_file(path) except paramiko.PasswordRequiredException: username, passwd = callback(transport_key[0], "sftp", "RSA key pass phrase", username) key = paramiko.RSAKey.from_private_key_file(path, passwd) try: t.auth_publickey(username, key) if cls.debug: dprint("RSA private key authorization successful.") except paramiko.AuthenticationException: dprint("RSA private key authorization failed.") if not t.is_active(): t = get_transport(transport_key) if not t.is_authenticated(): path = os.path.join(os.environ['HOME'], '.ssh', 'id_dsa') if os.path.exists(path): if cls.debug: dprint("Trying DSS private key") try: key = paramiko.DSSKey.from_private_key_file(path) except paramiko.PasswordRequiredException: username, passwd = callback(transport_key[0], "sftp", "DSS key pass phrase", username) key = paramiko.DSSKey.from_private_key_file(path, password) try: t.auth_publickey(username, key) if cls.debug: dprint("DSS private key authorization successful.") except paramiko.AuthenticationException: if cls.debug: dprint("DSS private key authorization failed.") if not t.is_active(): t = get_transport(transport_key) return t