def test_guess_digest_algorithm(self): s = 'joe' md5_digest = hashlib.md5(s).hexdigest() self.assertEquals(guess_digest_algorithm(md5_digest), 'md5') sha1_digest = hashlib.sha1(s).hexdigest() self.assertEquals(guess_digest_algorithm(sha1_digest), 'sha1') # For now only md5 and sha1 are supported sha256_digest = hashlib.sha256(s).hexdigest() try: guess_digest_algorithm(sha256_digest) self.fail('Other algorithms than md5 and sha1 should not be supported for now') except: pass
def is_equal_digests( self, local_digest, remote_digest, local_path, remote_digest_algorithm=None, ): # type: (Text, Text, Text, Optional[Text]) -> bool """ Compare 2 document's digests. :param str local_digest: Digest of the local document. Set to None to force digest computation. :param str remote_digest: Digest of the remote document. :param str local_path: Local path of the document. :param str remote_digest_algorithm: Remote document digest algorithm :return bool: Digest are equals. """ if local_digest == remote_digest: return True if remote_digest_algorithm is None: remote_digest_algorithm = guess_digest_algorithm(remote_digest) if remote_digest_algorithm == self._digest_func: return False file_info = self.get_info(local_path) digest = file_info.get_digest(digest_func=remote_digest_algorithm) return digest == remote_digest
def is_equal_digests(self, local_digest, remote_digest, local_path, remote_digest_algorithm=None): if local_digest == remote_digest: return True if remote_digest_algorithm is None: remote_digest_algorithm = guess_digest_algorithm(remote_digest) if remote_digest_algorithm == self._digest_func: return False else: return self.get_info(local_path).get_digest(digest_func=remote_digest_algorithm) == remote_digest
def _prepare_edit(self, server_url, doc_id, user=None, download_url=None): engine = self._get_engine(server_url, user=user) if engine is None: values = dict() values['user'] = user values['server'] = server_url log.warn("No engine found for %s(%s)", server_url, doc_id) self._display_modal("DIRECT_EDIT_CANT_FIND_ENGINE", values) return # Get document info remote_client = engine.get_remote_doc_client() # Avoid any link with the engine, remote_doc are not cached so we can do that remote_client.check_suspended = self.stop_client info = remote_client.get_info(doc_id) filename = info.filename # Create local structure dir_path = os.path.join(self._folder, doc_id) if not os.path.exists(dir_path): os.mkdir(dir_path) log.debug("Editing %r", filename) file_path = os.path.join(dir_path, filename) # Download the file url = None if download_url is not None: url = server_url if not url.endswith('/'): url += '/' url += download_url tmp_file = self._download_content(engine, remote_client, info, file_path, url=url) if tmp_file is None: log.debug("Download failed") return # Set the remote_id dir_path = self._local_client.get_path(os.path.dirname(file_path)) self._local_client.set_remote_id(dir_path, doc_id) self._local_client.set_remote_id(dir_path, server_url, "nxdriveedit") if user is not None: self._local_client.set_remote_id(dir_path, user, "nxdriveedituser") if info.digest is not None: self._local_client.set_remote_id(dir_path, info.digest, "nxdriveeditdigest") # Set digest algorithm if not sent by the server digest_algorithm = info.digest_algorithm if digest_algorithm is None: digest_algorithm = guess_digest_algorithm(info.digest) self._local_client.set_remote_id(dir_path, digest_algorithm, "nxdriveeditdigestalgorithm") self._local_client.set_remote_id(dir_path, filename, "nxdriveeditname") # Rename to final filename # Under Windows first need to delete target file if exists, otherwise will get a 183 WindowsError if sys.platform == 'win32' and os.path.exists(file_path): os.unlink(file_path) os.rename(tmp_file, file_path) return file_path
def is_equal_digests(self, local_digest, remote_digest, local_path, remote_digest_algorithm=None): if local_digest == remote_digest: return True if remote_digest_algorithm is None: remote_digest_algorithm = guess_digest_algorithm(remote_digest) if remote_digest_algorithm == self._digest_func: return False else: return self.get_info(local_path).get_digest( digest_func=remote_digest_algorithm) == remote_digest
def _prepare_edit(self, server_url, doc_id, user=None, download_url=None): start_time = current_milli_time() engine = self._get_engine(server_url, user=user) if engine is None: values = dict() if user is None: values['user'] = '******' else: values['user'] = user values['server'] = server_url log.warn("No engine found for server_url=%s, user=%s, doc_id=%s", server_url, user, doc_id) self._display_modal("DIRECT_EDIT_CANT_FIND_ENGINE", values) return # Get document info remote_client = engine.get_remote_doc_client() # Avoid any link with the engine, remote_doc are not cached so we can do that remote_client.check_suspended = self.stop_client info = remote_client.get_info(doc_id) filename = info.filename # Create local structure dir_path = os.path.join(self._folder, doc_id) if not os.path.exists(dir_path): os.mkdir(dir_path) log.debug("Editing %r", filename) file_path = os.path.join(dir_path, filename) # Download the file url = None if download_url is not None: url = server_url if not url.endswith('/'): url += '/' url += download_url tmp_file = self._download_content(engine, remote_client, info, file_path, url=url) if tmp_file is None: log.debug("Download failed") return # Set the remote_id dir_path = self._local_client.get_path(os.path.dirname(file_path)) self._local_client.set_remote_id(dir_path, doc_id) self._local_client.set_remote_id(dir_path, server_url, "nxdirectedit") if user is not None: self._local_client.set_remote_id(dir_path, user, "nxdirectedituser") if info.digest is not None: self._local_client.set_remote_id(dir_path, info.digest, "nxdirecteditdigest") # Set digest algorithm if not sent by the server digest_algorithm = info.digest_algorithm if digest_algorithm is None: digest_algorithm = guess_digest_algorithm(info.digest) self._local_client.set_remote_id(dir_path, digest_algorithm, "nxdirecteditdigestalgorithm") self._local_client.set_remote_id(dir_path, filename, "nxdirecteditname") # Rename to final filename # Under Windows first need to delete target file if exists, otherwise will get a 183 WindowsError if sys.platform == 'win32' and os.path.exists(file_path): os.unlink(file_path) os.rename(tmp_file, file_path) self._last_action_timing = current_milli_time() - start_time self.openDocument.emit(info) return file_path
def do_get(self, url, file_out=None, digest=None, digest_algorithm=None): log.trace( 'Downloading file from %r to %r with digest=%s, digest_algorithm=%s', url, file_out, digest, digest_algorithm) h = None if digest is not None: if digest_algorithm is None: digest_algorithm = guess_digest_algorithm(digest) log.trace('Guessed digest algorithm from digest: %s', digest_algorithm) digester = getattr(hashlib, digest_algorithm, None) if digester is None: raise ValueError('Unknow digest method: ' + digest_algorithm) h = digester() headers = self._get_common_headers() base_error_message = ( "Failed to connect to Nuxeo server %r with user %r") % ( self.server_url, self.user_id) try: log.trace("Calling '%s' with headers: %r", url, headers) req = urllib2.Request(url, headers=headers) response = self.opener.open(req, timeout=self.blob_timeout) current_action = Action.get_current_action() # Get the size file if (current_action and response is not None and response.info() is not None): current_action.size = int(response.info().getheader( 'Content-Length', 0)) if file_out is not None: locker = self.unlock_path(file_out) try: with open(file_out, "wb") as f: while True: # Check if synchronization thread was suspended if self.check_suspended is not None: self.check_suspended('File download: %s' % file_out) buffer_ = response.read(self.get_download_buffer()) if buffer_ == '': break if current_action: current_action.progress += ( self.get_download_buffer()) f.write(buffer_) if h is not None: h.update(buffer_) if digest is not None: actual_digest = h.hexdigest() if digest != actual_digest: if os.path.exists(file_out): os.remove(file_out) raise CorruptedFile( "Corrupted file %r: expected digest = %s, actual digest = %s" % (file_out, digest, actual_digest)) return None, file_out finally: self.lock_path(file_out, locker) else: result = response.read() if h is not None: h.update(result) if digest is not None: actual_digest = h.hexdigest() if digest != actual_digest: raise CorruptedFile( "Corrupted file: expected digest = %s, actual digest = %s" % (digest, actual_digest)) return result, None except urllib2.HTTPError as e: if e.code == 401 or e.code == 403: raise Unauthorized(self.server_url, self.user_id, e.code) else: e.msg = base_error_message + ": HTTP error %d" % e.code raise e except Exception as e: if hasattr(e, 'msg'): e.msg = base_error_message + ": " + e.msg raise
def do_get(self, url, file_out=None, digest=None, digest_algorithm=None): h = None if digest is not None: if digest_algorithm is None: digest_algorithm = guess_digest_algorithm(digest) digester = getattr(hashlib, digest_algorithm, None) if digester is None: raise ValueError('Unknow digest method: ' + digest_algorithm) h = digester() headers = self._get_common_headers() base_error_message = ( "Failed to connect to Nuxeo server %r with user %r" ) % (self.server_url, self.user_id) try: log.trace("Calling '%s' with headers: %r", url, headers) req = urllib2.Request(url, headers=headers) response = self.opener.open(req, timeout=self.blob_timeout) current_action = Action.get_current_action() # Get the size file if (current_action and response is not None and response.info() is not None): current_action.size = int(response.info().getheader( 'Content-Length', 0)) if file_out is not None: locker = self.unlock_path(file_out) try: with open(file_out, "wb") as f: while True: # Check if synchronization thread was suspended if self.check_suspended is not None: self.check_suspended('File download: %s' % file_out) buffer_ = response.read(self.get_download_buffer()) if buffer_ == '': break if current_action: current_action.progress += ( self.get_download_buffer()) f.write(buffer_) if h is not None: h.update(buffer_) if self._remote_error is not None: # Simulate a configurable remote (e.g. network or # server) error for the tests raise self._remote_error if self._local_error is not None: # Simulate a configurable local error (e.g. "No # space left on device") for the tests raise self._local_error if digest is not None and digest != h.hexdigest(): if os.path.exists(file_out): os.remove(file_out) raise CorruptedFile("Corrupted file") return None, file_out finally: self.lock_path(file_out, locker) else: result = response.read() if h is not None: h.update(result) if digest is not None and digest != h.hexdigest(): raise CorruptedFile("Corrupted file") return result, None except urllib2.HTTPError as e: if e.code == 401 or e.code == 403: raise Unauthorized(self.server_url, self.user_id, e.code) else: e.msg = base_error_message + ": HTTP error %d" % e.code raise e except Exception as e: if hasattr(e, 'msg'): e.msg = base_error_message + ": " + e.msg raise
def _prepare_edit(self, server_url, doc_id, user=None, download_url=None): start_time = current_milli_time() engine = self._get_engine(server_url, user=user) if engine is None: values = dict() values['user'] = str(user) values['server'] = server_url log.warning( 'No engine found for server_url=%s, user=%s, doc_id=%s', server_url, user, doc_id) self._display_modal('DIRECT_EDIT_CANT_FIND_ENGINE', values) return None # Get document info remote_client = engine.get_remote_doc_client() # Avoid any link with the engine, remote_doc are not cached so we can do that remote_client.check_suspended = self.stop_client doc = remote_client.fetch( doc_id, extra_headers={'fetch-document': 'lock'}, enrichers=['permissions'], ) info = remote_client.doc_to_info(doc, fetch_parent_uid=False) if info.lock_owner is not None and info.lock_owner != engine.remote_user: log.debug( "Doc %s was locked by %s on %s, won't download it for edit", info.name, info.lock_owner, info.lock_created) self.directEditLocked.emit(info.name, info.lock_owner, info.lock_created) return None if info.permissions is not None and 'Write' not in info.permissions: log.debug("Doc %s is readonly for %s, won't download it for edit", info.name, user) self.directEditReadonly.emit(info.name) return None filename = info.filename # Create local structure dir_path = os.path.join(self._folder, doc_id) if not os.path.exists(dir_path): os.mkdir(dir_path) log.debug("Editing %r", filename) file_path = os.path.join(dir_path, filename) # Download the file url = None if download_url is not None: url = server_url if not url.endswith('/'): url += '/' url += download_url tmp_file = self._download_content(engine, remote_client, info, file_path, url=url) if tmp_file is None: log.debug("Download failed") return None # Set the remote_id dir_path = self._local_client.get_path(os.path.dirname(file_path)) self._local_client.set_remote_id(dir_path, doc_id) self._local_client.set_remote_id(dir_path, server_url, "nxdirectedit") if user is not None: self._local_client.set_remote_id(dir_path, user, "nxdirectedituser") if info.digest is not None: self._local_client.set_remote_id(dir_path, info.digest, "nxdirecteditdigest") # Set digest algorithm if not sent by the server digest_algorithm = info.digest_algorithm if digest_algorithm is None: digest_algorithm = guess_digest_algorithm(info.digest) self._local_client.set_remote_id(dir_path, digest_algorithm, "nxdirecteditdigestalgorithm") self._local_client.set_remote_id(dir_path, filename, "nxdirecteditname") # Rename to final filename # Under Windows first need to delete target file if exists, otherwise will get a 183 WindowsError if sys.platform == 'win32' and os.path.exists(file_path): os.unlink(file_path) os.rename(tmp_file, file_path) self._last_action_timing = current_milli_time() - start_time self.openDocument.emit(info) return file_path
def _prepare_edit(self, server_url, doc_id, user=None, download_url=None): start_time = current_milli_time() engine = self._get_engine(server_url, user=user) if engine is None: values = dict() values['user'] = str(user) values['server'] = server_url log.warning('No engine found for server_url=%s, user=%s, doc_id=%s', server_url, user, doc_id) self._display_modal('DIRECT_EDIT_CANT_FIND_ENGINE', values) return None # Get document info remote_client = engine.get_remote_doc_client() # Avoid any link with the engine, remote_doc are not cached so we can do that remote_client.check_suspended = self.stop_client doc = remote_client.fetch( doc_id, extra_headers={'fetch-document': 'lock'}, enrichers=['permissions'], ) info = remote_client.doc_to_info(doc, fetch_parent_uid=False) if info.lock_owner is not None and info.lock_owner != engine.remote_user: log.debug("Doc %s was locked by %s on %s, won't download it for edit", info.name, info.lock_owner, info.lock_created) self.directEditLocked.emit(info.name, info.lock_owner, info.lock_created) return None if info.permissions is not None and 'Write' not in info.permissions: log.debug("Doc %s is readonly for %s, won't download it for edit", info.name, user) self.directEditReadonly.emit(info.name) return None filename = info.filename # Create local structure dir_path = os.path.join(self._folder, doc_id) if not os.path.exists(dir_path): os.mkdir(dir_path) log.debug("Editing %r", filename) file_path = os.path.join(dir_path, filename) # Download the file url = None if download_url is not None: url = server_url if not url.endswith('/'): url += '/' url += download_url tmp_file = self._download_content(engine, remote_client, info, file_path, url=url) if tmp_file is None: log.debug("Download failed") return None # Set the remote_id dir_path = self._local_client.get_path(os.path.dirname(file_path)) self._local_client.set_remote_id(dir_path, doc_id) self._local_client.set_remote_id(dir_path, server_url, "nxdirectedit") if user is not None: self._local_client.set_remote_id(dir_path, user, "nxdirectedituser") if info.digest is not None: self._local_client.set_remote_id(dir_path, info.digest, "nxdirecteditdigest") # Set digest algorithm if not sent by the server digest_algorithm = info.digest_algorithm if digest_algorithm is None: digest_algorithm = guess_digest_algorithm(info.digest) self._local_client.set_remote_id(dir_path, digest_algorithm, "nxdirecteditdigestalgorithm") self._local_client.set_remote_id(dir_path, filename, "nxdirecteditname") # Rename to final filename # Under Windows first need to delete target file if exists, otherwise will get a 183 WindowsError if sys.platform == 'win32' and os.path.exists(file_path): os.unlink(file_path) os.rename(tmp_file, file_path) self._last_action_timing = current_milli_time() - start_time self.openDocument.emit(info) return file_path
def do_get(self, url, file_out=None, digest=None, digest_algorithm=None): log.trace('Downloading file from %r to %r with digest=%s, digest_algorithm=%s', url, file_out, digest, digest_algorithm) h = None if digest is not None: if digest_algorithm is None: digest_algorithm = guess_digest_algorithm(digest) log.trace('Guessed digest algorithm from digest: %s', digest_algorithm) digester = getattr(hashlib, digest_algorithm, None) if digester is None: raise ValueError('Unknow digest method: ' + digest_algorithm) h = digester() headers = self._get_common_headers() base_error_message = ( "Failed to connect to Nuxeo server %r with user %r" ) % (self.server_url, self.user_id) try: log.trace("Calling '%s' with headers: %r", url, headers) req = urllib2.Request(url, headers=headers) response = self.opener.open(req, timeout=self.blob_timeout) current_action = Action.get_current_action() # Get the size file if (current_action and response is not None and response.info() is not None): current_action.size = int(response.info().getheader( 'Content-Length', 0)) if file_out is not None: locker = self.unlock_path(file_out) try: with open(file_out, "wb") as f: while True: # Check if synchronization thread was suspended if self.check_suspended is not None: self.check_suspended('File download: %s' % file_out) buffer_ = response.read(FILE_BUFFER_SIZE) if buffer_ == '': break if current_action: current_action.progress += FILE_BUFFER_SIZE f.write(buffer_) if h is not None: h.update(buffer_) if digest is not None: actual_digest = h.hexdigest() if digest != actual_digest: if os.path.exists(file_out): os.remove(file_out) raise CorruptedFile("Corrupted file %r: expected digest = %s, actual digest = %s" % (file_out, digest, actual_digest)) return None, file_out finally: self.lock_path(file_out, locker) else: result = response.read() if h is not None: h.update(result) if digest is not None: actual_digest = h.hexdigest() if digest != actual_digest: raise CorruptedFile("Corrupted file: expected digest = %s, actual digest = %s" % (digest, actual_digest)) return result, None except urllib2.HTTPError as e: if e.code == 401 or e.code == 403: raise Unauthorized(self.server_url, self.user_id, e.code) else: e.msg = base_error_message + ": HTTP error %d" % e.code raise e except Exception as e: if hasattr(e, 'msg'): e.msg = base_error_message + ": " + e.msg raise
def _prepare_edit(self, server_url, doc_id, filename, user=None, download_url=None): engine = self._get_engine(server_url, user=user) if engine is None: # TO_REVIEW Display an error message log.debug("No engine found for %s(%s)", server_url, doc_id) return # Get document info remote_client = engine.get_remote_doc_client() # Avoid any link with the engine, remote_doc are not cached so we can do that remote_client.check_suspended = self.stop_client info = remote_client.get_info(doc_id) # Create local structure dir_path = os.path.join(self._folder, doc_id) if not os.path.exists(dir_path): os.mkdir(dir_path) log.trace('Raw filename: %r', filename) filename = safe_filename(urllib2.unquote(filename)) log.trace('Unquoted filename = %r', filename) decoded_filename = force_decode(filename) if decoded_filename is None: decoded_filename = filename else: # Always use utf-8 encoding for xattr filename = decoded_filename.encode('utf-8') log.debug("Editing %r ('nxdriveeditname' xattr: %r)", decoded_filename, filename) file_path = os.path.join(dir_path, decoded_filename) # Download the file url = None if download_url is not None: url = server_url if not url.endswith('/'): url += '/' url += download_url tmp_file = self._download_content(engine, remote_client, info, file_path, url=url) if tmp_file is None: log.debug("Download failed") return # Set the remote_id dir_path = self._local_client.get_path(os.path.dirname(file_path)) self._local_client.set_remote_id(dir_path, doc_id) self._local_client.set_remote_id(dir_path, server_url, "nxdriveedit") if user is not None: self._local_client.set_remote_id(dir_path, user, "nxdriveedituser") if info.digest is not None: self._local_client.set_remote_id(dir_path, info.digest, "nxdriveeditdigest") # Set digest algorithm if not sent by the server digest_algorithm = info.digest_algorithm if digest_algorithm is None: digest_algorithm = guess_digest_algorithm(info.digest) self._local_client.set_remote_id(dir_path, digest_algorithm, "nxdriveeditdigestalgorithm") self._local_client.set_remote_id(dir_path, filename, "nxdriveeditname") # Rename to final filename # Under Windows first need to delete target file if exists, otherwise will get a 183 WindowsError if sys.platform == 'win32' and os.path.exists(file_path): os.unlink(file_path) os.rename(tmp_file, file_path) return file_path