Example #1
0
class Window(QWidget, Ui_FormFrameworkTools):
    def __init__(self, *args, **kwargs):
        super(Window, self).__init__(*args, **kwargs)
        self.setupUi(self)
        # 初始化server
        self._server = QTcpServer(self)
        self._server.newConnection.connect(self.onNewConnection)
        self._server.listen(QHostAddress.LocalHost, 49496)
        self._getPsPath()
        self._initCodeEdit()

        # 设置默认代码和参数
        self.argsEdit.setPlainText('testColor("{}")'.format(
            os.path.abspath('Resources/GM6C6860.jpg').replace('\\', '/')))

        self.codeEdit.setText(self._formatArgs(Template))

    def _formatArgs(self, code):
        code = code.replace(
            '#1#',
            os.path.abspath('Resources/ProgressBar.jsx').replace('\\', '/'))
        code = code.replace(
            '#2#',
            os.path.abspath('Resources/Core.jsx').replace('\\', '/'))
        code = code.replace(
            '#3#',
            os.path.abspath('Resources/test.jsx').replace('\\', '/'))
        return code

    def _initCodeEdit(self):
        # 初始化编辑器的工作
        self.codeEdit.setUtf8(True)
        self.codeEdit.linesChanged.connect(self.onLinesChanged)  # 行改变
        # 代码高亮
        self.codeEdit.setLexer(QsciLexerJavaScript(self))
        # 自动折叠
        self.codeEdit.setMarginType(3, QsciScintilla.SymbolMargin)
        self.codeEdit.setMarginLineNumbers(3, False)
        self.codeEdit.setMarginWidth(3, 15)
        self.codeEdit.setMarginSensitivity(3, True)
        # 显示行号
        #self.codeEdit.setMarginType(0, QsciScintilla.NumberMargin)
        self.codeEdit.setMarginLineNumbers(0, True)
        self.onLinesChanged()
        # 代码提示
        sciApi = QsciAPIs(self.codeEdit.lexer())
        sciApi.prepare()
        self.codeEdit.setAutoCompletionSource(QsciScintilla.AcsAll)  # 设置源
        self.codeEdit.setAutoCompletionCaseSensitivity(True)  # 设置自动补全大小写敏感
        self.codeEdit.setAutoCompletionThreshold(1)  # 设置每输入一个字符就会出现自动补全的提示
        # 设置字体
        self.codeEdit.setFont(QFont('Consolas', 16))
        self.codeEdit.setMarginsFont(self.codeEdit.font())
        # 设置编码
        self.codeEdit.SendScintilla(QsciScintilla.SCI_SETCODEPAGE,
                                    QsciScintilla.SC_CP_UTF8)

        self.codeEdit.setBraceMatching(QsciScintilla.StrictBraceMatch)

        # 设置当前行高亮
        self.codeEdit.setCaretLineVisible(True)
        self.codeEdit.setCaretLineBackgroundColor(Qt.lightGray)
        self.codeEdit.setCaretForegroundColor(Qt.white)

        # tab
        # table relative
        self.codeEdit.setIndentationsUseTabs(True)
        self.codeEdit.setIndentationWidth(4)
        self.codeEdit.setTabIndents(True)
        self.codeEdit.setAutoIndent(True)
        self.codeEdit.setBackspaceUnindents(True)
        self.codeEdit.setTabWidth(4)

        # indentation guides
        self.codeEdit.setIndentationGuides(True)

        # folding margin
        self.codeEdit.setFolding(QsciScintilla.PlainFoldStyle)
        self.codeEdit.setMarginWidth(2, 12)

        # 自动换行
        self.codeEdit.setWrapMode(QsciScintilla.WrapWord)

    def onLinesChanged(self):
        # 动态设置左边的边距
        self.codeEdit.setMarginWidth(
            0,
            self.codeEdit.fontMetrics().width(str(self.codeEdit.lines())) + 5)

    def _getPsPath(self):
        # 获取ps的路径
        settings = QSettings('FrameworkTools', 'Settings')
        psPath = settings.value('path', '')
        if not psPath:  # 如果没有找到自己保存的路径则去找系统安装的路径
            settings = QSettings(
                'HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\Photoshop.exe',
                QSettings.NativeFormat)
            psPath = settings.value('.', '')
        self.pathEdit.setText(psPath)

    def onNewConnection(self):
        # 当有新的连接来时
        while self._server.hasPendingConnections():
            socket = self._server.nextPendingConnection()
            socket.readyRead.connect(self.onReadyRead)
            if socket.bytesAvailable() > 0:
                # 如果已有数据发送过来
                self.doRecv(socket)

    def onReadyRead(self):
        # 准备接收数据
        socket = self.sender()
        if socket.bytesAvailable() > 0:
            self.doRecv(socket)

    def doRecv(self, socket):
        # 接收数据
        try:
            data = socket.readAll().data().decode()
            # 对数据解密
            data = xxtea.decryptFromBase64(data, '0123456789abcdef')
            method, args = data.split('|')
            self.resultEdit.append('被调用函数: {}, 参数: {}'.format(method, args))
            try:
                args = eval(args)
            except Exception as e:
                args = []
            # 动态执行函数
            if hasattr(self, method):
                getattr(self, method)(socket, *args)
        except Exception as e:
            self.resultEdit.append(str(e))

    def getCode(self, socket):
        # 传递参数的函数
        args = self.argsEdit.toPlainText().strip()
        args = xxtea.encryptToBase64(args, '0123456789abcdef') + '\n'
        print('发送加密数据: ', args)
        socket.write(args.encode())
        socket.flush()

    def showError(self, _, message):
        # 显示错误消息
        if message:
            QMessageBox.critical(self, '错误', message)

    @pyqtSlot()
    def on_selectButton_clicked(self):
        # 手动选择路径
        path, _ = QFileDialog.getOpenFileName(self, '选择Ps路径', '',
                                              'Photoshop.exe')
        if path:
            self.pathEdit.setText(path)
            settings = QSettings('FrameworkTools', 'Settings')
            settings.setValue('path', path)
            settings.sync()

    @pyqtSlot()
    def on_runButton_clicked(self):
        # 运行按钮
        code = self.codeEdit.text().strip()
        if not code:
            return
        if not code.startswith('#target'):
            code = '#target photoshop\n' + code
        path = tempfile.mktemp('.jsx')
        open(path, 'wb').write(code.encode('utf-8'))
        subprocess.call([self.pathEdit.text().strip(), path])

    def closeEvent(self, event):
        if self._server.isListening():
            self._server.close()
            self._server.deleteLater()
        super(Window, self).closeEvent(event)
