mirror of
				https://github.com/ElvishArtisan/rivendell.git
				synced 2025-10-31 22:24:02 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			455 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			455 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // rddbconfig.cpp
 | |
| //
 | |
| // A Qt-based application to configure, backup, and restore
 | |
| // the Rivendell database.
 | |
| //
 | |
| //   (C) Copyright 2009-2019 Fred Gleason <fredg@paravelsystems.com>
 | |
| //
 | |
| //   This program is free software; you can redistribute it and/or modify
 | |
| //   it under the terms of the GNU General Public License version 2 as
 | |
| //   published by the Free Software Foundation.
 | |
| //
 | |
| //   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 General Public License for more details.
 | |
| //
 | |
| //   You should have received a copy of the GNU General Public
 | |
| //   License along with this program; if not, write to the Free Software
 | |
| //   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | |
| //
 | |
| 
 | |
| #include <stdlib.h>
 | |
| #include <syslog.h>
 | |
| #include <unistd.h>
 | |
| #include <sys/types.h>
 | |
| 
 | |
| #include <qapplication.h>
 | |
| #include <qfiledialog.h>
 | |
| #include <qmessagebox.h>
 | |
| #include <qprocess.h>
 | |
| 
 | |
| #include <dbversion.h>
 | |
| #include <rdapplication.h>
 | |
| #include <rdconf.h>
 | |
| #include <rdconfig.h>
 | |
| #include <rdpaths.h>
 | |
| 
 | |
| #include "../../icons/rivendell-22x22.xpm"
 | |
| 
 | |
| #include "rddbconfig.h"
 | |
| #include "db.h"
 | |
| #include "createdb.h"
 | |
| #include "mysql_login.h"
 | |
| 
 | |
| //
 | |
| // Globals
 | |
| //
 | |
| MainWidget::MainWidget(RDConfig *c,QWidget *parent)
 | |
|   : RDWidget(c,parent)
 | |
| {
 | |
|   QString err_msg;
 | |
| 
 | |
|   db_daemon_start_needed=false;
 | |
|   db=NULL;
 | |
| 
 | |
|   if(geteuid()!=0) {
 | |
|     QMessageBox::critical(this,tr("RDDbConfig Error"),
 | |
|       tr("This application requires root permissions."));
 | |
|       exit(256);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Open rd.conf(5)
 | |
|   //
 | |
|   rd_config=new RDConfig();
 | |
|   rd_config->load();
 | |
|   rd_config->setModuleName("rddbconfig");
 | |
| 
 | |
| 
 | |
|   //
 | |
|   // Create And Set Icon
 | |
|   //
 | |
|   setWindowIcon(QPixmap(rivendell_22x22_xpm));
 | |
|   setWindowTitle(tr("RDDbConfig")+" v"+VERSION);
 | |
| 
 | |
|   //
 | |
|   // Fix the Window Size
 | |
|   //
 | |
|   setMinimumSize(sizeHint());
 | |
| 
 | |
|   //
 | |
|   // Labels
 | |
|   //
 | |
|   QLabel *label=new QLabel(tr("Select an operation:"),this);
 | |
|   label->setGeometry(0,90,sizeHint().width(),16);
 | |
|   label->setFont(labelFont());
 | |
|   label->setAlignment(Qt::AlignCenter);
 | |
| 
 | |
|   label_hostname=new QLabel(QString().sprintf("SQL Server: %s",
 | |
|     (const char *)rd_config->mysqlHostname()),this);
 | |
|   label_hostname->setGeometry(0,5,sizeHint().width(),16);
 | |
|   label_hostname->setFont(day_font);
 | |
|   label_hostname->setAlignment(Qt::AlignCenter);
 | |
| 
 | |
|   label_username=new QLabel(QString().sprintf("SQL Usename: %s",
 | |
|     (const char *)rd_config->mysqlUsername()),this);
 | |
|   label_username->setGeometry(0,20,sizeHint().width(),16);
 | |
|   label_username->setFont(day_font);
 | |
|   label_username->setAlignment(Qt::AlignCenter);
 | |
| 
 | |
|   label_dbname=new QLabel(QString().sprintf("SQL Database: %s",
 | |
|     (const char *)rd_config->mysqlDbname()),this);
 | |
|   label_dbname->setGeometry(0,35,sizeHint().width(),16);
 | |
|   label_dbname->setFont(day_font);
 | |
|   label_dbname->setAlignment(Qt::AlignCenter);
 | |
| 
 | |
|   label_schema=new QLabel(this);
 | |
|   label_schema->setGeometry(0,50,sizeHint().width(),16);
 | |
|   label_schema->setFont(day_font);
 | |
|   label_schema->setAlignment(Qt::AlignCenter);
 | |
| 
 | |
|   //
 | |
|   // Create Button
 | |
|   //
 | |
|   db_create_button=new QPushButton(tr("Create"),this);
 | |
|   db_create_button->setFont(buttonFont());
 | |
|   connect(db_create_button,SIGNAL(clicked()),this,SLOT(createData()));
 | |
| 
 | |
|   //
 | |
|   // Backup Button
 | |
|   //
 | |
|   db_backup_button=new QPushButton(tr("Backup"),this);
 | |
|   db_backup_button->setFont(buttonFont());
 | |
|   connect(db_backup_button,SIGNAL(clicked()),this,SLOT(backupData()));
 | |
| 
 | |
|   //
 | |
|   // Restore Button
 | |
|   //
 | |
|   db_restore_button=new QPushButton(tr("Restore"),this);
 | |
|   db_restore_button->setFont(buttonFont());
 | |
|   connect(db_restore_button,SIGNAL(clicked()),this,SLOT(restoreData()));
 | |
| 
 | |
|   //
 | |
|   // Close Button
 | |
|   //
 | |
|   db_close_button=new QPushButton(tr("Close"),this);
 | |
|   db_close_button->setFont(buttonFont());
 | |
|   connect(db_close_button,SIGNAL(clicked()),this,SLOT(closeData()));
 | |
| 
 | |
|   //
 | |
|   // Signals
 | |
|   //
 | |
|   connect(this,SIGNAL(dbChanged()),this,SLOT(updateLabels()));
 | |
|   connect(this,SIGNAL(dbMismatch()),this,SLOT(mismatchData()));
 | |
| 
 | |
|   this->show();
 | |
| 
 | |
|   emit dbChanged();
 | |
| }
 | |
| 
 | |
| 
 | |
| MainWidget::~MainWidget()
 | |
| {
 | |
| }
 | |
| 
 | |
| 
 | |
| QSize MainWidget::sizeHint() const
 | |
| {
 | |
|   return QSize(280,330);
 | |
| }
 | |
| 
 | |
| 
 | |
| QSizePolicy MainWidget::sizePolicy() const
 | |
| {
 | |
|   return QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed);
 | |
| }
 | |
