This repository was archived by the owner on Dec 14, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfileprocessor.cpp
More file actions
278 lines (212 loc) · 7.16 KB
/
Copy pathfileprocessor.cpp
File metadata and controls
278 lines (212 loc) · 7.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
#include "Column.h"
#include "fileprocessor.h"
#include "libmagic/magic.h"
#include <QCoreApplication>
#include <QDirIterator>
#include <QFileInfo>
#include <QTemporaryFile>
#include <QThread>
FileProcessor::FileProcessor(QObject *parent) : QObject(parent)
{
file_list = new QHash<QString, QStringList>();
}
FileProcessor::~FileProcessor()
{
if(file_list)
delete file_list;
yr_finalize();
delete scanner;
}
void FileProcessor::processFiles(const QList<QUrl> &urls, bool yara)
{
file_list->clear();
yara_active = yara;
// get file count
file_count = 0;
for(const QUrl &url :urls)
{
if(url.isLocalFile())
{
QString file_path = url.toLocalFile();
QFileInfo file_info(file_path);
if(file_info.isDir())
{
QDirIterator dir_iter(file_path, QDir::Files | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
while(dir_iter.hasNext())
{
dir_iter.next();
++file_count;
}
}
else if(file_info.isFile())
{
++file_count;
}
}
}
emit fileCountSum(file_count);
// process files
file_counter = 0;
for(const QUrl &url : urls)
{
if(url.isLocalFile())
{
QString file_path = url.toLocalFile();
QFileInfo file_info(file_path);
if(file_info.isDir())
{
QDirIterator dir_iter(file_path, QDir::Files | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
while(dir_iter.hasNext())
{
QString iter_path = dir_iter.next();
insertFileListData(*file_list, iter_path);
}
}
else if(file_info.isFile())
{
insertFileListData(*file_list, file_path);
}
}
}
emit finishedProcessing(file_list);
}
void FileProcessor::insertFileListData(QHash<QString, QStringList> &file_list, const QString &file_path)
{
bool large_file_count = (file_count > 1000 ? true : false);
for(int i = 0; i < Column::NUM_COLUMNS; ++i)
file_list[file_path].append("");
QFileInfo file_info(file_path);
QString file_name = file_info.fileName();
file_list[file_path].replace(Column::FILENAME, file_name);
if(yara_active)
{
file_list[file_path].replace(Column::YARA, scanner->scanFile(file_path));
}
QLocale locale;
file_list[file_path].replace(Column::FILESIZE, locale.toString(file_info.size()));
file_list[file_path].replace(Column::FILE_EXTENSION, file_info.suffix());
file_list[file_path].replace(Column::MIMETYPE, getFileType(file_path, true));
file_list[file_path].replace(Column::FILETYPE, getFileType(file_path, false));
file_list[file_path].replace(Column::FULLPATH, file_path);
file_list[file_path].replace(Column::DIRPATH, file_info.dir().dirName() + "/" + file_name);
emit updateModel(file_list[file_path]);
++file_counter;
emit fileCount(file_counter);
if(large_file_count)
QThread::msleep(10);
}
QString FileProcessor::getFileType(const QString file_path, const bool &mime_type)
{
// hacky workaround with a 64k temp file in Windows, because of libmagics file limit to 2GB on Windows...
#ifdef Q_OS_WIN
bool large_win_file = false;
QString temp_file_path;
QTemporaryFile temp_file;
QFileInfo file_info(file_path);
if(file_info.exists() && (file_info.size() > 2147483647))
{
large_win_file = true;
if(temp_file.open())
{
QFile large_file(file_path);
if(large_file.open(QIODevice::ReadOnly))
{
const qint64 read_size = 65536;
QByteArray data = large_file.read(read_size);
temp_file.write(data);
temp_file.flush();
large_file.close();
}
else
{
qWarning() << "Failed to open large file for reading";
return "error";
}
temp_file_path = temp_file.fileName();
}
else
{
qWarning() << "Failed to create temporary file";
return "error";
}
}
#endif
magic_t magic_cookie;
if(mime_type)
magic_cookie = magic_open(MAGIC_MIME);
else
magic_cookie = magic_open(MAGIC_NONE);
if(magic_cookie == nullptr)
{
qWarning() << "Failed to initialize magic cookie";
}
QString app_path = QCoreApplication::applicationDirPath();
QString magic_mgc_path = app_path + "/db/magic.mgc";
if(magic_load(magic_cookie, magic_mgc_path.toStdString().c_str()) != 0)
{
magic_close(magic_cookie);
qWarning() << "Failed to load magic database";
}
const char *file_type;
#ifdef Q_OS_WIN
if(large_win_file)
file_type = magic_file(magic_cookie, temp_file_path.toStdString().c_str());
else
file_type = magic_file(magic_cookie, file_path.toStdString().c_str());
#else
file_type = magic_file(magic_cookie, file_path.toStdString().c_str());
#endif
if(file_type == nullptr)
{
QString error_msg = magic_error(magic_cookie);
magic_close(magic_cookie);
qWarning() << "Failed to get file type:" << error_msg;
}
QString result(file_type);
magic_close(magic_cookie);
return result;
}
void FileProcessor::initializeYara()
{
if(yr_initialize() != ERROR_SUCCESS)
{
qDebug() << "Unable to initialize YARA";
}
scanner = new YaraProcessor();
connect(scanner, &YaraProcessor::yaraError, this, &FileProcessor::yaraError);
connect(scanner, &YaraProcessor::yaraWarning, this, &FileProcessor::yaraWarning);
connect(scanner, &YaraProcessor::yaraSuccess, this, &FileProcessor::yaraSuccess);
yara_dir = QCoreApplication::applicationDirPath() + "/YARA";
if(!yara_dir.exists())
yara_dir.mkpath(".");
loadAndCompileYaraRules(yara_dir.absolutePath());
}
void FileProcessor::loadAndCompileYaraRules(const QString &yara_dir_path)
{
scanner->clearRules();
// load copiled rules
QDir compiled_rules_dir(yara_dir_path + "/Compiled");
if(!compiled_rules_dir.exists())
compiled_rules_dir.mkpath(".");
QDirIterator it_compiled(compiled_rules_dir.absolutePath(), QDir::NoDotAndDotDot | QDir::Files, QDirIterator::Subdirectories);
QStringList compiled_rule_list;
while(it_compiled.hasNext())
{
QString file_path = it_compiled.next();
compiled_rule_list.append(file_path);
}
scanner->loadCompiledYaraRules(compiled_rule_list);
// compile and load text rules
QDir text_rules_dir(yara_dir_path + "/Rules");
if(!text_rules_dir.exists())
text_rules_dir.mkpath(".");
QDirIterator it_text(text_rules_dir.absolutePath(), QDir::NoDotAndDotDot | QDir::Files, QDirIterator::Subdirectories);
QStringList text_rule_list;
while(it_text.hasNext())
{
QString file_path = it_text.next();
text_rule_list.append(file_path);
}
scanner->compileYaraRules(text_rule_list);
emit finishedLoadingYaraRules();
}