Skip to content

Commit

Permalink
Merge pull request #302 from gdt050579/300-eml-add-more-descriptions-…
Browse files Browse the repository at this point in the history
…to-the-eml-plugin

300 eml add more descriptions to the eml plugin
  • Loading branch information
rzaharia authored Apr 14, 2024
2 parents f96f209 + cd7300b commit 19482e2
Show file tree
Hide file tree
Showing 4 changed files with 203 additions and 79 deletions.
13 changes: 12 additions & 1 deletion GViewCore/src/View/DissasmViewer/Instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Config Instance::config;

constexpr size_t DISSASM_MAX_STORED_JUMPS = 5;

const std::array<AsmFunctionDetails, 8> KNOWN_FUNCTIONS = { {
const std::array<AsmFunctionDetails, 10> KNOWN_FUNCTIONS = { {
{ "WriteFile",
{ { "hFile", "HANDLE" },
{ "lpBuffer", "LPCVOID" },
Expand All @@ -30,8 +30,19 @@ const std::array<AsmFunctionDetails, 8> KNOWN_FUNCTIONS = { {
{ "dwCreationDisposition", "DWORD" },
{ "dwFlagsAndAttributes", "DWORD" },
{ "hTemplateFile", "HANDLE" } } },
{ "CreateFileA",
{
{ "lpFileName", "LPCSTR" },
{ "dwDesiredAccess", "DWORD" },
{ "dwShareMode", "DWORD" },
{ "lpSecurityAttributes", "LPSECURITY_ATTRIBUTES" },
{ "dwCreationDisposition", "DWORD" },
{ "dwFlagsAndAttributes", "DWORD" },
{ "hTemplateFile", "HANDLE" },
} },
{ "MessageBoxA", { { "hWnd", "HWND" }, { "lpText", "LPCTSTR" }, { "lpCaption", "LPCTSTR" }, { "uType", "UINT" } } },
{ "RegOpenKeyExW", { { "hKey", "HKEY" }, { "lpSubKey", "LPCWSTR" }, { "ulOptions", "DWORD" }, { "samDesired", "REGSAM" }, { "phkResult", "PHKEY" } } },
{ "RegOpenKeyExA", { { "hKey", "HKEY" }, { "lpSubKey", "LPCSTR" }, { "ulOptions", "DWORD" }, { "samDesired", "REGSAM" }, { "phkResult", "PHKEY" } } },
{ "RegSetValueExW",
{ { "hKey", "HKEY" },
{ "lpValueName", "LPCWSTR" },
Expand Down
12 changes: 12 additions & 0 deletions Types/EML/include/eml.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ struct EML_Item_Record
uint32 parentStartIndex;
uint32 startIndex;
uint32 dataLength;
std::u16string contentType;
std::u16string identifier;
bool leafNode;
};

Expand All @@ -32,6 +34,10 @@ namespace Type
private:
friend class Panels::Information;

//getting strings of format that start with "name=" and get the string between the quotes
std::optional<std::u16string> TryGetNameQuotes(std::u16string& contentTypeToSearch, bool removeIfFound = false);
std::u16string GetIdentifierFromContentType(std::u16string& contentTypeToChange);
std::u16string GetBufferNameFromHeaderFields();
std::vector<std::pair<std::u16string, std::u16string>> headerFields;

void ParsePart(GView::View::LexicalViewer::TextParser text, uint32 start, uint32 end);
Expand All @@ -52,6 +58,8 @@ namespace Type
// here
}
public:

bool ProcessData();
Reference<GView::Utils::SelectionZoneInterface> selectionZoneInterface;

uint32 GetSelectionZonesCount() override
Expand All @@ -68,6 +76,10 @@ namespace Type

return selectionZoneInterface->GetSelectionZone(index);
}
const std::vector<std::pair<std::u16string, std::u16string>>& GetHeaders()
{
return headerFields;
}

// View::ContainerViewer::EnumerateInterface
virtual bool BeginIteration(std::u16string_view path, AppCUI::Controls::TreeViewItem parent) override;
Expand Down
160 changes: 109 additions & 51 deletions Types/EML/src/EMLFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,51 @@ EMLFile::EMLFile()
{
}

bool EMLFile::ProcessData()
{
unicodeString.Set(obj->GetData().GetEntireFile());
TextParser text(unicodeString.ToStringView());

itemsIndex = 0;
items.clear();

ParsePart(text, 0, text.Len());
if (items.empty())
return false;

uint32 modeNr = 1, attachmentsNr = 1;
for (auto& itemData : items) {
itemData.contentType = itemData.leafNode ? contentType : ExtractContentType(text, itemData.startIndex, itemData.startIndex + itemData.dataLength);
itemData.identifier = GetIdentifierFromContentType(itemData.contentType);
if (!itemData.identifier.empty())
continue;
if (itemData.contentType.starts_with(u"multipart")) {
itemData.identifier = u"body message";
} else if (itemData.contentType.starts_with(u"application")) {
LocalString<32> attachment = {};
attachment.SetFormat("attachment %u", attachmentsNr);
LocalUnicodeStringBuilder<32> sb = {};
sb.Set(attachment.GetText());
itemData.identifier = sb.ToStringView();
attachmentsNr++;
} else {
LocalString<32> mode = {};
mode.SetFormat("mode %u", modeNr);
LocalUnicodeStringBuilder<32> sb = {};
sb.Set(mode.GetText());
itemData.identifier = sb.ToStringView();
modeNr++;
}
}

return true;
}

std::u16string EMLFile::ExtractContentType(TextParser text, uint32 start, uint32 end)
{
start = text.ParseUntillText(start, "content-type", true);

if (start >= text.Len())
{
if (start >= text.Len()) {
return u"";
}

Expand All @@ -33,33 +72,21 @@ std::u16string EMLFile::ExtractContentType(TextParser text, uint32 start, uint32

bool EMLFile::BeginIteration(std::u16string_view path, AppCUI::Controls::TreeViewItem parent)
{
unicodeString.Add(obj->GetData().GetEntireFile());
TextParser text(unicodeString.ToStringView());

itemsIndex = 0;
items.clear();

ParsePart(text, 0, text.Len());

return items.size() > 0;
return true;
}

bool EMLFile::PopulateItem(AppCUI::Controls::TreeViewItem item)
{
EML_Item_Record& itemData = items[itemsIndex];
TextParser text(unicodeString.ToStringView());

if (itemData.leafNode)
{
item.SetText(0, contentType);
}
else
{
item.SetText(0, ExtractContentType(text, itemData.startIndex, itemData.startIndex + itemData.dataLength));
}

item.SetText(1, String().Format("%u", itemData.dataLength));
item.SetText(2, String().Format("%u", itemData.startIndex + itemData.parentStartIndex));
std::u16string contentTypeNode = itemData.leafNode ? contentType : ExtractContentType(text, itemData.startIndex, itemData.startIndex + itemData.dataLength);

item.SetText(0, itemData.identifier);
item.SetText(1, itemData.contentType);
item.SetText(2, String().Format("%u", itemData.dataLength));
item.SetText(3, String().Format("%u", itemData.startIndex + itemData.parentStartIndex));

item.SetData<EML_Item_Record>(&itemData);

Expand All @@ -71,39 +98,39 @@ void EMLFile::OnOpenItem(std::u16string_view path, AppCUI::Controls::TreeViewIte
{
auto itemData = item.GetData<EML_Item_Record>();

TextParser text(unicodeString.ToStringView());
auto currentContentType = ExtractContentType(text, itemData->startIndex, itemData->startIndex + itemData->dataLength);

auto bufferView = obj->GetData().GetEntireFile();
BufferView itemBufferView(bufferView.GetData() + itemData->startIndex, itemData->dataLength);

if (!itemData->leafNode)
{
GView::App::OpenBuffer(itemBufferView, obj->GetName(), path, GView::App::OpenMethod::ForceType, "eml");
}
else
{
if (!itemData->leafNode) {
GView::App::OpenBuffer(itemBufferView, currentContentType, path, GView::App::OpenMethod::ForceType, "eml");
} else {
const auto& encodingHeader =
std::find_if(headerFields.begin(), headerFields.end(), [](const auto& item) { return item.first == u"Content-Transfer-Encoding"; });
std::find_if(headerFields.begin(), headerFields.end(), [](const auto& item) { return item.first == u"Content-Transfer-Encoding"; });

if (encodingHeader != headerFields.end() && encodingHeader->second == u"base64") {
Buffer output;

if (GView::Unpack::Base64::Decode(itemBufferView, output)) {
GView::App::OpenBuffer(output, obj->GetName(), path, GView::App::OpenMethod::BestMatch);
auto bufferName = GetBufferNameFromHeaderFields();
GView::App::OpenBuffer(output, bufferName, path, GView::App::OpenMethod::BestMatch);
} else {
AppCUI::Dialogs::MessageBox::ShowError("Error!", "Malformed base64 buffer!");
}

} else {
GView::App::OpenBuffer(itemBufferView, obj->GetName(), path, GView::App::OpenMethod::BestMatch);
auto bufferName = GetBufferNameFromHeaderFields();
GView::App::OpenBuffer(itemBufferView, bufferName, path, GView::App::OpenMethod::BestMatch);
}
}
}

uint32 EMLFile::ParseHeaderFieldBody(TextParser text, uint32 start)
{
uint32 end = text.ParseUntillText(start, "\r\n", false);

while (end + 2 < text.Len())
{

while (end + 2 < text.Len()) {
auto ch = text[end + 2];
if (ch != ' ' && ch != '\t')
break;
Expand All @@ -118,8 +145,7 @@ void EMLFile::ParseHeaders(GView::View::LexicalViewer::TextParser text, uint32&
{
uint32 start = index, end = index;

while (start < text.Len())
{
while (start < text.Len()) {
if (text.GetSubString(start, start + 2) == u"\r\n") // end of headers
{
start += 2; // skip CRLF
Expand All @@ -144,8 +170,7 @@ void EMLFile::ParseHeaders(GView::View::LexicalViewer::TextParser text, uint32&
while ((pos = fieldBody.find(u"\r\n", pos)) != std::u16string::npos)
fieldBody.replace(pos, 2, u"");

if (fieldName == u"Content-Type")
{
if (fieldName == u"Content-Type") {
contentType = fieldBody;
}

Expand All @@ -158,6 +183,46 @@ void EMLFile::ParseHeaders(GView::View::LexicalViewer::TextParser text, uint32&
index = start;
}

std::optional<std::u16string> EMLFile::TryGetNameQuotes(std::u16string& contentTypeToSearch, bool removeIfFound)
{
auto name_it = contentTypeToSearch.find(u"name=");
if (name_it == std::u16string::npos)
return { std::nullopt };
if (name_it + 5 /*strlen("name=")*/ + 2 /* 2* '"' */ >= contentTypeToSearch.size())
return {};
name_it += 5; // strlen("name=")
const auto actual_name = contentTypeToSearch.substr(name_it + 1, contentTypeToSearch.size() - name_it - 2);
auto name_string = std::u16string(actual_name);
if (removeIfFound) {
contentTypeToSearch.erase(name_it - 5, 5 + 2 + actual_name.size()); // strlen("name="
if (contentTypeToSearch[contentTypeToSearch.size() - 1] == u' ')
contentTypeToSearch.erase(contentTypeToSearch.size() - 1, 1);
if (contentTypeToSearch[contentTypeToSearch.size() - 1] == u';')
contentTypeToSearch.erase(contentTypeToSearch.size() - 1, 1);
}
return name_string;
}

std::u16string EMLFile::GetIdentifierFromContentType(std::u16string& contentTypeToChange)
{
auto name_value = TryGetNameQuotes(contentTypeToChange, true);
if (name_value.has_value())
return name_value.value();

return u"";
}

std::u16string EMLFile::GetBufferNameFromHeaderFields()
{
for (auto& header : headerFields) {
auto name_value = TryGetNameQuotes(header.second);
if (name_value.has_value())
return name_value.value();
}

return std::u16string(obj->GetName());
}

void EMLFile::ParsePart(GView::View::LexicalViewer::TextParser text, uint32 start, uint32 end)
{
ParseHeaders(text, start);
Expand All @@ -169,8 +234,7 @@ void EMLFile::ParsePart(GView::View::LexicalViewer::TextParser text, uint32 star

u16string_view type = contentTypeParser.GetSubString(0, typeEnd);

if (type == u"multipart")
{
if (type == u"multipart") {
// get the boundary for the parts
std::string boundary;

Expand All @@ -179,14 +243,11 @@ void EMLFile::ParsePart(GView::View::LexicalViewer::TextParser text, uint32 star

uint32 boundaryEnd;

if (contentTypeParser[boundaryStart] == '"')
{
if (contentTypeParser[boundaryStart] == '"') {
// the boundary is enclosed in quotes
boundaryStart++;
boundaryEnd = contentTypeParser.ParseUntillText(boundaryStart, "\"", false);
}
else
{
} else {
boundaryEnd = contentTypeParser.ParseUntillText(boundaryStart, ";", false);
}

Expand All @@ -198,13 +259,11 @@ void EMLFile::ParsePart(GView::View::LexicalViewer::TextParser text, uint32 star
uint32 partStart = start;
uint32 partEnd;

do
{
do {
partStart = text.ParseUntilNextCharacterAfterText(partStart, boundary, false);
partStart = text.ParseSpace(partStart, SpaceType::All);

if (text.ParseUntillText(partStart, "--", false) == partStart)
{
if (text.ParseUntillText(partStart, "--", false) == partStart) {
// end of part
break;
}
Expand All @@ -220,8 +279,7 @@ void EMLFile::ParsePart(GView::View::LexicalViewer::TextParser text, uint32 star
return;
}

if (type == u"message")
{
if (type == u"message") {
items.emplace_back(EML_Item_Record{ .parentStartIndex = 0, .startIndex = start, .dataLength = end - start, .leafNode = false });
return;
}
Expand Down
Loading

0 comments on commit 19482e2

Please sign in to comment.