Vidalia 0.2.12

TorrcDialog.cpp

Go to the documentation of this file.
00001 /*
00002 **  This file is part of Vidalia, and is subject to the license terms in the
00003 **  LICENSE file, found in the top level directory of this distribution. If you
00004 **  did not receive the LICENSE file with this file, you may obtain it from the
00005 **  Vidalia source package distributed by the Vidalia Project at
00006 **  http://www.vidalia-project.net/. No part of Vidalia, including this file,
00007 **  may be copied, modified, propagated, or distributed except according to the
00008 **  terms described in the LICENSE file.
00009 */
00010 
00011 /*
00012 ** \file TorrcDialog.cpp
00013 ** \brief Torrc Dialog, contains the dialog for displaying and editing the torrc
00014 **
00015 ** Implements the dialog for editing the torrc file inside Vidalia 
00016 */
00017 
00018 #include "TorrcDialog.h"
00019 #include "Vidalia.h"
00020 
00021 #include <QMessageBox>
00022 
00023 void
00024 TorHighlighter::highlightBlock(const QString &text)
00025 {
00026   bool firstFormatted = false;
00027 
00028   for (int i = 0; i < text.length(); ++i) {
00029     if(text.mid(i, 1) == " " and !firstFormatted) {
00030       setFormat(0, i, QColor(2,71,105));
00031       setFormat(i, text.length() - 1, Qt::gray);
00032       firstFormatted = true;
00033     } else if (text.mid(i, 1) == "#") {
00034       setFormat(i, text.length() - i, QColor(112,144,128));
00035       break;
00036     }
00037   }
00038 }
00039 
00040 /** Constructor */
00041 TorrcDialog::TorrcDialog(QWidget *parent)
00042 : QDialog(parent)
00043 {
00044   /* Invoke the Qt Designer generated object setup routine */
00045   ui.setupUi(this);
00046   TorHighlighter *highlighter = new TorHighlighter(ui.teditTorrc);
00047 
00048   /* Retrieve the global TorControl instance */
00049   tc = Vidalia::torControl();
00050   /* Load the torrc file to the TextEdit */
00051   loadTorrc();
00052 
00053   /* Connect the accepted event from the dialog with the parsing and saving
00054    * routine */
00055   connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(saveTorrc()));
00056 }
00057 
00058 /** Destructor */
00059 TorrcDialog::~TorrcDialog()
00060 {
00061 
00062 }
00063 
00064 /** Gives a shallow parse phase to the settings to catch most errors 
00065  * and passes on the error messages from Tor if the setting's value isn't
00066  * valid. It returns false if something went wrong.
00067  * If there's a problem in the setting stage, changes to that point will 
00068  * remaind but won't be saved. */
00069 bool 
00070 TorrcDialog::parseAndSet(QString *errmsg)
00071 {
00072   if(!errmsg) errmsg = new QString("");
00073   if(!tc || !tc->isConnected()) {
00074     *errmsg = tr("Error connecting to Tor");
00075     return false;
00076   }
00077 
00078   QString key, val;
00079   QStringList parts, lines;
00080   
00081   if(ui.rdoAll->isChecked())
00082     lines = ui.teditTorrc->toPlainText().split('\n', QString::SkipEmptyParts);
00083   else {
00084     QString tmp = ui.teditTorrc->toPlainText();
00085     QTextCursor tcursor = ui.teditTorrc->textCursor();
00086     int start = tcursor.selectionStart();
00087     int end = tcursor.selectionEnd();
00088     tmp = tmp.mid(start, end - start).trimmed();
00089     if(tmp.isEmpty()) {
00090       *errmsg = tr("Selection is empty. Please select some text, or check \"Apply all\"");
00091       return false;
00092     }
00093 
00094     lines = tmp.split('\n', QString::SkipEmptyParts);
00095   }
00096   /* First pass: parsing */
00097   int i = 0;
00098   foreach(QString line, lines) {
00099     i++;
00100     line = line.trimmed();
00101     if(line.startsWith("#")) continue; // Skip commentaries
00102     parts = line.split(" ", QString::SkipEmptyParts);
00103     if(parts.count() < 2) {
00104       *errmsg = tr("Error at line %1: \"%2\"").arg(i).arg(line);
00105       return false;
00106     }
00107   }
00108   /* Second pass: setting */
00109   QHash<QString,QString> settings;
00110   foreach(QString line, lines) {
00111     line = line.trimmed();
00112     parts = line.split(" ", QString::SkipEmptyParts);
00113     key = parts[0];
00114     parts.removeFirst();
00115     val = parts.join(" ");
00116     settings.insert(key, val);
00117   }
00118 
00119   if(!tc->setConf(settings, errmsg)) return false;
00120 
00121   return true;
00122 }
00123 
00124 /** Loads the saved torrc file that Tor's using to the TextEdit widget for
00125  * editing */
00126 void 
00127 TorrcDialog::loadTorrc()
00128 {
00129   if(tc && tc->isConnected()) {
00130     QString text = "";
00131     QFile file(tc->getInfo("config-file").toString());
00132     if(file.open(QFile::ReadOnly)) {
00133       QTextStream in(&file);
00134       QString line = "";
00135       do {
00136         line = in.readLine();
00137         text += line + "\n";
00138       } while(!line.isNull());
00139       ui.teditTorrc->setText(text);
00140     } else {
00141       QMessageBox::critical(this, tr("Error"), tr("An error ocurred while opening torrc file"));
00142     }
00143   }
00144 }
00145 
00146 /** Calls the parsing and setting routine, and if everything went right
00147  * it saves the configuration to the torrc file through the SAVECONF control */
00148 void 
00149 TorrcDialog::saveTorrc()
00150 {
00151   QString errmsg = "";
00152   if(tc && tc->isConnected()) {
00153     if(!parseAndSet(&errmsg)) {
00154       QMessageBox::critical(this, tr("Error"), errmsg);
00155       return;
00156     }
00157     if(ui.chkSave->isChecked()) {
00158       if(!tc->saveConf(&errmsg)) {
00159         QMessageBox::critical(this, tr("Error"), errmsg);
00160         return;
00161       }
00162     }
00163   }
00164   accept();
00165 }