Vidalia 0.2.15
|
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.torproject.org/projects/vidalia.html. No part of Vidalia, 00007 ** including this file, may be copied, modified, propagated, or distributed 00008 ** except according to the terms described in the LICENSE file. 00009 */ 00010 00011 /* 00012 ** \file main.cpp 00013 ** \brief Application that is run after Vidalia crashes and asks the 00014 ** user if they would like to submit the crash report. 00015 */ 00016 00017 #include "CrashReportDialog.h" 00018 00019 #include <QApplication> 00020 #include <QFileInfo> 00021 #include <QMessageBox> 00022 #include <QTextStream> 00023 #include <QTextCodec> 00024 00025 /** Read the crash dump annotations file given by <b>fileName</b> and parse 00026 * each line into a Key=Value pair. Returns a QHash containing the keys 00027 * mapped to their values on success. If a file or parse error occurs, this 00028 * returns a default-constructed QHash and sets <b>errorMessage</b> to a 00029 * string describing the error encountered. 00030 */ 00031 QHash<QString,QString> 00032 read_annotations_file(const QString &fileName, QString &errorMessage) 00033 { 00034 QHash<QString, QString> annotations; 00035 00036 /* Open the annotations file for reading text */ 00037 QFile infile(fileName); 00038 if (! infile.open(QIODevice::ReadOnly | QIODevice::Text)) { 00039 errorMessage = infile.errorString(); 00040 return QHash<QString,QString>(); 00041 } 00042 00043 /* The annotations file should be UTF-8 encoded */ 00044 QTextStream reader(&infile); 00045 reader.setCodec(QTextCodec::codecForName("utf-8")); 00046 while (! reader.atEnd()) { 00047 QString line = reader.readLine().trimmed(); 00048 if (line.isEmpty()) 00049 continue; 00050 00051 int idx = line.indexOf("="); 00052 if (idx > 0 && idx < line.length()-1) { 00053 QString key = line.mid(0, idx).trimmed(); 00054 QString val = line.mid(idx + 1).trimmed(); 00055 annotations.insert(key, val); 00056 } 00057 } 00058 return annotations; 00059 } 00060 00061 int 00062 main(int argc, char *argv[]) 00063 { 00064 QApplication app(argc, argv); 00065 CrashReportDialog crashDialog; 00066 QFileInfo minidumpFile, extraInfoFile; 00067 QString minidumpFilePath, extraInfoFilePath, errorMessage; 00068 QHash<QString,QString> annotations; 00069 00070 if (argc < 2) { 00071 errorMessage = "No minidump file specified."; 00072 goto err; 00073 } 00074 00075 /* Ensure that the specified minidump file exists and is readable */ 00076 minidumpFile = QFileInfo(argv[1]); 00077 minidumpFilePath = minidumpFile.absoluteFilePath(); 00078 if (! minidumpFile.exists() || ! minidumpFile.size()) { 00079 errorMessage = QString("The specified minidump file does not exist: %1") 00080 .arg(minidumpFilePath); 00081 goto err; 00082 } 00083 if (! minidumpFile.isReadable()) { 00084 errorMessage = QString("The specified minidump file is not readable: %1") 00085 .arg(minidumpFilePath); 00086 goto err; 00087 } 00088 00089 /* Ensure that the specified minidump has an associated extra crash 00090 * information file that exists and is readable. */ 00091 extraInfoFile = QFileInfo(minidumpFilePath + ".info"); 00092 extraInfoFilePath = extraInfoFile.absoluteFilePath(); 00093 if (! extraInfoFile.exists() || ! extraInfoFile.size()) { 00094 errorMessage = QString("The specified minidump does not have a " 00095 "corresponding crash annotations file: %1") 00096 .arg(extraInfoFilePath); 00097 goto err; 00098 } 00099 if (! extraInfoFile.isReadable()) { 00100 errorMessage = QString("The specified crash information file is not " 00101 "readable: %1").arg(extraInfoFilePath); 00102 goto err; 00103 } 00104 00105 /* Read and parse the crash annotations file */ 00106 annotations = read_annotations_file(extraInfoFilePath, errorMessage); 00107 if (annotations.isEmpty()) { 00108 errorMessage = QString("Unable to read crash annotations file '%1': %2") 00109 .arg(extraInfoFilePath) 00110 .arg(errorMessage); 00111 goto err; 00112 } 00113 00114 /* Display the crash reporting dialog */ 00115 crashDialog.setCrashAnnotations(annotations); 00116 crashDialog.setMinidumpFiles(minidumpFilePath, extraInfoFilePath); 00117 crashDialog.show(); 00118 return app.exec(); 00119 00120 err: 00121 /* We encountered an error trying to load the minidump or extra crash 00122 * information file. So, display an error and then bail, since now there's 00123 * nothing for us to send. */ 00124 QMessageBox dlg; 00125 dlg.setWindowIcon(QIcon(":/images/32x32/tools-report-bug.png")); 00126 dlg.setWindowTitle("Crash Reporter Error"); 00127 00128 dlg.setIconPixmap(QPixmap(":/images/64x64/tools-report-bug.png")); 00129 dlg.setStandardButtons(QMessageBox::Ok); 00130 00131 dlg.setText("<b>Vidalia encountered an error and needed to close</b>"); 00132 dlg.setInformativeText( 00133 "<p>Vidalia attempted to automatically create an error report to " 00134 "help diagnose the problem, but was unable to do so. Please report " 00135 "this problem, along with what you were doing before Vidalia crashed, " 00136 "to the developers at:</p><p>" 00137 "<a href=\"https://trac.torproject.org/projects/tor/newticket\">" 00138 "https://trac.torproject.org/projects/tor/newticket</a></p> " 00139 "<p>Click \"Show Details\" below for information about the problem " 00140 "encountered."); 00141 00142 dlg.setDetailedText(errorMessage); 00143 return dlg.exec(); 00144 }