<commit_before>//===========================================
//  PC-BSD source code
//  Copyright (c) 2016, PC-BSD Software/iXsystems
//  Available under the 3-clause BSD license
//  See the LICENSE file for full details
//===========================================
#include "C_Manager.h"
#include "ui_C_Manager.h"

#include "NewConnectionWizard.h"

#include <globals.h>

// OpenSSL includes
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/pkcs12.h>
#include <openssl/err.h>

#define EXPORTFILEDELIM "____^^^^^^^__^^^^^^^_____" //Don't care if this is unreadable - nobody should be viewing this file directly anyway

extern QHash<QString,sysadm_client*> CORES; // hostIP / core

C_Manager::C_Manager() : QMainWindow(), ui(new Ui::C_Manager){
  ui->setupUi(this);
  treeTimer = new QTimer(this);
    treeTimer->setSingleShot(true);
    treeTimer->setInterval(500); // 1/2 second
	
  radio_acts = new QActionGroup(this);
    radio_acts->addAction(ui->actionView_Connections);
    radio_acts->addAction(ui->actionSetup_SSL);
  connect(radio_acts, SIGNAL(triggered(QAction*)), this, SLOT(changePage(QAction*)) );
  //put a spacer between the finished action and the others
  QWidget *tmp = new QWidget(this);
    tmp->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
  ui->toolBar->insertWidget(ui->actionView_Connections, tmp);
	
  //Setup all the connections
  connect(ui->actionFinished, SIGNAL(triggered()), this, SLOT(close()) );
  connect(treeTimer, SIGNAL(timeout()), this, SLOT(SaveConnectionInfo()) );
  connect(ui->tree_conn->model(), SIGNAL(rowsInserted(const QModelIndex&,int,int)), this, SLOT(tree_items_changed()) );
  connect(ui->radio_ssl_bridge, SIGNAL(toggled(bool)), this, SLOT(LoadCertView()) );

  LoadConnectionInfo();
  verify_cert_inputs();
  //Connect some late signals/slots which might be impacted by the default loads
  connect(ui->line_cert_email, SIGNAL(textEdited(const QString&)), this, SLOT(verify_cert_inputs()) );
  connect(ui->line_cert_nick, SIGNAL(textEdited(const QString&)), this, SLOT(verify_cert_inputs()) );
	
  //Show the proper page
  checkFilesLoaded();
  //this->resize(this->sizeHint());
}

C_Manager::~C_Manager(){
	
}

// === PRIVATE ===
void C_Manager::LoadConnectionInfo(){
  ui->tree_conn->clear();
  //Load the files/settings and put it into the tree
  QStringList dirs = settings->allKeys().filter("C_Groups/");
  dirs.prepend("C_Groups"); //also need the "base" dir
  dirs.sort(); //this will ensure that we decend through the tree progressively
  //qDebug() << "Load Dirs:" << dirs;
  for(int i=0; i<dirs.length(); i++){
    //Create the item for this dir
    QTreeWidgetItem *item = 0;
    if(dirs[i]!="C_Groups"){ //real sub-dir
      item = new QTreeWidgetItem(); 
      item->setText(0, dirs[i].section("/",-1)); //dirs only have the "text" field set
      item->setIcon(0,QIcon(":/icons/black/box.svg") );
      //Now add the item to the proper parent
      QTreeWidgetItem *parent = FindItemParent(dirs[i]);
      if(parent==0){
        ui->tree_conn->addTopLevelItem(item);
      }else{
        parent->addChild(item);
      }
    }
    //Load all the connections within this dir
    QStringList conns = settings->value(dirs[i]).toStringList();
    //qDebug() << "Check Connections:" << dirs[i] << conns;
    for(int c=0; c<conns.length(); c++){
      if(conns[c].simplified().isEmpty()){ continue; }
       QTreeWidgetItem *tmp = new QTreeWidgetItem();
	    tmp->setText(0, settings->value("Hosts/"+conns[c],conns[c]).toString() + " ("+conns[c]+")");
	    tmp->setWhatsThis(0, conns[c]);
	    tmp->setIcon(0,QIcon(":/icons/black/globe.svg") );
        if(item==0){ ui->tree_conn->addTopLevelItem(tmp); }
	else{ item->addChild(tmp); }
    }
    QApplication::processEvents();
  }
  on_tree_conn_itemSelectionChanged();
}

void C_Manager::checkFilesLoaded(){
  bool ok = !SSL_cfg.isNull() && !SSL_cfg_bridge.isNull(); //check the validity of the globals
  ui->actionView_Connections->setEnabled( ok );
  ui->tabwidget_ssl_settings->setTabEnabled(1,ok);
  if(!ok ){
    ui->tabwidget_ssl_settings->setCurrentIndex(0);
    ui->actionSetup_SSL->trigger();
  }else{
    ui->actionView_Connections->trigger();
    LoadCertView();
  }
}

void C_Manager::SaveConnectionInfo(){
  //First clear the current tree from the settings file
  QStringList dirs = settings->allKeys().filter("C_Groups/");
  for(int i=0; i<dirs.length(); i++){ settings->remove(dirs[i]); }
  //Now go through the top-level item and let it save down through the tree
  QStringList topConns;
  for(int i=0; i<ui->tree_conn->topLevelItemCount(); i++){
    if(ui->tree_conn->topLevelItem(i)->whatsThis(0).isEmpty()){
      saveGroupItem(ui->tree_conn->topLevelItem(i)); //will recursively go through dirs
    }else{
      topConns << ui->tree_conn->topLevelItem(i)->whatsThis(0);
    }
  }
  //Now save these top-level items
  settings->setValue("C_Groups",topConns);
  //Let the tray know about the changes
  emit SettingsChanged();
  //Make sure the buttons are updated as needed
  on_tree_conn_itemSelectionChanged(); 
}

//Simplification functions for reading/writing tree widget paths
QTreeWidgetItem* C_Manager::FindItemParent(QString path){
  QString ppath = path.section("/",1,-2); //Cut off the C_Groups/ and current dir from the ends
  //qDebug() << "Item Parent:" << path << ppath;
  QList<QTreeWidgetItem*> found = ui->tree_conn->findItems(ppath.section("/",-1), Qt::MatchExactly | Qt::MatchRecursive);
  //qDebug() << "Matches Found:" << found;
  for(int i=0; i<found.length(); i++){
    QString check = found[i]->text(0);
    QTreeWidgetItem *tmp = found[i];
    while(tmp->parent()!=0){
      tmp = tmp->parent();
      check.prepend(tmp->text(0)+"/");
    }
    //qDebug() << "Check parent path:" << ppath << check;
    if(ppath==check){ return found[i]; } //found the parent item
  }
  return 0; //none found
}

void C_Manager::saveGroupItem(QTreeWidgetItem *group){
    //First assemble the full path of the group
    QString path = group->text(0);
    QTreeWidgetItem *tmp = group;
    while(tmp->parent()!=0){
      tmp = tmp->parent();
      path.prepend(tmp->text(0)+"/");
    }
    path.prepend("C_Groups/");
    //Now get all the children of this group which are not groups themselves
    QStringList conns;
    for(int i=0; i<group->childCount(); i++){
      if(group->child(i)->whatsThis(0).isEmpty()){ saveGroupItem(group->child(i)); }
      conns << group->child(i)->whatsThis(0);
    }
    //Now save the info to the settings file
    settings->setValue(path, conns);
}

// === SSL LIBRARY FUNCTIONS ===
bool C_Manager::generateKeyCertBundle(QString bundlefile, QString nickname, QString email, QString passphrase){
    RSA *rsakey=0;
    X509 *req=0;
    X509_NAME *subj=0;
    EVP_PKEY *pkey=0;
    EVP_MD *digest=0;
	
    //Get a "serial" number
    int serial = 1; //temporary placeholder

    // Generate the RSA key
    rsakey = RSA_generate_key(2048, RSA_F4, NULL, NULL);

    // Create evp obj to hold our rsakey
    if (!(pkey = EVP_PKEY_new())){
        qDebug() << "Could not create EVP object"; return false;
    }
    if (!(EVP_PKEY_set1_RSA(pkey, rsakey))){
        qDebug() << "Could not assign RSA key to EVP object"; return false;
    }
    // create request object
    if (!(req = X509_new())){
        qDebug() << "Failed to create X509_REQ object"; return false;<commit_msg>Another minor fix  - SSL issue with bridge bundle still not working right.<commit_after>//===========================================
//  PC-BSD source code
//  Copyright (c) 2016, PC-BSD Software/iXsystems
//  Available under the 3-clause BSD license
//  See the LICENSE file for full details
//===========================================
#include "C_Manager.h"
#include "ui_C_Manager.h"

#include "NewConnectionWizard.h"

#include <globals.h>

// OpenSSL includes
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/pkcs12.h>
#include <openssl/err.h>

#define EXPORTFILEDELIM "____^^^^^^^__^^^^^^^_____" //Don't care if this is unreadable - nobody should be viewing this file directly anyway

extern QHash<QString,sysadm_client*> CORES; // hostIP / core

C_Manager::C_Manager() : QMainWindow(), ui(new Ui::C_Manager){
  ui->setupUi(this);
  treeTimer = new QTimer(this);
    treeTimer->setSingleShot(true);
    treeTimer->setInterval(500); // 1/2 second
	
  radio_acts = new QActionGroup(this);
    radio_acts->addAction(ui->actionView_Connections);
    radio_acts->addAction(ui->actionSetup_SSL);
  connect(radio_acts, SIGNAL(triggered(QAction*)), this, SLOT(changePage(QAction*)) );
  //put a spacer between the finished action and the others
  QWidget *tmp = new QWidget(this);
    tmp->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
  ui->toolBar->insertWidget(ui->actionView_Connections, tmp);
	
  //Setup all the connections
  connect(ui->actionFinished, SIGNAL(triggered()), this, SLOT(close()) );
  connect(treeTimer, SIGNAL(timeout()), this, SLOT(SaveConnectionInfo()) );
  connect(ui->tree_conn->model(), SIGNAL(rowsInserted(const QModelIndex&,int,int)), this, SLOT(tree_items_changed()) );
  connect(ui->radio_ssl_bridge, SIGNAL(toggled(bool)), this, SLOT(LoadCertView()) );

  LoadConnectionInfo();
  verify_cert_inputs();
  //Connect some late signals/slots which might be impacted by the default loads
  connect(ui->line_cert_email, SIGNAL(textEdited(const QString&)), this, SLOT(verify_cert_inputs()) );
  connect(ui->line_cert_nick, SIGNAL(textEdited(const QString&)), this, SLOT(verify_cert_inputs()) );
	
  //Show the proper page
  checkFilesLoaded();
  //this->resize(this->sizeHint());
}

C_Manager::~C_Manager(){
	
}

// === PRIVATE ===
void C_Manager::LoadConnectionInfo(){
  ui->tree_conn->clear();
  //Load the files/settings and put it into the tree
  QStringList dirs = settings->allKeys().filter("C_Groups/");
  dirs.prepend("C_Groups"); //also need the "base" dir
  dirs.sort(); //this will ensure that we decend through the tree progressively
  //qDebug() << "Load Dirs:" << dirs;
  for(int i=0; i<dirs.length(); i++){
    //Create the item for this dir
    QTreeWidgetItem *item = 0;
    if(dirs[i]!="C_Groups"){ //real sub-dir
      item = new QTreeWidgetItem(); 
      item->setText(0, dirs[i].section("/",-1)); //dirs only have the "text" field set
      item->setIcon(0,QIcon(":/icons/black/box.svg") );
      //Now add the item to the proper parent
      QTreeWidgetItem *parent = FindItemParent(dirs[i]);
      if(parent==0){
        ui->tree_conn->addTopLevelItem(item);
      }else{
        parent->addChild(item);
      }
    }
    //Load all the connections within this dir
    QStringList conns = settings->value(dirs[i]).toStringList();
    //qDebug() << "Check Connections:" << dirs[i] << conns;
    for(int c=0; c<conns.length(); c++){
      if(conns[c].simplified().isEmpty()){ continue; }
       QTreeWidgetItem *tmp = new QTreeWidgetItem();
	    tmp->setText(0, settings->value("Hosts/"+conns[c],conns[c]).toString() + " ("+conns[c]+")");
	    tmp->setWhatsThis(0, conns[c]);
	    tmp->setIcon(0,QIcon(":/icons/black/globe.svg") );
        if(item==0){ ui->tree_conn->addTopLevelItem(tmp); }
	else{ item->addChild(tmp); }
    }
    QApplication::processEvents();
  }
  on_tree_conn_itemSelectionChanged();
}

void C_Manager::checkFilesLoaded(){
  bool ok = !SSL_cfg.isNull() && !SSL_cfg_bridge.isNull(); //check the validity of the globals
  ui->actionView_Connections->setEnabled( ok );
  ui->tabwidget_ssl_settings->setTabEnabled(1,ok);
  if(!ok ){
    ui->tabwidget_ssl_settings->setCurrentIndex(0);
    ui->actionSetup_SSL->trigger();
  }else{
    ui->actionView_Connections->trigger();
    LoadCertView();
  }
}

void C_Manager::SaveConnectionInfo(){
  //First clear the current tree from the settings file
  QStringList dirs = settings->allKeys().filter("C_Groups/");
  for(int i=0; i<dirs.length(); i++){ settings->remove(dirs[i]); }
  //Now go through the top-level item and let it save down through the tree
  QStringList topConns;
  for(int i=0; i<ui->tree_conn->topLevelItemCount(); i++){
    if(ui->tree_conn->topLevelItem(i)->whatsThis(0).isEmpty()){
      saveGroupItem(ui->tree_conn->topLevelItem(i)); //will recursively go through dirs
    }else{
      topConns << ui->tree_conn->topLevelItem(i)->whatsThis(0);
    }
  }
  //Now save these top-level items
  settings->setValue("C_Groups",topConns);
  //Let the tray know about the changes
  emit SettingsChanged();
  //Make sure the buttons are updated as needed
  on_tree_conn_itemSelectionChanged(); 
}

//Simplification functions for reading/writing tree widget paths
QTreeWidgetItem* C_Manager::FindItemParent(QString path){
  QString ppath = path.section("/",1,-2); //Cut off the C_Groups/ and current dir from the ends
  //qDebug() << "Item Parent:" << path << ppath;
  QList<QTreeWidgetItem*> found = ui->tree_conn->findItems(ppath.section("/",-1), Qt::MatchExactly | Qt::MatchRecursive);
  //qDebug() << "Matches Found:" << found;
  for(int i=0; i<found.length(); i++){
    QString check = found[i]->text(0);
    QTreeWidgetItem *tmp = found[i];
    while(tmp->parent()!=0){
      tmp = tmp->parent();
      check.prepend(tmp->text(0)+"/");
    }
    //qDebug() << "Check parent path:" << ppath << check;
    if(ppath==check){ return found[i]; } //found the parent item
  }
  return 0; //none found
}

void C_Manager::saveGroupItem(QTreeWidgetItem *group){
    //First assemble the full path of the group
    QString path = group->text(0);
    QTreeWidgetItem *tmp = group;
    while(tmp->parent()!=0){
      tmp = tmp->parent();
      path.prepend(tmp->text(0)+"/");
    }
    path.prepend("C_Groups/");
    //Now get all the children of this group which are not groups themselves
    QStringList conns;
    for(int i=0; i<group->childCount(); i++){
      if(group->child(i)->whatsThis(0).isEmpty()){ saveGroupItem(group->child(i)); }
      conns << group->child(i)->whatsThis(0);
    }
    //Now save the info to the settings file
    settings->setValue(path, conns);
}

// === SSL LIBRARY FUNCTIONS ===
bool C_Manager::generateKeyCertBundle(QString bundlefile, QString nickname, QString email, QString passphrase){
    RSA *rsakey=0;
    X509 *req=0;
    X509_NAME *subj=0;
    EVP_PKEY *pkey=0;
    EVP_MD *digest=0;
	
    //Get a "serial" number
    int serial = ( (bundlefile==SSLFile()) ? 1 : 2 ); //temporary placeholder

    // Generate the RSA key
    rsakey = RSA_generate_key(2048, RSA_F4, NULL, NULL);

    // Create evp obj to hold our rsakey
    if (!(pkey = EVP_PKEY_new())){
        qDebug() << "Could not create EVP object"; return false;
    }
    if (!(EVP_PKEY_set1_RSA(pkey, rsakey))){
        qDebug() << "Could not assign RSA key to EVP object"; return false;
    }
    // create request object
    if (!(req = X509_new())){
        qDebug() << "Failed to create X509_REQ object"; return false;
{'fraction_non_alphanumeric': 0.17302901770686058, 'fraction_numerical': 0.009493031710765503, 'mean_word_length': 4.066166439290587, 'pattern_counts': {'":': 4, '<': 101, '<?xml version=': 0, '>': 167, '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': '6793435', 'n_tokens_mistral': 5035, 'n_tokens_neox': 4885, 'n_words': 1158}