Vidalia  0.2.21
TorrcDialog.cpp
Go to the documentation of this file.
1 /*
2 ** This file is part of Vidalia, and is subject to the license terms in the
3 ** LICENSE file, found in the top level directory of this distribution. If you
4 ** did not receive the LICENSE file with this file, you may obtain it from the
5 ** Vidalia source package distributed by the Vidalia Project at
6 ** http://www.torproject.org/projects/vidalia.html. No part of Vidalia,
7 ** including this file, may be copied, modified, propagated, or distributed
8 ** except according to the terms described in the LICENSE file.
9 */
10 
11 /*
12 ** \file TorrcDialog.cpp
13 ** \brief Torrc Dialog, contains the dialog for displaying and editing the torrc
14 **
15 ** Implements the dialog for editing the torrc file inside Vidalia
16 */
17 
18 #include "TorrcDialog.h"
19 #include "Vidalia.h"
20 
21 #include <QMessageBox>
22 
23 void
24 TorHighlighter::highlightBlock(const QString &text)
25 {
26  bool firstFormatted = false;
27 
28  for (int i = 0; i < text.length(); ++i) {
29  if(text.mid(i, 1) == " " and !firstFormatted) {
30  setFormat(0, i, QColor(2,71,105));
31  setFormat(i, text.length() - 1, Qt::gray);
32  firstFormatted = true;
33  } else if (text.mid(i, 1) == "#") {
34  setFormat(i, text.length() - i, QColor(112,144,128));
35  break;
36  }
37  }
38 }
39 
40 /** Constructor */
41 TorrcDialog::TorrcDialog(QWidget *parent)
42 : QDialog(parent)
43 {
44  /* Invoke the Qt Designer generated object setup routine */
45  ui.setupUi(this);
46  TorHighlighter *highlighter = new TorHighlighter(ui.teditTorrc);
47 
48  /* Retrieve the global TorControl instance */
50  /* Load the torrc file to the TextEdit */
51  loadTorrc();
52 
53  /* Connect the accepted event from the dialog with the parsing and saving
54  * routine */
55  connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(saveTorrc()));
56 }
57 
58 /** Destructor */
60 {
61 
62 }
63 
64 /** Gives a shallow parse phase to the settings to catch most errors
65  * and passes on the error messages from Tor if the setting's value isn't
66  * valid. It returns false if something went wrong.
67  * If there's a problem in the setting stage, changes to that point will
68  * remaind but won't be saved. */
69 bool
70 TorrcDialog::parseAndSet(QString *errmsg)
71 {
72  if(!errmsg) errmsg = new QString("");
73  if(!tc || !tc->isConnected()) {
74  *errmsg = tr("Error connecting to Tor");
75  return false;
76  }
77 
78  QString key, val;
79  QStringList parts, lines;
80 
81  if(ui.rdoAll->isChecked())
82  lines = ui.teditTorrc->toPlainText().split('\n', QString::SkipEmptyParts);
83  else {
84  QString tmp = ui.teditTorrc->toPlainText();
85  QTextCursor tcursor = ui.teditTorrc->textCursor();
86  int start = tcursor.selectionStart();
87  int end = tcursor.selectionEnd();
88  tmp = tmp.mid(start, end - start).trimmed();
89  if(tmp.isEmpty()) {
90  *errmsg = tr("Selection is empty. Please select some text, or check \"Apply all\"");
91  return false;
92  }
93 
94  lines = tmp.split('\n', QString::SkipEmptyParts);
95  }
96  /* First pass: parsing */
97  int i = 0;
98  foreach(QString line, lines) {
99  i++;
100  int commentIndex = line.indexOf("#");
101  if(commentIndex != -1)
102  line = line.remove(commentIndex, line.length() - commentIndex);
103 
104  line = line.trimmed();
105  if(line.startsWith("#")) continue; // Skip commentaries
106  parts = line.split(" ", QString::SkipEmptyParts);
107  if(parts.count() < 2) {
108  *errmsg = tr("Error at line %1: \"%2\"").arg(i).arg(line);
109  return false;
110  }
111  }
112  /* Second pass: setting */
113  QHash<QString,QString> settings;
114  foreach(QString line, lines) {
115  line = line.trimmed();
116  parts = line.split(" ", QString::SkipEmptyParts);
117  key = parts[0];
118  parts.removeFirst();
119  val = parts.join(" ");
120  settings.insert(key, val);
121  }
122 
123  if(!tc->setConf(settings, errmsg)) return false;
124 
125  return true;
126 }
127 
128 /** Loads the saved torrc file that Tor's using to the TextEdit widget for
129  * editing */
130 void
132 {
133  if(tc && tc->isConnected()) {
134  QString text = "";
135  QFile file(tc->getInfo("config-file").toString());
136  if(file.open(QFile::ReadOnly)) {
137  QTextStream in(&file);
138  QString line = "";
139  do {
140  line = in.readLine();
141  text += line + "\n";
142  } while(!line.isNull());
143  ui.teditTorrc->setText(text);
144  } else {
145  QMessageBox::critical(this, tr("Error"), tr("An error ocurred while opening torrc file"));
146  }
147  }
148 }
149 
150 /** Calls the parsing and setting routine, and if everything went right
151  * it saves the configuration to the torrc file through the SAVECONF control */
152 void
154 {
155  QString errmsg = "";
156  if(tc && tc->isConnected()) {
157  if(!parseAndSet(&errmsg)) {
158  QMessageBox::critical(this, tr("Error"), errmsg);
159  return;
160  }
161  if(ui.chkSave->isChecked()) {
162  if(!tc->saveConf(&errmsg)) {
163  QMessageBox::critical(this, tr("Error"), errmsg);
164  return;
165  }
166  }
167  }
168  accept();
169 }