⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 phpdebugger.py

📁 Wxpython Implemented on Windows CE, Source code
💻 PY
📖 第 1 页 / 共 5 页
字号:
#---------------------------------------------------------------------------
# Name:         PHPDebugger.py
# Purpose:      php dbg client and supporting code
# Author:       Matt Fryer, Kevin Wang
# Created:      2/1/06
# Copyright:    (c) 2006 ActiveGrid, Inc.
# License:      wxWindows License
#---------------------------------------------------------------------------


import os
import socket
import sys
import threading
import traceback
import wx
import DebuggerService
import activegrid.util.sysutils as sysutils


DBGC_REPLY                              = 0x0               # reply to previous DBGA_REQUEST request
DBGC_STARTUP                            = 0x0001            # script startup
DBGC_END                                = 0x0002            # script done
DBGC_BREAKPOINT                         = 0x0003            # user definded breakpoint occured
DBGC_STEPINTO_DONE                      = 0x0004            # step to the next statement is completed
DBGC_STEPOVER_DONE                      = 0x0005            # step to the next statement is completed
DBGC_STEPOUT_DONE                       = 0x0006            # step to the next statement is completed
DBGC_EMBEDDED_BREAK                     = 0x0007            # breakpoint caused by DebugBreak() function
DBGC_ERROR                              = 0x0010            # error occured
DBGC_LOG                                = 0x0011            # logging support
DBGC_SID                                = 0x0012            # send SID
DBGC_PAUSE                              = 0x0013            # pause current session as soon as possible
DBGC_AG_SHUTDOWN_REQ                    = 0x0201            # special ActiveGrid UI shutdown listening thread command


FRAME_STACK                             = 100000            # "call:stack" - e.g. backtrace
FRAME_SOURCE                            = 100100            # source text
FRAME_SRC_TREE                          = 100200            # tree of source files
FRAME_RAWDATA                           = 100300            # raw data or string
FRAME_ERROR                             = 100400            # error notification
FRAME_EVAL                              = 100500            # evaluating/watching
FRAME_BPS                               = 100600            # set/remove breakpoint
FRAME_BPL                               = 100700            # breakpoint(s) request = get the list
FRAME_VER                               = 100800            # version request
FRAME_SID                               = 100900            # session id info
FRAME_SRCLINESINFO                      = 101000            # source lines info
FRAME_SRCCTXINFO                        = 101100            # source contexts info
FRAME_LOG                               = 101200            # logging
FRAME_PROF                              = 101300            # profiler
FRAME_PROF_C                            = 101400            # profiler counter/accuracy
FRAME_SET_OPT                           = 101500            # set/update options


DBGF_STARTED                            = 0x0001            # debugger has been started
DBGF_FINISHED                           = 0x0002            # DBGC_END notification has been sent
DBGF_WAITACK                            = 0x0004            # awaiting replay|request
DBGF_UNSYNC                             = 0x0008            # protocol has been unsynchronized
DBGF_REQUESTPENDING                     = 0x0010            # Debug session request pending
DBGF_REQUESTFOUND                       = 0x0020            # Debug session request found
DBGF_REJECTIONFOUND                     = 0x0040            # DBGSESSID=-1 found - session rejection


E_ERROR                                 = 1 << 0
E_WARNING                               = 1 << 1
E_PARSE                                 = 1 << 2
E_NOTICE                                = 1 << 3
E_CORE_ERROR                            = 1 << 4
E_CORE_WARNING                          = 1 << 5
E_COMPILE_ERROR                         = 1 << 6
E_COMPILE_WARNING                       = 1 << 7
E_USER_ERROR                            = 1 << 8
E_USER_WARNING                          = 1 << 9
E_USER_NOTICE                           = 1 << 10


BPS_DELETED                             = 0
BPS_DISABLED                            = 1
BPS_ENABLED                             = 2
BPS_UNRESOLVED                          = 0x100


DBG_SYNC                                = 0x5953
DBG_SYNC2_STR                           = chr(0) + chr(0) + chr(89) + chr(83)
RESPONSE_HEADER_SIZE                    = 16


_VERBOSE = False
def myprint(format, vlist=None):
    if _VERBOSE:
        if vlist:
            print format % vlist
        else:
            print format


#
# 4 Char's to an Integer
#
def C4ToInt(ch, startPos):
    retval = 0
    pos    = startPos

    retval = retval + (CharToInt(ch[pos]) << 24)
    pos    = pos + 1
    retval = retval + (CharToInt(ch[pos]) << 16)
    pos    = pos + 1
    retval = retval + (CharToInt(ch[pos]) << 8)
    pos    = pos + 1
    retval = retval + (CharToInt(ch[pos]) << 0)

    return retval


