<commit_before>#include "BitSharesApp.hpp"

#include "html5viewer/html5viewer.h"
#include "ClientWrapper.hpp"
#include "Utilities.hpp"
#include "MainWindow.hpp"

#include <boost/thread.hpp>
#include <bts/blockchain/config.hpp>
#include <bts/wallet/url.hpp>
#include <signal.h>

#include <QSettings>
#include <QPixmap>
#include <QErrorMessage>
#include <QSplashScreen>
#include <QDir>
#include <QWebSettings>
#include <QWebPage>
#include <QWebFrame>
#include <QJsonDocument>
#include <QGraphicsWebView>
#include <QTimer>
#include <QAuthenticator>
#include <QNetworkReply>
#include <QResource>
#include <QGraphicsWidget>
#include <QMainWindow>
#include <QMenuBar>
#include <QLayout>
#include <QLocalSocket>
#include <QLocalServer>
#include <QMessageBox>
#include <QProxyStyle>
#include <QComboBox>
#include <QTemporaryFile>

#include <boost/program_options.hpp>

#include <bts/client/client.hpp>
#include <bts/net/upnp.hpp>
#include <bts/blockchain/chain_database.hpp>
#include <bts/rpc/rpc_server.hpp>
#include <bts/cli/cli.hpp>
#include <bts/utilities/git_revision.hpp>
#include <fc/filesystem.hpp>
#include <fc/thread/thread.hpp>
#include <fc/log/file_appender.hpp>
#include <fc/log/logger_config.hpp>
#include <fc/io/json.hpp>
#include <fc/reflect/variant.hpp>
#include <fc/git_revision.hpp>
#include <fc/io/json.hpp>
#include <fc/log/logger_config.hpp>
#include <fc/signals.hpp>

#include <boost/iostreams/tee.hpp>
#include <boost/iostreams/stream.hpp>

#include <fstream>
#include <iostream>
#include <iomanip>

namespace
{
/// Initialized when notification about configuration loading comes
static fc::path g_P2PLogFilePath;

class TInitializationNotifier final : public ClientWrapper::INotifier
  {
  public:
    /// INotifier interface implementation:
    virtual void on_config_loaded(const bts::client::config& config) override
      {
#if defined(WIN32) && defined(USE_CRASHRPT)
      /// Reports generated by crashrpt engine should also contain newest part of p2p.log file
      for(const auto& appender : config.logging.appenders)
        {
        /// atm only p2p log is intresting and should be appended to crash report.
        if(appender.name == "p2p")
          {
          fc::file_appender::config aConfig = appender.args.as<fc::file_appender::config>();
          g_P2PLogFilePath = aConfig.filename;
          break;
          }
        }
#endif
      }
  };

/// Helper class to catch last 'n' lines of text from the stream
class TLimitedFileBuffer
  {
  public:
    typedef std::list<std::string> TStorage;
    typedef TStorage::const_iterator const_iterator;
    typedef TStorage::const_reference const_reference;
    typedef TStorage::value_type value_type;

    struct TLine
      {
      std::string text;
      operator const std::string& () const { return text; }

      friend std::istream& operator>>(std::istream& stream, TLine& l)
        {
        return std::getline(stream, l.text);
        }
      };

    explicit TLimitedFileBuffer(size_t lc) : _maxLineCount(lc) {}

    void push_back(const std::string& line)
      {
      _buffer.push_back(line);
      if(_buffer.size() > _maxLineCount)
        _buffer.pop_front();
      }

    const_iterator begin() const
      {
      return _buffer.begin();
      }

    const_iterator end() const
      {
      return _buffer.end();
      }

  private:
    size_t                 _maxLineCount;
    std::list<std::string> _buffer;
  };

} /// anonymous

// enable crashrpt win32 release only
#if defined(WIN32) && defined(USE_CRASHRPT) && defined(NDEBUG)

  #define APP_TRY /*try*/
  #define APP_CATCH /*Nothing*/

  #include "../../CrashRpt/include/CrashRpt.h"


  /* forwards SEH caught by fc's async tasks to CrashRpt */
  int unhandled_exception_filter(unsigned code, _EXCEPTION_POINTERS* info)
  { 
    return crExceptionFilter(code, info);
  }

  BOOL CALLBACK crashCallbackOld(LPVOID lpvState)
    {
    std::ifstream inputLog(g_P2PLogFilePath.generic_wstring());
    if(inputLog.good() == false)
      return TRUE;

    TLimitedFileBuffer buffer(15000);
    typedef TLimitedFileBuffer::TLine TLine;
    std::copy(std::istream_iterator<TLine>(inputLog), std::istream_iterator<TLine>(),
      std::back_inserter(buffer));

    fc::temp_file tFile;

    std::ofstream outputLog(tFile.path().generic_wstring());

    if(outputLog.good())
      std::copy(buffer.begin(), buffer.end(), std::ostream_iterator<std::string>(outputLog, "\n"));

    outputLog.close();

    std::string path = tFile.path().string();

    crAddFile2(path.c_str(), g_P2PLogFilePath.filename().string().c_str(), "P2P Log File",
      CR_AF_TAKE_ORIGINAL_FILE);

    tFile.release();

    return TRUE;
    }
<commit_msg>Add better version info to crash reports (include everything in the RPC "about" command)<commit_after>#include "BitSharesApp.hpp"

#include "html5viewer/html5viewer.h"
#include "ClientWrapper.hpp"
#include "Utilities.hpp"
#include "MainWindow.hpp"

#include <boost/thread.hpp>
#include <bts/blockchain/config.hpp>
#include <bts/wallet/url.hpp>
#include <signal.h>

