Vidalia  0.3.1
crashreporter/main.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 main.cpp
13 ** \brief Application that is run after Vidalia crashes and asks the
14 ** user if they would like to submit the crash report.
15 */
16 
17 #include "CrashReportDialog.h"
18 
19 #include <QApplication>
20 #include <QFileInfo>
21 #include <QMessageBox>
22 #include <QTextStream>
23 #include <QTextCodec>
24 
25 /** Read the crash dump annotations file given by <b>fileName</b> and parse
26  * each line into a Key=Value pair. Returns a QHash containing the keys
27  * mapped to their values on success. If a file or parse error occurs, this
28  * returns a default-constructed QHash and sets <b>errorMessage</b> to a
29  * string describing the error encountered.
30  */
31 QHash<QString,QString>
32 read_annotations_file(const QString &fileName, QString &errorMessage)
33 {
34  QHash<QString, QString> annotations;
35 
36  /* Open the annotations file for reading text */
37  QFile infile(fileName);
38  if (! infile.open(QIODevice::ReadOnly | QIODevice::Text)) {
39  errorMessage = infile.errorString();
40  return QHash<QString,QString>();
41  }
42 
43  /* The annotations file should be UTF-8 encoded */
44  QTextStream reader(&infile);
45  reader.setCodec(QTextCodec::codecForName("utf-8"));
46  while (! reader.atEnd()) {
47  QString line = reader.readLine().trimmed();
48  if (line.isEmpty())
49  continue;
50 
51  int idx = line.indexOf("=");
52  if (idx > 0 && idx < line.length()-1) {
53  QString key = line.mid(0, idx).trimmed();
54  QString val = line.mid(idx + 1).trimmed();
55  annotations.insert(key, val);
56  }
57  }
58  return annotations;
59 }
60 
61 int
62 main(int argc, char *argv[])
63 {
64  QApplication app(argc, argv);
65  CrashReportDialog crashDialog;
66  QFileInfo minidumpFile, extraInfoFile;
67  QString minidumpFilePath, extraInfoFilePath, errorMessage;
68  QHash<QString,QString> annotations;
69 
70  if (argc < 2) {
71  errorMessage = "No minidump file specified.";
72  goto err;
73  }
74 
75  /* Ensure that the specified minidump file exists and is readable */
76  minidumpFile = QFileInfo(argv[1]);
77  minidumpFilePath = minidumpFile.absoluteFilePath();
78  if (! minidumpFile.exists() || ! minidumpFile.size()) {
79  errorMessage = QString("The specified minidump file does not exist: %1")
80  .arg(minidumpFilePath);
81  goto err;
82  }
83  if (! minidumpFile.isReadable()) {
84  errorMessage = QString("The specified minidump file is not readable: %1")
85  .arg(minidumpFilePath);
86  goto err;
87  }
88 
89  /* Ensure that the specified minidump has an associated extra crash
90  * information file that exists and is readable. */
91  extraInfoFile = QFileInfo(minidumpFilePath + ".info");
92  extraInfoFilePath = extraInfoFile.absoluteFilePath();
93  if (! extraInfoFile.exists() || ! extraInfoFile.size()) {
94  errorMessage = QString("The specified minidump does not have a "
95  "corresponding crash annotations file: %1")
96  .arg(extraInfoFilePath);
97  goto err;
98  }
99  if (! extraInfoFile.isReadable()) {
100  errorMessage = QString("The specified crash information file is not "
101  "readable: %1").arg(extraInfoFilePath);
102  goto err;
103  }
104 
105  /* Read and parse the crash annotations file */
106  annotations = read_annotations_file(extraInfoFilePath, errorMessage);
107  if (annotations.isEmpty()) {
108  errorMessage = QString("Unable to read crash annotations file '%1': %2")
109  .arg(extraInfoFilePath)
110  .arg(errorMessage);
111  goto err;
112  }
113 
114  /* Display the crash reporting dialog */
115  crashDialog.setCrashAnnotations(annotations);
116  crashDialog.setMinidumpFiles(minidumpFilePath, extraInfoFilePath);
117  crashDialog.show();
118  return app.exec();
119 
120 err:
121  /* We encountered an error trying to load the minidump or extra crash
122  * information file. So, display an error and then bail, since now there's
123  * nothing for us to send. */
124  QMessageBox dlg;
125  dlg.setWindowIcon(QIcon(":/images/32x32/tools-report-bug.png"));
126  dlg.setWindowTitle("Crash Reporter Error");
127 
128  dlg.setIconPixmap(QPixmap(":/images/64x64/tools-report-bug.png"));
129  dlg.setStandardButtons(QMessageBox::Ok);
130 
131  dlg.setText("<b>Vidalia encountered an error and needed to close</b>");
132  dlg.setInformativeText(
133  "<p>Vidalia attempted to automatically create an error report to "
134  "help diagnose the problem, but was unable to do so. Please report "
135  "this problem, along with what you were doing before Vidalia crashed, "
136  "to the developers at:</p><p>"
137  "<a href=\"https://trac.torproject.org/projects/tor/newticket\">"
138  "https://trac.torproject.org/projects/tor/newticket</a></p> "
139  "<p>Click \"Show Details\" below for information about the problem "
140  "encountered.");
141 
142  dlg.setDetailedText(errorMessage);
143  return dlg.exec();
144 }
err
bool err(QString *str, const QString &errmsg)
Definition: stringutil.cpp:37
CrashReportDialog::setMinidumpFiles
void setMinidumpFiles(const QString &minidump, const QString &annotations)
Definition: CrashReportDialog.cpp:49
read_annotations_file
QHash< QString, QString > read_annotations_file(const QString &fileName, QString &errorMessage)
Definition: crashreporter/main.cpp:32
main
int main(int argc, char *argv[])
Definition: crashreporter/main.cpp:62
CrashReportDialog::setCrashAnnotations
void setCrashAnnotations(const QHash< QString, QString > &annotations)
Definition: CrashReportDialog.cpp:43
CrashReportDialog
Definition: CrashReportDialog.h:26
CrashReportDialog.h