Пример #1
0
    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
Пример #2
0
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
Пример #3
0
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)
Пример #4
0
    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
Пример #5
0
    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
Пример #6
0
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()
Пример #7
0
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
Пример #8
0
 def __init__(self, username, password="******"):
     self.thread = Thread(target=self.run, args=[])
     self.pssst = Pssst(username, password)
     self.pssst.create()
Пример #9
0
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()