diff --git a/code/nel/CMakeLists.txt b/code/nel/CMakeLists.txt index 53bf071e3..00290d097 100644 --- a/code/nel/CMakeLists.txt +++ b/code/nel/CMakeLists.txt @@ -84,3 +84,6 @@ IF(WITH_NEL_TOOLS OR WITH_NEL_MAXPLUGIN) ADD_SUBDIRECTORY(tools) ENDIF(WITH_NEL_TOOLS OR WITH_NEL_MAXPLUGIN) +IF(WITH_QT) + ADD_SUBDIRECTORY(rcerror) +ENDIF(WITH_QT) diff --git a/code/nel/include/nel/misc/report.h b/code/nel/include/nel/misc/report.h index 11745b6e3..6bf3df959 100644 --- a/code/nel/include/nel/misc/report.h +++ b/code/nel/include/nel/misc/report.h @@ -21,21 +21,8 @@ namespace NLMISC { -/** Display a custom message box. - * - * \param title set the title of the report. If empty, it'll display "NeL report". - * \param header message displayed before the edit text box. If empty, it displays the default message. - * \param body message displayed in the edit text box. This string will be sent by email. - * \param debugButton 0 for disabling it, 1 for enable with default behaviors (generate a breakpoint), 2 for enable with no behavior - * - * - * - * \return the button clicked or error - */ - -enum TReportResult { ReportDebug, ReportIgnore, ReportQuit, ReportError }; - -TReportResult report (const std::string &title, const std::string &header, const std::string &subject, const std::string &body, bool enableCheckIgnore, uint debugButton, bool ignoreButton, sint quitButton, bool sendReportButton, bool &ignoreNextTime, const std::string &attachedFile = ""); +/// Prepares the error report, writes it to disk and launches the error reporter +void report ( const std::string &body ); /** call this in the main of your appli to enable email: setReportEmailFunction (sendEmail); */ diff --git a/code/nel/rcerror/CMakeLists.txt b/code/nel/rcerror/CMakeLists.txt new file mode 100644 index 000000000..51522cf0c --- /dev/null +++ b/code/nel/rcerror/CMakeLists.txt @@ -0,0 +1,39 @@ +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SRC_DIR} ${QT_INCLUDES}) +FILE(GLOB RCERROR_SRC *.cpp) +FILE(GLOB RCERROR_HDR *h) + +SET(RCERROR_MOC_HDR +rcerror_socket.h +rcerror_widget.h +) + +SET(RCERROR_UI +rcerror_widget.ui +) + +SET(QT_USE_QTGUI TRUE) +SET(QT_USE_QTNETWORK TRUE) +SET(QT_USE_QTMAIN TRUE) +SET(QT_USE_QTOPENGL FALSE) +SET(QT_USE_QTXML FALSE) + +INCLUDE(${QT_USE_FILE}) +ADD_DEFINITIONS(${QT_DEFINITIONS}) + +QT4_WRAP_CPP(RCERROR_MOC_SRC ${RCERROR_MOC_HDR}) +QT4_WRAP_UI(RCERROR_UI_HDR ${RCERROR_UI}) + +SOURCE_GROUP(QtResources FILES ${RCERROR_UI}) +SOURCE_GROUP(QtGeneratedUiHdr FILES ${RCERROR_UI_HDR}) +SOURCE_GROUP(QtGeneratedMocQrcSrc FILES ${RCERROR_MOC_SRC}) +SOURCE_GROUP("source files" FILES ${RCERROR_SRC}) +SOURCE_GROUP("header files" FILES ${RCERROR_HDR}) + +ADD_EXECUTABLE(rcerror WIN32 MACOSX_BUNDLE ${RCERROR_SRC} ${RCERROR_MOC_HDR} ${RCERROR_MOC_SRC} ${RCERROR_UI_HDR}) +TARGET_LINK_LIBRARIES(rcerror ${QT_LIBRARIES} ${QT_QTMAIN_LIBRARY}) + +NL_DEFAULT_PROPS(rcerror "Ryzom Core Error Reporter") +NL_ADD_RUNTIME_FLAGS(rcerror) + +INSTALL(TARGETS rcerror RUNTIME DESTINATION ${NL_BIN_PREFIX}) + diff --git a/code/nel/rcerror/rcerror.cpp b/code/nel/rcerror/rcerror.cpp new file mode 100644 index 000000000..0d5088167 --- /dev/null +++ b/code/nel/rcerror/rcerror.cpp @@ -0,0 +1,33 @@ +// Ryzom Core MMORPG framework - Error Reporter +// +// Copyright (C) 2015 Laszlo Kis-Adam +// Copyright (C) 2010 Ryzom Core +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "rcerror_widget.h" +#include +#include + +int main( int argc, char **argv ) +{ + QApplication app( argc, argv ); + + RCErrorWidget w; + w.setFileName( "rcerrorlog.txt" ); + w.show(); + + return app.exec(); +} \ No newline at end of file diff --git a/code/nel/rcerror/rcerror_data.h b/code/nel/rcerror/rcerror_data.h new file mode 100644 index 000000000..9f12b12fd --- /dev/null +++ b/code/nel/rcerror/rcerror_data.h @@ -0,0 +1,33 @@ +// Ryzom Core MMORPG framework - Error Reporter +// +// Copyright (C) 2015 Laszlo Kis-Adam +// Copyright (C) 2010 Ryzom Core +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef RCERROR_DATA +#define RCERROR_DATA + +#include + + +struct RCErrorData +{ + QString description; + QString report; + QString email; +}; + +#endif diff --git a/code/nel/rcerror/rcerror_socket.cpp b/code/nel/rcerror/rcerror_socket.cpp new file mode 100644 index 000000000..8a011c046 --- /dev/null +++ b/code/nel/rcerror/rcerror_socket.cpp @@ -0,0 +1,70 @@ +// Ryzom Core MMORPG framework - Error Reporter +// +// Copyright (C) 2015 Laszlo Kis-Adam +// Copyright (C) 2010 Ryzom Core +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "rcerror_socket.h" +#include +#include +#include +#include + +namespace +{ + static const char *BUG_URL = "http://192.168.2.66/dfighter/r.php"; +} + +class RCErrorSocketPvt +{ +public: + QNetworkAccessManager mgr; +}; + +RCErrorSocket::RCErrorSocket( QObject *parent ) : +QObject( parent ) +{ + m_pvt = new RCErrorSocketPvt(); + + connect( &m_pvt->mgr, SIGNAL( finished( QNetworkReply* ) ), this, SLOT( onFinished( QNetworkReply* ) ) ); +} + +RCErrorSocket::~RCErrorSocket() +{ + delete m_pvt; +} + +void RCErrorSocket::sendReport( const RCErrorData &data ) +{ + QUrl params; + params.addQueryItem( "report", data.report ); + params.addQueryItem( "descr", data.description ); + params.addQueryItem( "email", data.email ); + + QUrl url( BUG_URL ); + QNetworkRequest request( url ); + request.setRawHeader( "Connection", "close" ); + + m_pvt->mgr.post( request, params.encodedQuery() ); +} + +void RCErrorSocket::onFinished( QNetworkReply *reply ) +{ + if( reply->error() != QNetworkReply::NoError ) + Q_EMIT reportFailed(); + else + Q_EMIT reportSent(); +} + diff --git a/code/nel/rcerror/rcerror_socket.h b/code/nel/rcerror/rcerror_socket.h new file mode 100644 index 000000000..a37fa32d0 --- /dev/null +++ b/code/nel/rcerror/rcerror_socket.h @@ -0,0 +1,51 @@ +// Ryzom Core MMORPG framework - Error Reporter +// +// Copyright (C) 2015 Laszlo Kis-Adam +// Copyright (C) 2010 Ryzom Core +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef RCERROR_SOCKET +#define RCERROR_SOCKET + +#include +#include "rcerror_data.h" + +class RCErrorSocketPvt; +class QNetworkReply; + +class RCErrorSocket : public QObject +{ + Q_OBJECT + +public: + RCErrorSocket( QObject *parent ); + ~RCErrorSocket(); + + void sendReport( const RCErrorData &data ); + +Q_SIGNALS: + void reportSent(); + void reportFailed(); + +private Q_SLOTS: + void onFinished( QNetworkReply *reply ); + +private: + RCErrorSocketPvt *m_pvt; +}; + +#endif + diff --git a/code/nel/rcerror/rcerror_widget.cpp b/code/nel/rcerror/rcerror_widget.cpp new file mode 100644 index 000000000..a28afbca6 --- /dev/null +++ b/code/nel/rcerror/rcerror_widget.cpp @@ -0,0 +1,110 @@ +// Ryzom Core MMORPG framework - Error Reporter +// +// Copyright (C) 2015 Laszlo Kis-Adam +// Copyright (C) 2010 Ryzom Core +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "rcerror_widget.h" +#include "rcerror_socket.h" +#include "rcerror_data.h" +#include +#include +#include +#include + +RCErrorWidget::RCErrorWidget( QWidget *parent ) : +QWidget( parent ) +{ + m_ui.setupUi( this ); + + m_socket = new RCErrorSocket( this ); + + QTimer::singleShot( 1, this, SLOT( onLoad() ) ); + + connect( m_ui.sendButton, SIGNAL( clicked( bool ) ), this, SLOT( onSendClicked() ) ); + connect( m_ui.canceButton, SIGNAL( clicked( bool ) ), this, SLOT( onCancelClicked() ) ); + connect( m_ui.emailCB, SIGNAL( stateChanged( int ) ), this, SLOT( onCBClicked() ) ); + + connect( m_socket, SIGNAL( reportSent() ), this, SLOT( onReportSent() ) ); + connect( m_socket, SIGNAL( reportFailed() ), this, SLOT( onReportFailed() ) ); +} + +RCErrorWidget::~RCErrorWidget() +{ + m_socket = NULL; +} + +void RCErrorWidget::onLoad() +{ + QFile f( m_fileName ); + bool b = f.open( QFile::ReadOnly | QFile::Text ); + if( !b ) + { + QMessageBox::information( this, + tr( "No log file found" ), + tr( "There was no log file found, therefore nothing to report. Exiting..." ) ); + close(); + } + + QTextStream ss( &f ); + m_ui.reportEdit->setPlainText( ss.readAll() ); + f.close(); +} + +void RCErrorWidget::onSendClicked() +{ + m_ui.sendButton->setEnabled( false ); + QApplication::setOverrideCursor( Qt::WaitCursor ); + + RCErrorData data; + data.description = m_ui.descriptionEdit->toPlainText(); + data.report = m_ui.reportEdit->toPlainText(); + data.email = m_ui.emailEdit->text(); + + m_socket->sendReport( data ); +} + +void RCErrorWidget::onCancelClicked() +{ + close(); +} + +void RCErrorWidget::onCBClicked() +{ + m_ui.emailEdit->setEnabled( m_ui.emailCB->isChecked() ); +} + +void RCErrorWidget::onReportSent() +{ + QApplication::setOverrideCursor( Qt::ArrowCursor ); + + QMessageBox::information( this, + tr( "Report sent" ), + tr( "The report has been sent." ) ); + + close(); +} + +void RCErrorWidget::onReportFailed() +{ + QApplication::setOverrideCursor( Qt::ArrowCursor ); + + QMessageBox::information( this, + tr( "Report failed" ), + tr( "Failed to send the report..." ) ); + + close(); +} \ No newline at end of file diff --git a/code/nel/rcerror/rcerror_widget.h b/code/nel/rcerror/rcerror_widget.h new file mode 100644 index 000000000..1dd51c2af --- /dev/null +++ b/code/nel/rcerror/rcerror_widget.h @@ -0,0 +1,53 @@ +// Ryzom Core MMORPG framework - Error Reporter +// +// Copyright (C) 2015 Laszlo Kis-Adam +// Copyright (C) 2010 Ryzom Core +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef RCERROR_WIDGET +#define RCERROR_WIDGET + + +#include "ui_rcerror_widget.h" + +class RCErrorSocket; + +class RCErrorWidget : public QWidget +{ + Q_OBJECT +public: + RCErrorWidget( QWidget *parent = NULL ); + ~RCErrorWidget(); + + void setFileName( const char *fn ){ m_fileName = fn; } + +private Q_SLOTS: + void onLoad(); + void onSendClicked(); + void onCancelClicked(); + void onCBClicked(); + + void onReportSent(); + void onReportFailed(); + +private: + Ui::RCErrorWidget m_ui; + QString m_fileName; + RCErrorSocket *m_socket; +}; + +#endif + diff --git a/code/nel/rcerror/rcerror_widget.ui b/code/nel/rcerror/rcerror_widget.ui new file mode 100644 index 000000000..72e5f92f5 --- /dev/null +++ b/code/nel/rcerror/rcerror_widget.ui @@ -0,0 +1,82 @@ + + + RCErrorWidget + + + Qt::ApplicationModal + + + + 0 + 0 + 400 + 407 + + + + Ryzom Core error report + + + + + + What were you doing when the crash occured? + + + + + + + + + + Contents of the report ( automatically generated ) + + + + + + + true + + + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Email me if you have further questions, or updates on this issue + + + + + + + false + + + Enter your email address here + + + + + + + Send + + + + + + + Cancel + + + + + + + + diff --git a/code/nel/src/misc/debug.cpp b/code/nel/src/misc/debug.cpp index c7667acc2..67c8cb0f3 100644 --- a/code/nel/src/misc/debug.cpp +++ b/code/nel/src/misc/debug.cpp @@ -83,7 +83,7 @@ using namespace std; #define LOG_IN_FILE NEL_LOG_IN_FILE // If true, debug system will trap crash even if the application is in debugger -static const bool TrapCrashInDebugger = false; +static const bool TrapCrashInDebugger = true; #ifdef DEBUG_NEW #define new DEBUG_NEW @@ -553,7 +553,7 @@ public: // yoyo: allow only to send the crash report once. Because users usually click ignore, // which create noise into list of bugs (once a player crash, it will surely continues to do it). bool i = false; - report (progname+shortExc, "", subject, _Reason, true, 1, true, 1, !isCrashAlreadyReported(), i, NL_CRASH_DUMP_FILE); + report ( _Reason ); // no more sent mail for crash setCrashAlreadyReported(true); @@ -1193,13 +1193,7 @@ void createDebug (const char *logPath, bool logInFile, bool eraseLastLog) INelContext::getInstance().setAssertLog(new CLog (CLog::LOG_ASSERT)); sd = new CStdDisplayer ("DEFAULT_SD"); - -#ifdef NL_OS_WINDOWS - if (TrapCrashInDebugger || !IsDebuggerPresent ()) - { - DefaultMsgBoxDisplayer = new CMsgBoxDisplayer ("DEFAULT_MBD"); - } -#endif + DefaultMsgBoxDisplayer = new CMsgBoxDisplayer ("DEFAULT_MBD"); #if LOG_IN_FILE if (logInFile) diff --git a/code/nel/src/misc/displayer.cpp b/code/nel/src/misc/displayer.cpp index d48c44d02..8296d1c0b 100644 --- a/code/nel/src/misc/displayer.cpp +++ b/code/nel/src/misc/displayer.cpp @@ -529,115 +529,7 @@ void CFileDisplayer::doDisplay ( const CLog::TDisplayInfo& args, const char *mes // in release "" void CMsgBoxDisplayer::doDisplay ( const CLog::TDisplayInfo& args, const char *message) { -#ifdef NL_OS_WINDOWS - - bool needSpace = false; -// stringstream ss; - string str; - - // create the string for the clipboard - - if (args.Date != 0) - { - str += dateToHumanString(args.Date); - needSpace = true; - } - - if (args.LogType != CLog::LOG_NO) - { - //if (needSpace) { ss << " "; needSpace = false; } - if (needSpace) { str += " "; needSpace = false; } - str += logTypeToString(args.LogType); - needSpace = true; - } - - if (!args.ProcessName.empty()) - { - //if (needSpace) { ss << " "; needSpace = false; } - if (needSpace) { str += " "; needSpace = false; } - str += args.ProcessName; - needSpace = true; - } - - if (args.FileName != NULL) - { - //if (needSpace) { ss << " "; needSpace = false; } - if (needSpace) { str += " "; needSpace = false; } - str += CFile::getFilename(args.FileName); - needSpace = true; - } - - if (args.Line != -1) - { - //if (needSpace) { ss << " "; needSpace = false; } - if (needSpace) { str += " "; needSpace = false; } - str += NLMISC::toString(args.Line); - needSpace = true; - } - - if (args.FuncName != NULL) - { - //if (needSpace) { ss << " "; needSpace = false; } - if (needSpace) { str += " "; needSpace = false; } - str += args.FuncName; - needSpace = true; - } - - if (needSpace) { str += ": "; needSpace = false; } - - str += message; - - CSystemUtils::copyTextToClipboard(str); - - // create the string on the screen - needSpace = false; -// stringstream ss2; - string str2; - -#ifdef NL_DEBUG - if (!args.ProcessName.empty()) - { - if (needSpace) { str2 += " "; needSpace = false; } - str2 += args.ProcessName; - needSpace = true; - } - - if (args.FileName != NULL) - { - if (needSpace) { str2 += " "; needSpace = false; } - str2 += CFile::getFilename(args.FileName); - needSpace = true; - } - - if (args.Line != -1) - { - if (needSpace) { str2 += " "; needSpace = false; } - str2 += NLMISC::toString(args.Line); - needSpace = true; - } - - if (args.FuncName != NULL) - { - if (needSpace) { str2 += " "; needSpace = false; } - str2 += args.FuncName; - needSpace = true; - } - - if (needSpace) { str2 += ": "; needSpace = false; } - -#endif // NL_DEBUG - - str2 += message; - str2 += "\n\n(this message was copied in the clipboard)"; - -/* if (IsDebuggerPresent ()) - { - // Must break in assert call - DebugNeedAssert = true; - } - else -*/ { - + // Display the report string body; @@ -657,70 +549,8 @@ void CMsgBoxDisplayer::doDisplay ( const CLog::TDisplayInfo& args, const char *m body += "Reason: " + toString(message); body += args.CallstackAndLog; - - string subject; - - // procname is host/service_name-sid we only want the service_name to avoid redondant mail - string procname; - string::size_type pos = args.ProcessName.find ("/"); - if (pos == string::npos) - { - procname = args.ProcessName; - } - else - { - string::size_type pos2 = args.ProcessName.find ("-", pos+1); - if (pos2 == string::npos) - { - procname = args.ProcessName.substr (pos+1); - } - else - { - procname = args.ProcessName.substr (pos+1, pos2-pos-1); - } - } - - subject += procname + " NeL " + toString(LogTypeToString[0][args.LogType]) + " " + (args.FileName?string(args.FileName):"") + " " + toString(args.Line) + " " + (args.FuncName?string(args.FuncName):""); - - // Check the envvar NEL_IGNORE_ASSERT - if (getenv ("NEL_IGNORE_ASSERT") == NULL) - { - // yoyo: allow only to send the crash report once. Because users usually click ignore, - // which create noise into list of bugs (once a player crash, it will surely continues to do it). - std::string filename = getLogDirectory() + NL_CRASH_DUMP_FILE; - - if (ReportDebug == report (args.ProcessName + " NeL " + toString(logTypeToString(args.LogType, true)), "", subject, body, true, 2, true, 1, !isCrashAlreadyReported(), IgnoreNextTime, filename.c_str())) - { - INelContext::getInstance().setDebugNeedAssert(true); - } - - // no more sent mail for crash - setCrashAlreadyReported(true); - } - -/* // Check the envvar NEL_IGNORE_ASSERT - if (getenv ("NEL_IGNORE_ASSERT") == NULL) - { - // Ask the user to continue, debug or ignore - int result = MessageBox (NULL, ss2.str().c_str (), logTypeToString(args.LogType, true), MB_ABORTRETRYIGNORE | MB_ICONSTOP); - if (result == IDABORT) - { - // Exit the program now - exit (EXIT_FAILURE); - } - else if (result == IDRETRY) - { - // Give the debugger a try - DebugNeedAssert = true; - } - else if (result == IDIGNORE) - { - // Continue, do nothing - } - } -*/ } - -#endif + + report( body ); } diff --git a/code/nel/src/misc/report.cpp b/code/nel/src/misc/report.cpp index 20b2b1c11..54c456ade 100644 --- a/code/nel/src/misc/report.cpp +++ b/code/nel/src/misc/report.cpp @@ -22,142 +22,39 @@ #include "nel/misc/report.h" #include "nel/misc/path.h" -#ifdef NL_OS_WINDOWS -# ifndef NL_COMP_MINGW -# define NOMINMAX -# endif -# include -# include -# include -#endif // NL_OS_WINDOWS - -#define NL_NO_DEBUG_FILES 1 - using namespace std; -#ifdef DEBUG_NEW - #define new DEBUG_NEW -#endif - namespace NLMISC { -#ifdef NL_OS_WINDOWS -static HWND sendReport=NULL; -#endif - //old doesn't work on visual c++ 7.1 due to default parameter typedef bool (*TEmailFunction) (const std::string &smtpServer, const std::string &from, const std::string &to, const std::string &subject, const std::string &body, const std::string &attachedFile = "", bool onlyCheck = false); typedef bool (*TEmailFunction) (const std::string &smtpServer, const std::string &from, const std::string &to, const std::string &subject, const std::string &body, const std::string &attachedFile, bool onlyCheck); -#define DELETE_OBJECT(a) if((a)!=NULL) { DeleteObject (a); a = NULL; } - static TEmailFunction EmailFunction = NULL; void setReportEmailFunction (void *emailFunction) { EmailFunction = (TEmailFunction)emailFunction; +} + +void report ( const std::string &body ) +{ + std::string fname = "rcerrorlog.txt"; + + std::ofstream f; + f.open( fname.c_str() ); + if( f.good() ) + { + f << body; + f.close(); #ifdef NL_OS_WINDOWS - if (sendReport) - EnableWindow(sendReport, FALSE); -#endif -} - -#ifndef NL_OS_WINDOWS - -// GNU/Linux, do nothing - -void report () -{ -} - + NLMISC::launchProgram( "rcerror.exe", fname ); #else - -// Windows specific version - -static string Body; -static string Subject; -static string AttachedFile; - -static HWND checkIgnore=NULL; -static HWND debug=NULL; -static HWND ignore=NULL; -static HWND quit=NULL; -static HWND dialog=NULL; - -static bool NeedExit; -static TReportResult Result; -static bool IgnoreNextTime; -static bool CanSendMailReport= false; - -static bool DebugDefaultBehavior, QuitDefaultBehavior; - -static void sendEmail() -{ - if (CanSendMailReport && SendMessage(sendReport, BM_GETCHECK, 0, 0) != BST_CHECKED) - { - bool res = EmailFunction ("", "", "", Subject, Body, AttachedFile, false); - if (res) - { - // EnableWindow(sendReport, FALSE); - // MessageBox (dialog, "The email was successfully sent", "email", MB_OK); -#ifndef NL_NO_DEBUG_FILES - CFile::createEmptyFile(getLogDirectory() + "report_sent"); -#endif - } - else - { -#ifndef NL_NO_DEBUG_FILES - CFile::createEmptyFile(getLogDirectory() + "report_failed"); -#endif - // MessageBox (dialog, "Failed to send the email", "email", MB_OK | MB_ICONERROR); - } - } - else - { -#ifndef NL_NO_DEBUG_FILES - CFile::createEmptyFile(getLogDirectory() + "report_refused"); + NLMISC::launchProgram( "rcerror", fname ); #endif } -} -static LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - //MSGFILTER *pmf; - - if (message == WM_COMMAND && HIWORD(wParam) == BN_CLICKED) - { - if ((HWND) lParam == checkIgnore) - { - IgnoreNextTime = !IgnoreNextTime; - } - else if ((HWND) lParam == debug) - { - sendEmail(); - NeedExit = true; - Result = ReportDebug; - if (DebugDefaultBehavior) - { - NLMISC_BREAKPOINT; - } - } - else if ((HWND) lParam == ignore) - { - sendEmail(); - NeedExit = true; - Result = ReportIgnore; - } - else if ((HWND) lParam == quit) - { - sendEmail(); - NeedExit = true; - Result = ReportQuit; - - if (QuitDefaultBehavior) - { - // ace: we cannot call exit() because it's call the static object dtor and can crash the application - // if the dtor call order is not good. - //exit(EXIT_SUCCESS); #ifdef NL_OS_WINDOWS #ifndef NL_COMP_MINGW // disable the Windows popup telling that the application aborted and disable the dr watson report. @@ -166,196 +63,7 @@ static LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM #endif // quit without calling atexit or static object dtors. abort(); - } - } - /*else if ((HWND) lParam == sendReport) - { - if (EmailFunction != NULL) - { - bool res = EmailFunction ("", "", "", Subject, Body, AttachedFile, false); - if (res) - { - EnableWindow(sendReport, FALSE); - MessageBox (dialog, "The email was successfully sent", "email", MB_OK); - CFile::createEmptyFile(getLogDirectory() + "report_sent"); - } - else - { - MessageBox (dialog, "Failed to send the email", "email", MB_OK | MB_ICONERROR); - } - } - }*/ - } - else if (message == WM_CHAR) - { - if (wParam == 27) - { - // ESC -> ignore - sendEmail(); - NeedExit = true; - Result = ReportIgnore; - } - } - - return DefWindowProc (hWnd, message, wParam, lParam); } -TReportResult report (const std::string &title, const std::string &header, const std::string &subject, const std::string &body, bool enableCheckIgnore, uint debugButton, bool ignoreButton, sint quitButton, bool sendReportButton, bool &ignoreNextTime, const string &attachedFile) -{ - // register the window - static bool AlreadyRegister = false; - if(!AlreadyRegister) - { - WNDCLASSW wc; - memset (&wc,0,sizeof(wc)); - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = (WNDPROC)WndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = GetModuleHandle(NULL); - wc.hIcon = NULL; - wc.hCursor = LoadCursor(NULL,IDC_ARROW); - wc.hbrBackground = (HBRUSH)COLOR_WINDOW; - wc.lpszClassName = L"NLReportWindow"; - wc.lpszMenuName = NULL; - if (!RegisterClassW(&wc)) return ReportError; - AlreadyRegister = true; - } - - ucstring formatedTitle = title.empty() ? ucstring("NeL report") : ucstring(title); - - - // create the window - dialog = CreateWindowW (L"NLReportWindow", (LPCWSTR)formatedTitle.c_str(), WS_DLGFRAME | WS_CAPTION /*| WS_THICKFRAME*/, CW_USEDEFAULT, CW_USEDEFAULT, 456, 400, NULL, NULL, GetModuleHandle(NULL), NULL); - - // create the font - HFONT font = CreateFont (-12, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial"); - - Subject = subject; - AttachedFile = attachedFile; - - // create the edit control - HWND edit = CreateWindowW (L"EDIT", NULL, WS_BORDER | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | ES_READONLY | ES_LEFT | ES_MULTILINE, 7, 70, 429, 212, dialog, (HMENU) NULL, (HINSTANCE) GetWindowLongPtr(dialog, GWLP_HINSTANCE), NULL); - SendMessage (edit, WM_SETFONT, (WPARAM) font, TRUE); - - // set the edit text limit to lot of :) - SendMessage (edit, EM_LIMITTEXT, ~0U, 0); - - Body = addSlashR (body); - - // set the message in the edit text - SendMessage (edit, WM_SETTEXT, (WPARAM)0, (LPARAM)Body.c_str()); - - if (enableCheckIgnore) - { - // create the combo box control - checkIgnore = CreateWindowW (L"BUTTON", L"Don't display this report again", WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX | BS_CHECKBOX, 7, 290, 429, 18, dialog, (HMENU) NULL, (HINSTANCE) GetWindowLongPtr(dialog, GWLP_HINSTANCE), NULL); - SendMessage (checkIgnore, WM_SETFONT, (WPARAM) font, TRUE); - - if(ignoreNextTime) - { - SendMessage (checkIgnore, BM_SETCHECK, BST_CHECKED, 0); - } - } - - // create the debug button control - debug = CreateWindowW (L"BUTTON", L"Debug", WS_CHILD | WS_VISIBLE, 7, 315, 75, 25, dialog, (HMENU) NULL, (HINSTANCE) GetWindowLongPtr(dialog, GWLP_HINSTANCE), NULL); - SendMessage (debug, WM_SETFONT, (WPARAM) font, TRUE); - - if (debugButton == 0) - EnableWindow(debug, FALSE); - - // create the ignore button control - ignore = CreateWindowW (L"BUTTON", L"Ignore", WS_CHILD | WS_VISIBLE, 75+7+7, 315, 75, 25, dialog, (HMENU) NULL, (HINSTANCE) GetWindowLongPtr(dialog, GWLP_HINSTANCE), NULL); - SendMessage (ignore, WM_SETFONT, (WPARAM) font, TRUE); - - if (ignoreButton == 0) - EnableWindow(ignore, FALSE); - - // create the quit button control - quit = CreateWindowW (L"BUTTON", L"Quit", WS_CHILD | WS_VISIBLE, 75+75+7+7+7, 315, 75, 25, dialog, (HMENU) NULL, (HINSTANCE) GetWindowLongPtr(dialog, GWLP_HINSTANCE), NULL); - SendMessage (quit, WM_SETFONT, (WPARAM) font, TRUE); - - if (quitButton == 0) - EnableWindow(quit, FALSE); - - // create the debug button control - sendReport = CreateWindowW (L"BUTTON", L"Don't send the report", WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, 7, 315+32, 429, 18, dialog, (HMENU) NULL, (HINSTANCE) GetWindowLongPtr(dialog, GWLP_HINSTANCE), NULL); - SendMessage (sendReport, WM_SETFONT, (WPARAM) font, TRUE); - - string formatedHeader; - if (header.empty()) - { - formatedHeader = "This application stopped to display this report."; - } - else - { - formatedHeader = header; - } - - // ace don't do that because it s slow to try to send a mail - //CanSendMailReport = sendReportButton && EmailFunction != NULL && EmailFunction("", "", "", "", "", true); - CanSendMailReport = sendReportButton && EmailFunction != NULL; - - if (CanSendMailReport) - formatedHeader += " Send report will only email the contents of the box below. Please, send it to help us (it could take few minutes to send the email, be patient)."; - else - EnableWindow(sendReport, FALSE); - - ucstring uc = ucstring::makeFromUtf8(formatedHeader); - - // create the label control - HWND label = CreateWindowW (L"STATIC", (LPCWSTR)uc.c_str(), WS_CHILD | WS_VISIBLE /*| SS_WHITERECT*/, 7, 7, 429, 51, dialog, (HMENU) NULL, (HINSTANCE) GetWindowLongPtr(dialog, GWLP_HINSTANCE), NULL); - SendMessage (label, WM_SETFONT, (WPARAM) font, TRUE); - - - DebugDefaultBehavior = debugButton==1; - QuitDefaultBehavior = quitButton==1; - - IgnoreNextTime = ignoreNextTime; - - // show until the cursor really show :) - while (ShowCursor(TRUE) < 0) - ; - - SetWindowPos (dialog, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); - - SetFocus(dialog); - SetForegroundWindow(dialog); - - NeedExit = false; - - while(!NeedExit) - { - MSG msg; - while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) - { - TranslateMessage(&msg); - DispatchMessageW(&msg); - } - nlSleep (1); - } - - // set the user result - ignoreNextTime = IgnoreNextTime; - - ShowWindow(dialog, SW_HIDE); - - - - DELETE_OBJECT(sendReport) - DELETE_OBJECT(quit) - DELETE_OBJECT(ignore) - DELETE_OBJECT(debug) - DELETE_OBJECT(checkIgnore) - DELETE_OBJECT(edit) - DELETE_OBJECT(label) - DELETE_OBJECT(dialog) - - return Result; -} - -#endif - } // NLMISC diff --git a/code/ryzom/client/src/connection.cpp b/code/ryzom/client/src/connection.cpp index 8b07cc7f2..22354e436 100644 --- a/code/ryzom/client/src/connection.cpp +++ b/code/ryzom/client/src/connection.cpp @@ -103,7 +103,6 @@ extern uint32 Version; // Client Version. extern UDriver *Driver; extern UTextContext *TextContext; extern bool game_exit; -extern CMsgBoxDisplayer MsgBoxError; extern CSoundManager *SoundMngr; diff --git a/code/ryzom/client/src/init.cpp b/code/ryzom/client/src/init.cpp index 6958fe790..f0fd40dae 100644 --- a/code/ryzom/client/src/init.cpp +++ b/code/ryzom/client/src/init.cpp @@ -142,7 +142,6 @@ using namespace std; // Ligo primitive class CLigoConfig LigoConfig; -CMsgBoxDisplayer MsgBoxError; CClientChatManager ChatMngr; bool LastScreenSaverEnabled = false; diff --git a/code/web/rcerror_web/config.inc.php b/code/web/rcerror_web/config.inc.php new file mode 100644 index 000000000..fe4b3e928 --- /dev/null +++ b/code/web/rcerror_web/config.inc.php @@ -0,0 +1,30 @@ + +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +class BugReportConfig +{ + static public $dbhost = "localhost"; + static public $dbport = "3306"; + static public $dbdb = "bugs"; + static public $dbuser = "bugs"; + static public $dbpw = "bugs"; +} + +?> diff --git a/code/web/rcerror_web/log.inc.php b/code/web/rcerror_web/log.inc.php new file mode 100644 index 000000000..71deee24f --- /dev/null +++ b/code/web/rcerror_web/log.inc.php @@ -0,0 +1,45 @@ + +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +/// Simple file logger class +class Logger +{ + private $lf = NULL; + + function __construct() + { + $this->lf = fopen( 'log.txt', 'a' ); + if( $this->lf === FALSE ) + exit( 1 ); + } + + function __destruct() + { + fclose( $this->lf ); + } + + public function log( $msg ) + { + $date = date( "[M d, Y H:i:s] " ); + fwrite( $this->lf, $date . $msg . "\n" ); + } +} + +?> diff --git a/code/web/rcerror_web/rcerror.php b/code/web/rcerror_web/rcerror.php new file mode 100644 index 000000000..d20214d11 --- /dev/null +++ b/code/web/rcerror_web/rcerror.php @@ -0,0 +1,112 @@ + +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +require_once( 'config.inc.php' ); +require_once( 'log.inc.php' ); + +/// Example web application that takes bug reports from the bug reporter Qt app +class BugReportGatherApp +{ + private $db = NULL; + private $logger = NULL; + + function __construct() + { + $this->logger = new Logger(); + } + + private function logPOSTVars() + { + $report = ""; + $descr = ""; + $email = ""; + + if( isset( $_POST[ 'report' ] ) ) + $report = $_POST[ 'report' ]; + + if( isset( $_POST[ 'descr' ] ) ) + $descr = $_POST[ 'descr' ]; + + if( isset( $_POST[ 'email' ] ) ) + $email = $_POST[ 'email' ]; + + $this->logger->log( 'report: ' . "\n" . $report ); + $this->logger->log( 'description: ' . "\n" . $descr ); + $this->logger->log( 'email: ' . "\n" . $email ); + } + + private function buildQuery() + { + $report = ""; + $descr = ""; + $email = ""; + + if( isset( $_POST[ 'report' ] ) ) + $report = $_POST[ 'report' ]; + + if( isset( $_POST[ 'descr' ] ) ) + $descr = $_POST[ 'descr' ]; + + if( isset( $_POST[ 'email' ] ) ) + $email = $_POST[ 'email' ]; + + $report = $this->db->real_escape_string( $report ); + $descr = $this->db->real_escape_string( $descr ); + $email = $this->db->real_escape_string( $email ); + + + $q = "INSERT INTO `bugs` (`report`,`description`,`email`) VALUES ("; + $q .= "'$report',"; + $q .= "'$descr',"; + $q .= "'$email')"; + + return $q; + } + + public function exec() + { + //$this->logPOSTVars(); + + $this->db = new mysqli( BugReportConfig::$dbhost, BugReportConfig::$dbuser, BugReportConfig::$dbpw, BugReportConfig::$dbdb, BugReportConfig::$dbport ); + if( mysqli_connect_error() ) + { + $this->logger->log( "Connection error :(" ); + $this->logger->log( mysqli_connect_error() ); + return; + } + + $q = $this->buildQuery(); + $result = $this->db->query( $q ); + if( $result !== TRUE ) + { + $this->logger->log( "Query failed :(" ); + $this->logger->log( 'Query: ' . $q ); + $this->logPOSTVars(); + } + + $this->db->close(); + } +} + + +$app = new BugReportGatherApp(); +$app->exec(); + +?> diff --git a/code/web/rcerror_web/rcerror_test.htm b/code/web/rcerror_web/rcerror_test.htm new file mode 100644 index 000000000..eb314d3f7 --- /dev/null +++ b/code/web/rcerror_web/rcerror_test.htm @@ -0,0 +1,19 @@ + +Ryzom Core Error Report Web application test harness + + + +Description +Something something dark side +Report +Mani bad crashes :( +Email + + + + + + + + +