def __init__(self, profile): """ Initializes the instance with the given profile. Parameters ---------- param profile : tuple The users profile. Raises ------ Exception Because the profile is required. """ if not profile: raise Exception("Profile required") self.buffer = [PssstChat.INTRO, ""] self.pssst = Pssst(*profile) self.halt = False
class Client: """ Simple test client that performs pulls """ def __init__(self, username, password="******"): self.thread = Thread(target=self.run, args=[]) self.pssst = Pssst(username, password) self.pssst.create() def start(self): self.thread.start() def stop(self): self.exit = True def run(self): self.exit = False self.time = [] while not self.exit: run = time.time() self.pssst.pull() self.time.append(time.time() - run) else: self.pssst.delete() # Clean up
def main(script, username=None, receiver=None, filename=None): """ Usage: %s USERNAME RECEIVER FILENAME """ script = os.path.basename(script) if not username: return main.__doc__.strip() % script try: name = Pssst.Name(username) filedata = io.open(filename, "rb").read() pssst = Pssst(name.user, name.password or getpass()) pssst.push([receiver], json.dumps({ "filename": os.path.basename(filename), "filedata": base64.b64encode(filedata).decode("ascii") })) print("Pushed file '%s'" % filename) except Exception as ex: return "%s error: %s" % (script, ex)
def __init__(self, profile, token): """ Initializes the instance with the security token. Parameters ---------- param profile : tuple The users profile. param token : Bytes Security token. Raises ------ Exception Because the profile is required. """ if not profile: raise Exception("Profile required") self.pssst = Pssst(*profile) self.token = token
class PssstChat: """ Basic chat class using the Pssst protocol. Methods ------- run() Starts the chat and runs its input processing. exit() Exits the chat and halts all its threads. """ INTRO = "Type 'USERNAME ...' to send a message and 'exit' to exit." def __init__(self, profile): """ Initializes the instance with the given profile. Parameters ---------- param profile : tuple The users profile. Raises ------ Exception Because the profile is required. """ if not profile: raise Exception("Profile required") self.buffer = [PssstChat.INTRO, ""] self.pssst = Pssst(*profile) self.halt = False def __repr__(self): """ Returns the chat version. Returns ------- string The chat version. """ return "Pssst Chat " + __version__ def __enter__(self): """ Sets the terminal mode and curses screen. Returns ------- PssstChat The chat instance. """ title = "%s - %s" % (repr(self.pssst), self.pssst.api) def setup(screen): """ Curses wrapped method. Parameters ---------- param screen : screen The curses screen. """ height, width = screen.getmaxyx() curses.noecho() curses.cbreak() screen.keypad(True) curses.use_default_colors() curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLUE) screen.addstr(0, 0, title.ljust(width), curses.color_pair(1)) self.screen = screen self.height = height self.width = width curses.wrapper(setup) return self def __exit__(self, *args): """ Resets the terminal mode. Parameters ---------- param args : tuple Unused parameters. """ curses.endwin() def __pssst_push(self, receiver, message): """ Pushes a chat message to the receiver. Parameters ---------- param receiver : string The chat receiver. param message : string The chat message. """ try: self.pssst.push(receiver, message) except Exception as ex: self.buffer.append("Error: %s" % ex) def __pssst_pull(self): """ Pulls all chat messages. Returns ------- List The chat messages. """ try: return self.pssst.pull() except Exception as ex: self.buffer.append("Error: %s" % ex) def __thread(self): """ Constantly pull messages to the buffer. Notes ----- This method runs asynchronous in a background thread. """ while not self.halt: for data in self.__pssst_pull() or []: data = data.decode("utf-8") chunks = range(0, len(data), self.width) self.buffer += [data[i:i + self.width] for i in chunks] self.__render() time.sleep(1) def __render(self): """ Renders the buffer. """ cursor = self.screen.getyx() window = self.buffer[-(self.height - 2):] for y in range(len(window)): self.screen.addstr(1 + y, 0, window[y]) self.screen.clrtoeol() self.screen.move(*cursor) self.screen.refresh() def __prompt(self): """ Returns the user input. Returns ------- string The user input. """ prompt, y = "%s> " % repr(self.pssst.user), self.height - 1 self.screen.addstr(y, 0, prompt) self.screen.move(y, len(prompt)) self.screen.clrtoeol() return self.screen.getstr().strip() def run(self): """ Starts the chat and runs its input processing. """ self.thread = Thread(target=self.__thread) self.thread.daemon = True self.thread.start() while True: self.__render() line = self.__prompt() if not line: continue # Exit command elif line.lower() == 'exit': return self.exit() # Push command elif re.match("^(pssst\.)?\w{2,63}\W+.+$", line): self.__pssst_push(*line.split(" ", 1)) # Unknown else: self.buffer.append("Error: Unknown command") def exit(self): """ Exits the chat and halts all its threads. """ self.halt = True self.thread.join() self.screen.clear() self.screen.refresh()
class PssstHtml: """ Local proxy for encrypted calls. Methods ------- call(params) Calls the CLI and returns the result. exit() Shuts down the proxy. name() Returns the canonical user name. pull() Overrides pull method with encoding. push(receiver, message) Overrides push method with encoding. """ def __init__(self, profile, token): """ Initializes the instance with the security token. Parameters ---------- param profile : tuple The users profile. param token : Bytes Security token. Raises ------ Exception Because the profile is required. """ if not profile: raise Exception("Profile required") self.pssst = Pssst(*profile) self.token = token def __encrypt(self, text): """ Returns the encrypted data. Parameters ---------- param text : string Decrypted text. Returns ------- Base64 Encrypted data. """ key, iv, size = self.token[:32], self.token[32:], AES.block_size data = text + (size - len(text) % size) * chr(size - len(text) % size) data = data.encode("utf-8") data = AES.new(key, AES.MODE_CBC, iv).encrypt(data) data = base64.b64encode(data) return data def __decrypt(self, data): """ Returns the decrypted text. Parameters ---------- param data : Base64 Encrypted data. Returns ------- string Decrypted text. """ key, iv = self.token[:32], self.token[32:] data = base64.b64decode(data) data = AES.new(key, AES.MODE_CBC, iv).decrypt(data) data = data.decode("utf-8") text = data[0:-ord(data[-1])] return text def call(self, request): """ Calls the CLI and returns the response. Parameters ---------- param request : string Encrypted request. Returns ------- string Encrypted response. """ try: request = json.loads(self.__decrypt(request)) method = request["method"] params = request["params"] for obj in [self, self.pssst]: if method in dir(obj): response = json.dumps(getattr(obj, method)(*params)) break except Exception as ex: cherrypy.response.status = 500 # Internal Server Error response = str(ex) finally: return self.__encrypt(response) def exit(self): """ Shuts down the proxy. """ raise SystemExit() def name(self): """ Returns the canonical user name. """ return repr(self.pssst.user) def pull(self): """ Overrides pull method with encoding. """ return [data.decode("utf-8") for data in self.pssst.pull()] def push(self, receiver, message): """ Overrides push method with encoding. """ self.pssst.push(receiver, message.encode("utf-8")) call.exposed = True
def __init__(self, username, password="******"): self.thread = Thread(target=self.run, args=[]) self.pssst = Pssst(username, password) self.pssst.create()