** `response`
* connection (conn)
** `eof` (end of flow)
+* file
+ ** `eof` (end of file)
* internal built-in checks which failed (weird)
** 'builtin' (internally-detected infraction is queued for further processing)
* triggered IPS rule, whether built-in or text or SO (notice)
TCP Events: s: SYN, h: SYN-ACK, a: Pure ACK or PUSH, d: Packet with payload, f: FIN, r: Reset.
+Fields supported for file:
+
+* `filename` - filename from headers in network protocols
+* `fuid` - unique file identifier
+* `source` - a protocol associated with the file
+* `inspector` - inspector associated with the file analysis
+* `mime_type` - mime attachment type (or file type identified by file magic)
+* `is_orig` - if sender was originator of the file transfer
+* `seen_bytes` - number of bytes processed for analysis
+* `total_bytes` - total file size in bytes
+* 'duration' - duration the file was analyzed for, in seconds
+* `timeout` - if file analysis timed out
+* `sha256` - SHA256 digest of the file contents
+* `extracted`- name of captured file
+* `extracted_size` - number of bytes captured
+* `extracted_cutoff` - true if the file being captured was cut off so the whole file was not logged
+
Fields supported for 'weird' and 'notice' logs:
* `sid` - unique signature number of the rule
file_type_context = nullptr;
}
-std::string FileContext::get_mime_type() const
+const char* FileContext::get_mime_type() const
{
const FileConfig* conf = get_file_config();
if (SNORT_FILE_TYPE_UNKNOWN != file_type_id and SNORT_FILE_TYPE_CONTINUE != file_type_id and conf)
{
const FileMeta* info = conf->get_rule_from_id(file_type_id);
- return info != nullptr ? info->type : std::string();
+ return info != nullptr ? info->type.c_str() : "";
}
- return std::string();
+ return "";
}
void FileContext::set_source(Flow *flow)
user_file_data_mutex.unlock();
- if (policy and log_needed)
+ if (processing_complete or log_needed)
{
hr_time now = SnortClock::now();
duration = (TO_USECS(now - start_time)) / 1000000.0; // Convert microseconds to seconds
FileCharEncoding encoding = get_character_encoding(filename.c_str(), fname_len);
FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, GET_CURRENT_PACKET,
- "File advance log: fuid-%s, source-%s, mime type-%s, file name-%s,"
- " duration-%f, is orig-%d, seen bytes-%lu, total bytes-%lu,"
+ "File advance log: fuid-%" PRIu64 ", source-%s, mime type-%s, file name-%s,"
+ " duration-%f, is orig-%d, seen bytes-%" PRIu64 ", total bytes-%" PRIu64 ","
" timedout-%d, sha256-%s, extracted name-%s, extracted cutoff-%d,"
- " extracted size-%lu\n", file_event.get_fuid().c_str(),
- file_event.get_source().c_str(), file_event.get_mime_type().c_str(),
+ " extracted size-%" PRIu64 "\n", file_event.get_fuid(),
+ file_event.get_source().c_str(), file_event.get_mime_type(),
(encoding == SNORT_CHAR_ENCODING_UTF_16LE) ? "" : filename.c_str(), file_event.get_duration(),
file_event.get_is_orig(), file_event.get_seen_bytes(),
file_event.get_total_bytes(), file_event.get_timedout(),
{
processed_bytes += data_size;
- FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL,
- GET_CURRENT_PACKET,
- "Updating file size of file_id %lu at position %d with processed_bytes %lu\n",
+ FILE_DEBUG(file_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL, GET_CURRENT_PACKET,
+ "Updating file size of file_id %" PRIu64 " at position %d with processed_bytes %" PRIu64 "\n",
file_id, position, processed_bytes);
if ((position == SNORT_FILE_END)or (position == SNORT_FILE_FULL))
{
bool re_eval = false;
// Indicates that file transmission goes through 206 HTTP Partial Content
bool is_partial = false;
- bool extracted_cutoff = true;
+ bool extracted_cutoff = false;
uint64_t extracted_size = 0;
std::string extracted_file_name;
};
FileInspect* get_inspector() { return inspector; }
double get_duration() const { return duration; } // Duration in seconds (fractional)
void set_duration(double d) { duration = d; }
- std::string get_mime_type() const;
+ const char* get_mime_type() const;
const std::string& get_source() const { return source; }
void set_source(Flow *flow);
bool get_timedout() const { return timedout; }
extractor_detection.h
extractor_dns.cc
extractor_enums.h
+ extractor_file.cc
+ extractor_file.h
extractor_flow_data.cc
extractor_flow_data.h
extractor_ftp.cc
static const Parameter extractor_proto_params[] =
{
- { "service", Parameter::PT_ENUM, "http | ftp | ssl | conn | dns | quic | weird | notice", nullptr,
+ { "service", Parameter::PT_ENUM, "http | ftp | ssl | conn | dns | quic | file | weird | notice", nullptr,
"service to extract from" },
{ "tenant_id", Parameter::PT_INT, "0:max32", "0",
{
if (f->session == nullptr)
return 0;
-
+
if (f->pkt_type == PktType::TCP)
return get_resp_bytes_tcp((const TcpSession*)f->session);
else if (f->pkt_type == PktType::UDP)
record.append(to_string(v));
}
+void CsvExtractorLogger::add_field(const char*, double v)
+{
+ const unsigned precision = 6;
+
+ // 20 digits for integer part + '.' + precision digits + '\0'
+ char buf[20 + 1 + precision + 1];
+ snort::SnortSnprintf(buf, sizeof(buf), "%.*f", (int)precision, v);
+
+ record.push_back(delimiter);
+ record.append(buf);
+}
+
void CsvExtractorLogger::add_field(const char*, const snort::SfIp& v)
{
record.push_back(delimiter);
void add_field(const char*, const char*) override;
void add_field(const char*, const char*, size_t) override;
void add_field(const char*, uint64_t) override;
+ void add_field(const char*, double) override;
void add_field(const char*, struct timeval) override;
void add_field(const char*, const snort::SfIp&) override;
void add_field(const char*, bool) override;
CONN,
DNS,
QUIC,
+ FILE,
IPS_BUILTIN,
IPS_USER,
ANY,
return "dns";
case QUIC:
return "quic";
+ case FILE:
+ return "file";
case IPS_BUILTIN:
return "weird";
case IPS_USER:
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2026-2026 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// 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, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// extractor_file.cc author Anna Norokh <anorokh@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "extractor_file.h"
+
+#include "pub_sub/file_events.h"
+#include "pub_sub/file_events_ids.h"
+
+#include "extractor.h"
+#include "extractor_enums.h"
+
+using namespace snort;
+using namespace std;
+
+
+static uint64_t get_seen_bytes(const DataEvent* event, const Flow*)
+{
+ return ((const FileEvent*)event)->get_seen_bytes();
+}
+
+static uint64_t get_total_bytes(const DataEvent* event, const Flow*)
+{
+ return ((const FileEvent*)event)->get_total_bytes();
+}
+
+static uint64_t get_extracted_size(const DataEvent* event, const Flow*)
+{
+ return ((const FileEvent*)event)->get_extracted_size();
+}
+
+static double get_duration(const DataEvent* event, const Flow*)
+{
+ return ((const FileEvent*)event)->get_duration();
+}
+
+static bool get_timedout(const DataEvent* event, const Flow*)
+{
+ return ((const FileEvent*)event)->get_timedout();
+}
+
+static bool get_is_orig(const DataEvent* event, const Flow*)
+{
+ return ((const FileEvent*)event)->get_is_orig();
+}
+
+static bool get_is_extracted_cutoff(const DataEvent* event, const Flow*)
+{
+ return ((const FileEvent*)event)->get_extracted_cutoff();
+}
+
+static const char* get_extracted_name(const DataEvent* event, const Flow*)
+{
+ return ((const FileEvent*)event)->get_extracted_name().c_str();
+}
+
+static uint64_t get_fuid(const DataEvent* event, const Flow*)
+{
+ return ((const FileEvent*)event)->get_fuid();
+}
+
+static const char* get_analyzer(const DataEvent*, const Flow* flow)
+{
+ if (flow->gadget)
+ return flow->gadget->get_name();
+
+ return "";
+}
+
+static const char* get_source(const DataEvent* event, const Flow*)
+{
+ return ((const FileEvent*)event)->get_source().c_str();
+}
+
+static const char* get_mime_type(const DataEvent* event, const Flow*)
+{
+ return ((const FileEvent*)event)->get_mime_type();
+}
+
+static const char* get_filename(const DataEvent* event, const Flow*)
+{
+ return ((const FileEvent*)event)->get_filename().c_str();
+}
+
+static const char* get_sha256(const DataEvent* event, const Flow*)
+{
+ return ((const FileEvent*)event)->get_sha256().c_str();
+}
+
+static const map<string, ExtractorEvent::NumGetFn> sub_num_getters =
+{
+ {"fuid", get_fuid},
+ {"seen_bytes", get_seen_bytes},
+ {"total_bytes", get_total_bytes},
+ {"extracted_size", get_extracted_size},
+};
+
+static const map<string, ExtractorEvent::BufGetFn> sub_buf_getters =
+{
+ {"analyzers", get_analyzer},
+ {"source", get_source},
+ {"filename", get_filename},
+ {"mime_type", get_mime_type},
+ {"extracted", get_extracted_name},
+ {"sha256", get_sha256},
+};
+
+static const map<string, ExtractorEvent::DblGetFn> sub_dbl_getters =
+{
+ {"duration", get_duration},
+};
+
+static const map<string, FileExtractor::SubGetFn> sub_getters =
+{
+ {"timedout", get_timedout},
+ {"is_orig", get_is_orig},
+ {"extracted_cutoff", get_is_extracted_cutoff},
+};
+
+THREAD_LOCAL const snort::Connector::ID* FileExtractor::log_id = nullptr;
+
+FileExtractor::FileExtractor(Extractor& i, uint32_t t, const vector<string>& fields)
+ : ExtractorEvent(ServiceType::FILE, i, t)
+{
+ for (const auto& f : fields)
+ {
+ if (append(nts_fields, nts_getters, f))
+ continue;
+ if (append(sip_fields, sip_getters, f))
+ continue;
+ if (append(num_fields, num_getters, f))
+ continue;
+ if (append(num_fields, sub_num_getters, f))
+ continue;
+ if (append(buf_fields, sub_buf_getters, f))
+ continue;
+ if (append(dbl_fields, sub_dbl_getters, f))
+ continue;
+ if (append(sub_fields, sub_getters, f))
+ continue;
+ }
+
+ DataBus::subscribe_global(file_adv_pub_key, FileEventIds::FILE_COMPLETE,
+ new Eof(*this, S_NAME), i.get_snort_config());
+}
+
+void FileExtractor::internal_tinit(const snort::Connector::ID* service_id)
+{ log_id = service_id; }
+
+void FileExtractor::handle(DataEvent& event, Flow* flow)
+{
+ // cppcheck-suppress unreadVariable
+ Profile profile(extractor_perf_stats);
+
+ if (!filter(flow))
+ return;
+
+ extractor_stats.total_events++;
+
+ logger->open_record();
+ log(nts_fields, &event, flow);
+ log(sip_fields, &event, flow);
+ log(num_fields, &event, flow);
+ log(sub_fields, &event, flow);
+ log(buf_fields, &event, flow);
+ log(dbl_fields, &event, flow);
+ logger->close_record(*log_id);
+}
+
+vector<const char*> FileExtractor::get_field_names() const
+{
+ vector<const char*> res = ExtractorEvent::get_field_names();
+
+ for (auto& f : sub_fields)
+ res.push_back(f.name);
+
+ return res;
+}
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2026-2026 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// 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, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// extractor_file.h author Anna Norokh <anorokh@cisco.com>
+
+#ifndef EXTRACTOR_FILE_H
+#define EXTRACTOR_FILE_H
+
+#include "extractors.h"
+
+class FileExtractor : public ExtractorEvent
+{
+public:
+ using SubGetFn = bool (*) (const DataEvent*, const Flow*);
+ using SubField = DataField<bool, const DataEvent*, const Flow*>;
+
+ FileExtractor(Extractor&, uint32_t tenant, const std::vector<std::string>& fields);
+
+ void handle(DataEvent&, Flow*);
+ std::vector<const char*> get_field_names() const override;
+
+private:
+ using Eof = Handler<FileExtractor>;
+
+ void internal_tinit(const snort::Connector::ID*) override;
+
+ std::vector<SubField> sub_fields;
+ static THREAD_LOCAL const snort::Connector::ID* log_id;
+};
+
+#endif
out_buffer += std::to_string(v);
}
+void JsonExtractorLogger::add_field(const char* f, double v)
+{
+ const unsigned precision = 6;
+
+ // 20 digits for integer part + '.' + precision digits + '\0'
+ char buf[20 + 1 + precision + 1];
+ std::snprintf(buf, sizeof(buf), "%.*f", (int)precision, v);
+
+ write_key(f);
+ out_buffer += buf;
+}
+
void JsonExtractorLogger::add_field(const char* f, const snort::SfIp& v)
{
snort::SfIpString buf;
void add_field(const char*, const char*) override;
void add_field(const char*, const char*, size_t) override;
void add_field(const char*, uint64_t) override;
+ void add_field(const char*, double) override;
void add_field(const char*, struct timeval) override;
void add_field(const char*, const snort::SfIp&) override;
void add_field(const char*, bool) override;
virtual void add_field(const char*, const char*) {}
virtual void add_field(const char*, const char*, size_t) {}
virtual void add_field(const char*, uint64_t) {}
+ virtual void add_field(const char*, double) {}
virtual void add_field(const char*, struct timeval) {}
virtual void add_field(const char*, const snort::SfIp&) {}
virtual void add_field(const char*, bool) {}
QuicExtractorFlowData(QuicExtractor& owner)
: ExtractorFlowData(type_id), owner(owner) { }
-
+
~QuicExtractorFlowData() override
{
if (has_data)
logger->add_field(f.name, (uint64_t)0);
log(fd_str_fields, &fd, logger->is_strict());
-
+
logger->close_record(*log_id);
}
#include "extractor_conn.h"
#include "extractor_detection.h"
#include "extractor_dns.h"
+#include "extractor_file.h"
#include "extractor_ftp.h"
#include "extractor_http.h"
#include "extractor_quic.h"
srv = new QuicExtractorService(cfg.tenant_id, cfg.fields, cfg.on_events, cfg.service, ins);
break;
+ case ServiceType::FILE:
+ srv = new FileExtractorService(cfg.tenant_id, cfg.fields, cfg.on_events, cfg.service, ins);
+ break;
+
case ServiceType::IPS_BUILTIN:
srv = new BuiltinExtractorService(cfg.tenant_id, cfg.fields, cfg.on_events, cfg.service, ins);
break;
validate_fields(QuicExtractorService::blueprint, cfg.fields);
break;
+ case ServiceType::FILE:
+ validate_events(FileExtractorService::blueprint, cfg.on_events);
+ validate_fields(FileExtractorService::blueprint, cfg.fields);
+ break;
+
case ServiceType::IPS_BUILTIN:
validate_fields(BuiltinExtractorService::blueprint, cfg.fields);
validate_events(BuiltinExtractorService::blueprint, cfg.on_events);
const snort::Connector::ID& QuicExtractorService::get_log_id()
{ return log_id; }
+//-------------------------------------------------------------------------
+// FileExtractorService
+//-------------------------------------------------------------------------
+
+const ServiceBlueprint FileExtractorService::blueprint =
+{
+ // events
+ {
+ "eof",
+ },
+ // fields
+ {
+ "fuid",
+ "source",
+ "analyzers",
+ "mime_type",
+ "filename",
+ "is_orig",
+ "seen_bytes",
+ "total_bytes",
+ "duration",
+ "timedout",
+ "extracted",
+ "extracted_cutoff",
+ "extracted_size",
+ "sha256"
+ },
+};
+
+THREAD_LOCAL Connector::ID FileExtractorService::log_id;
+
+FileExtractorService::FileExtractorService(uint32_t tenant, const std::vector<std::string>& srv_fields,
+ const std::vector<std::string>& srv_events, ServiceType s_type, Extractor& ins)
+ : ExtractorService(tenant, srv_fields, srv_events, blueprint, s_type, ins)
+{
+ for (const auto& event : get_events())
+ {
+ if (!strcmp("eof", event.c_str()))
+ handlers.push_back(new FileExtractor(ins, tenant_id, get_fields()));
+ }
+}
+
+const snort::Connector::ID& FileExtractorService::internal_tinit()
+{ return log_id = logger->get_id(type.c_str()); }
+
+const snort::Connector::ID& FileExtractorService::get_log_id()
+{ return log_id; }
+
//-------------------------------------------------------------------------
// IpsUserExtractorService
//-------------------------------------------------------------------------
ServiceType conn = ServiceType::CONN;
ServiceType dns = ServiceType::DNS;
ServiceType quic = ServiceType::QUIC;
+ ServiceType file = ServiceType::FILE;
ServiceType weird = ServiceType::IPS_BUILTIN;
ServiceType notice = ServiceType::IPS_USER;
ServiceType any = ServiceType::ANY;
CHECK_FALSE(strcmp("ftp", ftp.c_str()));
CHECK_FALSE(strcmp("ssl", ssl.c_str()));
CHECK_FALSE(strcmp("conn", conn.c_str()));
+ CHECK_FALSE(strcmp("file", file.c_str()));
CHECK_FALSE(strcmp("dns", dns.c_str()));
CHECK_FALSE(strcmp("quic", quic.c_str()));
CHECK_FALSE(strcmp("weird", weird.c_str()));
static THREAD_LOCAL snort::Connector::ID log_id;
};
+class FileExtractorService : public ExtractorService
+{
+public:
+ static const ServiceBlueprint blueprint;
+
+ FileExtractorService(uint32_t tenant, const std::vector<std::string>& fields,
+ const std::vector<std::string>& events, ServiceType, Extractor&);
+
+private:
+ const snort::Connector::ID& internal_tinit() override;
+ const snort::Connector::ID& get_log_id() override;
+
+ static THREAD_LOCAL snort::Connector::ID log_id;
+};
+
class BuiltinExtractorService : public ExtractorService
{
public:
for (auto& f : str_fields)
res.push_back(f.name);
+ for (auto& f : dbl_fields)
+ res.push_back(f.name);
+
return res;
}
using SipField = DataField<const SfIp&, const DataEvent*, const Flow*>;
using NumGetFn = uint64_t (*) (const DataEvent*, const Flow*);
using NumField = DataField<uint64_t, const DataEvent*, const Flow*>;
+ using DblGetFn = double (*) (const DataEvent*, const Flow*);
+ using DblField = DataField<double, const DataEvent*, const Flow*>;
using NtsGetFn = struct timeval (*) (const DataEvent*, const Flow*);
using NtsField = DataField<struct timeval, const DataEvent*, const Flow*>;
using StrGetFn = std::pair<const char*, uint16_t> (*) (const DataEvent*, const Flow*);
std::vector<NtsField> nts_fields;
std::vector<SipField> sip_fields;
std::vector<NumField> num_fields;
+ std::vector<DblField> dbl_fields;
std::vector<BufField> buf_fields;
std::vector<StrField> str_fields;
#include "file_events.h"
+#include <optional>
+
+#include "file_api/file_lib.h"
+#include "utils/util.h"
+
using namespace snort;
-std::string FileEvent::get_fuid() const
-{ return std::to_string(file_ctx.get_file_id()); }
+uint64_t FileEvent::get_fuid() const
+{ return file_ctx.get_file_id(); }
const std::string& FileEvent::get_source() const
{ return file_ctx.get_source(); }
-const std::string FileEvent::get_mime_type() const
-{ return file_ctx.get_mime_type(); }
+const char* FileEvent::get_mime_type() const
+{
+ return file_ctx.get_mime_type();
+}
const std::string& FileEvent::get_filename() const
-{ return file_ctx.get_file_name(); }
+{
+ if (!filename.has_value())
+ {
+ size_t fname_len = file_ctx.get_file_name().length();
+ filename = std::string();
+
+ if (fname_len)
+ {
+ char* outbuf = const_cast<FileContext&>(file_ctx).get_UTF8_fname(&fname_len);
+ const char* fname = (outbuf != nullptr) ? outbuf : file_ctx.get_file_name().c_str();
+
+ size_t pos = 0;
+ while (pos < fname_len)
+ {
+ if (isprint((int)fname[pos]))
+ {
+ (*filename) += fname[pos++];
+ }
+ else
+ {
+ (*filename) += '|';
+ bool add_space = false;
+ while ((pos < fname_len) && !isprint((int)fname[pos]))
+ {
+ if (add_space)
+ (*filename) += ' ';
+ else
+ add_space = true;
+
+ int ch = 0xff & fname[pos];
+ char buf[3];
+ snprintf(buf, sizeof(buf), "%02X", ch);
+ (*filename) += buf;
+ pos++;
+ }
+ (*filename) += '|';
+ }
+ }
+
+ snort_free(outbuf);
+ }
+ }
+
+ return *filename;
+}
double FileEvent::get_duration() const
{ return file_ctx.get_duration(); }
bool FileEvent::get_timedout() const
{ return file_ctx.get_timedout(); }
-const std::string FileEvent::get_sha256() const
-{ return (file_ctx.get_file_sig_sha256() ? file_ctx.sha_to_string(file_ctx.get_file_sig_sha256()) : std::string()); }
+const std::string& FileEvent::get_sha256() const
+{
+ if (!sha256.has_value())
+ sha256 = file_ctx.get_file_sig_sha256() ?
+ file_ctx.sha_to_string(file_ctx.get_file_sig_sha256()) : std::string();
+
+ return *sha256;
+}
-const std::string FileEvent::get_extracted_name() const
+const std::string& FileEvent::get_extracted_name() const
{ return file_ctx.get_extracted_name(); }
bool FileEvent::get_extracted_cutoff() const
#ifndef FILE_EVENTS_H
#define FILE_EVENTS_H
+#include <optional>
+
#include "file_api/file_cache.h"
#include "file_events_ids.h"
#include "framework/mp_data_bus.h"
public:
FileEvent(const FileContext& data) : file_ctx(data) { }
- std::string get_fuid() const;
+ uint64_t get_fuid() const;
const std::string& get_source() const;
- const std::string get_mime_type() const;
+ const char* get_mime_type() const;
const std::string& get_filename() const;
double get_duration() const; // Returns duration in seconds (fractional)
bool get_is_orig() const;
uint64_t get_seen_bytes() const;
uint64_t get_total_bytes() const;
bool get_timedout() const;
- const std::string get_sha256() const;
- const std::string get_extracted_name() const;
+ const std::string& get_sha256() const;
+ const std::string& get_extracted_name() const;
bool get_extracted_cutoff() const;
uint64_t get_extracted_size() const;
private:
const FileContext& file_ctx;
+ mutable std::optional<std::string> sha256;
+ mutable std::optional<std::string> filename;
};
}
const std::string& FileInfo::get_file_name() const { return file_name; }
-std::string FileContext::get_mime_type() const { return std::string(); }
+const char* FileContext::get_mime_type() const { return ""; }
+
+char* FileContext::get_UTF8_fname(size_t*) { return nullptr; }
FileDirection FileInfo::get_file_direction() const { return direction; }
FileEvent event(file_ctx);
- CHECK(event.get_fuid() == std::to_string(fuid));
+ CHECK(event.get_fuid() == fuid);
CHECK(event.get_source() == std::string());
CHECK(event.get_mime_type() == std::string());
CHECK(event.get_filename() == std::string(filename));
CHECK(event.get_timedout() == false);
CHECK(event.get_sha256() == std::string());
CHECK(event.get_extracted_name() == std::string());
- CHECK(event.get_extracted_cutoff() == true);
+ CHECK(event.get_extracted_cutoff() == false);
CHECK(event.get_extracted_size() == 0);
}