def CharToInt(ch):
    return int((ord(ch) & 0x00FF));


#
# An Integer to 4 Char's
#
def IntToC4(num):
    retval  = chr((num >> 24) & 0x00FF)
    retval += chr((num >> 16) & 0x00FF)
    retval += chr((num >> 8 ) & 0x00FF)
    retval += chr((num >> 0 ) & 0x00FF)

    return retval


DBGA_CONTINUE                           = IntToC4(0x8001)
DBGA_STOP                               = IntToC4(0x8002)
DBGA_STEPINTO                           = IntToC4(0x8003)
DBGA_STEPOVER                           = IntToC4(0x8004)
DBGA_STEPOUT                            = IntToC4(0x8005)
DBGA_IGNORE                             = IntToC4(0x8006)
DBGA_REQUEST                            = IntToC4(0x8010)


def getCommandString(code):
    if code == DBGC_REPLY:
        return "REPLY"
    elif code == DBGC_STARTUP:
        return "STARTUP"
    elif code == DBGC_END:
        return "END"
    elif code == DBGC_BREAKPOINT:
        return "BREAKPOINT"
    elif code == DBGC_STEPINTO_DONE:
        return "STEPINTO DONE"
    elif code == DBGC_STEPOVER_DONE:
        return "STEPOVER DONE"
    elif code == DBGC_STEPOUT_DONE:
        return "STEPOUT DONE"
    elif code == DBGC_EMBEDDED_BREAK:
        return "EMBEDDED BREAK"
    elif code == DBGC_PAUSE:
        return "PAUSE"
    elif code == DBGC_ERROR:
        return "ERROR"
    elif code == DBGC_LOG:
        return "LOG"
    elif code == DBGC_SID:
        return "SEND SID"
    elif code == DBGC_AG_SHUTDOWN_REQ:
        return "AG SHUTDOWN REQ"


def reportFlags(flagsValue):
    flagsRetVal = ""
    if flagsValue & DBGF_STARTED:                  # debugger has been started
        flagsRetVal += "started+"
    if flagsValue & DBGF_FINISHED:                 # DBGC_END notification has been sent
        flagsRetVal += "finished+"
    if flagsValue & DBGF_WAITACK:                  # awaiting replay|request
        flagsRetVal += "awaiting ack+"
    if flagsValue & DBGF_UNSYNC:                   # protocol has been unsynchronized
        flagsRetVal += "protocol unsynchronized+"
    if flagsValue & DBGF_REQUESTPENDING:           # Debug session request pending
        flagsRetVal += "request pending+"
    if flagsValue & DBGF_REQUESTFOUND:             # Debug session request found
        flagsRetVal += "request found+"
    if flagsValue & DBGF_REJECTIONFOUND :          # DBGSESSID=-1 found - session rejection
        flagsRetVal += "session rejection+"
    return flagsRetVal


def getErrorTypeString(code):
    if code == E_ERROR:
        return "[Error]"
    elif code == E_WARNING:
        return "[Warning]"
    elif code == E_PARSE:
         return "[Parse Error]"
    elif code == E_NOTICE:
        return "[Notice]"
    elif code == E_CORE_ERROR:
        return "[Core Error]"
    elif code == E_CORE_WARNING:
        return "[Core Warning]"
    elif code == E_COMPILE_ERROR:
        return  "[Compile Error]"
    elif code == E_COMPILE_WARNING:
        return  "[Compile Warning]"
    elif code == E_USER_ERROR:
        return  "[User Error]"
    elif code == E_USER_WARNING:
        return  "[User Warning]"
    elif code == E_USER_NOTICE:
        return  "[User Notice]"
    else:
        return "[Unexpected Error]"


class ResponseHeader(object):
    def __init__(self, conn, blocking = False):
        self.isValid = False
        receivedData = conn.recv(RESPONSE_HEADER_SIZE, blocking)

        if not receivedData:
            myprint("Tried to get %d bytes of PHP DBG header, got None\n" % RESPONSE_HEADER_SIZE)
            return
        elif len(receivedData) != RESPONSE_HEADER_SIZE:
            myprint("Tried to get %d bytes of PHP DBG header, got %d\n" % (RESPONSE_HEADER_SIZE, len(receivedData)))
            return

        self.sync    = C4ToInt(receivedData, 0)
        self.command = C4ToInt(receivedData, 4)
        self.flags   = C4ToInt(receivedData, 8)
        self.toRead  = C4ToInt(receivedData, 12)

        myprint("ResponseHeader: sync=%x, command=%s, flags=(%s), toRead=%s\n", (self.sync, getCommandString(self.command), reportFlags(self.flags), self.toRead))
        if self.sync != DBG_SYNC:
            myprint("Sync wrong for header! Expected %x, got %s\n" % (DBG_SYNC, self.sync))
            return

        self.isValid = True