Example #2
0
class CodeExecutor:
    """
    This class is responsible for executing code (when starting Tribler in debug mode).
    The protocol to execute code is as follows.
    First, a client that wants to execute some code opens a connection with the TCP server and sends the
    string: <code in base64 format> <task_id>\n
    This code will be executed and the result will be sent to the client in the following format:
    result <result> <task_id>\n.
    If Tribler crashes, the server sends the following result: crash <stack trace in base64 format>

    Note that the socket uses the newline as separator.
    """

    def __init__(self, port, shell_variables=None):
        self.logger = logging.getLogger(self.__class__.__name__)
        self.tcp_server = QTcpServer()
        self.sockets = []
        self.stack_trace = None
        if not self.tcp_server.listen(port=port):
            self.logger.error("Unable to start code execution socket! Error: %s", self.tcp_server.errorString())
        else:
            connect(self.tcp_server.newConnection, self._on_new_connection)

        self.shell = Console(locals=shell_variables or {}, logger=self.logger)

    def _on_new_connection(self):
        self.logger.info("CodeExecutor has new connection")

        while self.tcp_server.hasPendingConnections():
            socket = self.tcp_server.nextPendingConnection()
            connect(socket.readyRead, self._on_socket_read_ready)
            connect(socket.disconnected, self._on_socket_disconnect(socket))
            self.sockets.append(socket)

            # If Tribler has crashed, notify the other side immediately
            if self.stack_trace:
                self.on_crash(self.stack_trace)

    def run_code(self, code, task_id):
        self.logger.info(f"Run code for task {task_id}")
        self.logger.debug(f"Code for execution:\n{code}")

        try:
            self.shell.runcode(code)
        except SystemExit:
            pass

        if self.shell.last_traceback:
            self.on_crash(self.shell.last_traceback)
            return

        self.logger.info("Code execution with task %s finished:", task_id)

        return_value = b64encode(self.shell.locals.get('return_value', '').encode('utf-8'))
        for socket in self.sockets:
            socket.write(b"result %s %s\n" % (return_value, task_id))

    def on_crash(self, exception_text):
        self.logger.error(f"Crash in CodeExecutor:\n{exception_text}")

        self.stack_trace = exception_text
        for socket in self.sockets:
            socket.write(b"crash %s\n" % b64encode(exception_text.encode('utf-8')))

    def _on_socket_read_ready(self):
        data = bytes(self.sockets[0].readAll())
        parts = data.split(b" ")
        if len(parts) != 2:
            return

        try:
            code = b64decode(parts[0]).decode('utf8')
            task_id = parts[1].replace(b'\n', b'')
            self.run_code(code, task_id)
        except binascii.Error:
            self.logger.error("Invalid base64 code string received!")

    def _on_socket_disconnect(self, socket):
        def on_socket_disconnect_handler():
            self.sockets.remove(socket)
        return on_socket_disconnect_handler
