diff --git a/trunk/dlgaddkey.cpp b/trunk/dlgaddkey.cpp index f2a41d2..2989fa7 100644 --- a/trunk/dlgaddkey.cpp +++ b/trunk/dlgaddkey.cpp @@ -1,379 +1,446 @@ /******************************************************************************* * fred Copyright (c) 2011-2013 by Gillen Daniel * * * * 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 . * *******************************************************************************/ #include #include #include #include #include #include #include "dlgaddkey.h" #include "ui_dlgaddkey.h" #include "registryhive.h" #define MACROS_ENDIANNESS #include "macros.h" DlgAddKey::DlgAddKey(QWidget *p_parent, QString key_name, QString key_value_type, QByteArray key_value) : QDialog(p_parent), ui(new Ui::DlgAddKey) { this->p_current_widget=NULL; ui->setupUi(this); this->ansi_encoded=false; // Create widgets this->CreateValueWidgets(); // Set dialog title if(key_name.isEmpty() && key_value_type.isEmpty() && key_value.isEmpty()) { // If no values were passed, we consider this the ddd key dialog this->setWindowTitle(tr("Add key")); } else { // If a value was passed, this is considered the edit key dialog this->setWindowTitle(tr("Edit key")); this->ui->EdtKeyName->setEnabled(false); this->ui->CmbKeyType->setEnabled(false); } // Preload key value type values QStringList value_types=RegistryHive::GetKeyValueTypes(); this->ui->CmbKeyType->addItems(value_types); // Load values if(!key_name.isEmpty()) this->ui->EdtKeyName->setText(key_name); if(!key_value_type.isEmpty()) this->ui->CmbKeyType->setCurrentIndex(value_types.indexOf(key_value_type)); if(!key_value.isEmpty()) this->SetValueWidgetData(key_value,key_value_type); + + // Connect signals + this->connect(this->p_number_widget_rb_dec, + SIGNAL(clicked(bool)), + this, + SLOT(SlotNumberWidgetRbDecClicked(bool))); + this->connect(this->p_number_widget_rb_hex, + SIGNAL(clicked(bool)), + this, + SLOT(SlotNumberWidgetRbHexClicked(bool))); } DlgAddKey::~DlgAddKey() { this->DestroyValueWidgets(); delete ui; } QString DlgAddKey::KeyName() { return this->ui->EdtKeyName->text(); } QString DlgAddKey::KeyType() { return this->ui->CmbKeyType->currentText(); } QByteArray DlgAddKey::KeyValue() { return this->GetValueWidgetData(); } void DlgAddKey::on_BtnCancel_clicked() { this->reject(); } void DlgAddKey::on_BtnOk_clicked() { QString key_value_type=this->KeyType(); // Check entered data for correctness if(key_value_type=="REG_MULTI_SZ") { // REG_MULTI_SZ's can't contain empty sub-strings QString cur_data=this->p_text_widget_text_edit->toPlainText(); QString new_data=cur_data; // TODO: Do we need to check for \r\n on Windows?? new_data.replace(QRegExp("\n\n*"),"\n"); if(new_data.startsWith("\n")) new_data.remove(0,1); if(new_data.endsWith("\n")) new_data.chop(1); if(cur_data!=new_data) { if(QMessageBox::information(this, tr("Invalid data"), tr("A REG_MULTI_SZ can not contain empty " "sub-strings! If you continue, they " "will be removed."), QMessageBox::Yes, QMessageBox::No)==QMessageBox::Yes) { this->p_text_widget_text_edit->setPlainText(new_data); } else { return; } } } else if(key_value_type=="REG_DWORD" || key_value_type=="REG_DWORD_BIG_ENDIAN") { bool ok=false; - if(this->p_number_widget_rb_decimal->isChecked()) { + if(this->p_number_widget_rb_dec->isChecked()) { this->p_number_widget_line_edit->text().toInt(&ok); } else { // TODO: There seems to be a problem with 0xFFFFFFFF this->p_number_widget_line_edit->text().toInt(&ok,16); } if(!ok) { QMessageBox::information(this, tr("Invalid data"), tr("The value you entered could not be " "converted to a %1! Please correct it.") .arg(key_value_type), QMessageBox::Ok); return; } } else if(key_value_type=="REG_QWORD") { bool ok=false; - if(this->p_number_widget_rb_decimal->isChecked()) { + if(this->p_number_widget_rb_dec->isChecked()) { this->p_number_widget_line_edit->text().toLongLong(&ok); } else { this->p_number_widget_line_edit->text().toLongLong(&ok,16); } if(!ok) { QMessageBox::information(this, tr("Invalid data"), tr("The value you entered could not be " "converted to a %1! Please correct it.") .arg(key_value_type), QMessageBox::Ok); return; } } this->accept(); } void DlgAddKey::on_CmbKeyType_currentIndexChanged(const QString &arg1) { // Remove current widget from grid layout if(this->p_current_widget!=NULL) { this->ui->gridLayout->removeWidget(this->p_current_widget); this->p_current_widget->setVisible(false); this->p_current_widget=NULL; } // Add new widget for selected value type if(arg1=="REG_SZ" || arg1=="REG_EXPAND_SZ") { // Line edit widget for REG_SZ and REG_EXPAND_SZ this->ui->gridLayout->addWidget(this->p_line_widget,2,1); this->p_current_widget=this->p_line_widget; } else if(arg1=="REG_MULTI_SZ") { // Text edit widget for REG_MULTI_SZ this->ui->gridLayout->addWidget(this->p_text_widget,2,1); this->p_current_widget=this->p_text_widget; } else if(arg1=="REG_DWORD" || arg1=="REG_DWORD_BIG_ENDIAN" || arg1=="REG_QWORD") { // Number widget for REG_DWORD, REG_DWORD_BIG_ENDIAN and REG_QWORD this->ui->gridLayout->addWidget(this->p_number_widget,2,1); this->p_current_widget=this->p_number_widget; } else if(arg1=="REG_BINARY" || arg1=="REG_LINK" || arg1=="REG_RESOURCE_LIST" || arg1=="REG_FULL_RESOURCE_DESC" || arg1=="REG_RESOURCE_REQ_LIST") { // Binary widget for all other types this->ui->gridLayout->addWidget(this->p_binary_widget,2,1); this->p_current_widget=this->p_binary_widget; } if(arg1!="REG_NONE") { this->p_current_widget->setVisible(true); this->ui->LblKeyValue->setVisible(true); } else { this->ui->LblKeyValue->setVisible(false); } } void DlgAddKey::CreateValueWidgets() { this->p_line_widget=new QWidget(); this->p_line_widget_layout=new QHBoxLayout(this->p_line_widget); //this->p_line_widget_layout_rb_ansi=new QRadioButton(tr("Ansi")); //this->p_line_widget_layout_rb_unicode=new QRadioButton(tr("Unicode")); //this->p_line_widget_layout_rb_unicode->setChecked(true); this->p_line_widget_line_edit=new QLineEdit(); this->p_line_widget->setContentsMargins(0,0,0,0); this->p_line_widget_layout->setContentsMargins(0,0,0,0); this->p_line_widget_layout->addWidget(this->p_line_widget_line_edit); //this->p_line_widget_layout->addWidget(this->p_line_widget_layout_rb_ansi); //this->p_line_widget_layout->addWidget(this->p_line_widget_layout_rb_unicode); this->p_text_widget=new QWidget(); this->p_text_widget_layout=new QHBoxLayout(this->p_text_widget); this->p_text_widget_text_edit=new QPlainTextEdit(); this->p_text_widget->setContentsMargins(0,0,0,0); this->p_text_widget_layout->setContentsMargins(0,0,0,0); this->p_text_widget_layout->addWidget(this->p_text_widget_text_edit); this->p_number_widget=new QWidget(); this->p_number_widget_layout=new QHBoxLayout(this->p_number_widget); this->p_number_widget_line_edit=new QLineEdit(); - this->p_number_widget_rb_decimal=new QRadioButton(tr("Dec base")); - this->p_number_widget_rb_decimal->setChecked(true); + this->p_number_widget_rb_dec=new QRadioButton(tr("Dec base")); + this->p_number_widget_rb_dec->setChecked(true); this->p_number_widget_rb_hex=new QRadioButton(tr("Hex base")); this->p_number_widget->setContentsMargins(0,0,0,0); this->p_number_widget_layout->setContentsMargins(0,0,0,0); this->p_number_widget_layout->addWidget(this->p_number_widget_line_edit); - this->p_number_widget_layout->addWidget(this->p_number_widget_rb_decimal); + this->p_number_widget_layout->addWidget(this->p_number_widget_rb_dec); this->p_number_widget_layout->addWidget(this->p_number_widget_rb_hex); this->p_binary_widget=new QWidget(); this->p_binary_widget_layout=new QHBoxLayout(this->p_binary_widget); this->p_binary_widget_hex_edit=new HexEditWidget(this,false,false); this->p_binary_widget->setContentsMargins(0,0,0,0); this->p_binary_widget_layout->setContentsMargins(0,0,0,0); this->p_binary_widget_layout->addWidget(this->p_binary_widget_hex_edit); } void DlgAddKey::DestroyValueWidgets() { //delete this->p_line_widget_layout_rb_ansi; //delete this->p_line_widget_layout_rb_unicode; delete this->p_line_widget_line_edit; delete this->p_line_widget_layout; delete this->p_line_widget; delete this->p_text_widget_text_edit; delete this->p_text_widget_layout; delete this->p_text_widget; delete this->p_number_widget_rb_hex; - delete this->p_number_widget_rb_decimal; + delete this->p_number_widget_rb_dec; delete this->p_number_widget_line_edit; delete this->p_number_widget_layout; delete this->p_number_widget; delete this->p_binary_widget_hex_edit; delete this->p_binary_widget_layout; delete this->p_binary_widget; } void DlgAddKey::SetValueWidgetData(QByteArray &key_value, QString &key_value_type) { if(key_value_type=="REG_SZ" || key_value_type=="REG_EXPAND_SZ") { this->p_line_widget_line_edit->setText( RegistryHive::KeyValueToString(key_value, RegistryHive::StringToKeyValueType( key_value_type))); } else if(key_value_type=="REG_MULTI_SZ") { QStringList strings= RegistryHive::KeyValueToStringList(key_value,&(this->ansi_encoded)); this->p_text_widget_text_edit->setPlainText(strings.join("\n")); } else if(key_value_type=="REG_DWORD") { this->p_number_widget_line_edit->setText( RegistryHive::KeyValueToString(key_value,"int32")); } else if(key_value_type=="REG_DWORD_BIG_ENDIAN") { this->p_number_widget_line_edit->setText( RegistryHive::KeyValueToString(key_value,"int32",0,0,false)); } else if(key_value_type=="REG_QWORD") { this->p_number_widget_line_edit->setText( RegistryHive::KeyValueToString(key_value,"int64",0,0,false)); } else if(key_value_type=="REG_BINARY" || key_value_type=="REG_LINK" || key_value_type=="REG_RESOURCE_LIST" || key_value_type=="REG_FULL_RESOURCE_DESC" || key_value_type=="REG_RESOURCE_REQ_LIST") { this->p_binary_widget_hex_edit->SetData(key_value); } } QByteArray DlgAddKey::GetValueWidgetData() { QString key_value_type=this->KeyType(); if(key_value_type=="REG_SZ" || key_value_type=="REG_EXPAND_SZ") { // TODO: Wouldn't it be wise to let the user choose the encoding? // Get data QString data=this->p_line_widget_line_edit->text(); // Convert data to UTF16LE buffer uint16_t *p_buf=NULL; int buf_len=this->ToUtf16LeBuf(&p_buf,data.utf16(),data.size()); if(p_buf==NULL || buf_len==0) { // TODO: Inform user there was an error??? return QByteArray("\x00\x00",2); } // Construct ByteArray, free buffer and return QByteArray ret=QByteArray((char*)p_buf,buf_len); free(p_buf); return ret; } else if(key_value_type=="REG_MULTI_SZ") { // TODO: Let the user choose the encoding / endianness // TODO: Do we need to check for \r\n on Windows?? return RegistryHive::StringListToKeyValue( this->p_text_widget_text_edit-> toPlainText().split("\n", QString::SkipEmptyParts), true, this->ansi_encoded); } else if(key_value_type=="REG_DWORD" || key_value_type=="REG_DWORD_BIG_ENDIAN") { int32_t val; - if(this->p_number_widget_rb_decimal->isChecked()) { + if(this->p_number_widget_rb_dec->isChecked()) { val=this->p_number_widget_line_edit->text().toInt(); } else { val=this->p_number_widget_line_edit->text().toInt(0,16); } if(key_value_type=="REG_DWORD") val=HTOLE32(val); else val=HTOBE32(val); return QByteArray((char*)&val,4); } else if(key_value_type=="REG_QWORD") { int64_t val; - if(this->p_number_widget_rb_decimal->isChecked()) { + if(this->p_number_widget_rb_dec->isChecked()) { val=this->p_number_widget_line_edit->text().toLongLong(); } else { val=this->p_number_widget_line_edit->text().toLongLong(0,16); } val=HTOLE64(val); return QByteArray((char*)&val,8); } else if(key_value_type=="REG_BINARY" || key_value_type=="REG_LINK" || key_value_type=="REG_RESOURCE_LIST" || key_value_type=="REG_FULL_RESOURCE_DESC" || key_value_type=="REG_RESOURCE_REQ_LIST") { return this->p_binary_widget_hex_edit->GetData(); } return QByteArray(); } int DlgAddKey::ToUtf16LeBuf(uint16_t **pp_buf, const uint16_t *p_data, int ascii_len) { // Calculate utf16 buffer size // TODO: This fails if there are chars that need more than 16bit!! int buf_len=(ascii_len*2)+2; // Alloc buffer and set to 0x00h *pp_buf=(uint16_t*)malloc(buf_len); if(*pp_buf==NULL) return 0; memset(*pp_buf,0,buf_len); if(ascii_len==0) { // Empty string, we're done (buffer contains \0\0) return buf_len; } // Fill buffer with UTF16 string (ignoring \0\0 at the end) memcpy(*pp_buf,p_data,buf_len-2); // Make sure endianness is LE for(int i=0;iKeyType(); + + //if() TODO +} + +void DlgAddKey::SlotNumberWidgetRbDecClicked(bool checked) { + if(checked) { + bool ok=false; + if(this->KeyType()=="REG_QWORD") { + int64_t num=this->p_number_widget_line_edit->text().toLongLong(&ok,16); + if(ok) { + // Convert number to dec + this->p_number_widget_line_edit->setText(QString().arg(num)); + // Set input mask to 17 digit chars, 16 optional, 1 required + this->p_number_widget_line_edit->setInputMask("#000000000000000009;0"); + } + } else { + int32_t num=this->p_number_widget_line_edit->text().toLong(&ok,16); + if(ok) { + // Convert number to dec + this->p_number_widget_line_edit->setText(QString().arg(num)); + // Set input mask to 10 digit chars, 9 optional, 1 required + this->p_number_widget_line_edit->setInputMask("#0000000009;0"); + } + } + } +} + +void DlgAddKey::SlotNumberWidgetRbHexClicked(bool checked) { + if(checked) { + bool ok=false; + if(this->KeyType()=="REG_QWORD") { + uint64_t num=this->p_number_widget_line_edit->text().toULongLong(&ok); + if(ok) { + // Convert number to hex + this->p_number_widget_line_edit->setText(QString().sprintf("%016X", + num)); + // Set input mask to 16 hex chars, 15 optional, 1 required + this->p_number_widget_line_edit->setInputMask("hhhhhhhhhhhhhhhH;0"); + } + } else { + uint32_t num=this->p_number_widget_line_edit->text().toULong(&ok); + if(ok) { + // Convert number to hex + this->p_number_widget_line_edit->setText(QString().sprintf("%08X",num)); + // Set input mask to 8 hex chars, 7 optional, 1 required + this->p_number_widget_line_edit->setInputMask("hhhhhhhH;0"); + } + } + if(!ok) { + // TODO: Display error + this->p_number_widget_rb_dec->setChecked(true); + } + } +} diff --git a/trunk/dlgaddkey.h b/trunk/dlgaddkey.h index d7e7ac8..4331206 100644 --- a/trunk/dlgaddkey.h +++ b/trunk/dlgaddkey.h @@ -1,86 +1,89 @@ /******************************************************************************* * fred Copyright (c) 2011-2013 by Gillen Daniel * * * * 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 . * *******************************************************************************/ #ifndef DLGADDKEY_H #define DLGADDKEY_H #include #include #include #include #include #include #include #include "hexeditwidget.h" namespace Ui { class DlgAddKey; } class DlgAddKey : public QDialog { Q_OBJECT public: explicit DlgAddKey(QWidget *p_parent=0, QString key_name=QString(), QString key_value_type=QString(), QByteArray key_value=QByteArray()); ~DlgAddKey(); QString KeyName(); QString KeyType(); QByteArray KeyValue(); private slots: void on_BtnCancel_clicked(); void on_BtnOk_clicked(); void on_CmbKeyType_currentIndexChanged(const QString &arg1); + void SlotNumberWidgetRbDecClicked(bool checked); + void SlotNumberWidgetRbHexClicked(bool checked); private: Ui::DlgAddKey *ui; QWidget *p_current_widget; QWidget *p_line_widget; QHBoxLayout *p_line_widget_layout; //QRadioButton *p_line_widget_layout_rb_ansi; //QRadioButton *p_line_widget_layout_rb_unicode; QLineEdit *p_line_widget_line_edit; QWidget *p_text_widget; QHBoxLayout *p_text_widget_layout; QPlainTextEdit *p_text_widget_text_edit; QWidget *p_number_widget; QHBoxLayout *p_number_widget_layout; QLineEdit *p_number_widget_line_edit; - QRadioButton *p_number_widget_rb_decimal; + QRadioButton *p_number_widget_rb_dec; QRadioButton *p_number_widget_rb_hex; QWidget *p_binary_widget; QHBoxLayout *p_binary_widget_layout; HexEditWidget *p_binary_widget_hex_edit; bool ansi_encoded; void CreateValueWidgets(); void DestroyValueWidgets(); void SetValueWidgetData(QByteArray &key_value, QString &key_value_type); QByteArray GetValueWidgetData(); int ToUtf16LeBuf(uint16_t **pp_buf,const uint16_t *p_data, int ascii_len); + void SetNumberWidgetLineEditInputMask(); }; #endif // DLGADDKEY_H