def handle_delete(args): path = os.path.expanduser(args['path']) if os.path.isdir(path) and not os.path.islink(path): shutil.rmtree(path) else: os.remove(path) send_response_header({})
def handle_file_read(args): path = os.path.expanduser(args['path']) # Open the file before sending a response header fh = open(path, 'rb') # If a hash has been supplied, check if it matches. IF so, shortcut download. if 'cachedHash' in args: hash = hashlib.md5(fh.read()).hexdigest() if hash == args['cachedHash']: send_response_header({'hashMatch': True}) return fh.seek(0, 0) length = os.path.getsize(path) send_response_header({'length': length}) if length == 0: return chunkSize = 200 * 1024 while True: chunk = fh.read(chunkSize) if not chunk: break send_parcel(ParcelType.BODY, chunk) fh.close() send_parcel(ParcelType.ENDOFBODY, b'')
def handle_expand_path(args): path = os.path.expanduser(args['path']) if not os.path.exists(path): send_error(Error.ENOENT, 'Path not found') elif not os.path.isdir(path): send_error(Error.ENOTDIR, 'Not a directory') else: send_response_header({'path': path})
def handle_rename(args): fromPath = os.path.expanduser(args['from']) toPath = os.path.expanduser(args['to']) if os.path.exists(toPath): if args['overwrite']: os.unlink(toPath) else: raise OSError(Error.EEXIST, 'File already exists') os.rename(fromPath, toPath) send_response_header({})
def handle_file_write(args): path = os.path.expanduser(args['path']) alreadyExists = os.path.exists(path) if alreadyExists and not args['overwrite']: raise OSError(Error.EEXIST, 'File already exists') elif not alreadyExists and not args['create']: raise OSError(Error.ENOENT, 'File not found') fh = open(path, 'wb') fh.write(args['data']) fh.close() send_response_header({})
def handle_ls(args): base = os.path.expanduser(args['path']) selfStat = os.stat(base) result = {'stat': process_stat(selfStat)} if not stat.S_ISDIR(selfStat[stat.ST_MODE]): send_response_header(result) return dirs = {} dirLimit = 25 entryLimit = 2000 explore = deque(['.']) while len(explore) > 0 and dirLimit > 0 and entryLimit > 0: dirLimit -= 1 relPath = explore.popleft() absPath = base if relPath == '.' else os.path.join(base, relPath) try: children = {} for childName in os.listdir(absPath): entryLimit -= 1 if entryLimit < 0 and len(dirs) > 0: children = None break child_path = os.path.join(absPath, childName) try: childStat = os.stat(child_path) children[childName] = process_stat(childStat) isDir = stat.S_ISDIR(childStat[stat.ST_MODE]) if isDir and len(explore) < dirLimit: explore.append(os.path.join(relPath, childName)) except OSError as err: logging.warning('Skipping ' + child_path + ': ' + str(err)) if children is not None: dirs[relPath] = children except OSError as err: logging.warning('Error: ' + str(err)) if len(dirs) == 0: raise err # Only raise read errors on the first item. result['dirs'] = dirs send_response_header(result)
def handle_file_write_diff(args): path = os.path.expanduser(args['path']) if not os.path.exists(path): raise OSError(Error.ENOENT, 'File not found') with open(path, 'r', encoding='latin-1') as fh: original_data = bytearray(fh.read(), 'latin-1') original_hash = hashlib.md5(original_data).hexdigest() if original_hash != args['hashBefore']: raise CodedError( Error.EIO, 'File hash does not match client cached value: ' + args['hashBefore'] + ' vs ' + original_hash) # Apply diff; comes in as a flat array containing pairs; action, action data. updated_data = bytearray() read_cursor = 0 diff = args['diff'] for i in range(0, len(diff), 2): action = diff[i] action_data = diff[i + 1] if action == DiffAction.INSERTED: updated_data.extend( bytearray(action_data, 'latin-1')) # Action data contains new data inserted elif action == DiffAction.REMOVED: read_cursor += action_data # Action data contains number of bytes to remove else: # Action data contains number of bytes to copy from original updated_data.extend(original_data[read_cursor:read_cursor + action_data]) read_cursor += action_data updated_hash = hashlib.md5(updated_data).hexdigest() if updated_hash != args['hashAfter']: raise CodedError( Error.EINVAL, 'File hash after changes applied does not match expected') with open(path, 'wb') as fh: fh.write(updated_data) send_response_header({})
def handle_get_server_info(args): settingsPath = os.path.expanduser('~/.pony-ssh/') if not os.path.exists(settingsPath): os.makedirs(settingsPath) # Load or generate a cache key. cacheKey = None cacheKeyIsNew = False cacheKeyFile = settingsPath + 'cache.key' if os.path.exists(cacheKeyFile): with open(cacheKeyFile, 'r') as keyFileHandle: cacheKey = keyFileHandle.read(64) if cacheKey == None or len(cacheKey) < 64: cacheKeyIsNew = True cacheKey = os.urandom(32).encode('hex') with open(cacheKeyFile, 'wb') as keyFileHandle: keyFileHandle.write(cacheKey) send_response_header({ 'home': os.path.expanduser('~'), 'cacheKey': cacheKey, 'newCacheKey': cacheKeyIsNew })
def handle_mkdir(args): path = os.path.expanduser(args['path']) os.mkdir(path) send_response_header({})