📄 phpdebugger.py
字号:
def setLsnrAction(self, actioni):
self.lsnrAction = actioni
return
def getLsnrAction(self):
return self.lsnrAction
def currConnFinished(self):
self.clearInternals()
self.setLsnrAction(PHPDebuggerCallback.ACTION_LISTEN)
self.actionEvent.set()
self.ui.DisableAfterStop()
def stopPhpDbg(self):
#
# TODO: should send a request to stop the current running PHP program.
# should handle network blocking issue correctly, otherwise, we
# might hang here.
#
reqPacket = PHPDBGPacket(DBGA_STOP)
try:
reqPacket.sendPacket(self.lsnrThr)
self.awaitAndHandleResponse(stopping = True)
except PHPDBGConnException:
pass
self.currConnFinished()
return
def stopLsnr(self):
if not self.lsnrThr:
return
#
# Then we try to stop our listener thread.
#
if self.lsnrThr.hasBeenConnected():
#
# If the listener thread has already accepted a connection from a
# php debug module/client, it is sleeping now and wait for this
# condition object to be set so that it can exit.
#
self.setLsnrAction(PHPDebuggerCallback.ACTION_STOP)
self.actionEvent.set()
else:
#
# If the listener thread has never been connected from a php debug
# module/client, it is still blocking on a accept() call. We
# connect to it here and send a special shutdown command asking it
# to exit.
#
shutdownMessage = IntToC4(DBG_SYNC) + IntToC4(DBGC_AG_SHUTDOWN_REQ) + IntToC4(0) + IntToC4(0)
tempSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
tempSocket.connect((self.lsnrHost, self.lsnrPort))
tempSocket.sendall(shutdownMessage)
except:
myprint("shutdown connection/send message got exception!")
tempSocket.close()
self.lsnrThr.join()
self.lsnrThr = None
class PHPDBGLsnrThr(threading.Thread):
def __init__(self, interfacei, hosti, porti, actionEventi, uii):
threading.Thread.__init__(self)
self.interface = interfacei
self.svrHost = hosti
self.svrPort = porti
self.actionEvent = actionEventi
self.svrSocket = None
self.clntConn = None
self.clntAddr = None
self.nonBlockingTimeout = 1
self.connHeader = None
self.ui = uii
def initSvrSocket(self):
self.svrSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.svrSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.svrSocket.bind((self.svrHost, self.svrPort))
def waitForClntConn(self):
self.svrSocket.listen(5)
self.clntConn, self.clntAddr = self.svrSocket.accept()
self.clntConn.settimeout(self.nonBlockingTimeout)
def run(self):
#
# Initialize this server socket.
#
self.initSvrSocket()
while True:
#
# Block until we get a new connection from a php debug client or our
# debugger ui (with a special shutting down header/command).
#
self.waitForClntConn()
#
# Ok, a new connection comes in ... Read the header to see where it
# comes from.
#
self.connHeader = ResponseHeader(self)
if self.connHeader.command == DBGC_AG_SHUTDOWN_REQ:
#
# This is a special command coming from our UI asking this
# thread to exit. This only happens if after this thread has
# been waiting for new connections from PHP debug module, no one
# connects, and UI is ready to shutdown this thread.
#
self.shutdown()
break
else:
#
# Tell the main gui thread to handle this new connection.
#
wx.CallAfter(self.interface.newConnEventHandler)
#
# From now on, PHPDebuggerCallback will communicate with the php
# debug module using this thread's clntConn socket. This thread
# itself will keep sleeping until get notified to make some
# actions.
#
self.actionEvent.wait()
self.actionEvent.clear()
action = self.interface.getLsnrAction()
if action == PHPDebuggerCallback.ACTION_STOP:
self.shutdown()
break
elif action == PHPDebuggerCallback.ACTION_LISTEN:
if self.clntConn:
self.clntConn.shutdown(socket.SHUT_RDWR)
self.clntConn.close()
self.clntConn = None
continue
else:
continue
def shutdown(self):
#
# Cleanup and ready to exit.
#
self.clntConn.shutdown(socket.SHUT_RDWR)
self.clntConn.close()
self.svrSocket.close()
def recv(self, size, blocking = False):
if self.clntConn:
myprint("recv: trying to receive %d bytes of data ...", size)
if blocking:
self.clntConn.settimeout(None)
else:
self.clntConn.settimeout(self.nonBlockingTimeout)
try:
rData = self.clntConn.recv(size)
except socket.timeout:
myprint("recv: got timed out")
rData = None
except:
myprint("recv: got an unexpected exception: %s", sys.exc_info()[0])
raise PHPDBGConnException
return rData
else:
raise PHPDBGConnException
def sendall(self, message):
if self.clntConn:
try:
self.clntConn.sendall(message)
except:
myprint("sendall: got an unexpected exception: %s", sys.exc_info()[0])
raise PHPDBGConnException
else:
raise PHPDBGConnException
def hasBeenConnected(self):
return self.clntConn != None
def getConnHeader(self):
return self.connHeader
class PHPValue(object):
PEV_NAMES = ("undefined", "long", "double", "string", "array", "object", "boolean", "resource", "reference", "soft reference", "null")
PEVT_UNKNOWN = 0
PEVT_LONG = 1
PEVT_DOUBLE = 2
PEVT_STRING = 3
PEVT_ARRAY = 4
PEVT_OBJECT = 5
PEVT_BOOLEAN = 6
PEVT_RESOURCE = 7
PEVT_REF = 8
PEVT_SOFTREF = 9
PEVT_NULL = 10
NULL_VALUE_STR = "NULL"
TRUE_VALUE_STR = "True"
FALSE_VALUE_STR = "False"
OBJECT_VALUE_STR = "<%s> object"
STRING_VALUE_STR = "\"%s\""
REFERENCE_VALUE_STR = "<reference><%s>"
RESOURCE_VALUE_STR = "<%s><%s>"
def __init__(self, frame, type, valueList):
self.fStackFrame = frame
self.fValueType = type
if type == self.PEVT_OBJECT:
self.fValueString = self.OBJECT_VALUE_STR % valueList[0]
self.fVariables = valueList[1:]
elif type == self.PEVT_ARRAY:
self.fValueString = ''
self.fVariables = valueList
else:
self.fVariables = []
if type == self.PEVT_STRING:
self.fValueString = self.STRING_VALUE_STR % valueList[0]
elif type == self.PEVT_NULL:
self.fValueString = self.NULL_VALUE_STR
elif type == self.PEVT_BOOLEAN:
if valueList[0] == "0":
self.fValueString = self.FALSE_VALUE_STR
else:
self.fValueString = self.TRUE_VALUE_STR
elif type == self.PEVT_REF or type == self.PEVT_SOFTREF:
self.fValueString = self.REFERENCE_VALUE_STR % valueList[0]
elif type == self.PEVT_RESOURCE:
self.fValueString = self.RESOURCE_VALUE_STR % (valueList[0], valueList[1])
else:
self.fValueString = valueList[0]
def addVariable(self, item):
if item != None:
self.fVariables.append(item)
return self.fVariables
def setParent(self, parent):
if self.fVariables != None and len(self.fVariables) > 0:
for item in self.fVariables:
item.setParent(parent)
def getReferenceType(self):
return self.fValueType
def getReferenceTypeName(self):
return self.PEV_NAMES[self.fValueType]
def setReferenceType(self, type):
self.fValueType = type
def getValueString(self):
return self.fValueString
def getChildrenVariables(self):
return self.fVariables
def hasVariables(self):
return len(self.fVariables) > 0
def childrenIsSortable(self):
#
# TODO: if self.fValueType != self.PEVT_ARRAY:
#
return True
class PHPVariable(object):
def __init__(self, frame, parent, valueType, name, valueList):
self.fStackFrame = frame
self.fName = None
self.fLongName = None
self.fPureName = None
self.fValue = PHPValue(frame, valueType, valueList)
self.fParent = parent
self.setName(name)
self.setChildrensParent(valueList)
def setName(self, name):
self.fPureName = name
type = self.getReferenceType()
if type == PHPValue.PEVT_ARRAY:
numItems = len(self.getChildrenVariables())
self.fName = name + "[" + str(numItems) + "]"
else:
self.fName = name
if not self.fParent or self.fParent.getName() == None:
self.fLongName = name
else:
self.setLongName()
return
def setLongName(self):
parentType = self.fParent.getReferenceType()
if parentType == PHPValue.PEVT_ARRAY:
self.fLongName = self.fParent.getLongName() + "['" + self.fPureName + "']"
elif parentType == PHPValue.PEVT_OBJECT:
self.fLongName = self.fParent.getLongName() + "." + self.fName
else:
self.fLongName = self.fName
return
def getValue(self):
return self.fValue
def getValueString(self):
return self.fValue.getValueString()
def getChildrenVariables(self):
return self.fValue.getChildrenVariables()
def getName(self):
return self.fName
def getParent(self):
return self.fParent
def setParent(self, parent):
self.fParent = parent
self.setLongName()
return
def setChildrensParent(self, childrenList):
if self.fValue.hasVariables():
for child in self.fValue.getChildrenVariables():
child.setParent(self)
def getLongName(self):
return self.fLongName
def getReferenceTypeName(self):
return self.fValue.getReferenceTypeName()
def getReferenceType(self):
return self.fValue.getReferenceType()
def setReferenceType(self, type):
tp = self.getValue.setReferenceType(type)
return tp
def setValue(self, expression):
if self.fValue.getReferenceType() == PHPValue.PEVT_STRING:
evalString = self.fLongName + "=\"" + expression + "\""
else:
evalString = self.fLongName + "=" + expression
vars = self.fStackFrame.getPHPDBGInterface().evalBlock(self.fStackFrame, evalString)
self.fValue = vars[0].fValue
def toString(self):
rtype = self.getReferenceType()
if rtype == PHPValue.PEVT_ARRAY:
elements = len(self.fValue.getChildrenVariables())
if elements == 0:
tmpStr = self.getName() + " [no elements]"
elif elements == 1:
tmpStr = self.getName() + " [1 element]"
else:
tmpStr = self.getName() + " [" + str(elements) + " elements]"
elif rtype == PHPValue.PEVT_OBJECT:
tmpStr = self.getName() + " [ class: " + self.fValue.getValueString() + "]"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -