Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F4324302
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Size
118 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/trunk/dlgreportchooser.cpp b/trunk/dlgreportchooser.cpp
index 223fb92..bb95439 100644
--- a/trunk/dlgreportchooser.cpp
+++ b/trunk/dlgreportchooser.cpp
@@ -1,94 +1,148 @@
/*******************************************************************************
* fred Copyright (c) 2011-2013 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor *
* with special feautures useful during forensic analysis. *
* *
* This program is free software: you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the Free *
* Software Foundation, either version 3 of the License, or (at your option) *
* any later version. *
* *
* 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, see <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#include "dlgreportchooser.h"
#include "ui_dlgreportchooser.h"
#include <QString>
#include <QStringList>
#include <QListIterator>
-DlgReportChooser::DlgReportChooser(Reports *p_reps, QWidget *p_parent)
+#include <QDebug>
+
+DlgReportChooser::DlgReportChooser(Reports *p_reps,
+ QString hive_type_string,
+ QWidget *p_parent)
: QDialog(p_parent), ui(new Ui::DlgReportChooser)
{
- QTreeWidgetItem *p_category;
- QTreeWidgetItem *p_category_report;
+ QStringList tree_cats;
+ QString cur_tree_cat;
+ QTreeWidgetItem *p_tree_cat_widget;
+ QTreeWidgetItem *p_tree_cat_rep_widget;
+ QList<ReportTemplate*> tree_cat_reports;
+ ReportTemplate* p_report;
+ // Init private vars
this->ui->setupUi(this);
-
- // Save values for later use
this->p_reports=p_reps;
+ this->hive_type=hive_type_string;
+ this->tree_category_items.clear();
+ this->selected_reports.clear();
// Populate tree with reports
- QStringList report_cats=this->p_reports->GetAvailableReportCategories();
- QListIterator<QString> cat_it(report_cats);
- QString cur_cat;
- while(cat_it.hasNext()) {
- cur_cat=cat_it.next();
- p_category=new QTreeWidgetItem(this->ui->TrReports);
- p_category->setText(0,cur_cat);
- QStringList reports=this->p_reports->GetAvailableReports(cur_cat);
- QListIterator<QString> rep_it(reports);
- while(rep_it.hasNext()) {
- p_category_report=new QTreeWidgetItem(p_category);
- p_category_report->setText(0,rep_it.next());
- p_category_report->setFlags(Qt::ItemIsEnabled|
- Qt::ItemIsSelectable|
- Qt::ItemIsUserCheckable);
- p_category_report->setCheckState(0,Qt::Unchecked);
+ tree_cats=this->p_reports->GetAvailableReportCategories();
+ QListIterator<QString> tree_cat_it(tree_cats);
+ while(tree_cat_it.hasNext()) {
+ cur_tree_cat=tree_cat_it.next();
+ p_tree_cat_widget=new QTreeWidgetItem(this->ui->TrReports);
+ p_tree_cat_widget->setText(0,cur_tree_cat);
+ p_tree_cat_widget->setFlags(Qt::ItemIsEnabled|
+ Qt::ItemIsUserCheckable|
+ Qt::ItemIsTristate);
+ p_tree_cat_widget->setCheckState(0,Qt::Unchecked);
+ tree_cat_reports=this->p_reports->GetAvailableReports(cur_tree_cat);
+ QListIterator<ReportTemplate*> tree_cat_rep_it(tree_cat_reports);
+ while(tree_cat_rep_it.hasNext()) {
+ p_report=tree_cat_rep_it.next();
+
+ p_tree_cat_rep_widget=new QTreeWidgetItem(p_tree_cat_widget);
+ // Save pointer to ReportTemplate alongside
+ p_tree_cat_rep_widget->setData(0,
+ Qt::UserRole,
+ QVariant().fromValue(p_report));
+ p_tree_cat_rep_widget->setText(0,p_report->Name());
+ p_tree_cat_rep_widget->setFlags(Qt::ItemIsEnabled|
+ Qt::ItemIsSelectable|
+ Qt::ItemIsUserCheckable);
+ if(this->hive_type!="UNKNOWN" && this->hive_type==p_report->Hive()) {
+ p_tree_cat_rep_widget->setCheckState(0,Qt::Checked);
+ } else {
+ p_tree_cat_rep_widget->setCheckState(0,Qt::Unchecked);
+ }
}
+ this->tree_category_items.append(p_tree_cat_widget);
}
+
+ // Finally, expand all categories
+ this->ui->TrReports->expandAll();
}
DlgReportChooser::~DlgReportChooser() {
delete this->ui;
}
+QList<ReportTemplate*> DlgReportChooser::GetSelectedReports()
+{
+ return this->selected_reports;
+}
+
void DlgReportChooser::changeEvent(QEvent *e) {
QDialog::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
this->ui->retranslateUi(this);
break;
default:
break;
}
}
void DlgReportChooser::on_BtnCancel_clicked() {
this->reject();
}
-void DlgReportChooser::on_TrReports_currentItemChanged(QTreeWidgetItem *current,
- QTreeWidgetItem *previous)
+void DlgReportChooser::on_TrReports_currentItemChanged(
+ QTreeWidgetItem *p_current, QTreeWidgetItem *p_previous)
{
- QString category,name;
-
- if(current->parent()==NULL) return;
-
- category=current->parent()->text(0);
- name=current->text(0);
- QMap<QString,QString> report_infos=
- this->p_reports->GetReportInfo(category,name);
- this->ui->LblAuthor->setText(tr("Author: %1")
- .arg(report_infos["report_author"]));
- this->ui->LblDesc->setText(tr("Description:\n\n %1")
- .arg(report_infos["report_desc"]));
+ Q_UNUSED(p_previous)
+
+ // If item has no parent, clear labels and return
+ if(p_current->parent()==NULL) {
+ this->ui->LblAuthor->clear();
+ this->ui->LblDesc->clear();
+ return;
+ }
+
+ // Update labels
+ this->ui->LblAuthor->setText(
+ p_current->data(0,Qt::UserRole).value<ReportTemplate*>()->Author());
+ this->ui->LblDesc->setText(
+ p_current->data(0,Qt::UserRole).value<ReportTemplate*>()->Description());
+}
+
+void DlgReportChooser::on_BtnGenerate_clicked() {
+ QTreeWidgetItem *p_cat;
+ int i;
+
+ // Add selected reports to selected_reports
+ QListIterator<QTreeWidgetItem*> cat_it(this->tree_category_items);
+ while(cat_it.hasNext()) {
+ p_cat=cat_it.next();
+ for(i=0;i<p_cat->childCount();i++) {
+ if(p_cat->child(i)->checkState(0)==Qt::Checked) {
+ // Get saved pointer to ReportTemplate and append it to selected_reps
+ this->selected_reports.append(p_cat->
+ child(i)->data(0,Qt::UserRole).value<ReportTemplate*>());
+ }
+ }
+ }
+
+ this->accept();
}
diff --git a/trunk/dlgreportchooser.h b/trunk/dlgreportchooser.h
index 8751723..a8820b7 100644
--- a/trunk/dlgreportchooser.h
+++ b/trunk/dlgreportchooser.h
@@ -1,53 +1,62 @@
/*******************************************************************************
* fred Copyright (c) 2011-2013 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor *
* with special feautures useful during forensic analysis. *
* *
* This program is free software: you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the Free *
* Software Foundation, either version 3 of the License, or (at your option) *
* any later version. *
* *
* 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, see <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#ifndef DLGREPORTCHOOSER_H
#define DLGREPORTCHOOSER_H
#include "reports.h"
#include <QDialog>
+#include <QList>
#include <QTreeWidgetItem>
namespace Ui {
class DlgReportChooser;
}
class DlgReportChooser : public QDialog {
Q_OBJECT
public:
- explicit DlgReportChooser(Reports *p_reps, QWidget *p_parent=0);
+ explicit DlgReportChooser(Reports *p_reps,
+ QString hive_type_string,
+ QWidget *p_parent=0);
~DlgReportChooser();
+ QList<ReportTemplate*> GetSelectedReports();
+
protected:
void changeEvent(QEvent *e);
private slots:
void on_BtnCancel_clicked();
-
- void on_TrReports_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);
+ void on_TrReports_currentItemChanged(QTreeWidgetItem *p_current,
+ QTreeWidgetItem *p_previous);
+ void on_BtnGenerate_clicked();
private:
Ui::DlgReportChooser *ui;
Reports *p_reports;
+ QString hive_type;
+ QList<QTreeWidgetItem*> tree_category_items;
+ QList<ReportTemplate*> selected_reports;
};
#endif // DLGREPORTCHOOSER_H
diff --git a/trunk/dlgreportchooser.ui b/trunk/dlgreportchooser.ui
index 6e4877d..6d023e3 100644
--- a/trunk/dlgreportchooser.ui
+++ b/trunk/dlgreportchooser.ui
@@ -1,125 +1,209 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DlgReportChooser</class>
<widget class="QDialog" name="DlgReportChooser">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>400</width>
+ <width>599</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Generate report</string>
</property>
<property name="windowIcon">
<iconset resource="fred.qrc">
<normaloff>:/icons/resources/fred.png</normaloff>:/icons/resources/fred.png</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<property name="title">
<string>Available reports</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
+ <property name="topMargin">
+ <number>9</number>
+ </property>
+ <property name="rightMargin">
+ <number>9</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
<item>
<widget class="QTreeWidget" name="TrReports">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<property name="headerHidden">
<bool>true</bool>
</property>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>3</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>300</width>
+ <height>0</height>
+ </size>
+ </property>
<property name="title">
<string>Report details</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>9</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="font">
+ <font>
+ <weight>50</weight>
+ <bold>false</bold>
+ <underline>true</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>Author:</string>
+ </property>
+ </widget>
+ </item>
<item>
<widget class="QLabel" name="LblAuthor">
<property name="text">
<string/>
</property>
+ <property name="indent">
+ <number>10</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="font">
+ <font>
+ <weight>50</weight>
+ <bold>false</bold>
+ <underline>true</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>Description:</string>
+ </property>
</widget>
</item>
<item>
<widget class="QLabel" name="LblDesc">
<property name="text">
<string/>
</property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ <property name="indent">
+ <number>10</number>
+ </property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="BtnCancel">
<property name="text">
<string>&Cancel</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="BtnGenerate">
<property name="text">
<string>&Generate</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
+ <tabstops>
+ <tabstop>BtnGenerate</tabstop>
+ <tabstop>BtnCancel</tabstop>
+ <tabstop>TrReports</tabstop>
+ </tabstops>
<resources>
<include location="fred.qrc"/>
</resources>
<connections/>
</ui>
diff --git a/trunk/dlgreportviewer.cpp b/trunk/dlgreportviewer.cpp
index a962057..30d5675 100644
--- a/trunk/dlgreportviewer.cpp
+++ b/trunk/dlgreportviewer.cpp
@@ -1,88 +1,107 @@
/*******************************************************************************
* fred Copyright (c) 2011-2013 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor *
* with special feautures useful during forensic analysis. *
* *
* This program is free software: you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the Free *
* Software Foundation, either version 3 of the License, or (at your option) *
* any later version. *
* *
* 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, see <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#include "dlgreportviewer.h"
#include "ui_dlgreportviewer.h"
#include <QPrinter>
#include <QPrintDialog>
+#include <QFileDialog>
+#include <QTextDocument>
+#include <QTextDocumentWriter>
DlgReportViewer::DlgReportViewer(QString &report_data, QWidget *p_parent)
: QMainWindow(p_parent,Qt::Dialog | Qt::Popup), ui(new Ui::DlgReportViewer)
{
// Init local vars
ui->setupUi(this);
this->p_local_event_loop=NULL;
+ this->orig_report_data=report_data;
// Set report content
this->ui->WebView->setHtml(report_data);
// Set dialog title based on report content title
QString report_title=this->ui->WebView->title();
- if(report_title.isEmpty()) this->setWindowTitle("Report Viewer");
- else this->setWindowTitle(report_title.prepend("Report Viewer : "));
+ this->setWindowTitle("Report Viewer");
}
DlgReportViewer::~DlgReportViewer() {
delete ui;
if(this->p_local_event_loop!=NULL) this->p_local_event_loop->exit();
}
void DlgReportViewer::changeEvent(QEvent *e) {
QMainWindow::changeEvent(e);
switch(e->type()) {
case QEvent::LanguageChange:
ui->retranslateUi(this);
break;
default:
break;
}
}
void DlgReportViewer::closeEvent(QCloseEvent *event) {
// Make sure we exit the local event loop on exit
if(this->p_local_event_loop!=NULL) {
this->p_local_event_loop->exit();
this->p_local_event_loop=NULL;
}
event->accept();
}
void DlgReportViewer::exec() {
// Create local event loop
this->p_local_event_loop=new QEventLoop(this);
// Show window and enter loop
this->show();
this->p_local_event_loop->exec();
}
void DlgReportViewer::on_action_Print_triggered() {
// Print report
QPrinter printer;
QPrintDialog *p_dlg_print=new QPrintDialog(&printer);
if(p_dlg_print->exec()==QDialog::Accepted) {
this->ui->WebView->print(&printer);
}
delete p_dlg_print;
}
void DlgReportViewer::on_action_Close_triggered() {
this->close();
}
+
+void DlgReportViewer::on_action_Save_triggered() {
+ QString filename=QFileDialog::getSaveFileName(this,
+ tr("Save report as"),
+ "",
+ "ODF file (*.odf)");
+ if(filename!="") {
+ QTextDocument *p_doc=new QTextDocument(this);
+ p_doc->setHtml(this->orig_report_data);
+ QTextDocumentWriter *p_doc_writer=new QTextDocumentWriter(filename);
+ p_doc_writer->setFormat(QByteArray("ODF"));
+ p_doc_writer->write(p_doc);
+ delete p_doc_writer;
+ delete p_doc;
+ }
+}
diff --git a/trunk/dlgreportviewer.h b/trunk/dlgreportviewer.h
index 88c182f..89fc1d5 100644
--- a/trunk/dlgreportviewer.h
+++ b/trunk/dlgreportviewer.h
@@ -1,56 +1,59 @@
/*******************************************************************************
* fred Copyright (c) 2011-2013 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor *
* with special feautures useful during forensic analysis. *
* *
* This program is free software: you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the Free *
* Software Foundation, either version 3 of the License, or (at your option) *
* any later version. *
* *
* 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, see <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#ifndef DLGREPORTVIEWER_H
#define DLGREPORTVIEWER_H
#include <QMainWindow>
#include <QEventLoop>
#include <QCloseEvent>
namespace Ui {
class DlgReportViewer;
}
class DlgReportViewer : public QMainWindow {
Q_OBJECT
public:
explicit DlgReportViewer(QString &report_data,
QWidget *p_parent=0);
~DlgReportViewer();
void exec();
protected:
void changeEvent(QEvent *e);
void closeEvent(QCloseEvent *event);
private slots:
void on_action_Print_triggered();
void on_action_Close_triggered();
-private:
+ void on_action_Save_triggered();
+
+ private:
Ui::DlgReportViewer *ui;
QEventLoop *p_local_event_loop;
+ QString orig_report_data;
};
#endif // DLGREPORTVIEWER_H
diff --git a/trunk/dlgreportviewer.ui b/trunk/dlgreportviewer.ui
index 8e90a91..20a6ff9 100644
--- a/trunk/dlgreportviewer.ui
+++ b/trunk/dlgreportviewer.ui
@@ -1,82 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DlgReportViewer</class>
<widget class="QMainWindow" name="DlgReportViewer">
<property name="windowModality">
<enum>Qt::NonModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>605</width>
<height>497</height>
</rect>
</property>
<property name="windowTitle">
<string/>
</property>
<property name="windowIcon">
<iconset resource="fred.qrc">
<normaloff>:/icons/resources/fred.png</normaloff>:/icons/resources/fred.png</iconset>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
- <widget class="QWebView" name="WebView">
- <property name="url">
+ <widget class="QWebView" name="WebView" native="true">
+ <property name="url" stdset="0">
<url>
<string>about:blank</string>
</url>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>605</width>
- <height>27</height>
+ <height>29</height>
</rect>
</property>
<widget class="QMenu" name="menu_File">
<property name="title">
<string>&File</string>
</property>
+ <addaction name="action_Save"/>
<addaction name="action_Print"/>
<addaction name="separator"/>
<addaction name="action_Close"/>
</widget>
<addaction name="menu_File"/>
</widget>
- <action name="action_Save">
- <property name="text">
- <string>&Save</string>
- </property>
- </action>
<action name="action_Print">
<property name="text">
<string>&Print</string>
</property>
</action>
<action name="action_Close">
<property name="text">
<string>&Close</string>
</property>
</action>
+ <action name="action_Save">
+ <property name="text">
+ <string>&Save</string>
+ </property>
+ </action>
</widget>
<customwidgets>
<customwidget>
<class>QWebView</class>
<extends>QWidget</extends>
<header>QtWebKit/QWebView</header>
</customwidget>
</customwidgets>
<resources>
<include location="fred.qrc"/>
</resources>
<connections/>
</ui>
diff --git a/trunk/mainwindow.cpp b/trunk/mainwindow.cpp
index 7ddfe45..22d10e2 100644
--- a/trunk/mainwindow.cpp
+++ b/trunk/mainwindow.cpp
@@ -1,599 +1,637 @@
/*******************************************************************************
* fred Copyright (c) 2011-2013 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor *
* with special feautures useful during forensic analysis. *
* *
* This program is free software: you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the Free *
* Software Foundation, either version 3 of the License, or (at your option) *
* any later version. *
* *
* 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, see <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#ifndef FRED_REPORT_TEMPLATE_DIR
#ifndef __MINGW32__
#define FRED_REPORT_TEMPLATE_DIR "/usr/share/fred/report_templates/"
#else
#define FRED_REPORT_TEMPLATE_DIR ".\\report_templates\\"
#endif
#endif
#include <QFileDialog>
#include <QMessageBox>
#include <QStringList>
#include <QDesktopWidget>
#include <QDir>
#include <QSplitter>
+#include <QDebug>
+
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "dlgabout.h"
#include "dlgkeydetails.h"
#include "dlgreportchooser.h"
#include "dlgreportviewer.h"
#include "dlgsearch.h"
#include "compileinfo.h"
+/*******************************************************************************
+ * Public
+ ******************************************************************************/
+
MainWindow::MainWindow(ArgParser *p_arg_parser) :
QMainWindow(0), ui(new Ui::MainWindow)
{
ui->setupUi(this);
// Initialize private vars
this->p_args=p_arg_parser;
this->p_hive=new RegistryHive(this);
this->is_hive_open=false;
this->p_reg_node_tree_model=NULL;
this->p_reg_node_tree_model_proxy=NULL;
this->p_reg_key_table_model=NULL;
this->p_search_thread=NULL;
this->search_result_widgets.clear();
// Check for ~/.fred config dir
this->CheckUserConfigDir();
// Set main window size
int cur_screen=QApplication::desktop()->screenNumber(this);
int window_width=
QApplication::desktop()->availableGeometry(cur_screen).width()*0.5;
int window_height=
QApplication::desktop()->availableGeometry(cur_screen).height()*0.5;
int window_x=
(QApplication::desktop()->availableGeometry(cur_screen).width()/2)-
(window_width/2);
int window_y=
(QApplication::desktop()->availableGeometry(cur_screen).height()/2)-
(window_height/2);
this->setGeometry(window_x,
window_y,
window_width,
window_height);
// Create widgets
this->p_horizontal_splitter=new QSplitter();
this->p_horizontal_splitter->setOrientation(Qt::Horizontal);
this->p_node_tree=new RegistryNodeTree(this->p_horizontal_splitter);
this->p_vertical_splitter=new QSplitter(this->p_horizontal_splitter);
this->p_vertical_splitter->setOrientation(Qt::Vertical);
this->p_key_table=new RegistryKeyTable(this->p_vertical_splitter);
this->p_tab_widget=new TabWidget(this->p_vertical_splitter);
this->p_hex_edit_widget=new HexEditWidget();
// Add hexedit page to tab_widget
this->p_tab_widget->addTab(this->p_hex_edit_widget,tr("Hex viewer"));
// Add widgets to their splitters
this->p_vertical_splitter->addWidget(this->p_key_table);
this->p_vertical_splitter->addWidget(this->p_tab_widget);
this->p_horizontal_splitter->addWidget(this->p_node_tree);
this->p_horizontal_splitter->addWidget(this->p_vertical_splitter);
// Set stretch factors
QSizePolicy node_tree_policy=this->p_node_tree->sizePolicy();
node_tree_policy.setHorizontalStretch(1);
node_tree_policy.setVerticalStretch(100);
this->p_node_tree->setSizePolicy(node_tree_policy);
QSizePolicy vertical_splitter_policy=this->p_vertical_splitter->sizePolicy();
vertical_splitter_policy.setHorizontalStretch(4);
vertical_splitter_policy.setVerticalStretch(100);
this->p_vertical_splitter->setSizePolicy(vertical_splitter_policy);
QSizePolicy key_table_policy=this->p_key_table->sizePolicy();
key_table_policy.setVerticalStretch(5);
key_table_policy.setHorizontalStretch(100);
this->p_key_table->setSizePolicy(key_table_policy);
QSizePolicy tab_widget_policy=this->p_tab_widget->sizePolicy();
tab_widget_policy.setVerticalStretch(2);
tab_widget_policy.setHorizontalStretch(200);
this->p_tab_widget->setSizePolicy(tab_widget_policy);
// Connect signals
this->connect(this->p_node_tree,
SIGNAL(clicked(QModelIndex)),
this,
SLOT(SlotNodeTreeClicked(QModelIndex)));
this->connect(this->p_node_tree,
SIGNAL(activated(QModelIndex)),
this,
SLOT(SlotNodeTreeClicked(QModelIndex)));
this->connect(this->p_node_tree,
SIGNAL(CurrentItemChanged(QModelIndex)),
this,
SLOT(SlotNodeTreeClicked(QModelIndex)));
this->connect(this->p_key_table,
SIGNAL(clicked(QModelIndex)),
this,
SLOT(SlotKeyTableClicked(QModelIndex)));
this->connect(this->p_key_table,
SIGNAL(doubleClicked(QModelIndex)),
this,
SLOT(SlotKeyTableDoubleClicked(QModelIndex)));
this->connect(this->p_key_table,
SIGNAL(CurrentItemChanged(QModelIndex)),
this,
SLOT(SlotKeyTableClicked(QModelIndex)));
this->connect(this->p_tab_widget,
SIGNAL(tabCloseRequested(int)),
this,
SLOT(SlotTabCloseButtonClicked(int)));
// Add central widget
this->setCentralWidget(this->p_horizontal_splitter);
this->centralWidget()->setContentsMargins(4,4,4,0);
// Set window title
this->UpdateWindowTitle();
// Set last open location to home dir
this->last_open_location=QDir::homePath();
/*
// Load report templates
this->p_data_reporter=new DataReporter();
// Load reports from system wide include dir
this->p_data_reporter->LoadReportTemplates(FRED_REPORT_TEMPLATE_DIR);
// Load user's report templates
this->p_data_reporter->LoadReportTemplates(QDir::homePath()
.append(QDir::separator())
.append(".fred")
.append(QDir::separator())
.append("report_templates"));
this->UpdateDataReporterMenu();
*/
// Load report templates
this->p_reports=new Reports();
// Load reports from system wide include dir
this->p_reports->LoadReportTemplates(FRED_REPORT_TEMPLATE_DIR);
// Load user's report templates
this->p_reports->LoadReportTemplates(QDir::homePath()
.append(QDir::separator())
.append(".fred")
.append(QDir::separator())
.append("report_templates"));
// Finally, react on some command line arguments
if(this->p_args->IsSet("maximized")) {
this->setWindowState(Qt::WindowMaximized);
}
if(this->p_args->IsSet("fullscreen")) {
this->setWindowState(Qt::WindowFullScreen);
}
if(this->p_args->IsSet("hive-file")) {
this->OpenHive(this->p_args->GetArgVal("hive-file"));
}
}
MainWindow::~MainWindow() {
if(this->is_hive_open) {
this->p_hive->Close();
}
delete ui;
}
+/*******************************************************************************
+ * Private slots
+ ******************************************************************************/
+
void MainWindow::on_action_Quit_triggered() {
qApp->exit();
}
void MainWindow::on_action_Open_hive_triggered() {
QString hive_file="";
hive_file=QFileDialog::getOpenFileName(this,
tr("Open registry hive"),
this->last_open_location,
tr("All files (*)"));
if(hive_file=="") return;
this->OpenHive(hive_file);
}
void MainWindow::on_action_Close_hive_triggered() {
if(this->is_hive_open) {
// Remove search results
while(this->p_tab_widget->count()>1) {
this->p_tab_widget->removeTab(this->p_tab_widget->count()-1);
delete this->search_result_widgets.at(this->p_tab_widget->count()-1);
this->search_result_widgets.removeLast();
}
// Delete models
if(this->p_reg_node_tree_model!=NULL) {
this->p_node_tree->setModel(NULL);
delete this->p_reg_node_tree_model_proxy;
delete this->p_reg_node_tree_model;
this->p_reg_node_tree_model_proxy=NULL;
this->p_reg_node_tree_model=NULL;
}
if(this->p_reg_key_table_model!=NULL) {
this->p_key_table->setModel(NULL);
delete this->p_reg_key_table_model;
this->p_reg_key_table_model=NULL;
}
// Remove any data from hex edit and data interpreter
this->p_hex_edit_widget->SetData(QByteArray());
this->p_hex_edit_widget->setEnabled(false);
// Close hive
this->p_hive->Close();
this->is_hive_open=false;
this->ui->action_Close_hive->setEnabled(false);
this->ui->ActionSearch->setEnabled(false);
this->ui->MenuReports->setEnabled(false);
this->UpdateWindowTitle();
}
}
void MainWindow::on_actionAbout_Qt_triggered() {
QMessageBox::aboutQt(this,tr("About Qt"));
}
void MainWindow::on_actionAbout_fred_triggered() {
DlgAbout dlg_about(this);
dlg_about.exec();
}
void MainWindow::on_ActionSearch_triggered() {
DlgSearch dlg_search(this);
if(dlg_search.exec()==QDialog::Accepted) {
// Create search thread and connect needed signals/slots
this->p_search_thread=new ThreadSearch(this);
// Add new search widget to tabwidget and to internal widget list
SearchResultWidget *p_search_widget=
new SearchResultWidget(this->p_tab_widget);
p_search_widget->setEnabled(false);
this->search_result_widgets.append(p_search_widget);
this->connect(p_search_widget,
SIGNAL(doubleClicked(QModelIndex)),
this,
SLOT(SlotSearchResultWidgetDoubleClicked(QModelIndex)));
this->p_tab_widget->addTab(p_search_widget,tr("Search results"),true);
this->p_tab_widget->setCurrentIndex(this->p_tab_widget->count()-1);
// Connect search thread to result widget
this->connect(this->p_search_thread,
SIGNAL(SignalFoundMatch(ThreadSearch::eMatchType,
QString,QString,QString)),
p_search_widget,
SLOT(SlotFoundMatch(ThreadSearch::eMatchType,
QString,QString,QString)));
this->connect(this->p_search_thread,
SIGNAL(finished()),
this,
SLOT(SlotSearchFinished()));
this->connect(this->p_search_thread,
SIGNAL(finished()),
p_search_widget,
SLOT(SlotSearchFinished()));
// Start searching
this->ui->ActionSearch->setEnabled(false);
p_search_thread->Search(this->p_hive->Filename(),
dlg_search.Keywords(),
dlg_search.SearchNodeNames(),
dlg_search.SearchKeyNames(),
dlg_search.SearchKeyValues());
}
}
+void MainWindow::on_ActionGenerateReport_triggered() {
+ DlgReportChooser dlg_repchooser(this->p_reports,
+ this->p_hive->HiveTypeToString(
+ this->p_hive->HiveType()),
+ this);
+ if(dlg_repchooser.exec()==QDialog::Accepted) {
+ QList<ReportTemplate*> selected_reports;
+
+ // Get selected report
+ selected_reports=dlg_repchooser.GetSelectedReports();
+ if(selected_reports.isEmpty()) return;
+
+ // Generate report(s)
+ QString report_result="";
+ if(this->p_reports->GenerateReport(this->p_hive,
+ selected_reports,
+ report_result,
+ false))
+ {
+ // Report generation was successfull, show reports
+ DlgReportViewer *p_dlg_report_view=new DlgReportViewer(report_result,
+ this);
+ p_dlg_report_view->exec();
+ delete p_dlg_report_view;
+ } else {
+ // TODO: Inform user
+ qDebug()<<"ERROR: "<<report_result;
+ }
+ }
+}
+
void MainWindow::SlotNodeTreeClicked(QModelIndex index) {
QString node_path;
if(!index.isValid()) return;
// Map proxy index to tree model index
index=this->p_reg_node_tree_model_proxy->mapToSource(index);
// Built node path
node_path=this->p_reg_node_tree_model->GetNodePath(index);
// Create table model and attach it to the table view
if(this->p_reg_key_table_model!=NULL) {
// If a previous model was set, delete it and clear hexedit etc...
this->p_key_table->setModel(NULL);
delete this->p_reg_key_table_model;
this->p_hex_edit_widget->SetData(QByteArray());
}
this->p_reg_key_table_model=new RegistryKeyTableModel(this->p_hive,node_path);
this->p_key_table->setModel(this->p_reg_key_table_model);
// Set focus back to nodetree to be able to navigate with keyboard
this->p_node_tree->setFocus();
}
+void MainWindow::SlotKeyTableClicked(QModelIndex index) {
+ if(!index.isValid()) return;
+
+ this->selected_key_value=
+ this->p_reg_key_table_model->data(this->p_reg_key_table_model->
+ index(index.row(),2),
+ RegistryKeyTableModel::
+ AdditionalRoles_GetRawData)
+ .toByteArray();
+ this->p_hex_edit_widget->SetData(this->selected_key_value);
+ // Set focus back to nodetree to be able to navigate with keyboard
+ this->p_key_table->setFocus();
+}
+
void MainWindow::SlotKeyTableDoubleClicked(QModelIndex index) {
Q_UNUSED(index);
/*
QModelIndex key_index;
QModelIndex node_index;
QStringList nodes;
QString key_name;
QString key_type;
QByteArray key_value;
if(!index.isValid()) return;
// Get key name, type and value
key_index=this->p_reg_key_table_model->index(index.row(),0);
key_name=this->p_reg_key_table_model->data(key_index,Qt::DisplayRole)
.toString();
key_index=this->p_reg_key_table_model->index(index.row(),1);
key_type=this->p_reg_key_table_model->data(key_index,Qt::DisplayRole)
.toString();ThreadSearch
key_index=this->p_reg_key_table_model->index(index.row(),2);
key_value=this->p_reg_key_table_model->data(key_index,
RegistryKeyTableModel::
AdditionalRoles_GetRawData)
.toByteArray();
// Get current node
node_index=this->p_node_tree->currentIndex();
//Built node path
nodes.clear();
nodes.append(this->p_reg_node_tree_model->
data(node_index,Qt::DisplayRole).toString());
while(this->p_reg_node_tree_model->parent(node_index)!=QModelIndex()) {
// Prepend all parent nodes
node_index=this->p_reg_node_tree_model->parent(node_index);
nodes.prepend(this->p_reg_node_tree_model->
data(node_index,Qt::DisplayRole).toString());
}
DlgKeyDetails dlg_key_details(this);
dlg_key_details.SetValues(nodes,key_name,key_type,key_value);
dlg_key_details.exec();
*/
}
-void MainWindow::SlotKeyTableClicked(QModelIndex index) {
- if(!index.isValid()) return;
-
- this->selected_key_value=
- this->p_reg_key_table_model->data(this->p_reg_key_table_model->
- index(index.row(),2),
- RegistryKeyTableModel::
- AdditionalRoles_GetRawData)
- .toByteArray();
- this->p_hex_edit_widget->SetData(this->selected_key_value);
- // Set focus back to nodetree to be able to navigate with keyboard
- this->p_key_table->setFocus();
-}
-
/*
void MainWindow::SlotReportClicked() {
// Get report category and name from sender and it's parent
QString category=((QMenu*)((QAction*)QObject::sender())->parent())->title();
QString report=((QAction*)QObject::sender())->text();
// Generate report
QString report_content=this->p_data_reporter->GenerateReport(this->p_hive,
category,
report);
// Show result in report viewer
if(report_content!=QString()) {
DlgReportViewer *p_dlg_report_view=new DlgReportViewer(report_content,this);
p_dlg_report_view->exec();
delete p_dlg_report_view;
} else {
// TODO: Something went wrong!
}
}
*/
void MainWindow::SlotSearchFinished() {
delete this->p_search_thread;
this->p_search_thread=NULL;
this->ui->ActionSearch->setEnabled(true);
// Enable result widget
this->search_result_widgets.last()->setEnabled(true);
}
void MainWindow::SlotSearchResultWidgetDoubleClicked(QModelIndex index) {
SearchResultWidget *p_sender;
QString path;
QString match_type;
QString value;
QString key="";
int i;
if(!index.isValid()) return;
// Get pointer to sender
p_sender=(SearchResultWidget*)QObject::sender();
// Get path and matchtype
path=p_sender->item(index.row(),0)->text();
match_type=p_sender->item(index.row(),1)->text();
value=p_sender->item(index.row(),2)->text();
if(match_type==tr("Node name")) {
// Node name is not part of path. Add it
if(path=="\\") path.append(value);
else path.append("\\").append(value);
} else if(match_type==tr("Key name")) {
// Key name is stored in value
key=value;
} else if(match_type==tr("Key value")) {
// Key name is part of path. Save and remove it
QStringList nodes=path.split("\\",QString::SkipEmptyParts);
key=nodes.at(nodes.count()-1);
// Remove \<key name> from path
path.chop(key.length()+1);
}
// Expand treeview to correct node
QList<QModelIndex> indexes=
this->p_reg_node_tree_model->GetIndexListOf(path);
for(i=0;i<indexes.count();i++) {
indexes.replace(i,this->p_reg_node_tree_model_proxy->
mapFromSource(indexes.at(i)));
this->p_node_tree->expand(indexes.at(i));
}
if(indexes.count()>0) {
// Scroll to last expanded node, select it and update widgets
this->p_node_tree->scrollTo(indexes.at(indexes.count()-1),
QAbstractItemView::PositionAtCenter);
this->p_node_tree->selectionModel()->clear();
this->p_node_tree->selectionModel()->
select(indexes.at(indexes.count()-1),
QItemSelectionModel::Select);
// TODO: This does not work!!
this->SlotNodeTreeClicked(indexes.at(indexes.count()-1));
}
// Select correct key if search matched on keay name / value
if(key!="") {
int row=this->p_reg_key_table_model->GetKeyRow(key);
this->p_key_table->clearSelection();
this->p_key_table->scrollTo(this->p_reg_key_table_model->index(row,0),
QAbstractItemView::PositionAtCenter);
this->p_key_table->selectRow(row);
this->SlotKeyTableClicked(this->p_reg_key_table_model->index(row,0));
}
}
void MainWindow::SlotTabCloseButtonClicked(int index) {
// Delete tab widget and remove tab
this->p_tab_widget->removeTab(index);
delete this->search_result_widgets.at(index-1);
this->search_result_widgets.removeAt(index-1);
}
+/*******************************************************************************
+ * Private
+ ******************************************************************************/
+
void MainWindow::CheckUserConfigDir() {
QString user_config_dir=QDir::homePath()
.append(QDir::separator())
.append(".fred");
if(!QDir(user_config_dir).exists()) {
// User config dir does not exists, try to create it
if(!QDir().mkpath(user_config_dir)) {
// TODO: Maybe warn user
return;
}
user_config_dir.append(QDir::separator()).append("report_templates");
if(!QDir().mkpath(user_config_dir)) {
// TODO: Maybe warn user
return;
}
}
}
void MainWindow::UpdateWindowTitle(QString filename) {
if(filename=="") {
this->setWindowTitle(QString("%1 v%2").arg(APP_TITLE,APP_VERSION));
} else {
this->setWindowTitle(QString("%1 v%2 - %3").arg(APP_TITLE,
APP_VERSION,
filename.toLocal8Bit()
.constData()));
}
}
/*
void MainWindow::UpdateDataReporterMenu() {
int i=0,ii=0;
QMenu *p_category_entry;
QAction *p_report_entry;
QStringList categories=this->p_data_reporter->GetAvailableReportCategories();
QStringList reports;
for(i=0;i<categories.count();i++) {
// First create category submenu
p_category_entry=this->ui->MenuReports->addMenu(categories.value(i));
// Now add category reports
reports=this->p_data_reporter->GetAvailableReports(categories.value(i));
for(ii=0;ii<reports.count();ii++) {
p_report_entry=new QAction(reports.value(ii),p_category_entry);
p_category_entry->addAction(p_report_entry);
this->connect(p_report_entry,
SIGNAL(triggered()),
this,
SLOT(SlotReportClicked()));
}
}
}
*/
void MainWindow::OpenHive(QString hive_file) {
// Update last open location
this->last_open_location=hive_file.left(hive_file.
lastIndexOf(QDir::separator()));
// If another hive is currently open, close it
if(this->is_hive_open) this->on_action_Close_hive_triggered();
// Try to open hive
if(!this->p_hive->Open(hive_file)) {
QMessageBox::critical(this,
tr("Error opening hive file"),
tr("Unable to open file '%1'").arg(hive_file));
return;
}
// Create tree model & proxy
this->p_reg_node_tree_model=new RegistryNodeTreeModel(this->p_hive);
this->p_reg_node_tree_model_proxy=new RegistryNodeTreeModelProxy(this);
//this->p_reg_node_tree_model_proxy->setDynamicSortFilter(true);
this->p_reg_node_tree_model_proxy->
setSourceModel(this->p_reg_node_tree_model);
this->p_node_tree->setModel(this->p_reg_node_tree_model_proxy);
this->is_hive_open=true;
this->ui->action_Close_hive->setEnabled(true);
this->ui->ActionSearch->setEnabled(true);
this->ui->MenuReports->setEnabled(true);
// Enable data interpreter
this->p_hex_edit_widget->setEnabled(true);
this->UpdateWindowTitle(hive_file);
}
-
-void MainWindow::on_ActionGenerateReport_triggered() {
- DlgReportChooser dlg_repchooser(this->p_reports,this);
- if(dlg_repchooser.exec()==QDialog::Accepted) {
-
- }
-}
diff --git a/trunk/mainwindow.h b/trunk/mainwindow.h
index 38de0c8..e20238e 100644
--- a/trunk/mainwindow.h
+++ b/trunk/mainwindow.h
@@ -1,131 +1,130 @@
/*******************************************************************************
* fred Copyright (c) 2011-2013 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor *
* with special feautures useful during forensic analysis. *
* *
* This program is free software: you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the Free *
* Software Foundation, either version 3 of the License, or (at your option) *
* any later version. *
* *
* 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, see <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QWidget>
#include <QLabel>
#include <QTabWidget>
#include <QVBoxLayout>
#include <QSplitter>
#include <QString>
#include <QByteArray>
#include <hivex.h>
#include "argparser.h"
#include "registryhive.h"
#include "registrynodetree.h"
#include "registrynodetreemodel.h"
#include "registrynodetreemodelproxy.h"
#include "registrykeytable.h"
#include "registrykeytablemodel.h"
#include "hexeditwidget.h"
//#include "datareporter.h"
#include "reports.h"
#include "threadsearch.h"
#include "searchresultwidget.h"
#include "tabwidget.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(ArgParser *p_arg_parser);
~MainWindow();
private slots:
void on_action_Quit_triggered();
void on_action_Open_hive_triggered();
void on_action_Close_hive_triggered();
void on_actionAbout_Qt_triggered();
void on_actionAbout_fred_triggered();
void on_ActionSearch_triggered();
+ void on_ActionGenerateReport_triggered();
void SlotNodeTreeClicked(QModelIndex index);
void SlotKeyTableClicked(QModelIndex index);
void SlotKeyTableDoubleClicked(QModelIndex index);
// void SlotReportClicked();
void SlotSearchFinished();
void SlotSearchResultWidgetDoubleClicked(QModelIndex index);
void SlotTabCloseButtonClicked(int index);
- void on_ActionGenerateReport_triggered();
-
private:
Ui::MainWindow *ui;
ArgParser *p_args;
QString last_open_location;
RegistryHive *p_hive;
bool is_hive_open;
QByteArray selected_key_value;
QList<SearchResultWidget*> search_result_widgets;
// Models
RegistryNodeTreeModel *p_reg_node_tree_model;
RegistryNodeTreeModelProxy *p_reg_node_tree_model_proxy;
RegistryKeyTableModel *p_reg_key_table_model;
// Widgets etc...
RegistryNodeTree *p_node_tree;
RegistryKeyTable *p_key_table;
TabWidget *p_tab_widget;
HexEditWidget *p_hex_edit_widget;
QSplitter *p_horizontal_splitter;
QSplitter *p_vertical_splitter;
// DataReporter *p_data_reporter;
Reports *p_reports;
// Threads
ThreadSearch *p_search_thread;
/*
* CheckUserConfigDir
*
* Checks for and possibly creates the ~/.fred directory
*/
void CheckUserConfigDir();
/*
* UpdateWindowTitle
*
* Updates the window title
*/
void UpdateWindowTitle(QString filename="");
/*
* UpdateDataReporterMenu
*
*/
// void UpdateDataReporterMenu();
/*
* OpenHive
*
* Open a registry hive
*/
void OpenHive(QString hive_file);
};
#endif // MAINWINDOW_H
diff --git a/trunk/mainwindow.ui b/trunk/mainwindow.ui
index 4fe3b89..88d50fd 100644
--- a/trunk/mainwindow.ui
+++ b/trunk/mainwindow.ui
@@ -1,154 +1,154 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>508</width>
<height>317</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<property name="windowIcon">
<iconset resource="fred.qrc">
<normaloff>:/icons/resources/fred.png</normaloff>:/icons/resources/fred.png</iconset>
</property>
<widget class="QWidget" name="MainWidget"/>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>508</width>
- <height>27</height>
+ <height>29</height>
</rect>
</property>
<widget class="QMenu" name="MenuFile">
<property name="title">
<string>&File</string>
</property>
<addaction name="action_Open_hive"/>
<addaction name="action_Close_hive"/>
<addaction name="separator"/>
<addaction name="action_Quit"/>
</widget>
<widget class="QMenu" name="MenuHelp">
<property name="title">
<string>&Help</string>
</property>
<addaction name="actionAbout_Qt"/>
<addaction name="actionAbout_fred"/>
</widget>
<widget class="QMenu" name="MenuReports">
<property name="enabled">
<bool>false</bool>
</property>
<property name="title">
<string>&Reports</string>
</property>
<addaction name="ActionGenerateReport"/>
<addaction name="ActionReloadReportTemplates"/>
</widget>
<widget class="QMenu" name="MenuEdit">
<property name="title">
<string>&Edit</string>
</property>
<addaction name="ActionSearch"/>
<addaction name="separator"/>
<addaction name="ActionPreferences"/>
</widget>
<addaction name="MenuFile"/>
<addaction name="MenuEdit"/>
<addaction name="MenuReports"/>
<addaction name="MenuHelp"/>
</widget>
<widget class="QStatusBar" name="StatusBar"/>
<action name="action_Open_hive">
<property name="text">
<string>&Open hive</string>
</property>
<property name="shortcut">
<string>Ctrl+O</string>
</property>
</action>
<action name="action_Close_hive">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Close hive</string>
</property>
</action>
<action name="action_Quit">
<property name="text">
<string>&Quit</string>
</property>
<property name="shortcut">
<string>Ctrl+Q</string>
</property>
</action>
<action name="actionAbout_Qt">
<property name="text">
<string>About Qt</string>
</property>
</action>
<action name="actionAbout_fred">
<property name="text">
<string>About fred</string>
</property>
</action>
<action name="ActionSearch">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>&Search</string>
</property>
<property name="shortcut">
<string>Ctrl+S</string>
</property>
</action>
<action name="ActionPreferences">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>&Preferences</string>
</property>
</action>
<action name="ActionGenerateReport">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Generate report</string>
</property>
</action>
<action name="ActionReloadReportTemplates">
<property name="text">
<string>Reload report templates</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>
<include location="fred.qrc"/>
</resources>
<connections/>
</ui>
diff --git a/trunk/registryhive.cpp b/trunk/registryhive.cpp
index fdf90bc..a11abea 100644
--- a/trunk/registryhive.cpp
+++ b/trunk/registryhive.cpp
@@ -1,628 +1,701 @@
/*******************************************************************************
* fred Copyright (c) 2011-2013 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor *
* with special feautures useful during forensic analysis. *
* *
* This program is free software: you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the Free *
* Software Foundation, either version 3 of the License, or (at your option) *
* any later version. *
* *
* 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, see <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#include "registryhive.h"
#include <QStringList>
#include <QDateTime>
#include <stdlib.h>
#include <stdio.h>
// TODO: __WORDSIZE is not defined under mingw and I currently have no idea how
// to identify a 64bit windows
#ifndef __WORDSIZE
#define __WORDSIZE 32
#endif
#if __WORDSIZE == 64
#define EPOCH_DIFF 0x19DB1DED53E8000
#else
#define EPOCH_DIFF 0x19DB1DED53E8000LL
#endif
/*
* RegistryHive
*/
RegistryHive::RegistryHive(QObject *p_parent) : QObject(p_parent) {
this->erro_msg="";
this->is_error=false;
this->hive_file="";
this->p_hive=NULL;
this->is_hive_open=false;
}
/*
* ~RegistryHive
*/
RegistryHive::~RegistryHive() {
if(this->is_hive_open) this->Close();
}
/*
* Error
*/
bool RegistryHive::Error() {
return this->is_error;
}
/*
* GetErrorMsg
*/
QString RegistryHive::GetErrorMsg() {
QString msg=this->erro_msg;
this->erro_msg="";
this->is_error=false;
return msg;
}
/*
* Open
*/
bool RegistryHive::Open(QString file, bool read_only) {
if(this->is_hive_open) return false;
// Open hive file
this->p_hive=hivex_open(file.toAscii().constData(),
read_only ? 0 : HIVEX_OPEN_WRITE);
if(this->p_hive==NULL) return false;
// Set local vars
this->hive_file=file;
this->is_hive_open=true;
return true;
}
/*
* Close
*/
bool RegistryHive::Close(bool commit_changes) {
if(this->is_hive_open) {
if(commit_changes) {
// Commit changes before closing hive.
// TODO: Maybe it would be more secure to commit changes to a new file and
// then move it over the original one.
hivex_commit(this->p_hive,NULL,0);
}
// As hivex_close will _ALWAYS_ free the handle, we don't need the following
// values anymore
this->hive_file="";
this->is_hive_open=false;
// Close hive
if(hivex_close(this->p_hive)!=0) return false;
}
return true;
}
+/*
+ * Filename
+ */
QString RegistryHive::Filename() {
if(this->is_hive_open) return this->hive_file;
return QString();
}
+/*
+ * HiveType
+ */
+RegistryHive::teHiveType RegistryHive::HiveType() {
+ // Check for SYSTEM hive
+ if(this->PathExists("\\Select") && this->PathExists("\\MountedDevices"))
+ return RegistryHive::eHiveType_SYSTEM;
+ // Check for SOFTWARE hive
+ if(this->PathExists("\\Microsoft\\Windows\\CurrentVersion") &&
+ this->PathExists("\\Microsoft\\Windows NT\\CurrentVersion"))
+ return RegistryHive::eHiveType_SOFTWARE;
+ // Check for SAM
+ if(this->PathExists("SAM\\Domains\\Account\\Users"))
+ return RegistryHive::eHiveType_SAM;
+ // Check for SECURITY
+ if(this->PathExists("\\Policy\\Accounts") &&
+ this->PathExists("\\Policy\\PolAdtEv"))
+ return RegistryHive::eHiveType_SECURITY;
+ // Check for NTUSER.DAT
+ if(this->PathExists("\\Software\\Microsoft\\Windows\\CurrentVersion"))
+ return RegistryHive::eHiveType_NTUSER;
+ // Unknown hive
+ return RegistryHive::eHiveType_UNKNOWN;
+}
+
+/*
+ * HiveTypeToString
+ */
+QString RegistryHive::HiveTypeToString(teHiveType hive_type) {
+ switch(hive_type) {
+ case RegistryHive::eHiveType_SYSTEM:
+ return "SYSTEM";
+ break;
+ case RegistryHive::eHiveType_SOFTWARE:
+ return "SOFTWARE";
+ break;
+ case RegistryHive::eHiveType_SAM:
+ return "SAM";
+ break;
+ case RegistryHive::eHiveType_SECURITY:
+ return "SECURITY";
+ break;
+ case RegistryHive::eHiveType_NTUSER:
+ return "NTUSER";
+ break;
+ default:
+ return "UNKNOWN";
+ }
+}
+
/*
* GetNodes
*/
QMap<QString,int> RegistryHive::GetNodes(QString path) {
hive_node_h parent_node;
// Get handle to last node in path
if(!this->GetNodeHandle(path,&parent_node)) return QMap<QString,int>();
// Get and return nodes
return this->GetNodesHelper(parent_node);
}
/*
* GetNodes
*/
QMap<QString,int> RegistryHive::GetNodes(int parent_node) {
if(parent_node==0) {
this->SetError(tr("Invalid parent node handle specified!"));
return QMap<QString,int>();
}
// Get and return nodes
return this->GetNodesHelper(parent_node);
}
/*
* GetKeys
*/
QMap<QString,int> RegistryHive::GetKeys(QString path) {
hive_node_h parent_node;
// Get handle to last node in path
if(!this->GetNodeHandle(path,&parent_node)) return QMap<QString,int>();
// Get and return keys
return this->GetKeysHelper(parent_node);
}
/*
* GetKeys
*/
QMap<QString,int> RegistryHive::GetKeys(int parent_node) {
if(parent_node==0) {
this->SetError(tr("Invalid parent node handle specified!"));
return QMap<QString,int>();
}
// Get and return keys
return this->GetKeysHelper(parent_node);
}
/*
* GetKeyValue
*/
QByteArray RegistryHive::GetKeyValue(QString path,
QString key,
int *p_value_type,
size_t *p_value_len)
{
hive_node_h parent_node;
hive_value_h hive_key;
// Get handle to last node in path
if(!this->GetNodeHandle(path,&parent_node)) return QByteArray();
// Get key handle
hive_key=hivex_node_get_value(this->p_hive,
parent_node,key.toAscii().constData());
if(hive_key==0) {
this->SetError(tr("Unable to get key handle!"));
*p_value_len=-1;
return QByteArray();
}
// Get and return key value
return this->GetKeyValueHelper(hive_key,p_value_type,p_value_len);
}
/*
* GetKeyValue
*/
QByteArray RegistryHive::GetKeyValue(int hive_key,
int *p_value_type,
size_t *p_value_len)
{
if(hive_key==0) {
this->SetError(tr("Invalid key handle specified!"));
*p_value_type=-1;
return QByteArray();
}
// Get and return key value
return this->GetKeyValueHelper(hive_key,p_value_type,p_value_len);
}
/*
* GetKeyModTime
*/
int64_t RegistryHive::GetNodeModTime(QString path) {
hive_node_h node;
// Get handle to last node in path
if(!this->GetNodeHandle(path,&node)) {
this->SetError(tr("Unable to get node handle!"));
return 0;
}
// Get and return node's last modification timestamp
return this->GetNodeModTime(node);
}
/*
* GetKeyModTime
*/
int64_t RegistryHive::GetNodeModTime(int node) {
if(node==0) {
this->SetError(tr("Invalid node handle specified!"));
return 0;
}
// Get and return key's last modification timestamp
return hivex_node_timestamp(this->p_hive,node);
}
/*
* KeyValueToString
*/
QString RegistryHive::KeyValueToString(QByteArray value, int value_type) {
QString ret="";
int i=0;
#define ToHexStr() { \
for(i=0;i<value.size();i++) { \
ret.append(QString().sprintf("%02X ",(uint8_t)(value.constData()[i]))); \
} \
ret.chop(1); \
}
switch(value_type) {
case hive_t_REG_NONE:
// Just a key without a value, but to be certain...
ToHexStr();
break;
case hive_t_REG_SZ:
// A Windows string (encoding is unknown, but often UTF16-LE)
// TODO: What happens if encoding is not UTF16-LE ??? Thx Billy!!!
ret=value.size() ? QString().fromUtf16((ushort*)(value.constData())) : "";
break;
case hive_t_REG_EXPAND_SZ:
// A Windows string that contains %env% (environment variable expansion)
ret=value.size() ? QString().fromUtf16((ushort*)(value.constData())) : "";
break;
case hive_t_REG_BINARY:
// A blob of binary
ToHexStr();
break;
case hive_t_REG_DWORD:
// DWORD (32 bit integer), little endian
ret=QString().sprintf("0x%08X",*(uint32_t*)value.constData());
break;
case hive_t_REG_DWORD_BIG_ENDIAN:
// DWORD (32 bit integer), big endian
ret=QString().sprintf("0x%08X",*(uint32_t*)value.constData());
break;
case hive_t_REG_LINK:
// Symbolic link to another part of the registry tree
ToHexStr();
break;
case hive_t_REG_MULTI_SZ:
// Multiple Windows strings.
// See http://blogs.msdn.com/oldnewthing/archive/2009/10/08/9904646.aspx
ToHexStr();
break;
case hive_t_REG_RESOURCE_LIST:
// Resource list
ToHexStr();
break;
case hive_t_REG_FULL_RESOURCE_DESCRIPTOR:
// Resource descriptor
ToHexStr();
break;
case hive_t_REG_RESOURCE_REQUIREMENTS_LIST:
// Resouce requirements list
ToHexStr();
break;
case hive_t_REG_QWORD:
// QWORD (64 bit integer). Usually little endian.
ret=
QString("0x%1").arg((quint64)(*(uint64_t*)value.constData()),16,16,QChar('0'));
break;
default:
ToHexStr();
}
#undef ToHexStr
return ret;
}
/*
* KeyValueToString
*/
QString RegistryHive::KeyValueToString(QByteArray key_value,
QString format,
int offset,
int length,
bool little_endian)
{
int remaining_data_len;
const char *p_data;
QString ret="";
// Calculate how many bytes are remainig after specified offset
remaining_data_len=key_value.size()-offset;
if(!remaining_data_len>0) {
// Nothing to show
return QString();
}
// Get pointer to data at specified offset
p_data=key_value.constData();
p_data+=offset;
// TODO: This will fail on platforms with different endianness!
#define bswap_16(value) ((((value) & 0xff) << 8) | ((value) >> 8))
#define bswap_32(value) \
(((uint32_t)bswap_16((uint16_t)((value) & 0xffff)) << 16) | \
(uint32_t)bswap_16((uint16_t)((value) >> 16)))
#define bswap_64(value) \
(((uint64_t)bswap_32((uint32_t)((value) & 0xffffffff)) << 32) | \
(uint64_t)bswap_32((uint32_t)((value) >> 32))) \
// ConvertFull name
if(format=="int8" && remaining_data_len>=1) {
ret=QString().sprintf("%d",*(int8_t*)p_data);
} else if(format=="uint8" && remaining_data_len>=1) {
ret=QString().sprintf("%u",*(uint8_t*)p_data);
} else if(format=="int16" && remaining_data_len>=2) {
int16_t val=*(int16_t*)p_data;
if(little_endian) ret=QString().sprintf("%d",val);
else ret=QString().sprintf("%d",bswap_16(val));
} else if(format=="uint16" && remaining_data_len>=2) {
uint16_t val=*(uint16_t*)p_data;
if(little_endian) ret=QString().sprintf("%u",val);
else ret=QString().sprintf("%u",bswap_16(val));
} else if(format=="int32" && remaining_data_len>=4) {
int32_t val=*(int32_t*)p_data;
if(little_endian) ret=QString().sprintf("%d",val);
else ret=QString().sprintf("%d",bswap_32(val));
} else if(format=="uint32" && remaining_data_len>=4) {
uint32_t val=*(uint32_t*)p_data;
if(little_endian) ret=QString().sprintf("%u",val);
else ret=QString().sprintf("%u",bswap_32(val));
} else if(format=="unixtime" && remaining_data_len>=4) {
uint32_t val=*(uint32_t*)p_data;
if(!little_endian) val=bswap_32(val);
if(val==0) {
ret="n/a";
} else {
QDateTime date_time;
date_time.setTimeSpec(Qt::UTC);
date_time.setTime_t(val);
ret=date_time.toString("yyyy/MM/dd hh:mm:ss");
}
} else if(format=="int64" && remaining_data_len>=8) {
int64_t val=*(int64_t*)p_data;
if(little_endian) ret=QString("%1").arg(val);
else ret=QString("%1").arg((int64_t)bswap_64(val));
} else if(format=="uint64" && remaining_data_len>=8) {
uint64_t val=*(uint64_t*)p_data;
if(little_endian) ret=QString("%1").arg(val);
else ret=QString("%1").arg(bswap_64(val));
/*
// TODO: Check how one could implement this
} else if(format=="unixtime64" && remaining_data_len>=8) {
if(*(uint64_t*)p_data==0) {
ret="n/a";
} else {
uint64_t secs=*(uint64_t*)p_data;
QDateTime date_time;
date_time.setTimeSpec(Qt::UTC);
// Set 32bit part of date/time
date_time.setTime_t(secs&0xFFFFFFFF);
// Now add high 32bit part of date/time
date_time.addSecs(secs>>32);
ret=date_time.toString("yyyy/MM/dd hh:mm:ss");
}
*/
} else if(format=="filetime" && remaining_data_len>=8) {
uint64_t val=*(uint64_t*)p_data;
if(!little_endian) val=bswap_64(val);
if(val==0) {
ret="n/a";
} else {
// TODO: Warn if >32bit
QDateTime date_time;
date_time.setTimeSpec(Qt::UTC);
date_time.setTime_t(RegistryHive::FiletimeToUnixtime(val));
ret=date_time.toString("yyyy/MM/dd hh:mm:ss");
}
} else if(format=="ascii") {
// TODO: This fails bad if the string is not null terminated!! It might be
// wise checking for a null char here
ret=QString().fromAscii((char*)p_data,length);
} else if(format=="utf16" && remaining_data_len>=2) {
ret=QString().fromUtf16((ushort*)p_data,length);
} else {
// Unknown variant type or another error
return QString();
}
return ret;
}
/*
* KeyTypeToString
*/
QString RegistryHive::KeyTypeToString(int value_type) {
QString ret="";
switch(value_type) {
case hive_t_REG_NONE:
ret="REG_NONE";
break;
case hive_t_REG_SZ:
ret="REG_SZ";
break;
case hive_t_REG_EXPAND_SZ:
ret="REG_EXPAND_SZ";
break;
case hive_t_REG_BINARY:
ret="REG_BINARY";
break;
case hive_t_REG_DWORD:
ret="REG_DWORD";
break;
case hive_t_REG_DWORD_BIG_ENDIAN:
ret="REG_DWORD_BIG_ENDIAN";
break;
case hive_t_REG_LINK:
ret="REG_LINK";
break;
case hive_t_REG_MULTI_SZ:
ret="REG_MULTI_SZ";
break;
case hive_t_REG_RESOURCE_LIST:
ret="REG_RESOURCE_LIST";
break;
case hive_t_REG_FULL_RESOURCE_DESCRIPTOR:
ret="REG_FULL_RESOURCE_DESC";
break;
case hive_t_REG_RESOURCE_REQUIREMENTS_LIST:
ret="REG_RESOURCE_REQ_LIST";
break;
case hive_t_REG_QWORD:
ret="REG_QWORD";
break;
default:
ret=QString().sprintf("0x%08X",(uint32_t)value_type);
}
return ret;
}
/*
* FiletimeToUnixtime
*/
uint64_t RegistryHive::FiletimeToUnixtime(int64_t filetime) {
return (unsigned)((filetime-EPOCH_DIFF)/10000000);
}
/*
* SetError
*/
void RegistryHive::SetError(QString msg) {
this->erro_msg=msg;
this->is_error=true;
}
/*
* GetNodeHandle
*/
bool RegistryHive::GetNodeHandle(QString &path, hive_node_h *p_node) {
QStringList nodes;
int i=0;
// Get root node handle
*p_node=hivex_root(this->p_hive);
if(*p_node==0) {
this->SetError(tr("Unable to get root node!"));
return false;
}
if(path!="\\") {
// If we aren't listing the root node, we have to get a handle to the
// last node in the path. Split path into nodes
nodes=path.split('\\',QString::SkipEmptyParts);
// Iterate to the correct parent node
for(i=0;i<nodes.count();i++) {
// printf("Spotting node '%s'\n",nodes.value(i).toAscii().constData());
*p_node=hivex_node_get_child(this->p_hive,
*p_node,
nodes.value(i).toAscii().constData());
if(*p_node==0) {
this->SetError(tr("Unable to find node '%1'!").arg(nodes.value(i)));
return false;
}
}
}
return true;
}
/*
* GetNodesHelper
*/
QMap<QString,int> RegistryHive::GetNodesHelper(hive_node_h parent_node) {
QMap<QString,int> keys;
char *p_name;
int i=0;
// Get child nodes
hive_node_h *child_nodes=hivex_node_children(this->p_hive,parent_node);
if(child_nodes==NULL) {
this->SetError(
tr("Unable to enumerate child nodes!"));
return QMap<QString,int>();
}
// Build result
keys.clear();
i=0;
while(child_nodes[i]) {
p_name=hivex_node_name(this->p_hive,child_nodes[i]);
if(p_name==NULL) {
this->SetError(tr("Unable to get node name!"));
free(child_nodes);
return QMap<QString,int>();
}
keys.insert(QString(p_name),(int)child_nodes[i]);
free(p_name);
i++;
}
free(child_nodes);
return keys;
}
/*
* GetKeysHelper
*/
QMap<QString,int> RegistryHive::GetKeysHelper(hive_node_h parent_node) {
QMap<QString,int> keys;
char *p_name;
int i=0;
// Get child keys
hive_value_h *p_keys=hivex_node_values(this->p_hive,parent_node);
if(p_keys==NULL) {
this->SetError(
tr("Unable to enumerate child keys!"));
return QMap<QString,int>();
}
// Build result list
keys.clear();
i=0;
while(p_keys[i]) {
p_name=hivex_value_key(this->p_hive,p_keys[i]);
if(p_name==NULL) {
this->SetError(tr("Unable to get key name!"));
return QMap<QString,int>();
}
keys.insert(QString(p_name),p_keys[i]);
free(p_name);
i++;
}
free(p_keys);
return keys;
}
+/*
+ * GetKeyValueHelper
+ */
QByteArray RegistryHive::GetKeyValueHelper(hive_value_h hive_key,
int *p_value_type,
size_t *p_value_len)
{
QByteArray key_value;
char *p_key_value;
p_key_value=hivex_value_value(this->p_hive,
hive_key,
(hive_type*)p_value_type,
p_value_len);
if(p_key_value==NULL) {
this->SetError(tr("Unable to get key value!"));
*p_value_type=-1;
return QByteArray();
}
// Feed QByteArray and free p_key_value
key_value=QByteArray(p_key_value,*p_value_len);
free(p_key_value);
return key_value;
}
+
+/*
+ * PathExists
+ */
+bool RegistryHive::PathExists(QString path) {
+ bool ret;
+ hive_node_h node;
+
+ ret=this->GetNodeHandle(path,&node);
+ if(!ret || this->Error()) {
+ // Clear error and return false
+ this->GetErrorMsg();
+ return false;
+ }
+
+ return true;
+}
diff --git a/trunk/registryhive.h b/trunk/registryhive.h
index d6b65f2..e2f307f 100644
--- a/trunk/registryhive.h
+++ b/trunk/registryhive.h
@@ -1,83 +1,95 @@
/*******************************************************************************
* fred Copyright (c) 2011-2013 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor *
* with special feautures useful during forensic analysis. *
* *
* This program is free software: you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the Free *
* Software Foundation, either version 3 of the License, or (at your option) *
* any later version. *
* *
* 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, see <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#ifndef REGISTRYHIVE_H
#define REGISTRYHIVE_H
#include <QObject>
#include <QMap>
#include <hivex.h>
class RegistryHive : public QObject {
Q_OBJECT
public:
+ typedef enum eHiveType {
+ eHiveType_UNKNOWN=0,
+ eHiveType_SYSTEM,
+ eHiveType_SOFTWARE,
+ eHiveType_SAM,
+ eHiveType_SECURITY,
+ eHiveType_NTUSER
+ } teHiveType;
+
explicit RegistryHive(QObject *p_parent=0);
~RegistryHive();
bool Error();
QString GetErrorMsg();
bool Open(QString file, bool read_only=true);
bool Close(bool commit_changes=false);
QString Filename();
+ teHiveType HiveType();
+ QString HiveTypeToString(teHiveType hive_type);
QMap<QString,int> GetNodes(QString path="\\");
QMap<QString,int> GetNodes(int parent_node=0);
QMap<QString,int> GetKeys(QString path="\\");
QMap<QString,int> GetKeys(int parent_node=0);
QByteArray GetKeyValue(QString path,
QString key,
int *p_value_type,
size_t *p_value_len);
QByteArray GetKeyValue(int hive_key,
int *p_value_type,
size_t *p_value_len);
int64_t GetNodeModTime(QString path);
int64_t GetNodeModTime(int node);
static QString KeyValueToString(QByteArray value, int value_type);
static QString KeyValueToString(QByteArray value,
QString format,
int offset=0,
int length=0,
bool little_endian=true);
static QString KeyTypeToString(int value_type);
static uint64_t FiletimeToUnixtime(int64_t filetime);
private:
QString erro_msg;
bool is_error;
QString hive_file;
hive_h *p_hive;
bool is_hive_open;
void SetError(QString msg);
bool GetNodeHandle(QString &path, hive_node_h *p_node);
QMap<QString,int> GetNodesHelper(hive_node_h parent_node);
QMap<QString,int> GetKeysHelper(hive_node_h parent_node);
QByteArray GetKeyValueHelper(hive_value_h hive_key,
int *p_value_type,
size_t *p_value_len);
+ bool PathExists(QString path);
};
#endif // REGISTRYHIVE_H
diff --git a/trunk/reportengine.cpp b/trunk/reportengine.cpp
index 638b60f..8784e26 100644
--- a/trunk/reportengine.cpp
+++ b/trunk/reportengine.cpp
@@ -1,446 +1,518 @@
/*******************************************************************************
* fred Copyright (c) 2011-2013 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor *
* with special feautures useful during forensic analysis. *
* *
* This program is free software: you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the Free *
* Software Foundation, either version 3 of the License, or (at your option) *
* any later version. *
* *
* 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, see <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#include "reportengine.h"
#include <QFile>
#include <QTextStream>
#include <QDateTime>
#include <QtDebug>
/*******************************************************************************
* Public
******************************************************************************/
ReportEngine::ReportEngine(RegistryHive *p_hive) : QScriptEngine() {
// Init vars
this->p_registry_hive=p_hive;
this->report_content="";
// Add our constants
this->globalObject().setProperty("ENGINE_API_VERSION",
FRED_REPORTENGINE_API_VERSION,
QScriptValue::ReadOnly|
QScriptValue::Undeletable);
/*
this->globalObject().setProperty("HIVE_FILE",
this->p_registry_hive->Filename(),
QScriptValue::ReadOnly|
QScriptValue::Undeletable);
*/
// Add our types to engine
qScriptRegisterMetaType<s_RegistryKeyValue>(this,
this->RegistryKeyValueToScript,
this->RegistryKeyValueFromScript);
this->p_type_byte_array=new ByteArray(this);
this->globalObject().setProperty("ByteArray",
this->p_type_byte_array->constructor());
// Add our functions
// print
QScriptValue func_print=this->newFunction(this->Print);
this->globalObject().setProperty("print",func_print);
// println
QScriptValue func_println=this->newFunction(this->PrintLn);
this->globalObject().setProperty("println",func_println);
- // GetRegistryNodes
- QScriptValue func_get_nodes=this->newFunction(this->GetRegistryNodes,1);
- func_get_nodes.setData(this->newQObject(this->p_registry_hive));
- this->globalObject().setProperty("GetRegistryNodes",func_get_nodes);
- // GetRegistryKeys
- QScriptValue func_get_keys=this->newFunction(this->GetRegistryKeys,1);
- func_get_keys.setData(this->newQObject(this->p_registry_hive));
- this->globalObject().setProperty("GetRegistryKeys",func_get_keys);
- // GetRegistryKeyValue
- QScriptValue func_get_key_value=this->newFunction(this->GetRegistryKeyValue,
- 2);
- func_get_key_value.setData(this->newQObject(this->p_registry_hive));
- this->globalObject().setProperty("GetRegistryKeyValue",func_get_key_value);
- // GetRegistryNodeModTime
- QScriptValue func_get_node_modt=
- this->newFunction(this->GetRegistryNodeModTime,1);
- func_get_node_modt.setData(this->newQObject(this->p_registry_hive));
- this->globalObject().setProperty("GetRegistryNodeModTime",func_get_node_modt);
+
// RegistryKeyValueToString
QScriptValue func_value_to_string=
this->newFunction(this->RegistryKeyValueToString,2);
this->globalObject().setProperty("RegistryKeyValueToString",
func_value_to_string);
// RegistryKeyValueToVariant
QScriptValue func_value_to_variant=
this->newFunction(this->RegistryKeyValueToVariant);
this->globalObject().setProperty("RegistryKeyValueToVariant",
func_value_to_variant);
// RegistryKeyTypeToString
QScriptValue func_type_to_string=
this->newFunction(this->RegistryKeyTypeToString,1);
this->globalObject().setProperty("RegistryKeyTypeToString",
func_type_to_string);
}
ReportEngine::~ReportEngine() {
delete this->p_type_byte_array;
}
/*
* GetReportTemplateInfo
*/
QMap<QString,QVariant> ReportEngine::GetReportTemplateInfo(QString file) {
- // Open report template file
- QFile template_file(file);
- if(!template_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ // Read template file
+ QString report_code;
+ if(!this->GetReportTemplateFileContents(file,report_code)) {
QMap<QString,QVariant> error_msg;
- error_msg["error"]=QString("Couldn't open report template file '%1'!")
- .arg(file);
+ error_msg["error"]=report_code;
return error_msg;
}
- // Read template file and close it
- QString report_code;
- QTextStream in(&template_file);
- while(!in.atEnd()) report_code.append(in.readLine()).append("\n");
- template_file.close();
-
// Evaluate report template script
QScriptValue report_result=this->evaluate(report_code,file);
if (report_result.isError() || this->hasUncaughtException()) {
QMap<QString,QVariant> error_msg;
error_msg["error"]=QString("File: %1\n Line: %2\nError: %3")
.arg(file)
.arg(report_result.property("lineNumber").toInt32())
.arg(report_result.toString());
return error_msg;
}
// Try to call the fred_report_info script function and return result
QScriptValue fred_report_info_func=
this->globalObject().property("fred_report_info");
if(!fred_report_info_func.isFunction()) {
QMap<QString,QVariant> error_msg;
error_msg["error"]=
QString("Report template '%1' does not have a fred_report_info function!")
.arg(file)
.arg(report_result.property("lineNumber").toInt32())
.arg(report_result.toString());
return error_msg;
}
QScriptValue fred_report_info_res=fred_report_info_func.call();
// TODO: Maybe do more checking on return value
return fred_report_info_res.toVariant().toMap();
}
+/*
+ * GenerateReport
+ */
+bool ReportEngine::GenerateReport(RegistryHive *p_hive,
+ QString report_file,
+ QString &report_result,
+ bool console_mode)
+{
+ // Clear internal buffer
+ this->report_content.clear();
+
+ // Update exported functions
+ this->UpdateExportedFunctions(p_hive);
+
+ // Read template file
+ QString report_code;
+ if(!this->GetReportTemplateFileContents(report_file,report_code)) {
+ report_result=report_code;
+ return false;
+ }
+
+ // Evaluate report template script
+ QScriptValue script_result=this->evaluate(report_code,report_file);
+ if (script_result.isError() || this->hasUncaughtException()) {
+ script_result=QString("File: %1\n Line: %2\nError: %3")
+ .arg(report_file)
+ .arg(script_result.property("lineNumber").toInt32())
+ .arg(script_result.toString());
+ return false;
+ }
+
+ // Try to call the fred_report_html script function and return result
+ QScriptValue fred_report_html_func=
+ this->globalObject().property("fred_report_html");
+ if(!fred_report_html_func.isFunction()) {
+ report_result=
+ QString("Report template '%1' does not have a fred_report_info function!")
+ .arg(report_file)
+ .arg(script_result.property("lineNumber").toInt32())
+ .arg(script_result.toString());
+ return false;
+ }
+ QScriptValue fred_report_html_res=fred_report_html_func.call();
+
+ // TODO: Maybe do more checking on return value
+ report_result=this->report_content;
+ return true;
+}
+
/*******************************************************************************
* Public Slots
******************************************************************************/
/*******************************************************************************
* Private
******************************************************************************/
/*
* Print
*/
QScriptValue ReportEngine::Print(QScriptContext *context,
QScriptEngine *engine)
{
int i;
QString content;
// Append all arguments to content
for(i=0;i<context->argumentCount();++i) {
//if(i>0) content.append(" ");
content.append(context->argument(i).toString());
}
qobject_cast<ReportEngine*>(engine)->report_content.append(content);
return engine->undefinedValue();
}
/*
* PrintLn
*/
QScriptValue ReportEngine::PrintLn(QScriptContext *context,
QScriptEngine *engine)
{
int i;
QString content;
// Append all arguments to content
for(i=0;i<context->argumentCount();++i) {
//if(i>0) content.append(" ");
content.append(context->argument(i).toString());
}
qobject_cast<ReportEngine*>(engine)->
report_content.append(content).append("\n");
return engine->undefinedValue();
}
/*
* GetRegistryNodes
*/
QScriptValue ReportEngine::GetRegistryNodes(QScriptContext *context,
QScriptEngine *engine)
{
QScriptValue calleeData;
RegistryHive *p_hive;
QMap<QString,int> nodes;
QScriptValue ret_nodes;
int ii=0;
// This function needs one argument, parent node path
if(context->argumentCount()!=1) return engine->undefinedValue();
// Get calle data (Pointer to RegistryHive class)
calleeData=context->callee().data();
p_hive=qobject_cast<RegistryHive*>(calleeData.toQObject());
// Get nodes
nodes=p_hive->GetNodes(context->argument(0).toString());
if(p_hive->Error()) {
// Clear error state
p_hive->GetErrorMsg();
return engine->undefinedValue();
}
// Build script array
ret_nodes=engine->newArray(nodes.count());
QMapIterator<QString,int> i(nodes);
while(i.hasNext()) {
i.next();
ret_nodes.setProperty(ii++,QScriptValue(i.key()));
}
return ret_nodes;
}
/*
* GetRegistryKeys
*/
QScriptValue ReportEngine::GetRegistryKeys(QScriptContext *context,
QScriptEngine *engine)
{
QScriptValue calleeData;
RegistryHive *p_hive;
QMap<QString,int> keys;
QScriptValue ret_keys;
int ii=0;
// This function needs one argument, parent node path
if(context->argumentCount()!=1) return engine->undefinedValue();
// Get calle data (Pointer to RegistryHive class)
calleeData=context->callee().data();
p_hive=qobject_cast<RegistryHive*>(calleeData.toQObject());
// Get keys
keys=p_hive->GetKeys(context->argument(0).toString());
if(p_hive->Error()) {
// Clear error state
p_hive->GetErrorMsg();
return engine->undefinedValue();
}
// Build script array
ret_keys=engine->newArray(keys.count());
QMapIterator<QString,int> i(keys);
while(i.hasNext()) {
i.next();
ret_keys.setProperty(ii++,QScriptValue(i.key()));
}
return ret_keys;
}
/*
* RegistryKeyValueToScript
*/
QScriptValue ReportEngine::RegistryKeyValueToScript(QScriptEngine *engine,
const s_RegistryKeyValue &s)
{
QScriptValue obj=engine->newObject();
obj.setProperty("type",s.type);
obj.setProperty("length",s.length);
ByteArray *p_byte_array=new ByteArray(engine);
obj.setProperty("value",p_byte_array->newInstance(s.value));
return obj;
}
/*
* RegistryKeyValueFromScriptValue
*/
void ReportEngine::RegistryKeyValueFromScript(const QScriptValue &obj,
s_RegistryKeyValue &s)
{
s.type=obj.property("type").toInt32();
s.length=obj.property("length").toInt32();
// TODO: Don't know if this works, but it probably does ;)
s.value=qvariant_cast<QByteArray>(obj.property("value").data().toVariant());
}
/*
* GetRegistryKeyValue
*/
QScriptValue ReportEngine::GetRegistryKeyValue(QScriptContext *context,
QScriptEngine *engine)
{
QScriptValue calleeData;
RegistryHive *p_hive;
QByteArray key_value;
int key_type=0;
size_t key_length=0;
s_RegistryKeyValue script_key_value;
// This function needs two arguments, key path and key name
if(context->argumentCount()!=2) return engine->undefinedValue();
// Get calle data (Pointer to RegistryHive class)
calleeData=context->callee().data();
p_hive=qobject_cast<RegistryHive*>(calleeData.toQObject());
// Get key value
key_value=p_hive->GetKeyValue(context->argument(0).toString(),
context->argument(1).toString(),
&key_type,
&key_length);
if(p_hive->Error()) {
// Get error message to clear error state
p_hive->GetErrorMsg();
// printf("\nError: %s\n",p_hive->GetErrorMsg().toAscii().constData());
return engine->undefinedValue();
}
// Save key value to s_RegistryKeyValue struct
script_key_value.type=key_type;
script_key_value.length=key_length;
script_key_value.value=key_value;
return ReportEngine::RegistryKeyValueToScript(engine,script_key_value);
}
/*
* RegistryKeyValueToString
*/
QScriptValue ReportEngine::RegistryKeyValueToString(QScriptContext *context,
QScriptEngine *engine)
{
QByteArray key_value;
QString ret="";
// This function needs two arguments, key value and value type
if(context->argumentCount()!=2) return engine->undefinedValue();
// Cast ByteArray argument to QByteArray and convert
key_value=qvariant_cast<QByteArray>(context->argument(0).data().toVariant());
ret=RegistryHive::KeyValueToString(key_value,
context->argument(1).toInt32());
return engine->newVariant(ret);
}
/*
* RegistryKeyValueToVariant
*/
QScriptValue ReportEngine::RegistryKeyValueToVariant(QScriptContext *context,
QScriptEngine *engine)
{
int offset=0;
int length=-1;
bool little_endian=true;
QByteArray key_value;
QString format="";
QString ret="";
// This function needs at least two arguments, key value and variant type,
// and may have three optional arguments, offset, length and little_endian
if(context->argumentCount()<2 || context->argumentCount()>5) {
return engine->undefinedValue();
}
if(context->argumentCount()==3) {
offset=context->argument(2).toInt32();
}
if(context->argumentCount()==4) {
offset=context->argument(2).toInt32();
length=context->argument(3).toInt32();
}
if(context->argumentCount()==5) {
offset=context->argument(2).toInt32();
length=context->argument(3).toInt32();
little_endian=(context->argument(4).toInt32()==1);
}
// Cast ByteArray argument to QByteArray
key_value=qvariant_cast<QByteArray>(context->argument(0).data().toVariant());
format=context->argument(1).toString();
ret=RegistryHive::KeyValueToString(key_value,format,offset,length,little_endian);
return engine->newVariant(ret);
}
/*
* RegistryKeyTypeToString
*/
QScriptValue ReportEngine::RegistryKeyTypeToString(QScriptContext *context,
QScriptEngine *engine)
{
QString ret="";
// This function needs one argument, key type
if(context->argumentCount()!=1) return engine->undefinedValue();
ret=RegistryHive::KeyTypeToString(context->argument(0).toInt32());
return engine->newVariant(ret);
}
/*
* GetRegistryNodeModTime
*/
QScriptValue ReportEngine::GetRegistryNodeModTime(QScriptContext *context,
QScriptEngine *engine)
{
QScriptValue calleeData;
RegistryHive *p_hive;
int64_t mod_time=0;
// This function needs one argument, node path
if(context->argumentCount()!=1) return engine->undefinedValue();
// Get calle data (Pointer to RegistryHive class)
calleeData=context->callee().data();
p_hive=qobject_cast<RegistryHive*>(calleeData.toQObject());
mod_time=p_hive->GetNodeModTime(context->argument(0).toString());
if(p_hive->Error()) {
// Get error message to clear error state
p_hive->GetErrorMsg();
return engine->undefinedValue();
}
QDateTime date_time;
date_time.setTimeSpec(Qt::UTC);
date_time.setTime_t(RegistryHive::FiletimeToUnixtime(mod_time));
return engine->newVariant(date_time.toString("yyyy/MM/dd hh:mm:ss"));
}
+
+/*
+ * GetReportTemplateFileContents
+ */
+bool ReportEngine::GetReportTemplateFileContents(QString file,
+ QString &contents)
+{
+ // Open report template file
+ QFile template_file(file);
+ if(!template_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ contents=QString("Couldn't open report template file '%1'!").arg(file);
+ return false;
+ }
+
+ // Read template file and close it
+ contents.clear();
+ QTextStream in(&template_file);
+ while(!in.atEnd()) contents.append(in.readLine()).append("\n");
+ template_file.close();
+
+ return true;
+}
+
+/*
+ * UpdateExportedFunctions
+ */
+void ReportEngine::UpdateExportedFunctions(RegistryHive *p_hive) {
+ this->p_registry_hive=p_hive;
+ // GetRegistryNodes
+ QScriptValue func_get_nodes=this->newFunction(this->GetRegistryNodes,1);
+ func_get_nodes.setData(this->newQObject(this->p_registry_hive));
+ this->globalObject().setProperty("GetRegistryNodes",func_get_nodes);
+ // GetRegistryKeys
+ QScriptValue func_get_keys=this->newFunction(this->GetRegistryKeys,1);
+ func_get_keys.setData(this->newQObject(this->p_registry_hive));
+ this->globalObject().setProperty("GetRegistryKeys",func_get_keys);
+ // GetRegistryKeyValue
+ QScriptValue func_get_key_value=this->newFunction(this->GetRegistryKeyValue,
+ 2);
+ func_get_key_value.setData(this->newQObject(this->p_registry_hive));
+ this->globalObject().setProperty("GetRegistryKeyValue",func_get_key_value);
+ // GetRegistryNodeModTime
+ QScriptValue func_get_node_modt=
+ this->newFunction(this->GetRegistryNodeModTime,1);
+ func_get_node_modt.setData(this->newQObject(this->p_registry_hive));
+ this->globalObject().setProperty("GetRegistryNodeModTime",func_get_node_modt);
+}
diff --git a/trunk/reportengine.h b/trunk/reportengine.h
index b1bfd10..a66e151 100644
--- a/trunk/reportengine.h
+++ b/trunk/reportengine.h
@@ -1,81 +1,89 @@
/*******************************************************************************
* fred Copyright (c) 2011-2013 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor *
* with special feautures useful during forensic analysis. *
* *
* This program is free software: you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the Free *
* Software Foundation, either version 3 of the License, or (at your option) *
* any later version. *
* *
* 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, see <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#ifndef REPORTENGINE_H
#define REPORTENGINE_H
#include <QObject>
#include <QtScript/QScriptEngine>
#include <QtScript/QScriptValue>
#include <QtScript/QScriptContext>
#include <QString>
#include <QVariant>
#include <QMap>
#include "registryhive.h"
#include "qtscript_types/bytearray.h"
#define FRED_REPORTENGINE_API_VERSION 2
class ReportEngine : public QScriptEngine {
Q_OBJECT
public:
struct s_RegistryKeyValue {
int type;
int length;
QByteArray value;
};
RegistryHive *p_registry_hive;
QString report_content;
ReportEngine(RegistryHive *p_hive);
~ReportEngine();
+
QMap<QString,QVariant> GetReportTemplateInfo(QString file);
+ bool GenerateReport(RegistryHive *p_hive,
+ QString report_file,
+ QString &report_result,
+ bool console_mode=true);
private:
ByteArray *p_type_byte_array;
static QScriptValue Print(QScriptContext *context, QScriptEngine *engine);
static QScriptValue PrintLn(QScriptContext *context, QScriptEngine *engine);
static QScriptValue GetRegistryNodes(QScriptContext *context,
QScriptEngine *engine);
static QScriptValue GetRegistryKeys(QScriptContext *context,
QScriptEngine *engine);
static QScriptValue RegistryKeyValueToScript(QScriptEngine *engine,
const s_RegistryKeyValue &s);
static void RegistryKeyValueFromScript(const QScriptValue &obj,
s_RegistryKeyValue &s);
static QScriptValue GetRegistryKeyValue(QScriptContext *context,
QScriptEngine *engine);
static QScriptValue RegistryKeyValueToString(QScriptContext *context,
QScriptEngine *engine);
static QScriptValue RegistryKeyValueToVariant(QScriptContext *context,
QScriptEngine *engine);
static QScriptValue RegistryKeyTypeToString(QScriptContext *context,
QScriptEngine *engine);
static QScriptValue GetRegistryNodeModTime(QScriptContext *context,
QScriptEngine *engine);
+
+ bool GetReportTemplateFileContents(QString file, QString &contents);
+ void UpdateExportedFunctions(RegistryHive *p_hive);
};
Q_DECLARE_METATYPE(ReportEngine::s_RegistryKeyValue)
#endif // REPORTENGINE_H
diff --git a/trunk/reports.cpp b/trunk/reports.cpp
index 2f673e8..15a5b43 100644
--- a/trunk/reports.cpp
+++ b/trunk/reports.cpp
@@ -1,161 +1,183 @@
/*******************************************************************************
* fred Copyright (c) 2011-2013 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor *
* with special feautures useful during forensic analysis. *
* *
* This program is free software: you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the Free *
* Software Foundation, either version 3 of the License, or (at your option) *
* any later version. *
* *
* 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, see <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#include "reports.h"
#include <QListIterator>
#include <QDir>
#include <QMap>
#include <QDebug>
+/*******************************************************************************
+ * Public
+ ******************************************************************************/
+
Reports::Reports() {
this->p_engine=new ReportEngine(NULL);
this->report_templates.clear();
}
Reports::~Reports() {
qDeleteAll(this->report_templates);
delete this->p_engine;
}
void Reports::LoadReportTemplates(QString dir) {
QString report_template="";
QString report_category,report_name,report_author,report_desc,report_hive;
bool found;
int i;
ReportTemplate *p_report;
// Get all template files in report_templates directory
QDir report_dir(dir);
QStringList found_report_templates=report_dir.
entryList(QStringList()<<"*.qs");
QListIterator<QString> it(found_report_templates);
while(it.hasNext()) {
// Build path to template file
report_template=report_dir.path();
report_template.append(QDir::separator());
report_template.append(it.next());
// Get report info
QMap<QString,QVariant> report_info=this->p_engine->
GetReportTemplateInfo(report_template);
if(report_info.contains("error")) {
// TODO: Inform user
qDebug()<<"Error in report '"<<report_template<<"'\n"
<<report_info["error"].toString();
continue;
}
// Make sure report is compatible with current API
if(report_info.value("fred_api",QVariant(0)).toInt()>
FRED_REPORTENGINE_API_VERSION)
{
// TODO: Inform user
qDebug()<<"Report '"<<report_template<<"' is not compatible with current API!";
}
// Extract info values. If a value isn't present, it will be set to ""
report_category=report_info.value("report_cat").toString();
report_name=report_info.value("report_name").toString();
report_author=report_info.value("report_author").toString();
report_desc=report_info.value("report_desc").toString();
- report_hive=report_info.value("report_hive").toString();
+ report_hive=report_info.value("hive").toString().toUpper();
// Check if a report with the same category and name was already added
found=false;
for(i=0;i<this->report_templates.count();i++) {
if(this->report_templates.at(i)->Category()==report_category &&
this->report_templates.at(i)->Name()==report_name)
{
found=true;
break;
}
}
// Add to or update report template list
if(!found) {
// Add report to list
p_report=new ReportTemplate(report_template,
report_category,
report_name,
report_author,
report_desc,
report_hive);
this->report_templates.append(p_report);
} else {
// Update report entry
p_report=this->report_templates.at(i);
p_report->SetFile(report_template);
p_report->SetAuthor(report_author);
p_report->SetDescription(report_desc);
}
}
}
QStringList Reports::GetAvailableReportCategories() {
QStringList ret;
QString cat;
int i;
ret.clear();
for(i=0;i<this->report_templates.count();i++) {
cat=this->report_templates.value(i)->Category();
if(!ret.contains(cat)) ret.append(cat);
}
ret.sort();
return ret;
}
-QStringList Reports::GetAvailableReports(QString category) {
- QStringList ret;
+QList<ReportTemplate*> Reports::GetAvailableReports(QString category) {
+ QList<ReportTemplate*> ret;
QString cat;
int i=0;
ret.clear();
for(i=0;i<this->report_templates.count();i++) {
cat=this->report_templates.value(i)->Category();
- if(cat==category) ret.append(this->report_templates.value(i)->Name());
+ if(cat==category) ret.append(this->report_templates.value(i));
}
- ret.sort();
return ret;
}
-QMap<QString,QString> Reports::GetReportInfo(QString category, QString name) {
- QMap<QString,QString> ret;
- int i=0;
+bool Reports::GenerateReport(RegistryHive *p_hive,
+ QString report_file,
+ QString &report_result,
+ bool console_mode)
+{
+ return this->p_engine->GenerateReport(p_hive,
+ report_file,
+ report_result,
+ console_mode);
+}
- // Search requested report
- for(i=0;i<this->report_templates.count();i++) {
- if(this->report_templates.value(i)->Category()==category &&
- this->report_templates.value(i)->Name()==name)
- {
- ret["report_author"]=this->report_templates.value(i)->Author();
- ret["report_desc"]=this->report_templates.value(i)->Description();
- break;
- }
+bool Reports::GenerateReport(RegistryHive *p_hive,
+ QList<ReportTemplate*> report_list,
+ QString &report_result,
+ bool console_mode)
+{
+ bool ret;
+ QString res;
+
+ QListIterator<ReportTemplate*> rep_it(report_list);
+ while(rep_it.hasNext()) {
+ res="";
+ ret=this->GenerateReport(p_hive,
+ rep_it.next()->File(),
+ res,
+ console_mode);
+ if(ret) report_result.append(res);
+ // TODO: Inform user something didn't work
}
- return ret;
+ return true;
}
+
+/*******************************************************************************
+ * Private
+ ******************************************************************************/
diff --git a/trunk/reports.h b/trunk/reports.h
index 397b89e..13fcba3 100644
--- a/trunk/reports.h
+++ b/trunk/reports.h
@@ -1,54 +1,53 @@
/*******************************************************************************
* fred Copyright (c) 2011-2013 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor *
* with special feautures useful during forensic analysis. *
* *
* This program is free software: you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the Free *
* Software Foundation, either version 3 of the License, or (at your option) *
* any later version. *
* *
* 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, see <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#ifndef REPORTS_H
#define REPORTS_H
#include "reporttemplate.h"
#include "reportengine.h"
#include <QList>
-#include <QMap>
#include <QString>
+#include <QStringList>
class Reports {
public:
Reports();
~Reports();
void LoadReportTemplates(QString dir);
QStringList GetAvailableReportCategories();
- QStringList GetAvailableReports(QString category);
- QMap<QString,QString> GetReportInfo(QString category, QString name);
+ QList<ReportTemplate*> GetAvailableReports(QString category);
-/*
- QString GenerateReport(RegistryHive *p_hive,
- QString report_category,
- QString report_name);
- QString GenerateReport(RegistryHive *p_hive,
- QString report_template,
- bool console_mode=false);
-*/
+ bool GenerateReport(RegistryHive *p_hive,
+ QString report_file,
+ QString &report_result,
+ bool console_mode=false);
+ bool GenerateReport(RegistryHive *p_hive,
+ QList<ReportTemplate*> report_list,
+ QString &report_result,
+ bool console_mode=false);
private:
QList<ReportTemplate*> report_templates;
ReportEngine *p_engine;
};
#endif // REPORTS_H
diff --git a/trunk/reporttemplate.h b/trunk/reporttemplate.h
index 2a3fba1..84ff695 100644
--- a/trunk/reporttemplate.h
+++ b/trunk/reporttemplate.h
@@ -1,58 +1,61 @@
/*******************************************************************************
* fred Copyright (c) 2011-2013 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor *
* with special feautures useful during forensic analysis. *
* *
* This program is free software: you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the Free *
* Software Foundation, either version 3 of the License, or (at your option) *
* any later version. *
* *
* 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, see <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#ifndef REPORTTEMPLATE_H
#define REPORTTEMPLATE_H
+#include <QMetaType>
#include <QString>
class ReportTemplate {
public:
ReportTemplate(QString report_template_file,
QString report_category,
QString report_name,
QString report_author,
QString report_desc,
QString report_hive);
void SetFile(QString new_file);
void SetCategory(QString new_category);
void SetName(QString new_name);
void SetAuthor(QString new_author);
void SetDescription(QString new_desc);
void SetHive(QString new_hive);
QString File();
QString Category();
QString Name();
QString Author();
QString Description();
QString Hive();
private:
QString template_file;
QString category;
QString name;
QString author;
QString description;
QString hive;
};
+Q_DECLARE_METATYPE(ReportTemplate*)
+
#endif // REPORTTEMPLATE_H
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Dec 23, 5:22 AM (49 m, 43 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1176854
Default Alt Text
(118 KB)
Attached To
Mode
rFRED fred
Attached
Detach File
Event Timeline
Log In to Comment