Example #3
0
class CodeExecutor(object):
    """
    This class is responsible for executing code (when starting Tribler in debug mode).
    The protocol to execute code is as follows.
    First, a client that wants to execute some code opens a connection with the TCP server and sends the
    string: <code in base64 format> <task_id>\n
    This code will be executed and the result will be sent to the client in the following format:
    result <result> <task_id>\n.
    If Tribler crashes, the server sends the following result: crash <stack trace in base64 format>

    Note that the socket uses the newline as separator.
    """
    def __init__(self, port, shell_variables={}):
        self.logger = logging.getLogger(self.__class__.__name__)
        self.tcp_server = QTcpServer()
        self.sockets = []
        self.stack_trace = None
        if not self.tcp_server.listen(port=port):
            self.logger.error(
                "Unable to start code execution socket! Error: %s",
                self.tcp_server.errorString())
        else:
            self.tcp_server.newConnection.connect(self._on_new_connection)

        self.shell = Console(locals=shell_variables)

    def _on_new_connection(self):
        while self.tcp_server.hasPendingConnections():
            socket = self.tcp_server.nextPendingConnection()
            socket.readyRead.connect(self._on_socket_read_ready)
            socket.disconnected.connect(
                lambda dc_socket=socket: self._on_socket_disconnect(dc_socket))
            self.sockets.append(socket)

            # If Tribler has crashed, notify the other side immediately
            if self.stack_trace:
                self.on_crash(self.stack_trace)

    def run_code(self, code, task_id):
        self.shell.runcode(code)
        stdout = self.shell.stdout.read()
        stderr = self.shell.stderr.read()

        self.logger.info("Code execution with task %s finished:", task_id)
        self.logger.info("Stdout of task %s: %s", task_id, stdout)
        if 'Traceback' in stderr and 'SystemExit' not in stderr:
            self.logger.error("Executed code with failure: %s",
                              b64encode(code))

        # Determine the return value
        if 'return_value' not in self.shell.console.locals:
            return_value = ''.encode('base64')
        else:
            return_value = str(
                self.shell.console.locals['return_value']).encode('base64')

        for socket in self.sockets:
            socket.write("result %s %s\n" % (return_value, task_id))

    def on_crash(self, exception_text):
        self.stack_trace = exception_text
        for socket in self.sockets:
            socket.write("crash %s\n" % exception_text.encode('base64'))

    def _on_socket_read_ready(self):
        data = str(self.sockets[0].readAll())
        parts = data.split(" ")
        if len(parts) != 2:
            return

        try:
            code = parts[0].decode('base64')
            task_id = parts[1].replace('\n', '')
            self.run_code(code, task_id)
        except binascii.Error:
            self.logger.error("Invalid base64 code string received!")

    def _on_socket_disconnect(self, socket):
        self.sockets.remove(socket)
