From e9ae80694875f869892f13f4fcaf1170a00dea41 Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features. BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdewebdev@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- quanta/components/debugger/dbgp/Makefile.am | 17 + quanta/components/debugger/dbgp/dbgpnetwork.cpp | 314 ++++++ quanta/components/debugger/dbgp/dbgpnetwork.h | 76 ++ quanta/components/debugger/dbgp/dbgpsettings.cpp | 44 + quanta/components/debugger/dbgp/dbgpsettings.h | 35 + quanta/components/debugger/dbgp/dbgpsettingss.ui | 728 ++++++++++++++ quanta/components/debugger/dbgp/qbytearrayfifo.cpp | 76 ++ quanta/components/debugger/dbgp/qbytearrayfifo.h | 43 + .../debugger/dbgp/quantadebuggerdbgp.cpp | 1042 ++++++++++++++++++++ .../debugger/dbgp/quantadebuggerdbgp.desktop | 44 + .../components/debugger/dbgp/quantadebuggerdbgp.h | 166 ++++ 11 files changed, 2585 insertions(+) create mode 100644 quanta/components/debugger/dbgp/Makefile.am create mode 100644 quanta/components/debugger/dbgp/dbgpnetwork.cpp create mode 100644 quanta/components/debugger/dbgp/dbgpnetwork.h create mode 100644 quanta/components/debugger/dbgp/dbgpsettings.cpp create mode 100644 quanta/components/debugger/dbgp/dbgpsettings.h create mode 100644 quanta/components/debugger/dbgp/dbgpsettingss.ui create mode 100644 quanta/components/debugger/dbgp/qbytearrayfifo.cpp create mode 100644 quanta/components/debugger/dbgp/qbytearrayfifo.h create mode 100644 quanta/components/debugger/dbgp/quantadebuggerdbgp.cpp create mode 100644 quanta/components/debugger/dbgp/quantadebuggerdbgp.desktop create mode 100644 quanta/components/debugger/dbgp/quantadebuggerdbgp.h (limited to 'quanta/components/debugger/dbgp') diff --git a/quanta/components/debugger/dbgp/Makefile.am b/quanta/components/debugger/dbgp/Makefile.am new file mode 100644 index 00000000..fbff3bdf --- /dev/null +++ b/quanta/components/debugger/dbgp/Makefile.am @@ -0,0 +1,17 @@ +METASOURCES = AUTO + +kde_module_LTLIBRARIES = quantadebuggerdbgp.la + +quantadebuggerdbgp_la_SOURCES = quantadebuggerdbgp.cpp dbgpsettingss.ui \ + dbgpsettings.cpp dbgpnetwork.cpp qbytearrayfifo.cpp +quantadebuggerdbgp_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +quantadebuggerdbgp_la_LIBADD = ../interfaces/libdebuggerinterface.la $(LIB_KPARTS) +kde_services_DATA = quantadebuggerdbgp.desktop + +INCLUDES = -I$(top_srcdir)/quanta/components/debugger \ + -I$(top_srcdir)/quanta/components/debugger/interfaces -I$(top_srcdir)/quanta/components/debugger/dbgp \ + -I$(top_srcdir)/quanta/project -I$(top_srcdir)/quanta/utility $(all_includes) + + +noinst_HEADERS = dbgpsettings.h quantadebuggerdbgp.h dbgpnetwork.h \ + qbytearrayfifo.h diff --git a/quanta/components/debugger/dbgp/dbgpnetwork.cpp b/quanta/components/debugger/dbgp/dbgpnetwork.cpp new file mode 100644 index 00000000..87306448 --- /dev/null +++ b/quanta/components/debugger/dbgp/dbgpnetwork.cpp @@ -0,0 +1,314 @@ +/* + * Copyright (C) 2005 by Linus McCabe, + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "dbgpnetwork.h" + +#include +#include +#include +#include + +DBGpNetwork::DBGpNetwork() +: QObject() +{ + m_socket = NULL; + m_server = NULL; + m_datalen = -1; + m_transaction_id = 0; +} + +DBGpNetwork::~DBGpNetwork() +{ +} + +void DBGpNetwork::sessionStart(bool useproxy, const QString& server, const QString & service) +{ + + kdDebug(24002) << k_funcinfo << ", m_server: " << m_server << ", m_socket" << m_socket << endl; + m_useproxy = useproxy; + + if(m_useproxy) + { + if(m_socket) + { +// m_socket->setBufferSize(-1); + connect(m_socket, SIGNAL(gotError(int)), this, SLOT(slotError(int))); + connect(m_socket, SIGNAL(connected(const KResolverEntry &)), this, SLOT(slotConnected(const KNetwork::KResolverEntry &))); + connect(m_socket, SIGNAL(closed()), this, SLOT(slotConnectionClosed())); + connect(m_socket, SIGNAL(readyRead()), this, SLOT(slotReadyRead())); + connect(m_socket, SIGNAL(destroyed()), this, SLOT(slotSocketDestroyed())); + m_socket->connect(); + emit active(false); + kdDebug(24002) << k_funcinfo << ", proxy:" << server << ", " << service << endl; + } + } + else + { + if(!m_server) + { + m_server = new KNetwork::KServerSocket(service); + + m_server->setAddressReuseable(true); + connect(m_server, SIGNAL(readyAccept()), this, SLOT(slotReadyAccept())); + connect(m_server, SIGNAL(gotError(int)), this, SLOT(slotError(int))); + + if(m_server->listen()) + { + emit active(true); + emit networkError(i18n("Listening on port %1").arg(service), true); + } + else + { + delete m_server; + m_server = NULL; + emit active(false); + emit networkError(i18n("Unable to listen on port %1").arg(service), true); + } + } + } +} + + +void DBGpNetwork::sessionEnd() +{ + // Close socket + if(m_socket) + { + m_socket->flush(); + disconnect(m_socket, SIGNAL(closed()), this, SLOT(slotConnectionClosed())); + if (m_socket) + m_socket->close(); + delete m_socket; + m_socket = 0L; + } + + // Close the server + if(m_server) + { + m_server->close(); + delete m_server; + m_server = NULL; + } + + // Fake a connection closed signal + slotConnectionClosed(); + emit active(false); +} + + +// Socket errors +void DBGpNetwork::slotError(int) +{ + kdDebug(24002) << k_funcinfo << ", m_server: " << m_server << ", m_socket" << m_socket << endl; + if(m_socket) + { + kdDebug(24002) << k_funcinfo << ", " << m_socket->errorString() << endl; + if(m_socket->error() == KNetwork::KSocketBase::RemotelyDisconnected) + { + slotConnectionClosed(); + emit networkError(i18n("Disconnected from remote host"), true); + return; + } + + if(m_socket->error()) + { + emit networkError(m_socket->errorString(), true); + } + } + + if(m_server && m_server->error()) + { + kdDebug(24002) << k_funcinfo << ", " << m_server->errorString() << endl; + emit networkError(m_server->errorString(), true); + } +} + +// slotReadyAccept +void DBGpNetwork::slotReadyAccept() +{ + + kdDebug(24002) << k_funcinfo << ", m_server: " << m_server << ", m_socket" << m_socket << endl; + if(!m_socket) + { + disconnect(m_server, SIGNAL(readyAccept()), this, SLOT(slotReadyAccept())); + + m_socket = (KNetwork::KStreamSocket *)m_server->accept(); // KSocketServer returns a KStreamSocket (!) + if(m_socket) + { + kdDebug(24002) << k_funcinfo << ", ready" << ", m_socket" << m_socket << endl; + m_socket->enableRead(true); + m_socket->setAddressReuseable(true); +// m_socket->setSocketFlags(KExtendedSocket::inetSocket | KExtendedSocket::inputBufferedSocket); +// m_socket->setBufferSize(-1); + connect(m_socket, SIGNAL(gotError(int)), this, SLOT(slotError(int))); + connect(m_socket, SIGNAL(connected(const KResolverEntry &)), this, SLOT(slotConnected(const KResolverEntry &))); + connect(m_socket, SIGNAL(closed()), this, SLOT(slotConnectionClosed())); + connect(m_socket, SIGNAL(readyRead()), this, SLOT(slotReadyRead())); + connected(); + } + else + { + kdDebug(24002) << k_funcinfo << ", " << m_server->errorString() << endl; + } + } + +} + +// Connection established +void DBGpNetwork::slotConnected(const KResolverEntry &) +{ + connected(); +} + +bool DBGpNetwork::isConnected() +{ + return m_socket != NULL && m_socket->state() == KNetwork::KClientSocketBase::Connected; +} + +bool DBGpNetwork::isActive() +{ + return + (m_socket != NULL && m_socket->state() == KNetwork::KClientSocketBase::Connected) + || (m_server != NULL); +} + +void DBGpNetwork::connected() +{ + + kdDebug(24002) << k_funcinfo << endl; + emit connected(true); +// debuggerInterface()->enableAction("debug_disconnect", true); +// debuggerInterface()->enableAction("debug_request", false); +} + +// Connectio closed +void DBGpNetwork::slotConnectionClosed() +{ + kdDebug(24002) << k_funcinfo << ", m_server: " << m_server << ", m_socket" << m_socket << endl; + + // Check if we have more data to read + slotReadyRead(); +// kdDebug(24002) << k_funcinfo << "buffer: " << m_buffer << endl; + + if(m_socket) + { + m_socket->flush(); + m_socket->close(); + delete m_socket; + m_socket = NULL; + } + + if(m_server) + connect(m_server, SIGNAL(readyAccept()), this, SLOT(slotReadyAccept())); + + // Disable all session related actions and enable connection action + emit connected(false); + emit active(m_server != NULL); + +} + + +//called when m_socket is destroyed either by deleting it or if XDebug disconnects from the client +void DBGpNetwork::slotSocketDestroyed() +{ + kdDebug(24002) << k_funcinfo << " , m_server: " << m_server << ", m_socket" << m_socket << endl; + + m_socket = NULL; //m_socket is already wrong, without this the app would crash on the next m_socket->close() or delete m_socket call. + slotConnectionClosed(); +} + + +// Data from socket +void DBGpNetwork::slotReadyRead() +{ + + // Data from dbgp + while(m_socket && (m_socket->bytesAvailable() > 0 || m_fifo.length() >= (unsigned long)m_datalen)) + { + int bytes; + QString data; + + if(m_socket && m_socket->bytesAvailable() > 0 ) + { + // Read all available bytes from socket and append them to the buffer + bytes = m_socket->bytesAvailable(); + char* buffer = new char[bytes]; + m_socket->readBlock(buffer, bytes); + + // Put it in the fifo buffer + m_fifo.append(buffer, bytes); + + delete[] buffer; + } + + while(1) + { + // If datalen == -1, we didnt read the size yet, otherwise we're reading data. + if(m_datalen == -1) + { + bytes = m_fifo.find('\0'); + if(bytes < 0) + break; + + data = m_fifo.retrieve(); + m_datalen = data.toLong(); + + } + if(m_datalen != -1 && (long)m_fifo.length() >= m_datalen + 1) + { + data = m_fifo.retrieve(); + m_datalen = -1; + emit command(data); + } + else + break; + } + } +} + +long DBGpNetwork::sendCommand(const QString & command) +{ + return sendCommand(command, ""); +} + +long DBGpNetwork::sendCommand(const QString & command, const QString & arguments) +{ + if(!isConnected()) + return false; + + m_transaction_id++; + QString commandline = command + QString(" -i %1").arg(m_transaction_id) + (!arguments.isEmpty() ? " " : "") + arguments; + + kdDebug(24002) << k_funcinfo << ", sending: " << commandline << endl; + + m_socket->writeBlock(commandline.latin1(), commandline.length() + 1); // Send string + NULL termination + + return m_transaction_id; +} + +long DBGpNetwork::sendCommand( const QString & command, const QString & arguments, const QString & data ) +{ + QByteArrayFifo buffer; + buffer.append(data.ascii(), data.length()); + return sendCommand(command, arguments + " -- " + buffer.base64Encoded()); +} + +// #include "dbgpnetwork.moc" + +#include "dbgpnetwork.moc" diff --git a/quanta/components/debugger/dbgp/dbgpnetwork.h b/quanta/components/debugger/dbgp/dbgpnetwork.h new file mode 100644 index 00000000..0651bc08 --- /dev/null +++ b/quanta/components/debugger/dbgp/dbgpnetwork.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2005 by Linus McCabe, + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef dbgpnetwork_H +#define dbgpnetwork_H + +#include +#include + +#include "qbytearrayfifo.h" + +//using namespace KNetwork; +class KResolverEntry; + +class DBGpNetwork : public QObject +{ + Q_OBJECT + + private: + KNetwork::KStreamSocket *m_socket; + KNetwork::KServerSocket *m_server; + QByteArrayFifo m_fifo; + bool m_useproxy; + long m_datalen; + long m_transaction_id; + + void connected(); + + signals: + void active(bool isOnline); + void connected(bool isConnected); + void networkError(const QString &error, bool log); + void command(const QString& data); + + public: + DBGpNetwork(); + ~DBGpNetwork(); + + virtual void sessionStart(bool useproxy, const QString& server, const QString & service); + virtual void sessionEnd(); + + bool isConnected(); + bool isActive(); + + long sendCommand(const QString & command); + long sendCommand(const QString & command, const QString & arguments); + long sendCommand(const QString & command, const QString & arguments, const QString & data); + + public slots: + // Socket slots + void slotConnected(const KResolverEntry &); + void slotConnectionClosed(); + void slotError(int); + void slotReadyRead(); + void slotReadyAccept(); + void slotSocketDestroyed(); +}; + + +#endif // dbgpnetwork_H diff --git a/quanta/components/debugger/dbgp/dbgpsettings.cpp b/quanta/components/debugger/dbgp/dbgpsettings.cpp new file mode 100644 index 00000000..80b7eaf1 --- /dev/null +++ b/quanta/components/debugger/dbgp/dbgpsettings.cpp @@ -0,0 +1,44 @@ +/*************************************************************************** + dbgpsettings.cpp + ------------------- + begin : 2004-04-05 + copyright : (C) 2004 Linus McCabe + ***************************************************************************/ + +/**************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + + +#include "qlineedit.h" +#include "qcheckbox.h" +#include "dbgpsettings.h" +#include + +DBGpSettings::DBGpSettings(const QString &protocolversion) + : DBGpSettingsS(0, "DBGpSettings", false, 0) +{ + textAbout->setText(textAbout->text().replace("%PROTOCOLVERSION%", protocolversion)); + connect(checkLocalProject, SIGNAL(toggled(bool)), this, SLOT(slotLocalProjectToggle(bool))); +} + +DBGpSettings::~DBGpSettings() +{ +} + +void DBGpSettings::slotLocalProjectToggle( bool localproject) +{ + lineServerBasedir->setEnabled(!localproject); + lineLocalBasedir->setEnabled(!localproject); +} + + + + +#include "dbgpsettings.moc" + diff --git a/quanta/components/debugger/dbgp/dbgpsettings.h b/quanta/components/debugger/dbgp/dbgpsettings.h new file mode 100644 index 00000000..4f2721ff --- /dev/null +++ b/quanta/components/debugger/dbgp/dbgpsettings.h @@ -0,0 +1,35 @@ +/*************************************************************************** + dbgpsettings.h + ------------------- + begin : 2005-08-01 + copyright : (C) 2005 Linus McCabe + ***************************************************************************/ + +/**************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef DBGPSETTINGS_H +#define DBGPSETTINGS_H + +#include "dbgpsettingss.h" + +class DBGpSettings : public DBGpSettingsS +{ + Q_OBJECT + + public: + DBGpSettings(const QString &protocolversion); + ~DBGpSettings(); + + public slots: + virtual void slotLocalProjectToggle(bool localproject); +}; + +#endif + diff --git a/quanta/components/debugger/dbgp/dbgpsettingss.ui b/quanta/components/debugger/dbgp/dbgpsettingss.ui new file mode 100644 index 00000000..2b846a7e --- /dev/null +++ b/quanta/components/debugger/dbgp/dbgpsettingss.ui @@ -0,0 +1,728 @@ + +DBGpSettingsS + + + DBGpSettingsS + + + + 0 + 0 + 569 + 467 + + + + DBGp Settings + + + true + + + + unnamed + + + + Layout1 + + + + unnamed + + + 0 + + + 6 + + + + Horizontal Spacing2 + + + Horizontal + + + Expanding + + + + 20 + 20 + + + + + + buttonOk + + + &OK + + + + + + true + + + true + + + + + buttonCancel + + + Ca&ncel + + + true + + + + + + + tabWidget2 + + + true + + + + 5 + 5 + 1 + 1 + + + + + tab + + + &General + + + + unnamed + + + + groupBox2 + + + Connection Settings + + + + unnamed + + + + lblDebuggerServerListenPort + + + + 5 + 5 + 1 + 0 + + + + Listen port: + + + + + lineServerListenPort + + + + 7 + 0 + 4 + 0 + + + + + + lblRequest + + + + 5 + 5 + 1 + 0 + + + + Request URL: + + + + + lineStartSession + + + + 7 + 0 + 4 + 0 + + + + See "What's This?" for available variables + + + %afn - Filename of the current script +%afd - Absolute directory of the current script +%afp - Absolute path (directory + filename) of the current script + +%rfpd - Directory of the current script relative to project root +%rfpp - Path of the current script relative to project root + +%rfdd - Directory of the current script relative to document root +%rfdp - Path of the current script relative to document root + +%apd - Project root +%add - Document root of current script + + + + + + + spacer4 + + + Vertical + + + Expanding + + + + 21 + 40 + + + + + + groupBox1 + + + Directory Mapping + + + + unnamed + + + + lineServerBasedir + + + + 7 + 0 + 4 + 0 + + + + + + lblDebuggerServerBasedir + + + + 5 + 5 + 1 + 0 + + + + Server basedir: + + + + + lineLocalBasedir + + + + 7 + 0 + 4 + 0 + + + + + + + + + checkLocalProject + + + + 1 + 0 + 4 + 0 + + + + + + + + + + + + lblDebuggerLocalBasedir + + + + 5 + 5 + 1 + 0 + + + + Local basedir: + + + + + lblLocalProject + + + + 5 + 5 + 1 + 0 + + + + Local project: + + + + + + + groupBox3_2 + + + Profiling + + + + unnamed + + + + lineProfilerFilename + + + + 7 + 0 + 4 + 0 + + + + See "What's This?" for available variables + + + Path to the profiler output +%a - Appid as returned from the debugger +%c - CRC32 of the initial filepath + + + + + lblRequest_2 + + + + 5 + 5 + 1 + 0 + + + + Profiler output: + + + + + lblLocalProject_2 + + + + 5 + 5 + 1 + 0 + + + + Map profiler output: + + + + + checkProfilerMapFilename + + + + 1 + 0 + 4 + 0 + + + + + + + + + + If this checkbox is checked, the profiler output filename will be mapped using the basedirs just like the remote script files. + + + + + lblLocalProject_2_2 + + + + 5 + 5 + 1 + 0 + + + + Open automatically: + + + + + checkProfilerAutoOpen + + + + 1 + 0 + 4 + 0 + + + + + + + + + + If this checkbox is checked, the profiler output will be opened automatically once the session ends. + + + + + + + + + tab + + + Deb&ug Behavior + + + + unnamed + + + + groupBox4 + + + Error Handling + + + + unnamed + + + + checkBreakOnUserError + + + + 7 + 0 + 0 + 0 + + + + User errors + + + + + lblBreakOn + + + Break on: + + + AlignTop + + + + + checkBreakOnUserWarning + + + + 7 + 0 + 0 + 0 + + + + User warnings + + + + + checkBreakOnUserNotice + + + + 7 + 0 + 0 + 0 + + + + User notices + + + + + checkBreakOnNotice + + + + 7 + 0 + 0 + 0 + + + + Notices + + + + + checkBreakOnWarning + + + + 7 + 0 + 0 + 0 + + + + W&arnings + + + + + + + groupBox5 + + + Execution + + + + unnamed + + + + + Pause + + + image0 + + + + + Run + + + image1 + + + + comboDefaultExecutionState + + + + + lblDefaultExecutionMode + + + Default mode: + + + AlignVCenter + + + + + + + spacer4_3 + + + Vertical + + + Expanding + + + + 21 + 40 + + + + + + + + TabPage + + + &About + + + + unnamed + + + + textLabel1 + + + + 5 + 4 + 0 + 0 + + + + <h4>DBGp Plugin for Quanta +</h4> + + + + + textAbout + + + true + + + <html><head><meta name="qrichtext" content="1" /></head><body style="font-size:10pt;font-family:Bitstream Vera Sans"> +<p><span style="font-weight:600">About</span></p> +<p>DBGp is a debugger protocol defined by the developers of Xdebug. This plugin integrates debuggers that supports the DBGp protocol with Quanta. </p> +<p>In order to use this plugin for PHP debugging, you need to get a supporting debugger. Currently, only <a href="http://xdebug.org">Xdebug</a> is tested.</p> +<p>For more info about Xdebug, please visit the Xdebug website at <a href="http://xdebug.org">http://xdebug.org</a> </p> +<p><span style="font-weight:600">Technical Details</span></p> +<p>This version of the debugger supports version %PROTOCOLVERSION% of the DBGp protocol. </p> +</body></html> + + + + + + + + + + 89504e470d0a1a0a0000000d49484452000000100000001008060000001ff3ff610000027f49444154388d7d93df4b53611cc69ff73de7ccb375dcdad46d2e3269036d21c4420a0b898484e82a08a2a02238a41741dd77e14dff4074d521efbae8a61b2f6a892062604e53117165e28f864dd73adb999e3cdb79cfe9c25a9c4dfa5e3e3ccfe7fdfee02538a412830b226075c3b662804d006b9567a5d4b4d2a7d77a494d5002c81370c20075797dc7fd157804139f77445846a14898fe9a67ead38f4aff661d2031b81006a1e3a16053c7ddcb3e5c3cc5c1ebe1000046c5c6a7af3a86c776b1b2bef3c3cdb2373ebcb83a5e052406e725103a9388473a1e5d13d1e8e60f9b0c1566e1655245727a3b2f19cb5d13c3b7bfff71da43a16073c7bd4b024667b56aa0b7cb0b009858fca75deff1622367357d59d58764597e481203332238317be74ad8d7798ca2ffacbf6a4eceaa00e0d0dea554ac6feb50deaabbc15f635d3c806e9728f9fc6e865cc172b49c2b9875633c1bf34033fca00db6a495a33d3c805840a2c8692638426a00953a40a9dc0000a0820842f9180f80941987cd3c0717ef04bc598ac02354f0b80642c8c1f6096cca03d66a51b791ce37d7bd06007a45a80b7304d8370db82c3d4379564a31a350a404a0f45086a3dc0283c83358fbea5e80a5e7e8b4d2a713a60f53238b36afe630c75b54c45b5487d6eed3408d2c04333712e437b608009c93937e2634a5cec79ba3019febbf1dfc2c9631b594cb448cd19b216e2d55ddda0579245a165adf9f89f94e76b649203517b16d1be9cd5dccafa8997065f241982c4f2a8aa2395cbdf75fb5eac289218fe7c8adf6904b3ada7870b242c9c07ab6bc67e8ea48c89c7a1ee2d6161545d1809adf0800b22cbbbe99a7231a17ed21948f11d894587a26c0d273417e630b405e5194f25fff6f6493fb9b9d8e82910000000049454e44ae426082 + + + 89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000000ac49444154388ded94c10dc33008453f5637ea061ec24cd2293289976083ce440f6d2262b012da5b95277188133f7f4560e0e2039dfc4eb39e621f164097894455c30280debbdb539c0180881c25dcd15a73f2509c8588c0cc3b795a4c445b0170bf65e596158f821969f19af4e8b02bf1f7e2b3890bf09eb8f145660223b63eb6a267ad00e209b47d6cfb39143f824be42e825aab5b4f27b6f2993483db2c223a4aa3db6b0633ff14e80f79015c6574466adcb13f0000000049454e44ae426082 + + + + + buttonOk + clicked() + DBGpSettingsS + accept() + + + buttonCancel + clicked() + DBGpSettingsS + reject() + + + + tabWidget2 + lineLocalBasedir + lineServerBasedir + lineServerListenPort + checkBreakOnNotice + checkBreakOnWarning + checkBreakOnUserNotice + checkBreakOnUserWarning + checkBreakOnUserError + comboDefaultExecutionState + buttonOk + buttonCancel + + + slotLocalProjectToggled(bool) + checkLocalProject_toggled(bool) + slotLocalProjectToggle(bool) + + + + ktextbrowser.h + + diff --git a/quanta/components/debugger/dbgp/qbytearrayfifo.cpp b/quanta/components/debugger/dbgp/qbytearrayfifo.cpp new file mode 100644 index 00000000..3060e43d --- /dev/null +++ b/quanta/components/debugger/dbgp/qbytearrayfifo.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2005 by Linus McCabe, + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "qbytearrayfifo.h" +#include +#include + +QByteArrayFifo::QByteArrayFifo( ) +{ + m_size = 0; + m_array.resize(0); +} + +QString QByteArrayFifo::retrieve( ) +{ + // See if there's a null teminator somewhere + QString str(m_array); + size_t size = str.length() + 1; + + // Decrease size and move bytes to the beginning of the array + m_size -= size; + for(size_t cnt = 0; cnt < m_size; cnt++) + m_array[cnt] = m_array[cnt + size]; + + // Resize array, needed for find() to work + m_array.resize(m_size); + + return str; +} + +bool QByteArrayFifo::append(const char * chars, size_t size ) +{ + // Resize the array, fail if not possible + if(!m_array.resize(m_size + size )) + return false; + + // Copy the elements + for(size_t cnt = 0; cnt < size; cnt++) + m_array[cnt + m_size] = chars[cnt]; + + // Increase size var + m_size += size; + + return true; +} + +long QByteArrayFifo::find( char character ) +{ + // If size is 0, find() outputs a warning for some reason + if(m_size == 0) + return -1; + + return m_array.find(character); +} + +QString QByteArrayFifo::base64Encoded() +{ + return KCodecs::base64Encode(m_array); +} + diff --git a/quanta/components/debugger/dbgp/qbytearrayfifo.h b/quanta/components/debugger/dbgp/qbytearrayfifo.h new file mode 100644 index 00000000..a422bc3d --- /dev/null +++ b/quanta/components/debugger/dbgp/qbytearrayfifo.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2005 by Linus McCabe, + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef qbytearrayfifo_H +#define qbytearrayfifo_H + +#include +#include + +class QByteArrayFifo +{ + + public: + QByteArrayFifo(); + bool append(const char * chars, size_t size); + QString retrieve(); + QString base64Encoded(); + long find(char character); + size_t length() { return m_size; } + + private: + QByteArray m_array; + size_t m_size; + +}; + +#endif // qbytearrayfifo_H diff --git a/quanta/components/debugger/dbgp/quantadebuggerdbgp.cpp b/quanta/components/debugger/dbgp/quantadebuggerdbgp.cpp new file mode 100644 index 00000000..100ec9d3 --- /dev/null +++ b/quanta/components/debugger/dbgp/quantadebuggerdbgp.cpp @@ -0,0 +1,1042 @@ +/*************************************************************************** + quantadebuggerdbgp.cpp + ------------------- + begin : 2004-03-12 + copyright : (C) 2004 Linus McCabe + ***************************************************************************/ + +/**************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "debuggerclient.h" +#include "quantadebuggerdbgp.h" +#include "debuggerinterface.h" +#include "debuggerbreakpoint.h" +#include "dbgpsettings.h" +#include "debuggervariable.h" +#include "variableslistview.h" +#include "pathmapper.h" + + + +K_EXPORT_COMPONENT_FACTORY( quantadebuggerdbgp, + KGenericFactory("quantadebuggerdbgp")) + +const char QuantaDebuggerDBGp::protocolversion[] = "1.0"; + +QuantaDebuggerDBGp::QuantaDebuggerDBGp (QObject *parent, const char*, const QStringList&) + : DebuggerClient (parent, "DBGp") +{ + // Create a socket object and set up its signals + m_errormask = 1794; + m_supportsasync = false; + m_defaultExecutionState = Starting; + setExecutionState(m_defaultExecutionState); + emit updateStatus(DebuggerUI::NoSession); + + connect(&m_network, SIGNAL(command(const QString&)), this, SLOT(processCommand(const QString&))); + connect(&m_network, SIGNAL(active(bool)), this, SLOT(slotNetworkActive(bool))); + connect(&m_network, SIGNAL(connected(bool)), this, SLOT(slotNetworkConnected(bool))); + connect(&m_network, SIGNAL(networkError(const QString &, bool)), this, SLOT(slotNetworkError(const QString &, bool))); + +} + + +QuantaDebuggerDBGp::~QuantaDebuggerDBGp () +{ + +// kdDebug(24002) << k_funcinfo << endl; + + m_network.sessionEnd(); +} + +void QuantaDebuggerDBGp::slotNetworkActive(bool active) +{ + // debuggerInterface() might not be available, for example from project dialog + if(!debuggerInterface()) + return; + + debuggerInterface()->enableAction("debug_request", active); + debuggerInterface()->enableAction("debug_connect", !active); + debuggerInterface()->enableAction("debug_disconnect", active); + + setExecutionState(m_defaultExecutionState); + + if(active) + emit updateStatus(DebuggerUI::AwaitingConnection); + else + emit updateStatus(DebuggerUI::NoSession); + +} + +void QuantaDebuggerDBGp::slotNetworkConnected(bool connected) +{ + // debuggerInterface() might not be available, for example from project dialog + if(!debuggerInterface()) + return; + + m_active = connected; + + debuggerInterface()->enableAction("debug_run", connected); + debuggerInterface()->enableAction("debug_leap", connected); + debuggerInterface()->enableAction("debug_pause", connected); + debuggerInterface()->enableAction("debug_kill", connected); + + debuggerInterface()->enableAction("debug_stepinto", connected); + debuggerInterface()->enableAction("debug_stepover", connected); + debuggerInterface()->enableAction("debug_stepout", connected); + + debuggerInterface()->setActiveLine("", 0); + if(connected) + emit updateStatus(DebuggerUI::Connected); + else + { + setExecutionState(m_defaultExecutionState); + emit updateStatus(DebuggerUI::AwaitingConnection); + + profilerOpen(false); + } + +} + +void QuantaDebuggerDBGp::slotNetworkError(const QString &errormsg, bool log) +{ + debuggerInterface()->showStatus(errormsg, log); +} + + +// Try to make a connection to the dbgp server +void QuantaDebuggerDBGp::startSession() +{ + kdDebug(24002) << k_funcinfo << endl; + + m_network.sessionStart(m_useproxy, m_serverHost, m_useproxy ? m_serverPort : m_listenPort); +// setExecutionState(Starting); +} + + +void QuantaDebuggerDBGp::endSession() +{ + + kdDebug(24002) << k_funcinfo << endl; + + // Close the socket + m_network.sessionEnd(); + +// debuggerInterface()->enableAction("debug_request", false); +// debuggerInterface()->enableAction("debug_run", false); +// debuggerInterface()->enableAction("debug_leap", false); +// debuggerInterface()->enableAction("debug_pause", false); + +} + + +// Change executionstate of the script +void QuantaDebuggerDBGp::setExecutionState( const State & state, bool forcesend ) +{ + if(m_executionState != state || forcesend) + { + if(state == Running) + m_network.sendCommand("run"); + else if (state == Break) + m_network.sendCommand("break"); + } + m_executionState = state; + + if(debuggerInterface()) { + // The run action will be active if we're started, stopped or paused + debuggerInterface()->enableAction("debug_run", m_executionState == Break || m_executionState == Starting || m_executionState == Stopped); + + // The pause action will be enabled if we're running and either supports async or we're not connected (ie will start running) + debuggerInterface()->enableAction("debug_pause", m_executionState == Running && (m_supportsasync || !isActive())) ; + + // Kill is active if we're paused, just started of the debugger supports async, as long as we have an active session + debuggerInterface()->enableAction("debug_kill", isActive() && (m_executionState == Break || (m_executionState == Running && m_supportsasync) || m_executionState == Starting || m_executionState == Stopping )); + + // These are only activated when we have an active seesion and are paused + debuggerInterface()->enableAction("debug_stepinto", isActive() && (m_executionState == Break || m_executionState == Starting )); + debuggerInterface()->enableAction("debug_stepout", isActive() && (m_executionState == Break || m_executionState == Starting)); + debuggerInterface()->enableAction("debug_stepover", isActive() && (m_executionState == Break || m_executionState == Starting)); + } + +} + +// Change executionstate of the script +void QuantaDebuggerDBGp::setExecutionState(const QString &state) +{ + kdDebug(24002) << k_funcinfo << state << endl; + + if(state == "starting") + { + setExecutionState(Starting); + emit updateStatus(DebuggerUI::Paused); + } + else if(state == "stopping") + { + setExecutionState(Stopping); + emit updateStatus(DebuggerUI::Paused); + m_network.slotSocketDestroyed(); //XDebug disconnects when stopped and destroys our socket + } + else if(state == "stopped") + { + setExecutionState(Stopped); + emit updateStatus(DebuggerUI::Paused); + m_network.slotSocketDestroyed(); //XDebug disconnects when stopped and destroys our socket + } + else if(state == "running") + { + setExecutionState(Running); + emit updateStatus(DebuggerUI::Running); + } + else if(state == "break") + { + setExecutionState(Break); + emit updateStatus(DebuggerUI::Paused); + } + +} + +// Return capabilities of dbgp +const uint QuantaDebuggerDBGp::supports(DebuggerClientCapabilities::Capabilities cap) +{ + switch(cap) + { + case DebuggerClientCapabilities::LineBreakpoints: +// case DebuggerClientCapabilities::ConditionalBreakpoints: + case DebuggerClientCapabilities::StartSession: + case DebuggerClientCapabilities::EndSession: + case DebuggerClientCapabilities::Kill: + case DebuggerClientCapabilities::Pause: + case DebuggerClientCapabilities::Run: + //case DebuggerClientCapabilities::Skip: + case DebuggerClientCapabilities::StepOut: + case DebuggerClientCapabilities::StepInto: + case DebuggerClientCapabilities::StepOver: + case DebuggerClientCapabilities::Watches: + case DebuggerClientCapabilities::VariableSetValue: + case DebuggerClientCapabilities::ProfilerOpen: + return true; + + default: + return false; + } +} + + +// Process a dbgp command +void QuantaDebuggerDBGp::processCommand(const QString& datas) +{ + kdDebug(24002) << k_lineinfo << datas.left(50) << " (" << datas.length() << " bytes)" << endl; + + QDomDocument data; + data.setContent(datas); + kdDebug(24002) << datas << endl; + + // Did we get a normal response? + if(data.elementsByTagName("response").count() > 0) + { + QDomNode response = data.elementsByTagName("response").item(0); + QString command = attribute(response, "command"); + + // Status command + if(command == "status") + setExecutionState(attribute(response, "status")); + + // Callback stack + else if(command == "stack_get") + stackShow(response); + + // Reply from a user execution action + else if(command == "break" + || command == "step_over" + || command == "step_into" + || command == "step_out") + { + handleError(response); + // If this is the acknoledge of a step command, request the call stack + m_network.sendCommand("stack_get"); + setExecutionState(attribute(response, "status")); + handleError(response); + m_network.sendCommand("feature_get", "-n profiler_filename"); + sendWatches(); + } + + // Run + else if(command == "run" ) + { + setExecutionState(attribute(response, "status")); + handleError(response); + m_network.sendCommand("stack_get"); + } + + // Feature get replu + else if(command == "feature_get") + checkSupport(response); + + // Reply after adding a breakpoint + else if(command == "breakpoint_set") + setBreakpointKey(response); + + else if(command == "typemap_get") + typemapSetup(response); + + else if(command == "property_get") + showWatch(response); + + else if(command == "property_set") + propertySetResponse(response); + else if(command == "stop") + setExecutionState("stopped"); + + // Unknown command... + else + { + kdDebug(24002) << " * Unknown command: " << command << endl; + } + } + else if(data.elementsByTagName("init").count() > 0) + { + QDomNode init = data.elementsByTagName("init").item(0); + initiateSession(init); + return; + } + else + { + debuggerInterface()->showStatus(i18n("Unrecognized package: '%1%2'").arg(datas.left(50)).arg(datas.length() > 50 ? "..." : ""), true); + + kdDebug(24002) << datas << endl; + } + +} + +void QuantaDebuggerDBGp::initiateSession(const QDomNode& initpacket) +{ + if(attribute(initpacket, "protocol_version") != protocolversion) + { + debuggerInterface()->showStatus( + i18n("The debugger for %1 uses an unsupported protocol version (%2)") + .arg(attribute(initpacket, "language")) + .arg(attribute(initpacket, "protocol_version")) + , true); + + endSession(); + return; + } + QString path = attribute(initpacket, "fileuri"); + if (path.startsWith("file://")) + { + path.remove(0, 7); + } + debuggerInterface()->setActiveLine(mapServerPathToLocal(path), 0); + + // Store some vars + m_initialscript = attribute(initpacket, "fileuri"); + m_appid = attribute(initpacket, "appid"); + +// setExecutionState(Starting); +// m_network.sendCommand("feature_get", "-n encoding"); + m_network.sendCommand("feature_get", "-n supports_async"); +// m_network.sendCommand("feature_get", "-n breakpoint_types"); +// m_network.sendCommand("feature_get", "-n profiler_filename"); + m_network.sendCommand("feature_get", "-n breakpoint_set"); + m_network.sendCommand("feature_get", "-n supports_postmortem"); + m_network.sendCommand("typemap_get"); + m_network.sendCommand("feature_get", "-n quanta_initialized"); +} + +void QuantaDebuggerDBGp::stackShow(const QDomNode&node) +{ + bool foundlowlevel = false; + BacktraceType type; + QString typestr; + + // Clear backtrace + debuggerInterface()->backtraceClear(); + + // Add new one + for(QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) + { + // Type isnt currently correct with xdebug +// type = (attribute(child, "type") == "file" ? File : Eval); + typestr = attribute(child, "filename"); + if(typestr.find(QRegExp(".*%28[0-9]+%29%20%3A%20eval")) >= 0) + type = Eval; + else + type = File; + +// kdDebug(24002) << " * Stck " << attribute(child, "level") << ": " << attribute(child, "type") << " (" << type << ") = " << attribute(child, "filename") << ", " << attribute(child, "lineno") << endl; + + + // If this is the lowest level and the type + if(type == File && !foundlowlevel) + { + foundlowlevel = true; + debuggerInterface()->setActiveLine(mapServerPathToLocal(attribute(child, "filename")), attribute(child, "lineno").toLong() - 1); + } + + debuggerInterface()->backtraceShow( + attribute(child, "level").toLong(), + type, + attribute(child, "filename"), + attribute(child, "lineno").toLong() - 1, // Quanta lines are 0-based, DBGp is 1 based + attribute(child, "where")); + } + +} + +void QuantaDebuggerDBGp::checkSupport( const QDomNode & node ) +{ + QString feature = attribute(node, "feature_name"); + QString data = node.nodeValue(); + if(feature == "supports_async") + m_supportsasync = data.toLong(); + + // if the debugger supports breakpoints, we have to send all current ones + else if(feature == "breakpoint_set"/* && data.toLong()*/) + debuggerInterface()->refreshBreakpoints(); + + // Our own feature, probably not available but then we know we're done initiating + else if(feature == "quanta_initialized" ) + { + m_network.sendCommand("stack_get"); + if(m_executionState != Break) + setExecutionState(m_executionState, true); + } + +} + +QString QuantaDebuggerDBGp::attribute(const QDomNode&node, const QString &attribute) +{ + return node.attributes().namedItem(attribute).nodeValue(); +} + +// Turn on/off actions related to a debugging session +void QuantaDebuggerDBGp::debuggingState(bool enable) +{ + debuggerInterface()->enableAction("debug_kill", enable); + debuggerInterface()->enableAction("debug_stepout", enable); + debuggerInterface()->enableAction("debug_stepinto", enable); + debuggerInterface()->enableAction("debug_stepover", enable); + debuggerInterface()->enableAction("debug_skip", enable); +} + + +void QuantaDebuggerDBGp::sendWatches() +{ + for(QValueList::iterator it = m_watchlist.begin(); it != m_watchlist.end(); ++it) + m_network.sendCommand("property_get", "-n " + (*it)); +} + +// Return name of debugger +QString QuantaDebuggerDBGp::getName() +{ + return "DBGp"; // no i18n on the name +} + + +// Send HTTP Request +void QuantaDebuggerDBGp::request() +{ + QString request; + request = debuggerInterface()->activeFileParts(m_startsession); + + //if(request.startsWith(m_localBasedir, false)) + // request.remove(0, m_localBasedir.length()); + + //request = m_startsession + request; + kdDebug(24002) << k_funcinfo << ", request: " << request << endl; + debuggerInterface()->sendRequest(request); +} + + +// Go as fast as possible and dont update current line or watches +void QuantaDebuggerDBGp::run() +{ + setExecutionState(Running); +// m_network.sendCommand("run"); +// m_network.sendCommand("status"); +} + +// Step into function +void QuantaDebuggerDBGp::stepInto() +{ + m_network.sendCommand("step_into"); +} + +// Step over function +void QuantaDebuggerDBGp::stepOver() +{ + if(m_executionState == Starting) + m_network.sendCommand("step_into"); + else + m_network.sendCommand("step_over"); +} + +// Step out of function +void QuantaDebuggerDBGp::stepOut() +{ + m_network.sendCommand("step_out"); +} + + +// Kill the running script +void QuantaDebuggerDBGp::kill() +{ + m_network.sendCommand("stop"); +} + +// Pause execution +void QuantaDebuggerDBGp::pause() +{ + if(isActive()) + setExecutionState(Break); + else + setExecutionState(Starting); +// m_network.sendCommand("break"); +// m_network.sendCommand("status"); +} + + +// Add a breakpoint +void QuantaDebuggerDBGp::addBreakpoint (DebuggerBreakpoint* breakpoint) +{ + QString type; + if(breakpoint->type() == DebuggerBreakpoint::LineBreakpoint) + type = "line"; + else if(breakpoint->type() == DebuggerBreakpoint::ConditionalTrue) + type = "conditional"; + else + type = "watch"; + + long id = m_network.sendCommand( + "breakpoint_set", + "-t " + type + + " -f " + mapLocalPathToServer(breakpoint->filePath()) + + " -n " + QString::number(breakpoint->line() + 1) + , breakpoint->condition()); + + breakpoint->setKey(QString("id %1").arg(id)); +} + +void QuantaDebuggerDBGp::setBreakpointKey( const QDomNode & response ) +{ + long id; + + id = attribute(response, "transaction_id").toLong(); + if(id > 0) + { + QString oldkey = QString("id %1").arg(id); + DebuggerBreakpoint *bp = debuggerInterface()->findDebuggerBreakpoint(oldkey); + if(bp) + debuggerInterface()->updateBreakpointKey(*bp, attribute(response, "id")); + } +} + + +// Clear a breakpoint +void QuantaDebuggerDBGp::removeBreakpoint(DebuggerBreakpoint* bp) +{ + m_network.sendCommand("breakpoint_remove", "-d " + bp->key()); +} + +// A file was opened... +void QuantaDebuggerDBGp::fileOpened(const QString&) +{ +// sendCommand("reinitialize", 0); +} + +// Watch a variable +void QuantaDebuggerDBGp::addWatch(const QString & variable) +{ + if(m_watchlist.find(variable) == m_watchlist.end()) + m_watchlist.append(variable); + m_network.sendCommand("property_get", "-n " + variable); +} +// Remove watch +void QuantaDebuggerDBGp::removeWatch(DebuggerVariable *variable) +{ + if(m_watchlist.find(variable->name()) != m_watchlist.end()) + m_watchlist.remove(m_watchlist.find(variable->name())); +} + +// Show conditional breakpoint state +void QuantaDebuggerDBGp::showCondition(const StringMap &) +{ + +// DebuggerBreakpoint *bp = debuggerInterface()->newDebuggerBreakpoint(); +// bp->setType(args["type"] == "true" ? DebuggerBreakpoint::ConditionalTrue : DebuggerBreakpoint::ConditionalChange); +// bp->setCondition(args["expression"]); +// bp->setFilePath(mapServerPathToLocal(args["filename"])); +// bp->setClass(args["class"]); +// bp->setFunction(args["function"]); +// bp->setValue(args["value"]); +// +// bp->setState(DebuggerBreakpoint::Undefined); +// +// debuggerInterface()->showBreakpoint(*bp); +} + +// Read configuration +void QuantaDebuggerDBGp::readConfig(QDomNode node) +{ + // Server + QDomNode valuenode = node.namedItem("serverhost"); + m_serverHost = valuenode.firstChild().nodeValue(); + if(m_serverHost.isEmpty()) + m_serverHost = "localhost"; + + valuenode = node.namedItem("serverport"); + m_serverPort = valuenode.firstChild().nodeValue(); + if(m_serverPort.isEmpty()) + m_serverPort = "9000"; + + valuenode = node.namedItem("localbasedir"); + m_localBasedir = valuenode.firstChild().nodeValue(); + if(debuggerInterface()) + debuggerInterface()->Mapper()->setLocalBasedir(m_localBasedir); + + valuenode = node.namedItem("serverbasedir"); + m_serverBasedir = valuenode.firstChild().nodeValue(); + if(debuggerInterface()) + debuggerInterface()->Mapper()->setServerBasedir(m_serverBasedir); + + valuenode = node.namedItem("listenport"); + m_listenPort = valuenode.firstChild().nodeValue(); + if(m_listenPort.isEmpty()) + m_listenPort = "9000"; + + valuenode = node.namedItem("startsession"); + m_startsession = valuenode.firstChild().nodeValue(); + if(m_startsession.isEmpty()) + m_startsession = "http://localhost/%rfpp?XDEBUG_SESSION_START=1&XDEBUG_PROFILE"; + + valuenode = node.namedItem("defaultexecutionstate"); + if(valuenode.firstChild().nodeValue().isEmpty()) + m_defaultExecutionState = Starting; + else + { + if(valuenode.firstChild().nodeValue() == "break") + m_defaultExecutionState = Starting; + else + m_defaultExecutionState = Running; + } + + valuenode = node.namedItem("useproxy"); + m_useproxy = valuenode.firstChild().nodeValue() == "1"; + + valuenode = node.namedItem("errormask"); + m_errormask = valuenode.firstChild().nodeValue().toLong(); + kdDebug(24002) << k_funcinfo << ", m_errormask = " << m_errormask << endl; + + // Profiler + valuenode = node.namedItem("profilerfilename"); + m_profilerFilename = valuenode.firstChild().nodeValue(); + if(m_profilerFilename.isEmpty()) + m_profilerFilename = "/tmp/cachegrind.out.%a"; + + valuenode = node.namedItem("profiler_autoopen"); + m_profilerAutoOpen = valuenode.firstChild().nodeValue().toLong(); + + valuenode = node.namedItem("profiler_mapfilename"); + m_profilerMapFilename = valuenode.firstChild().nodeValue().toLong(); + + +} + + +// Show configuration +void QuantaDebuggerDBGp::showConfig(QDomNode node) +{ + DBGpSettings set(protocolversion); + + readConfig(node); + + if(m_localBasedir == "/" && m_serverBasedir == "/") + set.checkLocalProject->setChecked(true); + set.lineLocalBasedir->setText(m_localBasedir); + set.lineServerBasedir->setText(m_serverBasedir); + set.lineServerListenPort->setText(m_listenPort); + set.lineStartSession->setText(m_startsession); + if(m_defaultExecutionState == Starting) + set.comboDefaultExecutionState->setCurrentItem(0); + else + set.comboDefaultExecutionState->setCurrentItem(1); + + set.checkBreakOnNotice->setChecked(QuantaDebuggerDBGp::Notice & m_errormask); + set.checkBreakOnWarning->setChecked(QuantaDebuggerDBGp::Warning & m_errormask); + set.checkBreakOnUserNotice->setChecked(QuantaDebuggerDBGp::User_Notice & m_errormask); + set.checkBreakOnUserWarning->setChecked(QuantaDebuggerDBGp::User_Warning & m_errormask); + set.checkBreakOnUserError->setChecked(QuantaDebuggerDBGp::User_Error & m_errormask); + + set.lineProfilerFilename->setText(m_profilerFilename); + if(m_profilerAutoOpen) + set.checkProfilerAutoOpen->setChecked(true); + if(m_profilerMapFilename) + set.checkProfilerMapFilename->setChecked(true); + + if(set.exec() == QDialog::Accepted ) + { + QDomElement el; + + el = node.namedItem("localproject").toElement(); + if (!el.isNull()) + el.parentNode().removeChild(el); + el = node.ownerDocument().createElement("localproject"); + node.appendChild( el ); + if(set.checkLocalProject->isChecked()) + { + m_localBasedir = "/"; + m_serverBasedir = "/"; + } + else + { + m_localBasedir = set.lineLocalBasedir->text(); + m_serverBasedir = set.lineServerBasedir->text(); + if (!m_localBasedir.endsWith("/")) + m_localBasedir.append('/'); + if (!m_serverBasedir.endsWith("/")) + m_serverBasedir.append('/'); + } + + el = node.namedItem("localbasedir").toElement(); + if (!el.isNull()) + el.parentNode().removeChild(el); + el = node.ownerDocument().createElement("localbasedir"); + node.appendChild( el ); + el.appendChild( node.ownerDocument().createTextNode(m_localBasedir) ); + if(debuggerInterface()) + debuggerInterface()->Mapper()->setLocalBasedir(m_localBasedir); + + el = node.namedItem("serverbasedir").toElement(); + if (!el.isNull()) + el.parentNode().removeChild(el); + el = node.ownerDocument().createElement("serverbasedir"); + node.appendChild( el ); + if(debuggerInterface()) + debuggerInterface()->Mapper()->setServerBasedir(m_serverBasedir); + el.appendChild( node.ownerDocument().createTextNode(m_serverBasedir) ); + + el = node.namedItem("listenport").toElement(); + if (!el.isNull()) + el.parentNode().removeChild(el); + el = node.ownerDocument().createElement("listenport"); + node.appendChild( el ); + m_listenPort = set.lineServerListenPort->text(); + el.appendChild( node.ownerDocument().createTextNode(m_listenPort) ); + + el = node.namedItem("startsession").toElement(); + if (!el.isNull()) + el.parentNode().removeChild(el); + el = node.ownerDocument().createElement("startsession"); + node.appendChild( el ); + m_startsession = set.lineStartSession->text(); + el.appendChild(node.ownerDocument().createTextNode(m_startsession)); + + el = node.namedItem("defaultexecutionstate").toElement(); + if (!el.isNull()) + el.parentNode().removeChild(el); + el = node.ownerDocument().createElement("defaultexecutionstate"); + node.appendChild( el ); + if(set.comboDefaultExecutionState->currentItem() == 0) + { + m_defaultExecutionState = Starting; + el.appendChild(node.ownerDocument().createTextNode("break")); + } + else + { + m_defaultExecutionState = Running; + el.appendChild(node.ownerDocument().createTextNode("run")); + + } + + el = node.namedItem("errormask").toElement(); + if (!el.isNull()) + el.parentNode().removeChild(el); + el = node.ownerDocument().createElement("errormask"); + node.appendChild( el ); + m_errormask = (set.checkBreakOnNotice->isChecked() ? QuantaDebuggerDBGp::Notice : 0) + + (set.checkBreakOnWarning->isChecked() ? QuantaDebuggerDBGp::Warning : 0) + + (set.checkBreakOnUserNotice->isChecked() ? QuantaDebuggerDBGp::User_Notice : 0) + + (set.checkBreakOnUserWarning->isChecked() ? QuantaDebuggerDBGp::User_Warning : 0) + + (set.checkBreakOnUserError->isChecked() ? QuantaDebuggerDBGp::User_Error : 0); + kdDebug(24002) << k_funcinfo << ", m_errormask = " << m_errormask << endl; + el.appendChild( node.ownerDocument().createTextNode(QString::number(m_errormask))); + + // Profiler + el = node.namedItem("profilerfilename").toElement(); + if (!el.isNull()) + el.parentNode().removeChild(el); + el = node.ownerDocument().createElement("profilerfilename"); + node.appendChild( el ); + m_profilerFilename = set.lineProfilerFilename->text(); + el.appendChild(node.ownerDocument().createTextNode(m_profilerFilename)); + + el = node.namedItem("profilerfilename_map").toElement(); + if (!el.isNull()) + el.parentNode().removeChild(el); + el = node.ownerDocument().createElement("profilerfilename_map"); + node.appendChild( el ); + m_profilerMapFilename = (set.checkProfilerMapFilename->isChecked() ? true : false); + el.appendChild(node.ownerDocument().createTextNode(m_profilerMapFilename ? "1" : "0")); + + el = node.namedItem("profiler_autoopen").toElement(); + if (!el.isNull()) + el.parentNode().removeChild(el); + el = node.ownerDocument().createElement("profiler_autoopen"); + node.appendChild( el ); + m_profilerAutoOpen = (set.checkProfilerAutoOpen->isChecked() ? true : false); + el.appendChild(node.ownerDocument().createTextNode(m_profilerAutoOpen ? "1" : "0")); + } +} + +// Map a server filepath to a local one using project settings +QString QuantaDebuggerDBGp::mapServerPathToLocal(const QString& serverpath) +{ + // Translate filename from server to local + return debuggerInterface()->Mapper()->mapServerPathToLocal(serverpath); +} + +// Map a local filepath to a server one using project settings +QString QuantaDebuggerDBGp::mapLocalPathToServer(const QString& localpath) +{ + // Translate filename from local to server + return debuggerInterface()->Mapper()->mapLocalPathToServer(localpath); +} + +void QuantaDebuggerDBGp::variableSetValue(const DebuggerVariable &variable) +{ + m_network.sendCommand("property_set", "-n " + variable.name(), variable.value()); + + for(QValueList::iterator it = m_watchlist.begin(); it != m_watchlist.end(); ++it) + if((*it) == variable.name()) + { + m_network.sendCommand("property_get", "-n " + variable.name(), variable.value()); + return; + } + + return; +} + +void QuantaDebuggerDBGp::profilerOpen() +{ + profilerOpen(true); +} + +void QuantaDebuggerDBGp::profilerOpen(bool forceopen) +{ + QString profileroutput = m_profilerFilename; + profileroutput.replace("%a", m_appid); + profileroutput.replace("%c", m_initialscript); + + if(m_profilerMapFilename) + profileroutput = mapServerPathToLocal( profileroutput); + + bool exists = QFile::exists(profileroutput); + if(m_profilerAutoOpen || forceopen) + { + if(exists) + { + KRun *run = new KRun(profileroutput); + run->setAutoDelete(true); + } + else + { + if(forceopen) + KMessageBox::sorry(NULL, i18n("Unable to open profiler output (%1)").arg(profileroutput), i18n("Profiler File Error")); + else + debuggerInterface()->showStatus(i18n("Unable to open profiler output (%1)").arg(profileroutput), false); + } + } + else + { + debuggerInterface()->enableAction("debug_profiler_open", exists); + } +} + +void QuantaDebuggerDBGp::typemapSetup( const QDomNode & typemapnode ) +{ + /* + + + + + + + + + */ + +// // First defaults in case they are not sent (which seems to be the case with hash and xdebug) +// m_variabletypes["bool"] = "bool"; +// m_variabletypes["int"] = "int"; +// m_variabletypes["float"] = "float"; +// m_variabletypes["string"] = "string"; +// m_variabletypes["null"] = "null"; +// m_variabletypes["array"] = "hash"; +// m_variabletypes["hash"] = "hash"; +// m_variabletypes["object"] = "object"; +// m_variabletypes["resource"] = "resource"; + + QDomNode child = typemapnode.firstChild(); + while(!child.isNull()) + { + if(child.nodeName() == "map") + { + m_variabletypes[attribute(child, "name")] = attribute(child, "type"); + } + child = child.nextSibling(); + } +} + + +void QuantaDebuggerDBGp::showWatch( const QDomNode & variablenode) +{ + debuggerInterface()->showVariable(buildVariable(variablenode.firstChild())); +} + +void QuantaDebuggerDBGp::propertySetResponse( const QDomNode & setnode) +{ + if(attribute(setnode, "success") == "0") + { + debuggerInterface()->showStatus(i18n("Unable to set value of variable."), true); + } +} + + +DebuggerVariable* QuantaDebuggerDBGp::buildVariable( const QDomNode & variablenode) +{ + /* + Sample: + + + + + + + + + + + + + + */ + QString name = attribute(variablenode, "name"); + QString type = m_variabletypes[attribute(variablenode, "type")]; + + if(type == "int") + { + QString value = variablenode.firstChild().nodeValue(); + return debuggerInterface()->newDebuggerVariable( name, value, DebuggerVariableTypes::Integer); + } + else if (type == "string") + { + QCString value = QCString(variablenode.firstChild().nodeValue()); + value = KCodecs::base64Decode(value); + return debuggerInterface()->newDebuggerVariable( name, value, DebuggerVariableTypes::String); + } + else if (type == "bool") + { + QString value = variablenode.firstChild().nodeValue(); + return debuggerInterface()->newDebuggerVariable( name, value, DebuggerVariableTypes::Boolean); + } + else if (type == "resource") + { + QString value = variablenode.firstChild().nodeValue(); + return debuggerInterface()->newDebuggerVariable( name, value, DebuggerVariableTypes::Resource); + } + else if (type == "float") + { + QString value = variablenode.firstChild().nodeValue(); + return debuggerInterface()->newDebuggerVariable( name, value, DebuggerVariableTypes::Float); + } + else if (type == "null") + { + QString value = variablenode.firstChild().nodeValue(); + return debuggerInterface()->newDebuggerVariable( name, "", DebuggerVariableTypes::Undefined); + } + else if (type == "hash" || type == "array" || type == "object") + { + QDomNode child = variablenode.firstChild(); + QPtrList vars ; + while(!child.isNull()) + { + DebuggerVariable* var = buildVariable( child); + if(var) + vars.append(var); + + child = child.nextSibling(); + } + if(type == "object") + return debuggerInterface()->newDebuggerVariable(name, vars, DebuggerVariableTypes::Object); + else + return debuggerInterface()->newDebuggerVariable(name, vars, DebuggerVariableTypes::Array); + } + + return debuggerInterface()->newDebuggerVariable(name, "", DebuggerVariableTypes::Error);; +} + +void QuantaDebuggerDBGp::handleError(const QDomNode & statusnode ) +{ + + if(attribute(statusnode, "reason") == "error" || attribute(statusnode, "reason") == "aborted") + { + QDomNode errornode = statusnode.firstChild(); + while(!errornode.isNull()) + { + if(errornode.nodeName() == "error") + { + if(attribute(statusnode, "reason") == "error") + { + // Managable error + long error = attribute(errornode, "code").toLong(); + if(!(error & m_errormask)) + { + setExecutionState(Running); + } + else + { + emit updateStatus(DebuggerUI::HaltedOnError); + debuggerInterface()->showStatus(errornode.firstChild().nodeValue(), true); + } + break; + } + else + { + // Fatal error + emit updateStatus(DebuggerUI::HaltedOnError); + debuggerInterface()->showStatus(errornode.firstChild().nodeValue(), true); + } + } + errornode = errornode.nextSibling(); + } + } + +} + +#include "quantadebuggerdbgp.moc" diff --git a/quanta/components/debugger/dbgp/quantadebuggerdbgp.desktop b/quanta/components/debugger/dbgp/quantadebuggerdbgp.desktop new file mode 100644 index 00000000..3bebcf06 --- /dev/null +++ b/quanta/components/debugger/dbgp/quantadebuggerdbgp.desktop @@ -0,0 +1,44 @@ +[Desktop Entry] +Type=Service +Name=DBGp +Comment=DBGp debugger plugin, see http://xdebug.org +Comment[bg]=Приставка на дебъгер DBGp, http://xdebug.org +Comment[ca]=Connector de depuració DBGp, consulteu http://xdebug.org +Comment[cs]=DBGp debugger plugin, viz http://xdebug.org +Comment[da]=DBGp fejlretter-plugin, se http://xdebug.org +Comment[de]=DBGp Debugger Plugin, siehe http://xdebug.org +Comment[el]=Πρόσθετο αποσφαλματωτή DBGp, δείτε το http://xdebug.org +Comment[es]=Extensión para el depurador DBGp, vea http://xdebug.org +Comment[et]=DBGp siluri plugin, vaata http://xdebug.org +Comment[eu]=DBGp araztailearen plugina, ikusi http://xdebug.org +Comment[fa]=وصلۀ اشکال‌زدای DBGp، http://xdebug.org را ببینید +Comment[fi]=DBGp-debugliitännäinen, katso http://xdebug.org +Comment[fr]=Module de débogage DBGp, consultez http://xdebug.org +Comment[ga]=Breiseán dífhabhtóra DBGp, féach ar http://xdebug.org +Comment[gl]=Extensión DBGp para o depurador, vexa tamén http://xdebug.org +Comment[hu]=DBGp nyomkövető modul, lásd: http://xdebug.org +Comment[is]=DBGp aflúsunaríforrit. Sjá http://xdebug.org +Comment[it]=Plugin di degub DBGp, vedi http://xdebug.org +Comment[ja]=DBGp デバッガ プラグイン。http://xdebug.org をご覧ください。 +Comment[ka]=DBGp განბზიკვის მოდული, იხილეთ http://xdebug.org +Comment[lt]=DBGp derintuvės priedas, žr. http://xdebug.org +Comment[ms]=Plugin nyahpepijat DBGp, lihat http://xdebug.org +Comment[nds]=Fehlersöök-Moduul för't DBGp, kiek bi http://xdebug.org +Comment[ne]=DBGp त्रुटिमोचक प्लगइन, http://xdebug.org हेर्नुहोस् +Comment[nl]=DBGp-debugger-plugin, zie http://xdebug.org +Comment[pl]=Wtyczka debugera DBGp, patrz http://xdebug.org +Comment[pt]='Plugin' de depuração DBGp, veja http://xdebug.org +Comment[pt_BR]=Plugin de depuração DBGp, veja http://xdebug.org +Comment[ru]=Модуль для отладчика DBGp, http://xdebug.org +Comment[sk]=DBGp debuger modul, pozri http://xdebug.org +Comment[sl]=Vstavek za razhoroščevanje DBGp, glej http://xdebug.org +Comment[sr]=DBGp прикључак, види http://xdebug.org +Comment[sr@Latn]=DBGp priključak, vidi http://xdebug.org +Comment[sv]=DBGp-insticksprogram för felsökning, se http://xdebug.org +Comment[uk]=Втулок зневаджувача DBGp, див. http://xdebug.org +Comment[zh_CN]=DBGp 调试器插件,参看 http://xdebug.org +Comment[zh_HK]=DBGp 除錯器外掛程式,請參閱 http://xdebug.org +Comment[zh_TW]=DBGp 除錯器外掛程式,請參閱 http://xdebug.org +Icon=kdbg +ServiceTypes=Quanta/Debugger +X-KDE-Library=quantadebuggerdbgp diff --git a/quanta/components/debugger/dbgp/quantadebuggerdbgp.h b/quanta/components/debugger/dbgp/quantadebuggerdbgp.h new file mode 100644 index 00000000..fd8eda22 --- /dev/null +++ b/quanta/components/debugger/dbgp/quantadebuggerdbgp.h @@ -0,0 +1,166 @@ +/*************************************************************************** + phpdebugdbgp.cpp + ------------------- + begin : 2004-03-12 + copyright : (C) 2004 Linus McCabe + ***************************************************************************/ + +/**************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QUANTADEBUGGERGUBED_H +#define QUANTADEBUGGERGUBED_H + +#include +#include +#include +#include +#include + +#include "debuggerclient.h" +#include "dbgpnetwork.h" + +typedef QValueList WatchList; +typedef QMap StringMap; + +class QuantaDebuggerDBGp : public DebuggerClient +{ + Q_OBJECT + + public: + QuantaDebuggerDBGp(QObject *parent, const char* name, const QStringList&); + ~QuantaDebuggerDBGp(); + + // Execution states + enum State + { + Starting = 0, + Stopping, + Stopped, + Running, + Break + }; + // Error codes + enum Errors + { + Warning = 2, + Notice = 8, + User_Error = 256, + User_Warning = 512, + User_Notice = 1024 + }; + + // Protocol version + static const char protocolversion[]; + + // Manager interaction + const uint supports(DebuggerClientCapabilities::Capabilities); + + // Execution control + void request(); + void run(); + void stepInto(); + void stepOver(); + void stepOut(); + void pause(); + void kill(); + void setExecutionState(const QString &state); + void setExecutionState(const State &state, bool forcesend = false); + + // Connection + void startSession(); + void endSession(); + + // Return name of debugger + QString getName(); + + // Initiation + void checkSupport(const QDomNode&node); + + // New file opened in quanta + void fileOpened(const QString& file); + + // Settings + void readConfig(QDomNode node); + void showConfig(QDomNode node); + + // Breakpoints + void addBreakpoint(DebuggerBreakpoint* breakpoint); + void removeBreakpoint(DebuggerBreakpoint* breakpoint); + void showCondition(const StringMap &args); + + // Variables + void addWatch(const QString &variable); + void removeWatch(DebuggerVariable *var); + void variableSetValue(const DebuggerVariable &variable); + void propertySetResponse( const QDomNode & setnode); + + // Call stack + void stackShow(const QDomNode&node); + + private: + DBGpNetwork m_network; + + QString m_serverBasedir; + QString m_localBasedir; + QString m_serverPort; + QString m_serverHost; + QString m_startsession; + QString m_listenPort; + QString m_profilerFilename; + QString m_appid; + QString m_initialscript; + + bool m_useproxy; + bool m_profilerAutoOpen; + bool m_profilerMapFilename; + State m_executionState, m_defaultExecutionState; + long m_errormask; + long m_displaydelay; + bool m_supportsasync; + + // Variable type mapping + StringMap m_variabletypes; + + // Internal watchlist + WatchList m_watchlist; + + void sendWatches(); + void debuggingState(bool enable); + void connected(); + + void handleError(const QDomNode & statusnode ); + + QString mapServerPathToLocal(const QString& serverpath); + QString mapLocalPathToServer(const QString& localpath); + QString bpToDBGp(DebuggerBreakpoint* breakpoint); + void setBreakpointKey(const QDomNode& response); + + QString attribute(const QDomNode&node, const QString &attribute); + void initiateSession(const QDomNode& initpacket); + + void typemapSetup(const QDomNode& typemapnode); + void showWatch(const QDomNode& typemapnode); + DebuggerVariable* buildVariable(const QDomNode& typemapnode); + + // Profiler + void profilerOpen(bool forceopen); + void profilerOpen(); + + public slots: + void slotNetworkActive(bool active); + void slotNetworkConnected(bool connected); + void slotNetworkError(const QString &errormsg, bool log); + void processCommand(const QString&); + + signals: + void updateStatus(DebuggerUI::DebuggerStatus); +}; + +#endif -- cgit v1.2.1