| 
 | |
| void MainWidget::mismatchData()
 | |
| {
 | |
|   if (!db->schema()) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   if (QMessageBox::question(this,tr("Database Mismatch"),QString().sprintf("Your database is version %d. Your Rivendell %s installation requires version %d. Would you like to modify your database to the current version?",db->schema(),VERSION,RD_VERSION_DATABASE),(QMessageBox::No|QMessageBox::Yes)) != QMessageBox::Yes) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   QProcess modifyProcess(this);
 | |
|   QStringList args;
 | |
|   args << QString("--modify");
 | |
|   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 | |
|   modifyProcess.start(QString("%1/sbin/rddbmgr").arg(RD_PREFIX), args);
 | |
|   bool r=modifyProcess.waitForFinished(-1);
 | |
|   QApplication::restoreOverrideCursor();
 | |
|   if(r) {
 | |
|     QString stderr=modifyProcess.readAllStandardError();
 | |
|     if (modifyProcess.exitCode()) {
 | |
|       QMessageBox::critical(this,tr("RDDbConfig Error"),stderr);
 | |
|     }
 | |
|     else {
 | |
|       if(!stderr.isEmpty()) {
 | |
|         QMessageBox::information(this,"Database Modified with Warnings",
 | |
|           QString().sprintf("Modified database to version %d with warnings:\n\n%s",
 | |
|             RD_VERSION_DATABASE,(const char *)stderr));
 | |
|       }
 | |
|       else {
 | |
|         QMessageBox::information(this,"Database Modified Successfully",
 | |
|           QString().sprintf("Modified database to version %d",
 | |
| 			    RD_VERSION_DATABASE));
 | |
|       }
 | |
|       RDApplication::syslog(rd_config,LOG_INFO,
 | |
| 			    "modified database to version %d",
 | |
| 			    RD_VERSION_DATABASE);
 | |
| 
 | |
|       emit dbChanged();
 | |
|     }
 | |
|   }
 | |
|   else {
 | |
|     QMessageBox::critical(this,tr("Database Update Error"),
 | |
|       QString("Error starting rddbmgr: code=%1").arg(modifyProcess.error()));
 | |
|   }
 | |
| }
 | |
| 
 | |
| void MainWidget::updateLabels()
 | |