Example #4
0
class Server(QObject):
    debug = True
    log = sys.stderr
    username = '******'
    password = '******'
    stopServing = pyqtSlot()

    def __init__(self, parent=None):
        super(Server, self).__init__(parent)
        self.proxy_server = QTcpServer(self)
        self.proxy_server.listen(QHostAddress.Any, 8000)
        self.proxy_server.newConnection.connect(self.manage_request)

        if self.debug:
            self.log.write('Server running on localhost port %s\n\n' %
                           self.port())

    def port(self):
        return self.proxy_server.serverPort()

    def addr(self):
        return self.proxy_server.serverAddress().toString()

    def stopServing(self):
        if self.debug:
            self.log.write('Service is stopping...\n\n')

        # does not "close" the server, just stop listening...
        self.proxy_server.close()

        if self.proxy_server.hasPendingConnections():
            socket = self.proxy_server.nextPendingConnection()
            while socket:
                socket.abort()
                socket = self.proxy_server.nextPendingConnection()

    def manage_request(self):
        proxy_server = self.sender()
        # Qt docs says that the caller of nextPendingConnection()
        # is the parent of the socket
        socket = proxy_server.nextPendingConnection()
        socket.readyRead.connect(self.process_request)
        socket.disconnected.connect(socket.deleteLater)

    def authorize_request(self, request_data):
        return True
        header = QHttpRequestHeader(QString(request_data))
        if self.debug:
            self.log.write(header.toString())

        auth = header.value('Proxy-Authorization')
        if not auth:
            return False

        challenge = base64.b64encode(self.username + ':' + self.password)
        return challenge == str(auth).split()[1]

    def process_request(self):
        socket = self.sender()
        request_data = socket.readAll()

        if not self.authorize_request(request_data):
            socket.write('HTTP/1.1 407 Proxy Authentication Required\r\n')
            if self.debug:
                self.log.write('407 Proxy Authentication Required\n\n')
            socket.write('Proxy-Authenticate: Basic realm="test"\r\n')
            socket.write('\r\n')
            socket.disconnectFromHost()
            return
        else:
            # remove Proxy-Authorization header
            start = request_data.indexOf('Proxy-Authorization:')
            end = request_data.lastIndexOf('\r\n')
            request_data.remove(start, end)
            request_data.append('\r\n')

        pos = request_data.indexOf('\r\n')
        request_line = request_data.left(pos)
        request_data.remove(0, pos + 2)

        entries = request_line.split(' ')
        method = entries[0]
        address = entries[1]
        version = entries[2]
        port = '80'

        if address.count(':') > 1:
            protocol, host, port = address.split(':')
        else:
            protocol, host = address.split(':')

        print('address' + str(address))

        #url = QUrl( protocol + host )
        url = QUrl.fromEncoded(address)
        #url.setHost( host )
        #url.setPort( int(port) )

        if not url.isValid():
            if self.debug:
                self.log.write('Invalid URL: %s\n\n', url)
            socket.disconnectFromHost()
            return

        host = url.host()
        port = 80 if (url.port() < 0) else url.port()
        req = url.encodedPath()
        if url.hasQuery():
            req.append('?').append(url.encodedQuery())
        request_line = method + ' ' + req + ' ' + version + '\r\n'
        request_data.prepend(request_line)

        if self.debug:
            self.log.write(method + ' ' + address + ' ' + version + '\n\n')

        key = host + ':' + QString.number(port)
        proxy_socket = socket.findChild(QTcpSocket, key)
        if proxy_socket:
            proxy_socket.setObjectName(key)
            proxy_socket.setProperty('url', url)
            proxy_socket.setProperty('request_data', request_data)
            proxy_socket.write(request_data)
        else:
            proxy_socket = QTcpSocket(socket)
            proxy_socket.setObjectName(key)
            proxy_socket.setProperty('url', url)
            proxy_socket.setProperty('request_data', request_data)
            proxy_socket.connected.connect(self.send_request)
            proxy_socket.readyRead.connect(self.transfer_data)
            proxy_socket.disconnected.connect(self.close_connection)
            proxy_socket.error.connect(self.close_connection)
            proxy_socket.connectToHost(host, port)

    def send_request(self):
        proxy_socket = self.sender()
        request_data = proxy_socket.property('request_data').toByteArray()
        proxy_socket.write(request_data)

    def transfer_data(self):
        proxy_socket = self.sender()
        socket = proxy_socket.parent()
        socket.write(proxy_socket.readAll())

    def close_connection(self):
        proxy_socket = self.sender()
        if proxy_socket:
            socket = proxy_socket.parent()
            if isinstance(socket, QTcpSocket) and socket:
                socket.disconnectFromHost()
            if proxy_socket.error() != QTcpSocket.RemoteHostClosedError:
                url = proxy_socket.property('url').toUrl()
                error_string = proxy_socket.errorString()

                if self.debug:
                    self.log.write('Error for %s %s\n\n' % (url, error_string))

            proxy_socket.deleteLater()
