def downloadSecureFile(conf, api: B2Api, fileId, destination): tempPath = security.getTempPath(destination) dest = DownloadDestLocalFile(tempPath) api.download_file_by_id(fileId, dest) security.decompressAndDecrypt(conf, tempPath, destination) util.silentRemove(tempPath) log.info(f"Downloaded secure file: '{fileId}' to '{destination}'") return 0
def decompressAndDecrypt(conf, path, destination): gpg = __getGpg(conf) computeHash = False util.silentRemove(destination) with open(path, 'rb') as fin: with open(destination, 'wb') as fout: with gpg.openDecryptStream(fin, conf.args.passphrase) as din: with GzipDecompressStream(din) as gzip: with HashStream(gzip) as hin: hin = hin if computeHash else gzip shutil.copyfileobj(hin, fout)
def compressAndEncryptWithHash(conf, filename, computeHash=True): gpg = __getGpg(conf) tempPath = getTempPath(filename) util.silentRemove(tempPath) with open(filename, 'rb') as fin: with open(tempPath, 'wb') as fout: with HashStream(fin) as hin: hin = hin if computeHash else fin with GzipCompressStream(hin) as gzip: with gpg.openEncryptStream(gzip, conf.GPGRecipient, compress=False) as ein: shutil.copyfileobj(ein, fout) hashDigest = hin.hexdigest() if computeHash else None return tempPath, hashDigest
def uploadSecureFile(conf, bucket: Bucket, filepath, saveModTime=False, customName=None): name = customName if customName else filepath if saveModTime: fileInfo = {SRC_LAST_MODIFIED_MILLIS: str(util.getModTime(filepath))} else: fileInfo = None tempPath = security.compressAndEncrypt(conf, filepath) secureName = security.generateSecureName(conf, name) uploadSource = UploadSourceLocalFile(tempPath) fileVersionInfo = bucket.upload(uploadSource, secureName, file_info=fileInfo) util.silentRemove(tempPath) log.info(f"Uploaded secure file: '{filepath}' to '{fileVersionInfo.id_}'") return fileVersionInfo
def do_action(self, remoteFolder, conf, reporter): parentDir = os.path.dirname(self.localPath) util.checkDirectory(parentDir) if self.remoteFile.isDir: util.checkDirectory(self.localPath) elif conf.args.test: util.silentRemove(self.localPath) open(self.localPath, 'a').close() else: # Download the file to a .tmp file downloadPath = self.localPath + util.APPLICATION_EXT destination = DownloadDestLocalFile(downloadPath) remoteFolder.bucket.download_file_by_name( self.remoteFile.nativePath, destination, SyncFileReporter(reporter)) security.decompressAndDecrypt(conf, downloadPath, self.localPath) util.silentRemove(downloadPath) modTime = self.remoteFile.latest_version().mod_time / 1000.0 os.utime(self.localPath, (modTime, modTime))
def do_action(self, remoteFolder, conf, reporter): sf = self.sourceFile ent = IndexEntry(path=sf.relativePath, isDir=sf.isDir, size=sf.latest_version().size, modTime=sf.latest_version().mod_time, hash=None, remoteId=None, remoteName=None) if not sf.isDir and not conf.args.testIndex: b2Name = security.generateSecureName(conf, sf.relativePath) resume = False getHash = sf.latest_version().hash is None # check if we need to resume a large file upload if os.path.exists(security.getTempPath(sf.nativePath)): log.info('Found temp file for: ' + sf.relativePath) ie = remoteFolder.secureIndex.get(sf.relativePath) resume = ie and ie.status == 'uploading' if not resume: log.info('No pending upload for file') tempPath = None if resume: log.info('Attempting to resume upload from temp file') sf.latest_version().hash = ie.hash #todo:add temp file validation log.info('Resuming previous upload') tempPath = security.getTempPath(sf.nativePath) if tempPath is None: tempPath, hashDigest = security.compressAndEncryptWithHash(conf, sf.nativePath, getHash) if getHash: sf.latest_version().hash = hashDigest ent.hash = sf.latest_version().hash # write working status so we don't have to re-encrypt when resuming large files if self.sourceFile.latest_version().size > conf.largeFileBytes: ent.status = 'uploading' remoteFolder.secureIndex.addorUpdate(ent) try: if not conf.args.test: info = remoteFolder.bucket.upload( UploadSourceLocalFile(tempPath), b2Name, min_large_file_size=conf.largeFileBytes, ignore_unfinished_check=not resume, progress_listener=SyncFileReporter(reporter) ) ent.remoteId = info.id_ ent.remoteName = info.file_name finally: # delete the temp file after the upload util.silentRemove(tempPath) ent.status = None remoteFolder.secureIndex.addorUpdate(ent)
def do_action(self, destinationDir, conf, reporter): util.silentRemove(self.path)