#include <QSettings>
#include <QPixmap>
#include <QErrorMessage>
#include <QSplashScreen>
#include <QDir>
#include <QWebSettings>
#include <QWebPage>
#include <QWebFrame>
#include <QJsonDocument>
#include <QGraphicsWebView>
#include <QTimer>
#include <QAuthenticator>
#include <QNetworkReply>
#include <QResource>
#include <QGraphicsWidget>
#include <QMainWindow>
#include <QMenuBar>
#include <QLayout>
#include <QLocalSocket>
#include <QLocalServer>
#include <QMessageBox>
#include <QProxyStyle>
#include <QComboBox>
#include <QTemporaryFile>

#include <boost/program_options.hpp>

#include <bts/client/client.hpp>
#include <bts/net/upnp.hpp>
#include <bts/blockchain/chain_database.hpp>
#include <bts/rpc/rpc_server.hpp>
#include <bts/cli/cli.hpp>
#include <bts/utilities/git_revision.hpp>
#include <fc/filesystem.hpp>
#include <fc/thread/thread.hpp>
#include <fc/log/file_appender.hpp>
#include <fc/log/logger_config.hpp>
#include <fc/io/json.hpp>
#include <fc/reflect/variant.hpp>
#include <fc/git_revision.hpp>
#include <fc/io/json.hpp>
#include <fc/log/logger_config.hpp>
#include <fc/signals.hpp>

#include <boost/iostreams/tee.hpp>
#include <boost/iostreams/stream.hpp>

#include <fstream>
#include <iostream>
#include <iomanip>

namespace
{
/// Initialized when notification about configuration loading comes
static fc::path g_P2PLogFilePath;

class TInitializationNotifier final : public ClientWrapper::INotifier
  {
  public:
    /// INotifier interface implementation:
    virtual void on_config_loaded(const bts::client::config& config) override
      {
#if defined(WIN32) && defined(USE_CRASHRPT)
      /// Reports generated by crashrpt engine should also contain newest part of p2p.log file
      for(const auto& appender : config.logging.appenders)
        {
        /// atm only p2p log is intresting and should be appended to crash report.
        if(appender.name == "p2p")
          {
          fc::file_appender::config aConfig = appender.args.as<fc::file_appender::config>();
          g_P2PLogFilePath = aConfig.filename;
          break;
          }
        }
#endif
      }
  };

/// Helper class to catch last 'n' lines of text from the stream
class TLimitedFileBuffer
  {
  public:
    typedef std::list<std::string> TStorage;
    typedef TStorage::const_iterator const_iterator;
    typedef TStorage::const_reference const_reference;
    typedef TStorage::value_type value_type;

    struct TLine
      {
      std::string text;
      operator const std::string& () const { return text; }

      friend std::istream& operator>>(std::istream& stream, TLine& l)
        {
        return std::getline(stream, l.text);
        }
      };

    explicit TLimitedFileBuffer(size_t lc) : _maxLineCount(lc) {}

    void push_back(const std::string& line)
      {
      _buffer.push_back(line);
      if(_buffer.size() > _maxLineCount)
        _buffer.pop_front();
      }

    const_iterator begin() const
      {
      return _buffer.begin();
      }

    const_iterator end() const
      {
      return _buffer.end();
      }

  private:
    size_t                 _maxLineCount;
    std::list<std::string> _buffer;
  };

} /// anonymous

// enable crashrpt win32 release only
#if defined(WIN32) && defined(USE_CRASHRPT) && defined(NDEBUG)

  #define APP_TRY /*try*/
  #define APP_CATCH /*Nothing*/

  #include "../../CrashRpt/include/CrashRpt.h"


  /* forwards SEH caught by fc's async tasks to CrashRpt */
  int unhandled_exception_filter(unsigned code, _EXCEPTION_POINTERS* info)
  { 
    return crExceptionFilter(code, info);
  }

  BOOL CALLBACK crashCallbackOld(LPVOID lpvState)
    {
    std::ifstream inputLog(g_P2PLogFilePath.generic_wstring());
    if(inputLog.good() == false)
      return TRUE;

    TLimitedFileBuffer buffer(15000);
    typedef TLimitedFileBuffer::TLine TLine;
    std::copy(std::istream_iterator<TLine>(inputLog), std::istream_iterator<TLine>(),
      std::back_inserter(buffer));

    fc::temp_file tFile;

    std::ofstream outputLog(tFile.path().generic_wstring());

    if(outputLog.good())
      std::copy(buffer.begin(), buffer.end(), std::ostream_iterator<std::string>(outputLog, "\n"));

    outputLog.close();

    std::string path = tFile.path().string();

    crAddFile2(path.c_str(), g_P2PLogFilePath.filename().string().c_str(), "P2P Log File",
      CR_AF_TAKE_ORIGINAL_FILE);

    tFile.release();

    fc::variant_object version_info(bts::client::version_info());
    for (fc::variant_object::iterator version_info_iter = version_info.begin();
         version_info_iter != version_info.end(); ++version_info_iter)
    {
      std::string cr_property_name = "version_info.";
      cr_property_name += version_info_iter->key();
      crAddPropertyA(cr_property_name.c_str(), version_info_iter->value().as_string().c_str());
    }

    return TRUE;
    }

{'fraction_non_alphanumeric': 0.13144826188304448, 'fraction_numerical': 0.004459308807134894, 'mean_word_length': 3.9241516966067866, 'pattern_counts': {'":': 0, '<': 115, '<?xml version=': 0, '>': 123, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '180365', 'n_tokens_mistral': 3360, 'n_tokens_neox': 3288, 'n_words': 681}