Example #5
0
class CodeExecutor(object):
    """
    This class is responsible for executing code (when starting Tribler in debug mode).
    The protocol to execute code is as follows.
    First, a client that wants to execute some code opens a connection with the TCP server and sends the
    string: <code in base64 format> <task_id>\n
    This code will be executed and the result will be sent to the client in the following format:
    result <result> <task_id>\n.
    If Tribler crashes, the server sends the following result: crash <stack trace in base64 format>

    Note that the socket uses the newline as separator.
    """

    def __init__(self, port, shell_variables={}):
        self.logger = logging.getLogger(self.__class__.__name__)
        self.tcp_server = QTcpServer()
        self.sockets = []
        self.stack_trace = None
        if not self.tcp_server.listen(port=port):
            self.logger.error("Unable to start code execution socket! Error: %s", self.tcp_server.errorString())
        else:
            self.tcp_server.newConnection.connect(self._on_new_connection)

        self.shell = Console(locals=shell_variables)

    def _on_new_connection(self):
        while self.tcp_server.hasPendingConnections():
            socket = self.tcp_server.nextPendingConnection()
            socket.readyRead.connect(self._on_socket_read_ready)
            socket.disconnected.connect(lambda dc_socket=socket: self._on_socket_disconnect(dc_socket))
            self.sockets.append(socket)

            # If Tribler has crashed, notify the other side immediately
            if self.stack_trace:
                self.on_crash(self.stack_trace)

    def run_code(self, code, task_id):
        self.shell.runcode(code)
        stdout = self.shell.stdout.read()
        stderr = self.shell.stderr.read()

        self.logger.info("Code execution with task %s finished:", task_id)
        self.logger.info("Stdout of task %s: %s", task_id, stdout)
        if 'Traceback' in stderr and 'SystemExit' not in stderr:
            self.logger.error("Executed code with failure: %s", b64encode(code))

        # Determine the return value
        if 'return_value' not in self.shell.console.locals:
            return_value = ''.encode('base64')
        else:
            return_value = str(self.shell.console.locals['return_value']).encode('base64')

        for socket in self.sockets:
            socket.write("result %s %s\n" % (return_value, task_id))

    def on_crash(self, exception_text):
        self.stack_trace = exception_text
        for socket in self.sockets:
            socket.write("crash %s\n" % exception_text.encode('base64'))

    def _on_socket_read_ready(self):
        data = str(self.sockets[0].readAll())
        parts = data.split(" ")
        if len(parts) != 2:
            return

        try:
            code = parts[0].decode('base64')
            task_id = parts[1].replace('\n', '')
            self.run_code(code, task_id)
        except binascii.Error:
            self.logger.error("Invalid base64 code string received!")

    def _on_socket_disconnect(self, socket):
        self.sockets.remove(socket)