| {
 | |
|   QString err_msg="";
 | |
| 
 | |
|   if(db!=NULL) {
 | |
|     delete db;
 | |
|   }
 | |
|   db = new Db(&err_msg,rd_config);
 | |
| 
 | |
|   if (!db->isOpen()) {
 | |
|     label_schema->setText("DB Version: unknown");
 | |
|     db_backup_button->setEnabled(false);
 | |
|     db_restore_button->setEnabled(false);
 | |
|   }
 | |
|   else {
 | |
|     label_schema->setText(QString().sprintf("DB Version: %d",db->schema()));
 | |
|     db_backup_button->setEnabled(true);
 | |
|     db_restore_button->setEnabled(true);
 | |
| 
 | |
|     if(db->schema()!=RD_VERSION_DATABASE) {
 | |
|       emit dbMismatch();
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| void MainWidget::closeData()
 | |
| {
 | |
|   exit(0);
 | |
| }
 | |
| 
 | |
| void MainWidget::createData()
 | |
| {
 | |
|   MySqlLogin *mysql_login;
 | |
|   QString hostname=rd_config->mysqlHostname();
 | |
|   QString dbname=rd_config->mysqlDbname();
 | |
|   QString admin_name;
 | |
|   QString admin_pwd;
 | |
|   QString err_str;
 | |
| 
 | |
|   if (db->isOpen()) {
 | |
|     if (QMessageBox::question(this,tr("Create Database"),tr("Creating a new database will erase all of your data. Are you sure you want to create a new database?"),(QMessageBox::No|QMessageBox::Yes)) != QMessageBox::Yes) {
 | |
|       return;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   mysql_login=new MySqlLogin(&admin_name,&admin_pwd);
 | |
| 
 | |
|   if(mysql_login->exec()) {
 | |
|     delete mysql_login;
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   delete mysql_login;
 | |
| 
 | |
|   if(admin_name.isEmpty()||admin_pwd.isEmpty()) {
 | |
|     QMessageBox::critical(this,tr("RDDbConfig Error"),tr("Did not specify username and/or password."));
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   stopDaemons();
 | |
| 
 | |
|   CreateDb *db_create=new CreateDb(hostname,dbname,admin_name,admin_pwd);
 | |
| 
 | |
|   if(db_create->create(this,&err_str,rd_config)) {
 | |
|     QMessageBox::critical(this,tr("RDDbConfig Error"),err_str);
 | |
|   }
 | |
|   else {
 | |
|     QMessageBox::information(this,tr("Success"),tr("A new database has been successfully created."));
 | |
|   }
 | |
| 
 | |
|   startDaemons();
 | |
| 
 | |
|   emit updateLabels();
 | |
| 
 | |
|   delete db_create;
 | |
| }
 | |
| 
 | |
| 
 | |
| void MainWidget::backupData()
 | |
| {
 | |
|   QString filename;
 | |
| 
 | |
|   if (!db->isOpen()) {
 | |
|     QMessageBox::critical(this,tr("RDDbConfig Error"),
 | |
|       QString().sprintf("Could not open %s database.",
 | |
|       (const char *)rd_config->mysqlDbname()));
 | |
|     return;
 | |
|   }
 | |
|   filename=QFileDialog::getSaveFileName(this,"RDDbConfig - "+
 | |
| 					tr("Enter the MySQL Backup Filename"),
 | |
| 					RDHomeDir(),
 | |
| 					"MySQL files (*.sql);;All files (*.*)");
 | |
| 
 | |
|   if (!filename.isEmpty()) {
 | |
|     QProcess backupProcess(this);
 | |
|     QStringList args;
 | |
|     args << QString().sprintf("--user=%s",(const char *)rd_config->mysqlUsername())
 | |
|       << QString().sprintf("--password=%s",(const char *)rd_config->mysqlPassword())
 | |
|       << QString().sprintf("--host=%s",(const char *)rd_config->mysqlHostname())
 | |
|       << rd_config->mysqlDbname();
 | |
|     backupProcess.setStandardOutputFile(filename);
 | |
|     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 | |
|     backupProcess.start("mysqldump", args);
 | |
|     backupProcess.waitForFinished(-1);
 | |
|     QApplication::restoreOverrideCursor();
 | |
|     if (backupProcess.exitCode()) {
 | |
|       QMessageBox::critical(this,tr("RDDbConfig Error"),
 | |
|         QString(backupProcess.readAllStandardError()));
 | |
|     }
 | |
|     else {
 | |
|       QMessageBox::information(this,"Database Backed Up Successfully",
 | |
|         QString().sprintf("Backed up %s database to %s",
 | |
|           (const char *)rd_config->mysqlDbname(),
 | |
|           (const char *)filename));
 | |
|       RDApplication::syslog(rd_config,LOG_INFO,"backed up %s database to %s",
 | |
| 			    (const char *)rd_config->mysqlDbname(),
 | |
| 			    (const char *)filename);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| void MainWidget::restoreData()
 | |
| {
 | |
|   QString filename;
 | |
| 
 | |
|   if (!db->isOpen()) {
 | |
|     QMessageBox::critical(this,tr("RDDbConfig Error"),
 | |
|       tr("Could not open Rivendell database."));
 | |
|     return;
 | |
|   }
 | |
|   filename=
 | |
|     QFileDialog::getOpenFileName(this,"RDDbConfig - "+
 | |
| 				 tr("Choose the MySQL Backup File to Restore"),
 | |
| 				 RDHomeDir(),
 | |
| 				 "MySQL files (*.sql);;All files (*.*)");
 | |
| 
 | |
|   if(!filename.isEmpty()) {
 | |
|     if (QMessageBox::question(this,tr("Restore Entire Database"),tr("Are you sure you want to restore your entire Rivendell database?"),(QMessageBox::No|QMessageBox::Yes)) != QMessageBox::Yes) {
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     db->clearDatabase(rd_config->mysqlDbname());
 | |
| 
 | |
|     QProcess restoreProcess(this);
 | |
|     QStringList args;
 | |
|     args << QString().sprintf("--user=%s",(const char *)rd_config->mysqlUsername())
 | |
|       << QString().sprintf("--password=%s",(const char *)rd_config->mysqlPassword())
 | |
|       << QString().sprintf("--host=%s",(const char *)rd_config->mysqlHostname())
 | |
|       << rd_config->mysqlDbname();
 | |
|     restoreProcess.setStandardInputFile(filename);
 | |
|     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 | |
|     stopDaemons();
 | |
|     restoreProcess.start("mysql", args);
 | |
|     restoreProcess.waitForFinished(-1);
 | |
|     QApplication::restoreOverrideCursor();
 | |
|     if (restoreProcess.exitCode()) {
 | |
|       QMessageBox::critical(this,tr("RDDbConfig Error"),
 | |
|       QString(restoreProcess.readAllStandardError()));
 | |
|     }
 | |
|     else {
 | |
|       QMessageBox::information(this,"Database Restored Successfully",
 | |
|         QString().sprintf("Restored %s database from %s",
 | |
|           (const char *)rd_config->mysqlDbname(),
 | |
|           (const char *)filename));
 | |
|       RDApplication::syslog(rd_config,LOG_INFO,"restored %s database from %s",
 | |
| 			    (const char *)rd_config->mysqlDbname(),
 | |
| 			    (const char *)filename);
 | |
|     }
 | |
|     emit updateLabels();
 | |
|     startDaemons();
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| void MainWidget::resizeEvent(QResizeEvent *e)
 | |
| {
 | |
|   db_create_button->
 | |
|     setGeometry(size().width()/2-80,110,160,50);
 | |
|   db_backup_button->
 | |
|     setGeometry(size().width()/2-80,165,160,50);
 | |
|   db_restore_button->
 | |
|     setGeometry(size().width()/2-80,220,160,50);
 | |
|   db_close_button->
 | |
|     setGeometry(size().width()/2-80,275,160,50);
 | |
| }
 | |
| 
 | |
| 
 | |
| int MainWidget::statusDaemons(QString service)
 | |
| {
 | |
|   QProcess statusProcess(this);
 | |
|   QStringList args;
 | |
|   args << "status" << service;
 | |
|   statusProcess.start("systemctl", args);
 | |
|   statusProcess.waitForFinished();
 | |
|   return statusProcess.exitCode();
 | |
| }
 | |
| 
 | |
| void MainWidget::stopDaemons()
 | |
| {
 | |
|   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 | |
|   if(!statusDaemons("rivendell")) {
 | |
|     QProcess stopProcess(this);
 | |
|     QStringList args;
 | |
|     args << "stop" << "rivendell";
 | |
|     stopProcess.start("systemctl", args);
 | |
|     stopProcess.waitForFinished();
 | |
|     if (!stopProcess.exitCode()) {
 | |
|       db_daemon_start_needed=true;
 | |
|     }
 | |
|   }
 | |
|   QApplication::restoreOverrideCursor();
 | |
| }
 | |
| 
 | |
| 
 | |
| void MainWidget::startDaemons()
 | |
| {
 | |
|   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 | |
|   if(statusDaemons("rivendell")) {
 | |
|     QProcess startProcess(this);
 | |
|     QStringList args;
 | |
|     args << "start" << "rivendell";
 | |
|     startProcess.start("systemctl", args);
 | |
|     startProcess.waitForFinished();
 | |
|   }
 | |
|   QApplication::restoreOverrideCursor();
 | |
| }
 | |
| 
 | |
| 
 | |
| int main(int argc,char *argv[])
 | |
| {
 | |
|   //
 | |
|   // Start GUI
 | |
|   //
 | |
|   RDConfig *config=new RDConfig();
 | |
|   config->load();
 | |
|   QApplication a(argc,argv);
 | |
|   MainWidget *w=new MainWidget(config);
 | |
|   a.setMainWidget(w);
 | |
|   return a.exec();
 | |
| }
 |