Exemplo n.º 1
0
        /// <summary>
        /// Send a command to XDebug. Returns a instance of the Response object or null
        /// upon failure.
        /// </summary>
        public XDebug.Response SendCommand(XDebug.Command c)
        {
            string transactionId = "xdc" + _cmdCounter.ToString();
            string Message       = "";

            _cmdCounter++;

            Message = String.Format(
                "{0} -i {1}",
                c.CommandText,
                transactionId
                );

            if (c.OptionsText.Length != 0)
            {
                Message += " " + c.OptionsText;
            }

            XDebugEventArgs e = new XDebugEventArgs();

            e.Message            = new XDebug.Response();
            e.Message.RawMessage = Message;
            e.EventType          = XDebugEventType.CommandSent;

            this.EventCallback(e);

            byte[] msg = System.Text.Encoding.ASCII.GetBytes(Message + "\0");
            this._client.Send(msg);

            return(this.ReceiveMessage());
        }
Exemplo n.º 2
0
        /// <summary>
        /// Deal with an incoming request. Also called when listening socket
        /// is terminated.
        /// </summary>
        private void OnConnectRequest(IAsyncResult ar)
        {
            try
            {
                Socket listener = (Socket)ar.AsyncState;
                _client = listener.EndAccept(ar);

                _listener.Close();

                XDebugEventArgs e = new XDebugEventArgs();
                e.EventType = XDebugEventType.DebuggerConnected;

                this.EventCallback(e);
            }
            catch
            {
                /* This can probably dealt with in a less hacky way:
                 *
                 * After closing the connection OnConnectRequest will be called. Then it dies
                 * with a ObjectDisposedException. Trap the exception. Not really anything else
                 * to do here. */
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Deal with the init-message xdebug sends us:
        ///     - See if we seem to be compatible language wise
        ///     - See if we're compatible protocol wise
        ///     - Find the initial file and fire off a ConnectionInitialized "event"
        /// 
        /// Returns true/false        
        /// </summary>        
        private bool handleInitMessage(XDebug.Response initMessage)
        {
            if (initMessage == null)
            {
                throw new Exception("Init message was empty.");
            }

            /* parse out the filename and check wether the version is
             * compatible with XdebugClient */

            XmlElement d = initMessage.XmlMessage.DocumentElement;

            if (d.Attributes["protocol_version"] != null)
            {
                string remoteVersion = d.Attributes["protocol_version"].Value;

                if (remoteVersion != supportedProtocolVersion)
                {
                    throw new Exception(
                        String.Format(
                            "Expected version '{0}' but got version '{1}' which is not supported.'",
                            supportedProtocolVersion,
                            remoteVersion
                        )
                    );

                }
            }

            if (d.Attributes["language"] != null)
            {
                string remoteLanguage = d.Attributes["language"].Value;

                if (remoteLanguage.ToLower() != supportedLanguage)
                {
                    throw new Exception(
                        String.Format(
                            "Expected language '{0}' but got '{1}' which is not supported.",
                            supportedLanguage,
                            remoteLanguage
                        )
                    );
                }
            }

            if (d.Attributes["fileuri"] != null)
            {
                string absoluteFilename = this.getLocalFilename(d.Attributes["fileuri"].Value);

                XDebugEventArgs xea = new XDebugEventArgs();
                xea.Filename = absoluteFilename;
                xea.EventType = XDebugEventType.ConnectionInitialized;

                if (this.EventCallback(xea))
                {
                    _State = XdebugClientState.Initialized;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                throw new Exception("Missing 'fileuri' attribute.");
            }

            return true;
        }
Exemplo n.º 4
0
        /// <summary>
        /// Send a command to XDebug. Returns a instance of the Response object or null
        /// upon failure.
        /// </summary>        
        public XDebug.Response SendCommand(XDebug.Command c)
        {
            string transactionId = "xdc" + _cmdCounter.ToString();
            string Message = "";

            _cmdCounter++;

            Message = String.Format(
                "{0} -i {1}",
                c.CommandText,
                transactionId
            );

            if (c.OptionsText.Length != 0)
            {
                Message += " " + c.OptionsText;
            }

            XDebugEventArgs e = new XDebugEventArgs();
            e.Message            = new XDebug.Response();
            e.Message.RawMessage = Message;
            e.EventType          = XDebugEventType.CommandSent;

            this.EventCallback(e);

            byte[] msg = System.Text.Encoding.ASCII.GetBytes(Message + "\0");
            this._client.Send(msg);

            return this.ReceiveMessage();
        }
Exemplo n.º 5
0
        /// <summary>
        /// Send a run, step_over or step_in command.
        /// </summary>        
        public void Run(string command)
        {
            XDebug.Command c = new Command(command, "");

            XDebug.Response resp = this.SendCommand(c);
            string status = resp.XmlMessage.DocumentElement.Attributes["status"].Value;
            string reason = resp.XmlMessage.DocumentElement.Attributes["reason"].Value;

            this.StackDepth = 0;

            XDebugEventArgs e;

            if (reason == "exception")
            {
                XmlNode ErrorNode = resp.XmlMessage.DocumentElement.FirstChild;

                this._State = XdebugClientState.Stopped;

                e              = new XDebugEventArgs();
                e.EventType    = XDebugEventType.ErrorOccured;
                e.ErrorMessage = ErrorNode.InnerText;

                switch ( ErrorNode.Attributes["exception"].Value )
                {
                    case Client.FatalErrorExceptionName:
                        e.ErrorType = XDebugErrorType.FatalError;
                        break;

                    case Client.NoticeExceptionName:
                        e.ErrorType = XDebugErrorType.Warning;
                        break;

                    default:
                        throw new Exception("Unknown exception type");
                }

                this.EventCallback(e);

                return;
            }
            else
            {

                switch (status)
                {
                    case "break":
                        /* execution stopped: breakpoint, step_over/step_in result, etc. */

                        this._State = XdebugClientState.Break;

                        List<StackEntry> CallStack = this.GetCallStack(0);

                        e = new XDebugEventArgs();

                        e.CurrentLocation = CallStack[0].Location;

                        e.EventType = XDebugEventType.BreakpointHit;

                        this.EventCallback(e);

                        break;

                    case "stopped":
                    case "stopping":
                        /* Script's done. */

                        this.Disconnect();

                        e = new XDebugEventArgs();
                        e.EventType = XDebugEventType.ScriptFinished;

                        this.EventCallback(e);

                        break;

                    default:
                        throw new Exception("Unknown status: " + status);
                }

            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Deal with the init-message xdebug sends us:
        ///     - See if we seem to be compatible language wise
        ///     - See if we're compatible protocol wise
        ///     - Find the initial file and fire off a ConnectionInitialized "event"
        ///
        /// Returns true/false
        /// </summary>
        private bool handleInitMessage(XDebug.Response initMessage)
        {
            if (initMessage == null)
            {
                throw new Exception("Init message was empty.");
            }

            /* parse out the filename and check wether the version is
             * compatible with XdebugClient */

            XmlElement d = initMessage.XmlMessage.DocumentElement;

            if (d.Attributes["protocol_version"] != null)
            {
                string remoteVersion = d.Attributes["protocol_version"].Value;

                if (remoteVersion != supportedProtocolVersion)
                {
                    throw new Exception(
                              String.Format(
                                  "Expected version '{0}' but got version '{1}' which is not supported.'",
                                  supportedProtocolVersion,
                                  remoteVersion
                                  )
                              );
                }
            }

            if (d.Attributes["language"] != null)
            {
                string remoteLanguage = d.Attributes["language"].Value;

                if (remoteLanguage.ToLower() != supportedLanguage)
                {
                    throw new Exception(
                              String.Format(
                                  "Expected language '{0}' but got '{1}' which is not supported.",
                                  supportedLanguage,
                                  remoteLanguage
                                  )
                              );
                }
            }

            if (d.Attributes["fileuri"] != null)
            {
                string absoluteFilename = this.getLocalFilename(d.Attributes["fileuri"].Value);

                XDebugEventArgs xea = new XDebugEventArgs();
                xea.Filename  = absoluteFilename;
                xea.EventType = XDebugEventType.ConnectionInitialized;

                if (this.EventCallback(xea))
                {
                    _State = XdebugClientState.Initialized;
                }
                else
                {
                    return(false);
                }
            }
            else
            {
                throw new Exception("Missing 'fileuri' attribute.");
            }

            return(true);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Parse a response by XDebug. Xdebug sends messages in 2 parts terminated
        /// by \0. The first part of the message is the length of the second part
        /// of the message.
        /// </summary>
        private XDebug.Response ReceiveMessage()
        {
            List <byte> MessageLengthList = new List <byte>();

            Byte[] c = new Byte[1];

            /* Determine the length of the message byte-by-byte */
            do
            {
                int bc = _client.Receive(c, 1, SocketFlags.None);
                if (bc == 0)
                {
                    // peer close, abort
                    throw new Exception("Socket read error");
                }

                if (c[0] != (byte)0x00)
                {
                    MessageLengthList.Add(c[0]);
                }
            } while (c[0] != (byte)0x00);

            /* Turn the MessageLengthList into a number by merging it
             * into a byte array, casting it to a string and then parsing
             * the integer from it. I wonder if there's a better way to do this.*/

            byte[] lengthBytes = MessageLengthList.ToArray();
            string lengthStr   = System.Text.Encoding.ASCII.GetString(lengthBytes);
            int    length      = Convert.ToInt32(lengthStr);

            /* The message length doesn't include the trailing NULL byte. Add it here */
            length++;

            byte[] messageBytes = new byte[length];
            int    bytesRead = 0, totalBytesRead = 0, currentByte = 0;

            do
            {
                byte[] xmlMessageBytes = new byte[length];
                bytesRead = _client.Receive(xmlMessageBytes, length, SocketFlags.None);

                if (bytesRead == 0 || bytesRead < 0)
                {
                    throw new Exception("Socket read error");
                }

                Buffer.BlockCopy(xmlMessageBytes, 0, messageBytes, totalBytesRead, bytesRead);
                totalBytesRead += bytesRead;

                //for (int i = 0; i < bytesRead; i++)
                //{
                //    messageBytes[currentByte++] = xmlMessageBytes[i];
                //}
            } while (totalBytesRead < length);

            string xmlMessage = System.Text.Encoding.ASCII.GetString(messageBytes);

            XDebug.Response resp = XDebug.Response.Parse(xmlMessage);

            if (resp != null)
            {
                if (resp.MessageType == XDebug.Response.MSG_ERROR)
                {
                    throw new Exception(resp.Attributes["ErrorMessage"]);
                }

                XDebugEventArgs xev = new XDebugEventArgs();
                xev.Message   = resp;
                xev.EventType = XDebugEventType.MessageReceived;

                this.EventCallback(xev);
            }


            return(resp);
        }
Exemplo n.º 8
0
 private void OnXdebugCommandSent(XDebugEventArgs e)
 {
     WriteDebugLine(" -> SENT: " + e.Message.RawMessage);
 }
Exemplo n.º 9
0
        /// <summary>
        /// Send a run, step_over or step_in command.
        /// </summary>
        public void Run(string command)
        {
            XDebug.Command c = new Command(command, "");

            XDebug.Response resp   = this.SendCommand(c);
            string          status = resp.XmlMessage.DocumentElement.Attributes["status"].Value;
            string          reason = resp.XmlMessage.DocumentElement.Attributes["reason"].Value;

            this.StackDepth = 0;

            XDebugEventArgs e;

            if (reason == "exception")
            {
                XmlNode ErrorNode = resp.XmlMessage.DocumentElement.FirstChild;

                this._State = XdebugClientState.Stopped;

                e              = new XDebugEventArgs();
                e.EventType    = XDebugEventType.ErrorOccured;
                e.ErrorMessage = ErrorNode.InnerText;

                switch (ErrorNode.Attributes["exception"].Value)
                {
                case Client.FatalErrorExceptionName:
                    e.ErrorType = XDebugErrorType.FatalError;
                    break;

                case Client.NoticeExceptionName:
                    e.ErrorType = XDebugErrorType.Warning;
                    break;

                default:
                    throw new Exception("Unknown exception type");
                }

                this.EventCallback(e);

                return;
            }
            else
            {
                switch (status)
                {
                case "break":
                    /* execution stopped: breakpoint, step_over/step_in result, etc. */

                    this._State = XdebugClientState.Break;

                    List <StackEntry> CallStack = this.GetCallStack(0);

                    e = new XDebugEventArgs();

                    e.CurrentLocation = CallStack[0].Location;

                    e.EventType = XDebugEventType.BreakpointHit;

                    this.EventCallback(e);

                    break;

                case "stopped":
                case "stopping":
                    /* Script's done. */

                    this.Disconnect();

                    e           = new XDebugEventArgs();
                    e.EventType = XDebugEventType.ScriptFinished;

                    this.EventCallback(e);

                    break;

                default:
                    throw new Exception("Unknown status: " + status);
                }
            }
        }
Exemplo n.º 10
0
        /* The methods in this region aren't neccessarily real events as
         * C# defines them. Some of them (those called from _client_EventCallback)
         * as just regular methods.
         *
         * The callback XDebugEventCallback is used as a centralized
         * place to further instruct the GUI what to do. We use only one event as
         * the client uses asynchronized methods (threading). By using 1 callback the
         * number of threading-related reinvoking (see MainForm.ReinvokeInOwnThread)
         */
        /// <summary>
        /// The XDebugEventCallback is called whenever something changes within the Xdebug.Client
        /// implementation. It serves mostly as a dispatcher.
        /// </summary>                
        private bool XDebugEventCallback(XDebugEventArgs e)
        {
            if (!this.ReinvokeInOwnThread(new XdebugClientCallback(XDebugEventCallback), new object[] { e }))
            {
                switch (e.EventType)
                {
                    case XDebugEventType.DebuggerConnected:
                        this.OnXdebuggerConnected(e);
                        break;

                    case XDebugEventType.ConnectionInitialized:
                        return this.OnXdebugConnectionInitialized(e);

                    case XDebugEventType.MessageReceived:
                        this.OnXdebugMessageReceived(e);
                        break;

                    case XDebugEventType.CommandSent:
                        this.OnXdebugCommandSent(e);

                        break;

                    case XDebugEventType.BreakpointHit:
                        this.OnXdebugBreakpointHit(e);
                        break;

                    case XDebugEventType.ErrorOccured:
                        this.OnXdebugErrorOccurred(e);
                        break;

                    case XDebugEventType.ScriptFinished:
                        this.OnXdebugScriptFinished(e);
                        break;

                    default:
                        WriteDebugLine("(!) Unknown event happened.");
                        break;
                }

            }

            return false;
        }
Exemplo n.º 11
0
        private void OnXdebugScriptFinished(XDebugEventArgs e)
        {
            _statusFrm.WriteStatusLine("(!) Script finished.");

            this.StopDebuggingSession();

            if (xdc.Properties.Settings.Default.auto_restart)
            {
                _statusFrm.WriteStatusLine("(-) Automatically restarting debugging.");

                try
                {
                    _client.listenForConnection();

                    startListeningToolStripMenuItem.Enabled = false;
                    stopDebuggingToolStripMenuItem.Enabled = true;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(
                        "Unable to re-create listening socket: " + ex.Message,
                        "Cannot open socket",
                        MessageBoxButtons.OK
                    );
                }
            }
        }
Exemplo n.º 12
0
 private void OnXdebugMessageReceived(XDebugEventArgs e)
 {
     // Nothing to do for now
 }
Exemplo n.º 13
0
        private void OnXdebuggerConnected(XDebugEventArgs e)
        {
            _statusFrm.WriteStatusLine("(-) Debugger connected.");

            try {
                if (_client.Initialize())
                {
                    _statusFrm.WriteStatusLine("(-) XDebugClient initialized.");

                    if (!xdc.Properties.Settings.Default.break_on_script_start)
                        this.SendContinuationCommand("run");
                    else
                        this.SendContinuationCommand("step_into");
                }
                else
                {
                    return;
                }
            }
            catch (Exception ex)
            {
                _statusFrm.WriteStatusLine("(-) Cannot initialize XDebugClient: " + ex.Message);

                MessageBox.Show(
                    "XDebugClient was unable to initialize. Debugging session terminated.\r\n\r\n" + ex.Message,
                    "System error",
                    MessageBoxButtons.OK
                );

                this.StopDebuggingSession();
            }
        }
Exemplo n.º 14
0
        private void OnXdebugErrorOccurred(XDebugEventArgs e)
        {
            if (e.ErrorType == XDebugErrorType.Warning)
            {
                WriteDebugLine("(!) PHP Notice: " + e.ErrorMessage);
                this._client.Run();
            }
            else
            {
                WriteDebugLine("(!) PHP Fatal error: " + e.ErrorMessage);

                MessageBox.Show(
                    "A Fatal error occurred:\r\n\r\n" + e.ErrorMessage + "\r\n\r\nYour script has been terminated.",
                    "Fatal Error",
                    MessageBoxButtons.OK
                );

                this.StopDebuggingSession();
            }
        }
Exemplo n.º 15
0
        private bool OnXdebugConnectionInitialized(XDebugEventArgs e)
        {
            if (this.LoadFile(e.Filename))
            {
                this.ToggleMenuItems(true);
                return true;
            }

            return false;
        }
Exemplo n.º 16
0
        /// <summary>
        /// Deal with an incoming request. Also called when listening socket
        /// is terminated.
        /// </summary>        
        private void OnConnectRequest(IAsyncResult ar)
        {
            try
            {
                Socket listener = (Socket)ar.AsyncState;
                _client = listener.EndAccept(ar);

                _listener.Close();

                XDebugEventArgs e = new XDebugEventArgs();
                e.EventType = XDebugEventType.DebuggerConnected;

                this.EventCallback(e);
            }
            catch
            {
                /* This can probably dealt with in a less hacky way:
                 *
                 * After closing the connection OnConnectRequest will be called. Then it dies
                 * with a ObjectDisposedException. Trap the exception. Not really anything else
                 * to do here. */
            }
        }
Exemplo n.º 17
0
        /// <summary>
        /// Parse a response by XDebug. Xdebug sends messages in 2 parts terminated 
        /// by \0. The first part of the message is the length of the second part 
        /// of the message.
        /// </summary>        
        private XDebug.Response ReceiveMessage()
        {
            List<byte> MessageLengthList = new List<byte>();
            Byte[] c = new Byte[1];

            /* Determine the length of the message byte-by-byte */
            do
            {
                int bc = _client.Receive(c, 1, SocketFlags.None);
                if (bc == 0)
                {
                    // peer close, abort
                    throw new Exception("Socket read error");
                }

                if (c[0] != (byte)0x00)
                {
                    MessageLengthList.Add(c[0]);
                }
            } while (c[0] != (byte)0x00);

            /* Turn the MessageLengthList into a number by merging it
             * into a byte array, casting it to a string and then parsing
             * the integer from it. I wonder if there's a better way to do this.*/

            byte[] lengthBytes = MessageLengthList.ToArray();
            string lengthStr = System.Text.Encoding.ASCII.GetString(lengthBytes);
            int length = Convert.ToInt32(lengthStr);

            /* The message length doesn't include the trailing NULL byte. Add it here */
            length++;

            byte[] messageBytes = new byte[length];
            int bytesRead = 0, totalBytesRead = 0, currentByte = 0;

            do
            {
                byte[] xmlMessageBytes = new byte[length];
                bytesRead = _client.Receive(xmlMessageBytes, length, SocketFlags.None);

                if (bytesRead == 0 || bytesRead < 0)
                    throw new Exception("Socket read error");

                Buffer.BlockCopy(xmlMessageBytes, 0, messageBytes, totalBytesRead, bytesRead);
                totalBytesRead += bytesRead;

                //for (int i = 0; i < bytesRead; i++)
                //{
                //    messageBytes[currentByte++] = xmlMessageBytes[i];
                //}

            } while (totalBytesRead < length);

            string xmlMessage    = System.Text.Encoding.ASCII.GetString(messageBytes);

            XDebug.Response resp = XDebug.Response.Parse(xmlMessage);

            if (resp != null)
            {
                if (resp.MessageType == XDebug.Response.MSG_ERROR)
                {
                    throw new Exception(resp.Attributes["ErrorMessage"]);
                }

                XDebugEventArgs xev = new XDebugEventArgs();
                xev.Message = resp;
                xev.EventType = XDebugEventType.MessageReceived;

                this.EventCallback(xev);
            }

            return resp;
        }
Exemplo n.º 18
0
        private void OnXdebugBreakpointHit(XDebugEventArgs e)
        {
            this.PrepareFileForAccess(e.CurrentLocation.filename);
            this.SetActiveFileAndLine(e.CurrentLocation);

            List<StackEntry> callstack = _client.GetCallStack(-1);
            _callstackFrm.setCallstack(callstack);
            // local and global context
            List<Property> ctx = _client.GetContext("0");
            _localContextFrm.LoadPropertyList(ctx);
            ctx = _client.GetContext("1");
            _globalContextFrm.LoadPropertyList(ctx);
        }