From b5d48a8f154a943a4cb6cc190331130a28e7137f Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sun, 22 Feb 2015 10:39:02 +0100 Subject: [PATCH] Merge with hotfix --- code/nel/CMakeLists.txt | 3 - code/nel/include/nel/misc/report.h | 17 +- code/nel/rcerror/CMakeLists.txt | 39 ---- code/nel/rcerror/rcerror.cpp | 33 --- code/nel/rcerror/rcerror_data.h | 33 --- code/nel/rcerror/rcerror_socket.cpp | 70 ------ code/nel/rcerror/rcerror_socket.h | 51 ---- code/nel/rcerror/rcerror_widget.cpp | 110 --------- code/nel/rcerror/rcerror_widget.h | 53 ----- code/nel/rcerror/rcerror_widget.ui | 82 ------- code/nel/src/misc/debug.cpp | 12 +- code/nel/src/misc/displayer.cpp | 176 +++++++++++++- code/nel/src/misc/report.cpp | 320 ++++++++++++++++++++++++-- code/ryzom/client/src/connection.cpp | 1 + code/ryzom/client/src/init.cpp | 1 + code/web/rcerror_web/config.inc.php | 30 --- code/web/rcerror_web/log.inc.php | 45 ---- code/web/rcerror_web/rcerror.php | 112 --------- code/web/rcerror_web/rcerror_test.htm | 19 -- 19 files changed, 505 insertions(+), 702 deletions(-) delete mode 100644 code/nel/rcerror/CMakeLists.txt delete mode 100644 code/nel/rcerror/rcerror.cpp delete mode 100644 code/nel/rcerror/rcerror_data.h delete mode 100644 code/nel/rcerror/rcerror_socket.cpp delete mode 100644 code/nel/rcerror/rcerror_socket.h delete mode 100644 code/nel/rcerror/rcerror_widget.cpp delete mode 100644 code/nel/rcerror/rcerror_widget.h delete mode 100644 code/nel/rcerror/rcerror_widget.ui delete mode 100644 code/web/rcerror_web/config.inc.php delete mode 100644 code/web/rcerror_web/log.inc.php delete mode 100644 code/web/rcerror_web/rcerror.php delete mode 100644 code/web/rcerror_web/rcerror_test.htm diff --git a/code/nel/CMakeLists.txt b/code/nel/CMakeLists.txt index 00290d097..53bf071e3 100644 --- a/code/nel/CMakeLists.txt +++ b/code/nel/CMakeLists.txt @@ -84,6 +84,3 @@ 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 6bf3df959..11745b6e3 100644 --- a/code/nel/include/nel/misc/report.h +++ b/code/nel/include/nel/misc/report.h @@ -21,8 +21,21 @@ namespace NLMISC { -/// Prepares the error report, writes it to disk and launches the error reporter -void report ( const std::string &body ); +/** 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 = ""); /** 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 deleted file mode 100644 index 51522cf0c..000000000 --- a/code/nel/rcerror/CMakeLists.txt +++ /dev/null @@ -1,39 +0,0 @@ -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 deleted file mode 100644 index 0d5088167..000000000 --- a/code/nel/rcerror/rcerror.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// 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 deleted file mode 100644 index 9f12b12fd..000000000 --- a/code/nel/rcerror/rcerror_data.h +++ /dev/null @@ -1,33 +0,0 @@ -// 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 deleted file mode 100644 index 8a011c046..000000000 --- a/code/nel/rcerror/rcerror_socket.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// 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 deleted file mode 100644 index a37fa32d0..000000000 --- a/code/nel/rcerror/rcerror_socket.h +++ /dev/null @@ -1,51 +0,0 @@ -// 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 deleted file mode 100644 index a28afbca6..000000000 --- a/code/nel/rcerror/rcerror_widget.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// 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 deleted file mode 100644 index 1dd51c2af..000000000 --- a/code/nel/rcerror/rcerror_widget.h +++ /dev/null @@ -1,53 +0,0 @@ -// 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 deleted file mode 100644 index 72e5f92f5..000000000 --- a/code/nel/rcerror/rcerror_widget.ui +++ /dev/null @@ -1,82 +0,0 @@ - - - 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 0fed6b86d..2a9c5282a 100644 --- a/code/nel/src/misc/debug.cpp +++ b/code/nel/src/misc/debug.cpp @@ -78,7 +78,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 = true; +static const bool TrapCrashInDebugger = false; #ifdef DEBUG_NEW #define new DEBUG_NEW @@ -548,7 +548,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 ( _Reason ); + report (progname+shortExc, "", subject, _Reason, true, 1, true, 1, !isCrashAlreadyReported(), i, NL_CRASH_DUMP_FILE); // no more sent mail for crash setCrashAlreadyReported(true); @@ -1188,7 +1188,13 @@ void createDebug (const char *logPath, bool logInFile, bool eraseLastLog) INelContext::getInstance().setAssertLog(new CLog (CLog::LOG_ASSERT)); sd = new CStdDisplayer ("DEFAULT_SD"); - DefaultMsgBoxDisplayer = new CMsgBoxDisplayer ("DEFAULT_MBD"); + +#ifdef NL_OS_WINDOWS + if (TrapCrashInDebugger || !IsDebuggerPresent ()) + { + DefaultMsgBoxDisplayer = new CMsgBoxDisplayer ("DEFAULT_MBD"); + } +#endif #if LOG_IN_FILE if (logInFile) diff --git a/code/nel/src/misc/displayer.cpp b/code/nel/src/misc/displayer.cpp index a4e96868f..4b9231663 100644 --- a/code/nel/src/misc/displayer.cpp +++ b/code/nel/src/misc/displayer.cpp @@ -520,7 +520,115 @@ 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; @@ -540,8 +648,70 @@ void CMsgBoxDisplayer::doDisplay ( const CLog::TDisplayInfo& args, const char *m body += "Reason: " + toString(message); body += args.CallstackAndLog; - - report( body ); + + 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 } diff --git a/code/nel/src/misc/report.cpp b/code/nel/src/misc/report.cpp index 54c456ade..20b2b1c11 100644 --- a/code/nel/src/misc/report.cpp +++ b/code/nel/src/misc/report.cpp @@ -22,39 +22,142 @@ #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 - NLMISC::launchProgram( "rcerror.exe", fname ); + if (sendReport) + EnableWindow(sendReport, FALSE); +#endif +} + +#ifndef NL_OS_WINDOWS + +// GNU/Linux, do nothing + +void report () +{ +} + #else - NLMISC::launchProgram( "rcerror", fname ); + +// 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"); #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. @@ -63,7 +166,196 @@ void report ( const std::string &body ) #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 3f3a3d809..92ecff0ac 100644 --- a/code/ryzom/client/src/connection.cpp +++ b/code/ryzom/client/src/connection.cpp @@ -103,6 +103,7 @@ 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 5484141a2..33bec822f 100644 --- a/code/ryzom/client/src/init.cpp +++ b/code/ryzom/client/src/init.cpp @@ -142,6 +142,7 @@ 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 deleted file mode 100644 index fe4b3e928..000000000 --- a/code/web/rcerror_web/config.inc.php +++ /dev/null @@ -1,30 +0,0 @@ - -// -// 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 deleted file mode 100644 index 71deee24f..000000000 --- a/code/web/rcerror_web/log.inc.php +++ /dev/null @@ -1,45 +0,0 @@ - -// -// 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 deleted file mode 100644 index d20214d11..000000000 --- a/code/web/rcerror_web/rcerror.php +++ /dev/null @@ -1,112 +0,0 @@ - -// -// 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 deleted file mode 100644 index eb314d3f7..000000000 --- a/code/web/rcerror_web/rcerror_test.htm +++ /dev/null @@ -1,19 +0,0 @@ - -Ryzom Core Error Report Web application test harness - -
- - - - - - - - - -
Description
Report
Email
- -
-
- -