class ResponsePacketFrame(object):
    def __init__(self, conn, size, data, blocking = False):
        self.isValid      = False
        self.conn         = conn
        self.data         = ''

        if data:
            self.data     = data
            newlyReceived = False
        elif conn:
            newlyReceived = True

            sizeToReceive = size
            while True:
                oneChunk  = conn.recv(sizeToReceive, blocking)
                sizeReceived = len(oneChunk)
                if sizeReceived > 0:
                    self.data = self.data + oneChunk

                if sizeReceived < sizeToReceive:
                    sizeToReceive = sizeToReceive - sizeReceived
                    continue
                else:
                    break

            if len(self.data) != size:
                myprint("Expected to get %d bytes of a PHP DBG packet, got %d\n" % (size, len(self.data)))
                return
        else:
            return

        self.frameName = C4ToInt(self.data, 0)
        self.frameSize = C4ToInt(self.data, 4)
        if newlyReceived:
            myprint("Newly received ResponsePacketFrame: frameName=%d, frameSize=%d", (self.frameName, self.frameSize))
        else:
            myprint("Created from existing ResponsePacketFrame: frameName=%d, frameSize=%d", (self.frameName, self.frameSize))

        if self.frameSize == 0:
            return

        self.currPos      = 8
        self.totalDataLen = len(self.data)
        self.length       = 8 + self.frameSize
        self.isValid      = True
        myprint("new ResponsePacketFrame: currPos=%s, totalDataLen=%s, length=%s", (repr(self.currPos), repr(self.totalDataLen), repr(self.length)))
        return

    def getNextInt(self):
        myprint("getNextInt(): currPos=%s, totalDataLen=%s, length=%s", (repr(self.currPos), repr(self.totalDataLen), repr(self.length)))
        if self.isValid and self.currPos + 4 <= self.length:
            val = C4ToInt(self.data, self.currPos)
            self.currPos = self.currPos + 4
            myprint("getNextInt(): got an integar: %s", repr(val))
            return val
        else:
            return self._errorReturn("getNextInt(): no more integar available with current frame: ")

    def getNextString(self, strLen):
        endPos = self.currPos + strLen
        if self.isValid and endPos <= self.length:
            #
            # Trim the ending '\0'.  TODO: confirm this applies to all raw string data.
            #
            str          = self.data[self.currPos:endPos - 1]
            self.currPos = endPos
            myprint("getNextString(): got a string: %s", str)
            return str
        else:
            return self._errorReturn("getNextString(): no more string available with current frame: ")

    def getNextFrame(self, useAbsolutePos = False):
        if useAbsolutePos:
            #
            # Skip this frame's header (8 bytes for frameSize and frameSize) and frame data (frameSize).
            #
            self.currPos = self.length

        if self.isValid and self.currPos < self.totalDataLen:
            return ResponsePacketFrame(None, None, self.data[self.currPos:])
        else:
            return self._errorReturn("getNextFrame(): no more frame available with current frame: ")

    def _errorReturn(self, preMsg = ''):
        myprint(preMsg + "frameName=%s, frameSize=%s, totalDataLen=%s, length=%s, currPos:%s", (repr(self.frameName), repr(self.frameSize), repr(self.totalDataLen), repr(self.length), repr(self.currPos)))
        self.isValid = False
        return None


class PHPDBGFrame(object):
    FRAME_HEADER_SIZE = 8
    def __init__(self, frameType):
        self.frameType = IntToC4(frameType)
        self.frameData = ""

    def addInt(self, intVal):
        self.frameData = self.frameData + IntToC4(intVal)

    def addChar(self, charVal):
        self.frameData = self.frameData + charVal

    def addStr(self, string):
        #
        # Add the trailing '\0'.
        #
        self.frameData = self.frameData + string + '\0'

    def getSize(self):
        return len(self.frameData) + PHPDBGFrame.FRAME_HEADER_SIZE

    def writeFrame(self, conn):
        header = self.frameType + IntToC4(len(self.frameData))
        conn.sendall(header)
        conn.sendall(self.frameData)


class PHPDBGPacket(object):
    def __init__(self, packetType):
        self.header     = DBG_SYNC2_STR + packetType
        self.frames     = []
        self.packetSize = 0

    def addFrame(self, frame):
        self.frames.append(frame)
        self.packetSize += frame.getSize()

    def sendPacket(self, conn, flags = 0):
        self.header += IntToC4(flags)
        self.header += IntToC4(self.packetSize)
        conn.sendall(self.header)
        for frame in self.frames:
            frame.writeFrame(conn)


class PHPDBGException(Exception):
    def __init__(self, msg = None, cause = None):
        if (msg == None):
            Exception.__init__(self)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -