Mark2020H

Part 2 CPP File for GUI SSH Generator

May 22nd, 2023
214
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.61 KB | None | 0 0
  1. /* This  code is  delivered in 4 or more parts and provides a  GUI mechanism  for  generating ssh keys using QT  C++
  2.  * For Debian 12  65 bit The entire project can also be downloaded  via  GIT-HUB for this whom want to know more and  would  
  3.  * Like to  re compile or gain  ideas as to how to do some of this
  4.  * All instructions plus  pre compiled code for  Debian 12  are available at git-hub  
  5.  * @ this address https://github.com/markh2016/GUISSHGenerator.git
  6.  * This is Part 2  The CPP file  MD Harrington London UK 22/05/2023
  7. */
  8.    
  9.  
  10. #include "dialog.h"
  11. #include "ui_dialog.h"
  12.  
  13. #include <QByteArray>
  14. #include <QKeyEvent>
  15.  
  16. Dialog::Dialog(QWidget *parent)
  17.     : QDialog(parent)
  18.     , ui(new Ui::Dialog)
  19. {
  20.     ui->setupUi(this);
  21.  
  22.     process= new QProcess(this) ;
  23.  
  24.     isLoaded =false ;
  25.  
  26.  
  27.     // need a file path and  file  name to read setting from and  write to
  28.  
  29.     file_name = "/creedentials.ini" ; // this  is the file name
  30.     file_path = QDir::currentPath() + file_name ;  // this is the file path
  31.  
  32.      // connect  buttons : click  signals to slots
  33.     connect(ui->btnSaveDetails,&QPushButton::clicked,this,&Dialog::saveDetails) ;
  34.  
  35.     connect(ui->btnLoaddetails, &QPushButton::clicked ,this, &Dialog::loadDetials);
  36.  
  37.     connect(ui->btnGenSSH, &QPushButton::clicked,this,&Dialog::processStartProcess);
  38.  
  39.     connect(ui->btnOK,&QPushButton::clicked,this,&Dialog::writeCommands) ;
  40.  
  41.     connect(ui->btnAddSSH,&QPushButton::clicked,this,&Dialog::addKeyToAgent);
  42.  
  43.     connect(ui->btnPrintSSHkey,&QPushButton::clicked,this,&Dialog::showSSK_Key) ;
  44.  
  45.     connect(ui->btnShowGit,&QPushButton::clicked,this,&Dialog::addKeyToGit);
  46.  
  47.  
  48.     //  handle  dialogs close  event dialog doesnt emit close  signal in qt
  49.     //  so we use  teh finished signal instead
  50.     connect(this, &QDialog::finished, this, &Dialog::handleClose);
  51.  
  52.  
  53.      // signals and call backs for Qprocess
  54.  
  55.     connect(process, &QProcess::readyReadStandardOutput, this, [this]() {
  56.         output = process->readAllStandardOutput() ;
  57.         ui->txtResponce->appendPlainText(output);
  58.  
  59.     });
  60.  
  61.     connect(process,&QProcess::readyReadStandardError , this, [this](){
  62.         output = process->readAllStandardError() ;
  63.         qDebug() << output ;
  64.     });
  65.  
  66.     // Connect the finished signal to a lambda function
  67.     connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus) {
  68.         // Process has finished executing
  69.  
  70.         qDebug() << "Process finished with exit code: " << exitCode;
  71.         qDebug() << "Exit status: " << exitStatus;
  72.         ui->txtResponce->appendPlainText("Process  ssh exited on with exit code of 1 " );
  73.         // clear replies line edit
  74.         ui->txtReplies->setText("");
  75.         process->close();
  76.  
  77.  
  78.     });
  79.  
  80.     // new process for add key to agent
  81.  
  82.    addProcess = new QProcess(this);
  83.  
  84.     // Set up the necessary connections for reading output and handling errors
  85.     connect(addProcess, &QProcess::readyReadStandardOutput, this, [this]{
  86.         QString output = addProcess->readAllStandardOutput();
  87.         ui->txtResponce->appendPlainText(output);
  88.     });
  89.  
  90.     connect(addProcess, &QProcess::readyReadStandardError, this, [this] {
  91.         QString output = addProcess->readAllStandardError();
  92.         ui->txtResponce->appendPlainText(output);
  93.     });
  94.  
  95.     connect(addProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus) {
  96.         // Process has finished executing
  97.         qDebug() << "Process finished with exit code: " << exitCode;
  98.         qDebug() << "Exit status: " << exitStatus;
  99.         // finally  close the process
  100.  
  101.         ui->txtResponce->appendPlainText("add key to  ssh agent succesfull") ;
  102.           addProcess->close() ;
  103.     });
  104.  
  105.     // new process for  cat sshkey.pub
  106.  
  107.     addProcess2 = new QProcess(this) ;
  108.     // Set up the necessary connections for reading output and handling errors
  109.     connect(addProcess2, &QProcess::readyReadStandardOutput, this, [this]{
  110.         QString output = addProcess2->readAllStandardOutput();
  111.         ui->txtResponce->appendPlainText(output);
  112.     });
  113.  
  114.     connect(addProcess2, &QProcess::readyReadStandardError, this, [this] {
  115.         QString output = addProcess2->readAllStandardError();
  116.         ui->txtResponce->appendPlainText(output);
  117.     });
  118.  
  119.     connect(addProcess2, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus) {
  120.         // Process has finished executing
  121.         qDebug() << "Process finished with exit code: " << exitCode;
  122.         qDebug() << "Exit status: " << exitStatus;
  123.         // finally  close the process
  124.  
  125.         ui->txtResponce->appendPlainText("Key is  printed above.\nPlease select and copy \n You will need this for Git") ;
  126.         addProcess2->close();
  127.     });
  128.  
  129.  
  130.     // new process for launching webpage
  131.  
  132.     process2 = new QProcess(this) ;
  133.  
  134.  
  135.     // Set up the necessary connections for reading output and handling errors
  136.     connect(process2, &QProcess::readyReadStandardOutput, this, [this]{
  137.         QString output = process2->readAllStandardOutput();
  138.         ui->txtResponce->appendPlainText(output);
  139.     });
  140.  
  141.     connect(process2, &QProcess::readyReadStandardError, this, [this] {
  142.         QString output = process2->readAllStandardError();
  143.         ui->txtResponce->appendPlainText(output);
  144.     });
  145.  
  146.     connect(process2, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus) {
  147.         // Process has finished executing
  148.         qDebug() << "Process finished with exit code: " << exitCode;
  149.         qDebug() << "Exit status: " << exitStatus;
  150.  
  151.  
  152.         ui->txtResponce->appendPlainText("Hopefully  this took you to correct page\nand you added ssh correctly ") ;
  153.         // finally  close the process
  154.         process2->close();
  155.     });
  156.  
  157.  
  158. }
  159.  
  160.  
  161.  
  162. Dialog::~Dialog()
  163. {
  164.  
  165.  
  166.     // deleting  eml pointer in destructor as  we  may still need this  elsewhere in program
  167.  
  168.     qDebug() << "Now In destructor ";
  169.     qDebug() << "Deleting pointer *eml";
  170.  
  171.     delete eml ;
  172.     qDebug() << "Deleting pointer *paswrd " ;
  173.     delete paswrd ;
  174.     qDebug() << "Deleting pointer *ui" ;
  175.     delete ui;
  176.  
  177.  
  178.     qDebug() << "Deleting process pointer" ;
  179.  
  180.     delete process ;
  181.     qDebug() << "Deleting AddProcess pointer  " ;
  182.     delete  addProcess ;
  183.     qDebug() << "Deleting AddProcess2 pointer  " ;
  184.  
  185.     delete addProcess2 ;
  186.  
  187.     qInfo() << "Deleting proccess2 pointer " ;
  188.  
  189.  
  190.  
  191. }
  192.  
  193.  
  194.  
  195.  
  196.  
  197. //  using pass by  reference   for arguments
  198.  
  199. void Dialog::showMessage(const QString &message, const QString &title, const int &msgtype)
  200. {
  201.  
  202.      // create the qmessage box  pointer
  203.     QMessageBox  *msg = new QMessageBox(this) ;
  204.     msg->setText(message);
  205.     msg->setWindowTitle(title);
  206.  
  207.     // switch case  is used to  select  which  icon to use
  208.     switch(msgtype){
  209.  
  210.     case 1: // informations
  211.         msg->setIcon(QMessageBox::Information);
  212.         break ;
  213.  
  214.     case 2:
  215.         msg->setIcon(QMessageBox::Warning);
  216.         break ;
  217.     case 3:
  218.         msg->setIcon(QMessageBox::Critical);
  219.         break ;
  220.     case 4:
  221.         msg->setIcon(QMessageBox::Question);
  222.         break ;
  223.  
  224.  
  225.     } // end switch
  226.  
  227.     msg->exec() ;
  228.  
  229.  
  230.  
  231.    //  we can delete the  msg pointer here as  we will only ever  call this
  232.    // function  from other functions
  233.  
  234.    // avoid  memory leaks  make sure any pointers  create are deleted
  235.  
  236.     delete msg  ;
  237.  
  238. }
  239.  
  240. //  called from save details of  all field validated
  241.  
  242. void Dialog::saveSettings()
  243. {
  244.     QSettings  *m_settings  = new QSettings (file_path, QSettings::IniFormat);
  245.     m_settings->setValue("email" , *eml);
  246.     m_settings->setValue("pasv" , *paswrd );
  247.  
  248.  
  249.     delete m_settings ;
  250.     isLoaded = true ;
  251. }
  252.  
  253. // save details to  poperties  file and check fields
  254.  
  255. void Dialog::saveDetails()
  256. {
  257.  
  258.     // 1step is to check and make sure all field are  validated  as nearset we can
  259.  
  260.  
  261.     static QRegularExpression regex("(\\w+)(\\.|_)?(\\w*)@(\\w+)(\\.(\\w+))+");
  262.  
  263.     /* Regex patter for password  */
  264.  
  265.     static QRegularExpression regExp("^(.{0,7}|[^0-9]*|[^A-Z]*|[^a-z]*|[a-zA-Z0-9]*)$") ;
  266.  
  267.     if( regex.match(ui->lineEmail->text().trimmed()).hasMatch()){
  268.        // we have a correct email formatted address
  269.        // save this for later use
  270.  
  271.         // when using pointers in C++  you have use the  new  keyword to allocate memmory
  272.         eml =  new QString(ui->lineEmail->text().trimmed()) ;
  273.  
  274.     }
  275.  
  276.     else {
  277.        showMessage("Email incorrect\nPlease redo" ,"Error" ,4) ;
  278.        ui->lineEmail->setText("");
  279.        delete eml ;
  280.        isLoaded = false ;
  281.        return  ;
  282.  
  283.     } // end of else  for if( regex.match(ui->lineEmail->text().trimmed()).hasMatch())
  284.  
  285.  
  286.  
  287.     /* if we get this far then all well  now  check and  revalidate  this field
  288.  
  289.      check number charcters is not less that  1 */
  290.  
  291.     if(ui->linePassword->text().trimmed().length() > 3){
  292.  
  293.        // we  have what may be a valid  password
  294.  
  295.        // create a Qstring pointer to this
  296.        paswrd = new QString(ui->linePassword->text().trimmed()) ;
  297.  
  298.        // validate this
  299.  
  300.  
  301.        if(!(regExp.match(*paswrd).hasMatch())) {
  302.  
  303.            showMessage("Password not validated or incorrect\nPlease redo" ,"Error" ,3) ;
  304.            ui->linePassword->setText("");
  305.            delete paswrd ;
  306.            isLoaded = false  ;
  307.            return  ;
  308.        }
  309.  
  310.  
  311.  
  312.  
  313.     } // end if ui->linePassword->text().trimmed().length() > 3)
  314.  
  315.  
  316.     /*****  Save this to file  *****/
  317.  
  318.     saveSettings() ;
  319.  
  320.  
  321.     showMessage("Settings successfully saved","File Informations",3 ) ;
  322.  
  323. }
  324.  
  325.  
  326.  
  327. //  load details from a properties file and populate fields
  328. void Dialog::loadDetials()
  329. {
  330.     QSettings  *m_settings  = new QSettings (file_path, QSettings::IniFormat);
  331.     if (QFile(file_path).exists()) {
  332.  
  333.        // update  fields on form
  334.        ui->lineEmail->setText(m_settings->value("email", "").toString());
  335.  
  336.  
  337.          eml =  new QString(ui->lineEmail->text().trimmed()) ;
  338.  
  339.  
  340.         ui->linePassword->setText(m_settings->value("pasv","").toString());
  341.  
  342.  
  343.  
  344.  
  345.         paswrd = new QString(ui->linePassword->text().trimmed());
  346.         isLoaded = true ;
  347.  
  348.     } else {
  349.  
  350.        showMessage("Ini file  needs to be created\nPlease complete email and password fields\nthen click save"
  351.                    ,"Settings File Missing", 1);
  352.          isLoaded = false  ;
  353.    }
  354.  
  355.     delete m_settings ;
  356.  
  357. }
  358.  
  359. void Dialog::handleClose()
  360. {
  361.     qDebug() << " Exiting programe  calling destructor ,  deleting any pointers etc"  ;
  362. }
  363.  
  364. void Dialog::processStartProcess()
  365. {
  366.  
  367.     if(isLoaded) {
  368.  
  369.  
  370.     homedir = QDir::homePath() ;
  371.  
  372.  
  373.     QString command = QString("ssh-keygen -t ed25519 -C \"%1\"").arg(ui->lineEmail->text().trimmed());
  374.  
  375.  
  376.  
  377.  
  378.     process->start("bash", QStringList() << "-c" << command);
  379.  
  380.     process->setProcessChannelMode(QProcess::MergedChannels);
  381.     process->setWorkingDirectory(homedir);
  382.  
  383.     process->start("bash", QStringList() << "-c" << command);
  384.  
  385.     //debugging purposes , to check this is not null
  386.  
  387.     qDebug()<< "email is " << *eml  << "password used was " << paswrd ;
  388.  
  389.     }
  390.  
  391.     else {
  392.      showMessage("No settings for email saved\nOr  loaded " , "Major error", 3);
  393.     }
  394. }
  395.  
  396.  
  397.  
  398. void Dialog::writeCommands()
  399. {
  400.  
  401.  
  402.  
  403.     ui->txtResponce->clear();
  404.     QString reply = ui->txtReplies->text();
  405.  
  406.     process->write(reply.toUtf8());
  407.     process->write("\n");
  408.  
  409.     if(process->waitForBytesWritten()){
  410.        qDebug()<<  "Bytes have been  written " << "Commands sent were " << reply ;
  411.  
  412.     }
  413.  
  414. }
  415.  
  416. void Dialog::addKeyToAgent()
  417. {
  418.  
  419.     QString command = "ssh-add ~/.ssh/id_ed25519" ;
  420.  
  421.  
  422.     addProcess->setProcessChannelMode(QProcess::MergedChannels);
  423.     addProcess->setWorkingDirectory(homedir);
  424.  
  425.     addProcess->start("bash", QStringList() << "-c" << command);
  426.     // Start the process to execute the command
  427.  
  428.  
  429.  
  430. }
  431.  
  432. bool Dialog:: checkSSHKeyFilesExist()
  433. {
  434.     QString sshDirPath = QDir::homePath() + "/.ssh";
  435.     QString privateKeyFilePath = sshDirPath + "/id_ed25519";
  436.     QString publicKeyFilePath = sshDirPath + "/id_ed25519.pub";
  437.  
  438.     QFile privateKeyFile(privateKeyFilePath);
  439.     QFile publicKeyFile(publicKeyFilePath);
  440.  
  441.     bool privateKeyExists = privateKeyFile.exists();
  442.     bool publicKeyExists = publicKeyFile.exists();
  443.  
  444.     if (privateKeyExists && publicKeyExists) {
  445.        qDebug() << "Both key files exist.";
  446.        return true;
  447.     } else {
  448.        if (!privateKeyExists) {
  449.            qDebug() << "Private key file does not exist.";
  450.        }
  451.        if (!publicKeyExists) {
  452.            qDebug() << "Public key file does not exist.";
  453.        }
  454.        return false;
  455.     }
  456. }
  457.  
  458.  
  459. void Dialog::showSSK_Key()
  460.  
  461.  
  462. {
  463.     if(checkSSHKeyFilesExist())
  464.     {
  465.  
  466.         QString command = "cat ~/.ssh/id_ed25519.pub" ;
  467.         addProcess2->setProcessChannelMode(QProcess::MergedChannels);
  468.         addProcess2->setWorkingDirectory(homedir);
  469.  
  470.         addProcess2->start("bash", QStringList() << "-c" << command);
  471.         // Start the process to execute the command
  472.     }
  473.     else {
  474.          showMessage("You have not created  ssh keys\nAnd added these to ssh agent ","Keys Not Created",3);
  475.     }
  476. }
  477.  
  478. void Dialog::addKeyToGit()
  479. {
  480.     if(checkSSHKeyFilesExist())
  481.     {
  482.          QString command = "xdg-open https://github.com/settings/keys" ;
  483.          process2->setProcessChannelMode(QProcess::MergedChannels);
  484.          process2->setWorkingDirectory(homedir);
  485.  
  486.          process2->start("bash", QStringList() << "-c" << command);
  487.          // Start the process to execute the command
  488.  
  489.  
  490.     }
  491.  
  492. }
  493.  
  494.  
  495.  
Add Comment
Please, Sign In to add comment