예제 #1
0
        /// <summary>
        /// Retrieve the source code to the specified file.
        /// </summary>
        public string Source(string URI)
        {
            string remoteURI = "file://";

            string s;

            if (URI[0] != '/')
            {
                remoteURI += "/";
            }

            remoteURI += System.Web.HttpUtility.UrlPathEncode(URI);

            XDebug.Command  c = new Command("source", "-f " + remoteURI);
            XDebug.Response r = this.SendCommand(c);

            if (r == null)
            {
                throw new Exception("Parse error");
            }

            if (r.XmlMessage.InnerText == "can not open file")
            {
                MessageBox.Show("Could not load source file. Possibly the source file is empty. Continuing with empty file...", "Source file");
                s = "";
            }
            else
            {
                s = r.XmlMessage.InnerText;
            }

            return(base64ToASCII(s));
        }
예제 #2
0
        /// <summary>
        /// Get the callstack up to this point.
        /// </summary>
        public List <StackEntry> GetCallStack(int Depth)
        {
            string options = "";

            if (Depth != -1)
            {
                options = "-d " + Depth;
            }

            XDebug.Command  c = new Command("stack_get", options);
            XDebug.Response m = this.SendCommand(c);

            List <StackEntry> CallStack = new List <StackEntry>();

            foreach (XmlElement n in m.XmlMessage.DocumentElement.ChildNodes)
            {
                if (n.Name.ToLower() == "stack")
                {
                    StackEntry se = new StackEntry();

                    se.fileName   = this.getLocalFilename(n.Attributes["filename"].Value);
                    se.lineNumber = System.Convert.ToInt32(n.Attributes["lineno"].Value);
                    se.level      = System.Convert.ToInt32(n.Attributes["level"].Value);
                    se.location   = n.Attributes["where"].Value;
                    // TODO redundant? just remove the old one?
                    /* Linenumbers have to be zero based. Xdebug uses 1-based. */
                    se.Location.filename = se.fileName;
                    se.Location.line     = se.lineNumber - 1;

                    CallStack.Add(se);
                }
            }

            return(CallStack);
        }
예제 #3
0
        public static XDebug.Response Parse(String xml)
        {
            System.Xml.XmlDocument d = new XmlDocument();
            d.LoadXml(xml);

            XDebug.Response m = new XDebug.Response();
            m.RawMessage = xml;
            m.XmlMessage = d;

            string messageType = d.DocumentElement.Name.ToLower();

            switch (messageType)
            {
            case "init":
                m.MessageType = XDebug.Response.MSG_INIT;

                string fileUri =
                    d.DocumentElement.Attributes["fileuri"].Value;

                m.Attributes.Add("file", fileUri);

                break;

            case "response":
                bool isError = false;
                //d.DocumentElement.FirstChild.Name.ToLower() == "error";

                if (isError)
                {
                    m.MessageType = XDebug.Response.MSG_ERROR;
                    m.Attributes.Add(
                        "ErrorMessage",
                        d.DocumentElement.FirstChild.InnerText
                        );

                    return(m);
                }

                m.MessageType = XDebug.Response.MSG_RESPONSE;

                //  m.TransactionID = d.DocumentElement.Attributes["transaction_id"].Value;
                if (d.DocumentElement.Attributes["status"] != null)
                {
                    m.Attributes.Add(
                        "status",
                        d.DocumentElement.Attributes["status"].Value
                        );
                }


                break;

            default:
                throw new Exception("Unknown message type: " + messageType);
            }

            return(m);
        }
예제 #4
0
        /// <summary>
        /// Tell xdebug to remove a line-based breakpoint. Other types
        /// not yet supported.
        /// </summary>
        public void RemoveBreakpoint(Breakpoint brk)
        {
            XDebug.Command c = new Command(
                "breakpoint_remove",
                String.Format("-d {0}", brk.xdebugId)
                );

            XDebug.Response resp = this.SendCommand(c);
        }
예제 #5
0
        public static XDebug.Response Parse(String xml)
        {
            System.Xml.XmlDocument d = new XmlDocument();
            d.LoadXml(xml);

            XDebug.Response m = new XDebug.Response();
            m.RawMessage = xml;
            m.XmlMessage = d;

            string messageType = d.DocumentElement.Name.ToLower();

            switch (messageType)
            {
                case "init":
                    m.MessageType = XDebug.Response.MSG_INIT;

                    string fileUri =
                        d.DocumentElement.Attributes["fileuri"].Value;

                    m.Attributes.Add("file", fileUri);

                    break;

                case "response":
                    bool isError = false;
                    //d.DocumentElement.FirstChild.Name.ToLower() == "error";

                    if (isError)
                    {
                        m.MessageType = XDebug.Response.MSG_ERROR;
                        m.Attributes.Add(
                            "ErrorMessage",
                            d.DocumentElement.FirstChild.InnerText
                        );

                        return m;
                    }

                    m.MessageType = XDebug.Response.MSG_RESPONSE;

                    //  m.TransactionID = d.DocumentElement.Attributes["transaction_id"].Value;
                    if (d.DocumentElement.Attributes["status"] != null)
                    {
                        m.Attributes.Add(
                            "status",
                            d.DocumentElement.Attributes["status"].Value
                        );
                    }

                    break;

                default:
                    throw new Exception("Unknown message type: " + messageType);
            }

            return m;
        }
예제 #6
0
        /// <summary>
        /// Tell xdebug to set a line-based breakpoint. Other types
        /// not yet supported.
        /// </summary>
        public void AddBreakpoint(Breakpoint brk)
        {
            string filename = "file://";

            if (brk.filename[0] != '/')
            {
                filename += "/";
            }

            filename += System.Web.HttpUtility.UrlPathEncode(brk.filename);
            XDebug.Command c = new Command(
                "breakpoint_set",
                String.Format(
                    "-t line -f {0} -n {1}",
                    filename, brk.LineNumber_XDebug)
                );

            XDebug.Response resp = this.SendCommand(c);

            brk.xdebugId = resp.XmlMessage.DocumentElement.Attributes["id"].Value;
        }
예제 #7
0
        /// <summary>
        /// Tells XDebug our preferences.
        /// </summary>
        public bool Initialize()
        {
            /* As soon as we've been connected we'll receive the DBGP init
             * message. Parse it into a XDebugMessage and pass it to the GUI so
             * it can load the initial file. */

            XDebug.Response initMessage = this.ReceiveMessage();

            /* This might throw a NullReference exception. */
            try
            {
                if (this.handleInitMessage(initMessage))
                {
                    if (xdc.Properties.Settings.Default.break_on_fatal_errors)
                    {
                        /* We'd like to know when Fatal errors occur */
                        XDebug.Command  c = new Command("breakpoint_set", "-t exception -x \"Fatal error\"");
                        XDebug.Response r = this.SendCommand(c);
                    }

                    if (xdc.Properties.Settings.Default.break_on_notices)
                    {
                        /* We'd like to know when Notices occur */
                        XDebug.Command  c2 = new Command("breakpoint_set", "-t exception -x \"Notice\"");
                        XDebug.Response r2 = this.SendCommand(c2);
                    }

                    return(true);
                }
            }
            catch (Exception e)
            {
                throw new Exception("Initialization failed: " + e.Message);
            }

            return(false);
        }
예제 #8
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);
        }
예제 #9
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);
        }
예제 #10
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);
                }
            }
        }