1 // copyright (c) 2019-2021 hors<horsicq@gmail.com>
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 
10 // The above copyright notice and this permission notice shall be included in all
11 // copies or substantial portions of the Software.
12 
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 // SOFTWARE.
20 //
21 #include "searchsignatureswidget.h"
22 #include "ui_searchsignatureswidget.h"
23 
SearchSignaturesWidget(QWidget * pParent)24 SearchSignaturesWidget::SearchSignaturesWidget(QWidget *pParent) :
25     XShortcutsWidget(pParent),
26     ui(new Ui::SearchSignaturesWidget)
27 {
28     ui->setupUi(this);
29     g_pDevice=nullptr;
30     g_pFilter=new QSortFilterProxyModel(this);
31     g_pModel=nullptr;
32     g_bInit=false;
33     g_scCopyName=nullptr;
34     g_scCopySignature=nullptr;
35     g_scCopyAddress=nullptr;
36     g_scCopyOffset=nullptr;
37     g_scHex=nullptr;
38 
39     ui->tableViewResult->installEventFilter(this);
40 }
41 
~SearchSignaturesWidget()42 SearchSignaturesWidget::~SearchSignaturesWidget()
43 {
44     g_watcher.waitForFinished();
45 
46     delete ui;
47 }
48 
setData(QIODevice * pDevice,XBinary::FT fileType,OPTIONS options,bool bAuto)49 void SearchSignaturesWidget::setData(QIODevice *pDevice, XBinary::FT fileType,OPTIONS options, bool bAuto)
50 {
51     this->g_pDevice=pDevice;
52     g_bInit=false;
53 
54     QSet<XBinary::FT> stFileType=XBinary::getFileTypes(pDevice,true);
55     stFileType.insert(XBinary::FT_COM);
56     QList<XBinary::FT> listFileTypes=XBinary::_getFileTypeListFromSet(stFileType);
57 
58     XBinary::FT _fileType=XFormats::setFileTypeComboBox(ui->comboBoxType,&listFileTypes,fileType);
59     XFormats::setEndianessComboBox(ui->comboBoxEndianness,_fileType);
60 
61     ui->tableViewResult->setModel(nullptr);
62 
63     g_fileType=fileType;
64 
65     setOptions(options);
66 
67     if(bAuto)
68     {
69         search();
70     }
71 }
72 
setOptions(SearchSignaturesWidget::OPTIONS options)73 void SearchSignaturesWidget::setOptions(SearchSignaturesWidget::OPTIONS options)
74 {
75     g_options=options;
76     setSignaturesPath(options.sSignaturesPath);
77 }
78 
getOptions()79 SearchSignaturesWidget::OPTIONS SearchSignaturesWidget::getOptions()
80 {
81     return g_options;
82 }
83 
setSignaturesPath(QString sPath)84 void SearchSignaturesWidget::setSignaturesPath(QString sPath)
85 {
86 #if QT_VERSION >= 0x050300
87     const QSignalBlocker block(ui->comboBoxFile);
88 #else
89     const bool bBlocked1=ui->comboBoxFile->blockSignals(true);
90 #endif
91 
92     ui->comboBoxFile->clear();
93 
94     if(g_options.sUserSignature!="")
95     {
96         ui->comboBoxFile->addItem("",g_options.sUserSignature);
97     }
98 
99     QList<QString> listFiles=XBinary::getAllFilesFromDirectory(XBinary::convertPathName(sPath),"*.db");
100 
101     int nNumberOfFiles=listFiles.count();
102 
103     for(int i=0;i<nNumberOfFiles;i++)
104     {
105         QString sFileName=listFiles.at(i);
106         ui->comboBoxFile->addItem(XBinary::getBaseFileName(sFileName),XBinary::convertPathName(sPath)+QDir::separator()+sFileName);
107     }
108 
109     if(g_options.sUserSignature!="")
110     {
111         loadSignatures("");
112     }
113     else if(nNumberOfFiles)
114     {
115         loadSignatures(ui->comboBoxFile->currentData().toString());
116     }
117 #if QT_VERSION < 0x050300
118     ui->comboBoxFile->blockSignals(bBlocked1);
119 #endif
120 }
121 
reload()122 void SearchSignaturesWidget::reload()
123 {
124     search();
125 }
126 
getInitStatus()127 bool SearchSignaturesWidget::getInitStatus()
128 {
129     return g_bInit;
130 }
131 
on_pushButtonSave_clicked()132 void SearchSignaturesWidget::on_pushButtonSave_clicked()
133 {
134     if(g_pModel)
135     {
136         QString sFileName=XBinary::getResultFileName(g_pDevice,QString("%1.txt").arg(tr("Signatures")));
137         sFileName=QFileDialog::getSaveFileName(this, tr("Save file"),sFileName, QString("%1 (*.txt);;%2 (*)").arg(tr("Text files"),tr("All files")));
138 
139         if(!sFileName.isEmpty())
140         {
141             XOptions::saveTable(g_pModel,sFileName);
142         }
143     }
144 }
145 
on_pushButtonSearch_clicked()146 void SearchSignaturesWidget::on_pushButtonSearch_clicked()
147 {
148     search();
149 }
150 
on_tableViewResult_customContextMenuRequested(const QPoint & pos)151 void SearchSignaturesWidget::on_tableViewResult_customContextMenuRequested(const QPoint &pos)
152 {
153     QMenu contextMenu(this);
154 
155     QAction actionCopyString(tr("Copy name"),this);
156     actionCopyString.setShortcut(getShortcuts()->getShortcut(XShortcuts::ID_SIGNATURES_COPYNAME));
157     connect(&actionCopyString,SIGNAL(triggered()),this,SLOT(_copyName()));
158     contextMenu.addAction(&actionCopyString);
159 
160     QAction actionCopySignature(tr("Copy signature"),this);
161     actionCopySignature.setShortcut(getShortcuts()->getShortcut(XShortcuts::ID_SIGNATURES_COPYSIGNATURE));
162     connect(&actionCopySignature,SIGNAL(triggered()),this,SLOT(_copySignature()));
163     contextMenu.addAction(&actionCopySignature);
164 
165     QAction actionCopyAddress(tr("Copy address"),this);
166     actionCopyAddress.setShortcut(getShortcuts()->getShortcut(XShortcuts::ID_SIGNATURES_COPYADDRESS));
167     connect(&actionCopyAddress,SIGNAL(triggered()),this,SLOT(_copyAddress()));
168     contextMenu.addAction(&actionCopyAddress);
169 
170     QAction actionCopyOffset(tr("Copy offset"),this);
171     actionCopyOffset.setShortcut(getShortcuts()->getShortcut(XShortcuts::ID_SIGNATURES_COPYOFFSET));
172     connect(&actionCopyOffset,SIGNAL(triggered()),this,SLOT(_copyOffset()));
173     contextMenu.addAction(&actionCopyOffset);
174 
175     QAction actionHex(tr("Hex"),this);
176 
177     if(g_options.bMenu_Hex)
178     {
179         actionHex.setShortcut(getShortcuts()->getShortcut(XShortcuts::ID_SIGNATURES_HEX));
180         connect(&actionHex,SIGNAL(triggered()),this,SLOT(_hex()));
181         contextMenu.addAction(&actionHex);
182     }
183 
184     contextMenu.exec(ui->tableViewResult->viewport()->mapToGlobal(pos));
185 }
186 
_copyName()187 void SearchSignaturesWidget::_copyName()
188 {
189     qDebug("void SearchSignaturesWidget::_copyName()");
190 
191     int nRow=ui->tableViewResult->currentIndex().row();
192 
193     if((nRow!=-1)&&(g_pModel))
194     {
195         QModelIndex index=ui->tableViewResult->selectionModel()->selectedIndexes().at(2);
196 
197         QString sString=ui->tableViewResult->model()->data(index).toString();
198 
199         QApplication::clipboard()->setText(sString);
200     }
201 }
202 
_copySignature()203 void SearchSignaturesWidget::_copySignature()
204 {
205     int nRow=ui->tableViewResult->currentIndex().row();
206 
207     if((nRow!=-1)&&(g_pModel))
208     {
209         QModelIndex index=ui->tableViewResult->selectionModel()->selectedIndexes().at(0);
210 
211         QString sString=ui->tableViewResult->model()->data(index,Qt::UserRole+MultiSearch::USERROLE_STRING).toString();
212 
213         QApplication::clipboard()->setText(sString);
214     }
215 }
216 
_copyAddress()217 void SearchSignaturesWidget::_copyAddress()
218 {
219     int nRow=ui->tableViewResult->currentIndex().row();
220 
221     if((nRow!=-1)&&(g_pModel))
222     {
223         QModelIndex index=ui->tableViewResult->selectionModel()->selectedIndexes().at(0);
224 
225         QString sString=ui->tableViewResult->model()->data(index).toString();
226 
227         QApplication::clipboard()->setText(sString);
228     }
229 }
230 
_copyOffset()231 void SearchSignaturesWidget::_copyOffset()
232 {
233     int nRow=ui->tableViewResult->currentIndex().row();
234 
235     if((nRow!=-1)&&(g_pModel))
236     {
237         QModelIndex index=ui->tableViewResult->selectionModel()->selectedIndexes().at(1);
238 
239         QString sString=ui->tableViewResult->model()->data(index).toString();
240 
241         QApplication::clipboard()->setText(sString);
242     }
243 }
244 
_hex()245 void SearchSignaturesWidget::_hex()
246 {
247     int nRow=ui->tableViewResult->currentIndex().row();
248 
249     if((nRow!=-1)&&(g_pModel))
250     {
251         QModelIndex index=ui->tableViewResult->selectionModel()->selectedIndexes().at(0);
252 
253         qint64 nOffset=ui->tableViewResult->model()->data(index,Qt::UserRole+MultiSearch::USERROLE_OFFSET).toLongLong();
254         qint64 nSize=ui->tableViewResult->model()->data(index,Qt::UserRole+MultiSearch::USERROLE_SIZE).toLongLong();
255 
256         emit showHex(nOffset,nSize);
257     }
258 }
259 
search()260 void SearchSignaturesWidget::search()
261 {
262     if(g_pDevice)
263     {
264         g_pOldModel=g_pModel;
265 
266         g_pFilter->setSourceModel(nullptr);
267         ui->tableViewResult->setModel(nullptr);
268 
269         XBinary::FT fileType=(XBinary::FT)(ui->comboBoxType->currentData().toInt());
270 
271         MultiSearch::OPTIONS options={};
272 
273         options.bMenu_Hex=g_options.bMenu_Hex;
274         options.memoryMap=XFormats::getMemoryMap(fileType,g_pDevice);
275         options.bSignature=true;
276         options.bIsBigEndian=(ui->comboBoxEndianness->currentData().toBool());
277         options.pListSignatureRecords=&g_listSignatureRecords;
278 
279         QList<XBinary::MS_RECORD> listRecords;
280 
281         QWidget *pParent=XOptions::getMainWidget(this);
282 
283         DialogMultiSearchProcess dsp(pParent);
284         dsp.processSearch(g_pDevice,&listRecords,options,MultiSearch::TYPE_SIGNATURES);
285         dsp.exec();
286 
287         DialogMultiSearchProcess dmp(pParent);
288         dmp.processModel(&listRecords,&g_pModel,options,MultiSearch::TYPE_SIGNATURES);
289         dmp.exec();
290 
291         g_pFilter->setSourceModel(g_pModel);
292         ui->tableViewResult->setModel(g_pFilter);
293 
294         ui->tableViewResult->setColumnWidth(0,120);  // TODO
295         ui->tableViewResult->setColumnWidth(1,120); // TODO
296         ui->tableViewResult->setColumnWidth(2,120); // TODO
297 
298         QFuture<void> future=QtConcurrent::run(this,&SearchSignaturesWidget::deleteOldModel);
299 
300         g_watcher.setFuture(future);
301 
302 //            watcher.waitForFinished();
303 
304         g_bInit=true;
305     }
306 }
307 
deleteOldModel()308 void SearchSignaturesWidget::deleteOldModel()
309 {
310     delete g_pOldModel;
311 }
312 
loadSignatures(QString sFileName)313 void SearchSignaturesWidget::loadSignatures(QString sFileName)
314 {
315     int nNumberOfSignatures=0;
316 
317     g_listSignatureRecords.clear();
318 
319     if(sFileName!="")
320     {
321         g_listSignatureRecords=MultiSearch::loadSignaturesFromFile(sFileName);
322         nNumberOfSignatures=g_listSignatureRecords.count();
323     }
324     else
325     {
326         // User signature
327         g_listSignatureRecords.append(MultiSearch::createSignature(g_options.sUserSignature,g_options.sUserSignature));
328         nNumberOfSignatures=1;
329     }
330 
331     ui->labelInfo->setText(QString("%1: %2").arg(tr("Signatures"),QString::number(nNumberOfSignatures)));
332 }
333 
on_comboBoxFile_currentIndexChanged(int index)334 void SearchSignaturesWidget::on_comboBoxFile_currentIndexChanged(int index)
335 {
336     Q_UNUSED(index)
337 
338     QString sFileName=ui->comboBoxFile->currentData().toString();
339 
340     loadSignatures(sFileName);
341 }
342 
registerShortcuts(bool bState)343 void SearchSignaturesWidget::registerShortcuts(bool bState)
344 {
345     if(bState)
346     {
347         if(!g_scCopyName)           g_scCopyName        =new QShortcut(getShortcuts()->getShortcut(XShortcuts::ID_SIGNATURES_COPYNAME),         this,SLOT(_copyName()));
348         if(!g_scCopySignature)      g_scCopySignature   =new QShortcut(getShortcuts()->getShortcut(XShortcuts::ID_SIGNATURES_COPYSIGNATURE),    this,SLOT(_copySignature()));
349         if(!g_scCopyAddress)        g_scCopyAddress     =new QShortcut(getShortcuts()->getShortcut(XShortcuts::ID_SIGNATURES_COPYADDRESS),      this,SLOT(_copyAddress()));
350         if(!g_scCopyOffset)         g_scCopyOffset      =new QShortcut(getShortcuts()->getShortcut(XShortcuts::ID_SIGNATURES_COPYOFFSET),       this,SLOT(_copyOffset()));
351         if(!g_scHex)                g_scHex             =new QShortcut(getShortcuts()->getShortcut(XShortcuts::ID_SIGNATURES_HEX),              this,SLOT(_hex()));
352     }
353     else
354     {
355         if(g_scCopyName)            {delete g_scCopyName;           g_scCopyName=nullptr;}
356         if(g_scCopySignature)       {delete g_scCopySignature;      g_scCopySignature=nullptr;}
357         if(g_scCopyAddress)         {delete g_scCopyAddress;        g_scCopyAddress=nullptr;}
358         if(g_scCopyOffset)          {delete g_scCopyOffset;         g_scCopyOffset=nullptr;}
359         if(g_scHex)                 {delete g_scHex;                g_scHex=nullptr;}
360     }
361 }
362