From c9524757d215e8e5de48bc138331aa7b4876ceda Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 21 Jul 2014 16:31:22 +0200 Subject: [PATCH] Adding Files::register_for_mime_type() to associate a file analyzer with a MIME type. Whenever that MIME is detected, Bro will now automatically activate the analyzer. The interface mimics how well-known ports are defined for protocol analyzers. This isn't actually used by any existing file analyzer (because we don't have any yet that target a specific file format), but there's a test making sure it works. --- scripts/base/frameworks/files/main.bro | 74 ++ src/BroDoc.cc | 671 ------------------ src/Func.cc | 2 +- src/Func.h | 2 +- src/analyzer/Component.cc | 2 +- src/file_analysis/Component.cc | 2 +- src/file_analysis/file_analysis.bif | 7 + .../files.log | 10 + .../file-analysis/bifs/register_mime_type.bro | 9 + 9 files changed, 104 insertions(+), 675 deletions(-) delete mode 100644 src/BroDoc.cc create mode 100644 testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.register_mime_type/files.log create mode 100644 testing/btest/scripts/base/frameworks/file-analysis/bifs/register_mime_type.bro diff --git a/scripts/base/frameworks/files/main.bro b/scripts/base/frameworks/files/main.bro index d522f8ba42..2aef1d424f 100644 --- a/scripts/base/frameworks/files/main.bro +++ b/scripts/base/frameworks/files/main.bro @@ -234,6 +234,42 @@ export { ## callback: Function to execute when the given file analyzer is being added. global register_analyzer_add_callback: function(tag: Files::Tag, callback: function(f: fa_file, args: AnalyzerArgs)); + ## Registers a set of MIME types for an analyzer. If a future connection on one of + ## these types is seen, the analyzer will be automatically assigned to parsing it. + ## The function *adds* to all MIME types already registered, it doesn't replace + ## them. + ## + ## tag: The tag of the analyzer. + ## + ## mts: The set of MIME types, each in the form "foo/bar" (case-insensitive). + ## + ## Returns: True if the MIME types were successfully registered. + global register_for_mime_types: function(tag: Analyzer::Tag, mts: set[string]) : bool; + + ## Registers a MIME type for an analyzer. If a future file with this type is seen, + ## the analyzer will be automatically assigned to parsing it. The function *adds* + ## to all MIME types already registered, it doesn't replace them. + ## + ## tag: The tag of the analyzer. + ## + ## mt: The MIME type in the form "foo/bar" (case-insensitive). + ## + ## Returns: True if the MIME type was successfully registered. + global register_for_mime_type: function(tag: Analyzer::Tag, mt: string) : bool; + + ## Returns a set of all MIME types currently registered for a specific analyzer. + ## + ## tag: The tag of the analyzer. + ## + ## Returns: The set of MIME types. + global registered_mime_types: function(tag: Analyzer::Tag) : set[string]; + + ## Returns a table of all MIME-type-to-analyzer mappings currently registered. + ## + ## Returns: A table mapping each analyzer to the set of MIME types registered for + ## it. + global all_registered_mime_types: function() : table[Analyzer::Tag] of set[string]; + ## Event that can be handled to access the Info record as it is sent on ## to the logging framework. global log_files: event(rec: Info); @@ -246,6 +282,9 @@ redef record fa_file += { # Store the callbacks for protocol analyzers that have files. global registered_protocols: table[Analyzer::Tag] of ProtoRegistration = table(); +# Store the MIME type to analyzer mappings. +global mime_types: table[Analyzer::Tag] of set[string]; + global analyzer_add_callbacks: table[Files::Tag] of function(f: fa_file, args: AnalyzerArgs) = table(); event bro_init() &priority=5 @@ -370,6 +409,41 @@ function register_protocol(tag: Analyzer::Tag, reg: ProtoRegistration): bool return result; } +function register_for_mime_types(tag: Analyzer::Tag, mime_types: set[string]) : bool + { + local rc = T; + + for ( mt in mime_types ) + { + if ( ! register_for_mime_type(tag, mt) ) + rc = F; + } + + return rc; + } + +function register_for_mime_type(tag: Analyzer::Tag, mt: string) : bool + { + if ( ! __register_for_mime_type(tag, mt) ) + return F; + + if ( tag !in mime_types ) + mime_types[tag] = set(); + + add mime_types[tag][mt]; + return T; + } + +function registered_mime_types(tag: Analyzer::Tag) : set[string] + { + return tag in mime_types ? mime_types[tag] : set(); + } + +function all_registered_mime_types(): table[Analyzer::Tag] of set[string] + { + return mime_types; + } + function describe(f: fa_file): string { local tag = Analyzer::get_tag(f$source); diff --git a/src/BroDoc.cc b/src/BroDoc.cc deleted file mode 100644 index 03c29d2201..0000000000 --- a/src/BroDoc.cc +++ /dev/null @@ -1,671 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "BroDoc.h" -#include "BroDocObj.h" -#include "util.h" -#include "plugin/Manager.h" -#include "analyzer/Manager.h" -#include "analyzer/Component.h" -#include "file_analysis/Manager.h" - -BroDoc::BroDoc(const std::string& rel, const std::string& abs) - { - size_t f_pos = abs.find_last_of('/'); - - if ( std::string::npos == f_pos ) - source_filename = abs; - else - source_filename = abs.substr(f_pos + 1); - - if ( rel[0] == '/' || rel[0] == '.' ) - { - // The Bro script isn't being loaded via BROPATH, so just use basename - // as the document title. - doc_title = source_filename; - } - else - { - // Keep the relative directory as part of the document title. - if ( rel.size() == 0 || rel[rel.size() - 1] == '/' ) - doc_title = rel + source_filename; - else - doc_title = rel + "/" + source_filename; - } - - downloadable_filename = source_filename; - -#if 0 - size_t ext_pos = downloadable_filename.find(".bif.bro"); - if ( std::string::npos != ext_pos ) - downloadable_filename.erase(ext_pos + 4); -#endif - - reST_filename = doc_title; - size_t ext_pos = reST_filename.find(".bro"); - - if ( std::string::npos == ext_pos ) - reST_filename += ".rst"; - else - reST_filename.replace(ext_pos, 4, ".rst"); - - reST_filename = doc_title.substr(0, ext_pos); - reST_filename += ".rst"; - - // Instead of re-creating the directory hierarchy based on related - // loads, just replace the directory separatories such that the reST - // output will all be placed in a flat directory (the working dir). - std::for_each(reST_filename.begin(), reST_filename.end(), replace_slash()); - - reST_file = fopen(reST_filename.c_str(), "w"); - - if ( ! reST_file ) - fprintf(stderr, "Failed to open %s\n", reST_filename.c_str()); - -#ifdef DOCDEBUG - fprintf(stdout, "Documenting absolute source: %s\n", abs.c_str()); - fprintf(stdout, "\trelative dir: %s\n", rel.c_str()); - fprintf(stdout, "\tdoc title: %s\n", doc_title.c_str()); - fprintf(stdout, "\tbro file: %s\n", source_filename.c_str()); - fprintf(stdout, "\trst file: %s\n", reST_filename.c_str()); -#endif - } - -BroDoc::~BroDoc() - { - if ( reST_file && fclose( reST_file ) ) - fprintf(stderr, "Failed to close %s\n", reST_filename.c_str()); - - FreeBroDocObjPtrList(all); - } - -void BroDoc::AddImport(const std::string& s) - { - std::string lname(s); - // First strip any .bro extension. - size_t ext_pos = lname.find(".bro"); - if ( ext_pos != std::string::npos ) - lname = lname.substr(0, ext_pos); - - const char* full_filename = NULL; - const char* subpath = NULL; - - FILE* f = search_for_file(lname.c_str(), "bro", &full_filename, true, - &subpath); - - if ( f && full_filename && subpath ) - { - char* tmp = copy_string(full_filename); - char* filename = basename(tmp); - extern char* PACKAGE_LOADER; - - if ( streq(filename, PACKAGE_LOADER) ) - { - // link to the package's index - string pkg(subpath); - pkg += "/index"; - imports.push_back(pkg); - } - else - { - if ( subpath[0] == '/' || subpath[0] == '.' ) - { - // it's not a subpath of scripts/, so just add the name of it - // as it's given in the @load directive - imports.push_back(lname); - } - else - { - // combine the base file name of script in the @load directive - // with the subpath of BROPATH's scripts/ directory - string fname(subpath); - char* othertmp = copy_string(lname.c_str()); - fname.append("/").append(basename(othertmp)); - imports.push_back(fname); - delete [] othertmp; - } - } - - delete [] tmp; - } - - else - fprintf(stderr, "Failed to document '@load %s' in file: %s\n", - s.c_str(), reST_filename.c_str()); - - if ( f ) - fclose(f); - - delete [] full_filename; - delete [] subpath; - } - -void BroDoc::SetPacketFilter(const std::string& s) - { - packet_filter = s; - size_t pos1 = s.find("{\n"); - size_t pos2 = s.find("}"); - - if ( pos1 != std::string::npos && pos2 != std::string::npos ) - packet_filter = s.substr(pos1 + 2, pos2 - 2); - - bool has_non_whitespace = false; - - for ( std::string::const_iterator it = packet_filter.begin(); - it != packet_filter.end(); ++it ) - { - if ( *it != ' ' && *it != '\t' && *it != '\n' && *it != '\r' ) - { - has_non_whitespace = true; - break; - } - } - - if ( ! has_non_whitespace ) - packet_filter.clear(); - } - -void BroDoc::WriteDocFile() const - { - WriteToDoc(reST_file, ".. Automatically generated. Do not edit.\n\n"); - - WriteToDoc(reST_file, ":tocdepth: 3\n\n"); - - WriteSectionHeading(reST_file, doc_title.c_str(), '='); - - WriteStringList(reST_file, ".. bro:namespace:: %s\n", modules); - - WriteToDoc(reST_file, "\n"); - - // WriteSectionHeading(reST_file, "Overview", '-'); - WriteStringList(reST_file, "%s\n", summary); - - WriteToDoc(reST_file, "\n"); - - if ( ! modules.empty() ) - { - WriteToDoc(reST_file, ":Namespace%s: ", (modules.size() > 1 ? "s" : "")); - // WriteStringList(reST_file, ":bro:namespace:`%s`", modules); - WriteStringList(reST_file, "``%s``, ", "``%s``", modules); - WriteToDoc(reST_file, "\n"); - } - - if ( ! imports.empty() ) - { - WriteToDoc(reST_file, ":Imports: "); - std::list::const_iterator it; - for ( it = imports.begin(); it != imports.end(); ++it ) - { - if ( it != imports.begin() ) - WriteToDoc(reST_file, ", "); - - string pretty(*it); - size_t pos = pretty.find("/index"); - if ( pos != std::string::npos && pos + 6 == pretty.size() ) - pretty = pretty.substr(0, pos); - WriteToDoc(reST_file, ":doc:`%s `", pretty.c_str(), it->c_str()); - } - WriteToDoc(reST_file, "\n"); - } - - WriteToDoc(reST_file, ":Source File: :download:`%s`\n", - downloadable_filename.c_str()); - - WriteToDoc(reST_file, "\n"); - - WriteInterface("Summary", '~', '#', true, true); - - if ( ! notices.empty() ) - WriteBroDocObjList(reST_file, notices, "Notices", '#'); - - if ( port_analysis.size() || packet_filter.size() ) - WriteSectionHeading(reST_file, "Configuration Changes", '#'); - - if ( ! port_analysis.empty() ) - { - WriteSectionHeading(reST_file, "Port Analysis", '^'); - WriteToDoc(reST_file, "Loading this script makes the following changes to " - ":bro:see:`dpd_config`.\n\n"); - WriteStringList(reST_file, "%s, ", "%s", port_analysis); - } - - if ( ! packet_filter.empty() ) - { - WriteSectionHeading(reST_file, "Packet Filter", '^'); - WriteToDoc(reST_file, "Loading this script makes the following changes to " - ":bro:see:`capture_filters`.\n\n"); - WriteToDoc(reST_file, "Filters added::\n\n"); - WriteToDoc(reST_file, "%s\n", packet_filter.c_str()); - } - - WriteInterface("Detailed Interface", '~', '#', true, false); - -#if 0 // Disabled for now. - BroDocObjList::const_iterator it; - bool hasPrivateIdentifiers = false; - - for ( it = all.begin(); it != all.end(); ++it ) - { - if ( ! IsPublicAPI(*it) ) - { - hasPrivateIdentifiers = true; - break; - } - } - - if ( hasPrivateIdentifiers ) - WriteInterface("Private Interface", '~', '#', false, false); -#endif - } - -void BroDoc::WriteInterface(const char* heading, char underline, - char sub, bool isPublic, bool isShort) const - { - WriteSectionHeading(reST_file, heading, underline); - WriteBroDocObjList(reST_file, options, isPublic, "Options", sub, isShort); - WriteBroDocObjList(reST_file, constants, isPublic, "Constants", sub, isShort); - WriteBroDocObjList(reST_file, state_vars, isPublic, "State Variables", sub, isShort); - WriteBroDocObjList(reST_file, types, isPublic, "Types", sub, isShort); - WriteBroDocObjList(reST_file, events, isPublic, "Events", sub, isShort); - WriteBroDocObjList(reST_file, hooks, isPublic, "Hooks", sub, isShort); - WriteBroDocObjList(reST_file, functions, isPublic, "Functions", sub, isShort); - WriteBroDocObjList(reST_file, redefs, isPublic, "Redefinitions", sub, isShort); - } - -void BroDoc::WriteStringList(FILE* f, const char* format, const char* last_format, - const std::list& l) - { - if ( l.empty() ) - { - WriteToDoc(f, "\n"); - return; - } - - std::list::const_iterator it; - std::list::const_iterator last = l.end(); - last--; - - for ( it = l.begin(); it != last; ++it ) - WriteToDoc(f, format, it->c_str()); - - WriteToDoc(f, last_format, last->c_str()); - } - -void BroDoc::WriteBroDocObjTable(FILE* f, const BroDocObjList& l) - { - int max_id_col = 0; - int max_com_col = 0; - BroDocObjList::const_iterator it; - - for ( it = l.begin(); it != l.end(); ++it ) - { - int c = (*it)->ColumnSize(); - - if ( c > max_id_col ) - max_id_col = c; - - c = (*it)->LongestShortDescLen(); - - if ( c > max_com_col ) - max_com_col = c; - } - - // Start table. - WriteRepeatedChar(f, '=', max_id_col); - WriteToDoc(f, " "); - - if ( max_com_col == 0 ) - WriteToDoc(f, "="); - else - WriteRepeatedChar(f, '=', max_com_col); - - WriteToDoc(f, "\n"); - - for ( it = l.begin(); it != l.end(); ++it ) - { - if ( it != l.begin() ) - WriteToDoc(f, "\n\n"); - (*it)->WriteReSTCompact(f, max_id_col); - } - - // End table. - WriteToDoc(f, "\n"); - WriteRepeatedChar(f, '=', max_id_col); - WriteToDoc(f, " "); - - if ( max_com_col == 0 ) - WriteToDoc(f, "="); - else - WriteRepeatedChar(f, '=', max_com_col); - - WriteToDoc(f, "\n\n"); - } - -void BroDoc::WriteBroDocObjList(FILE* f, const BroDocObjList& l, bool wantPublic, - const char* heading, char underline, bool isShort) - { - if ( l.empty() ) - return; - - BroDocObjList::const_iterator it; - bool (*f_ptr)(const BroDocObj* o) = 0; - - if ( wantPublic ) - f_ptr = IsPublicAPI; - else - f_ptr = IsPrivateAPI; - - it = std::find_if(l.begin(), l.end(), f_ptr); - - if ( it == l.end() ) - return; - - WriteSectionHeading(f, heading, underline); - - BroDocObjList filtered_list; - - while ( it != l.end() ) - { - filtered_list.push_back(*it); - it = find_if(++it, l.end(), f_ptr); - } - - if ( isShort ) - WriteBroDocObjTable(f, filtered_list); - else - WriteBroDocObjList(f, filtered_list); - } - -void BroDoc::WriteBroDocObjList(FILE* f, const BroDocObjMap& m, bool wantPublic, - const char* heading, char underline, bool isShort) - { - BroDocObjMap::const_iterator it; - BroDocObjList l; - - for ( it = m.begin(); it != m.end(); ++it ) - l.push_back(it->second); - - WriteBroDocObjList(f, l, wantPublic, heading, underline, isShort); - } - -void BroDoc::WriteBroDocObjList(FILE* f, const BroDocObjList& l, const char* heading, - char underline) - { - WriteSectionHeading(f, heading, underline); - WriteBroDocObjList(f, l); - } - -void BroDoc::WriteBroDocObjList(FILE* f, const BroDocObjList& l) - { - for ( BroDocObjList::const_iterator it = l.begin(); it != l.end(); ++it ) - (*it)->WriteReST(f); - } - -void BroDoc::WriteBroDocObjList(FILE* f, const BroDocObjMap& m, const char* heading, - char underline) - { - BroDocObjMap::const_iterator it; - BroDocObjList l; - - for ( it = m.begin(); it != m.end(); ++it ) - l.push_back(it->second); - - WriteBroDocObjList(f, l, heading, underline); - } - -void BroDoc::WriteToDoc(FILE* f, const char* format, ...) - { - va_list argp; - va_start(argp, format); - vfprintf(f, format, argp); - va_end(argp); - } - -void BroDoc::WriteSectionHeading(FILE* f, const char* heading, char underline) - { - WriteToDoc(f, "%s\n", heading); - WriteRepeatedChar(f, underline, strlen(heading)); - WriteToDoc(f, "\n"); - } - -void BroDoc::WriteRepeatedChar(FILE* f, char c, size_t n) - { - for ( size_t i = 0; i < n; ++i ) - WriteToDoc(f, "%c", c); - } - -void BroDoc::FreeBroDocObjPtrList(BroDocObjList& l) - { - for ( BroDocObjList::const_iterator it = l.begin(); it != l.end(); ++it ) - delete *it; - - l.clear(); - } - -void BroDoc::AddFunction(BroDocObj* o) - { - BroDocObjMap::const_iterator it = functions.find(o->Name()); - if ( it == functions.end() ) - { - functions[o->Name()] = o; - all.push_back(o); - } - else - functions[o->Name()]->Combine(o); - } - -static void WritePluginSectionHeading(FILE* f, const plugin::Plugin* p) - { - string name = p->Name(); - - fprintf(f, "%s\n", name.c_str()); - for ( size_t i = 0; i < name.size(); ++i ) - fprintf(f, "-"); - fprintf(f, "\n\n"); - - fprintf(f, "%s\n\n", p->Description().c_str()); - } - -static void WriteAnalyzerComponent(FILE* f, const analyzer::Component* c) - { - EnumType* atag = analyzer_mgr->GetTagEnumType(); - string tag = fmt("ANALYZER_%s", c->CanonicalName().c_str()); - - if ( atag->Lookup("Analyzer", tag.c_str()) < 0 ) - reporter->InternalError("missing analyzer tag for %s", tag.c_str()); - - fprintf(f, ":bro:enum:`Analyzer::%s`\n\n", tag.c_str()); - } - -static void WriteAnalyzerComponent(FILE* f, const file_analysis::Component* c) - { - EnumType* atag = file_mgr->GetTagEnumType(); - string tag = fmt("ANALYZER_%s", c->CanonicalName().c_str()); - - if ( atag->Lookup("Files", tag.c_str()) < 0 ) - reporter->InternalError("missing analyzer tag for %s", tag.c_str()); - - fprintf(f, ":bro:enum:`Files::%s`\n\n", tag.c_str()); - } - -static void WritePluginComponents(FILE* f, const plugin::Plugin* p) - { - plugin::Plugin::component_list components = p->Components(); - plugin::Plugin::component_list::const_iterator it; - - fprintf(f, "Components\n"); - fprintf(f, "++++++++++\n\n"); - - for ( it = components.begin(); it != components.end(); ++it ) - { - switch ( (*it)->Type() ) { - case plugin::component::ANALYZER: - { - const analyzer::Component* c = - dynamic_cast(*it); - - if ( c ) - WriteAnalyzerComponent(f, c); - else - reporter->InternalError("component type mismatch"); - } - break; - - case plugin::component::FILE_ANALYZER: - { - const file_analysis::Component* c = - dynamic_cast(*it); - - if ( c ) - WriteAnalyzerComponent(f, c); - else - reporter->InternalError("component type mismatch"); - } - break; - - case plugin::component::READER: - reporter->InternalError("docs for READER component unimplemented"); - - case plugin::component::WRITER: - reporter->InternalError("docs for WRITER component unimplemented"); - - default: - reporter->InternalError("docs for unknown component unimplemented"); - } - } - } - -static void WritePluginBifItems(FILE* f, const plugin::Plugin* p, - plugin::BifItem::Type t, const string& heading) - { - plugin::Plugin::bif_item_list bifitems = p->BifItems(); - plugin::Plugin::bif_item_list::iterator it = bifitems.begin(); - - while ( it != bifitems.end() ) - { - if ( it->GetType() != t ) - it = bifitems.erase(it); - else - ++it; - } - - if ( bifitems.empty() ) - return; - - fprintf(f, "%s\n", heading.c_str()); - for ( size_t i = 0; i < heading.size(); ++i ) - fprintf(f, "+"); - fprintf(f, "\n\n"); - - for ( it = bifitems.begin(); it != bifitems.end(); ++it ) - { - BroDocObj* o = doc_ids[it->GetID()]; - - if ( o ) - o->WriteReST(f); - else - reporter->Warning("No docs for ID: %s\n", it->GetID().c_str()); - } - } - -static void WriteAnalyzerTagDefn(FILE* f, EnumType* e, const string& module) - { - string tag_id= module + "::Tag"; - e = new CommentedEnumType(e); - e->SetTypeID(copy_string(tag_id.c_str())); - - ID* dummy_id = new ID(tag_id.c_str(), SCOPE_GLOBAL, true); - dummy_id->SetType(e); - dummy_id->MakeType(); - - list* r = new list(); - r->push_back("Unique identifiers for analyzers."); - - BroDocObj bdo(dummy_id, r, true); - - bdo.WriteReST(f); - } - -static bool ComponentsMatch(const plugin::Plugin* p, plugin::component::Type t, - bool match_empty = false) - { - plugin::Plugin::component_list components = p->Components(); - plugin::Plugin::component_list::const_iterator it; - - if ( components.empty() ) - return match_empty; - - for ( it = components.begin(); it != components.end(); ++it ) - if ( (*it)->Type() != t ) - return false; - - return true; - } - -void CreateProtoAnalyzerDoc(const char* filename) - { - FILE* f = fopen(filename, "w"); - - fprintf(f, "Protocol Analyzers\n"); - fprintf(f, "==================\n\n\n"); - fprintf(f, ".. contents::\n"); - fprintf(f, " :depth: 1\n\n"); - - WriteAnalyzerTagDefn(f, analyzer_mgr->GetTagEnumType(), "Analyzer"); - - plugin::Manager::plugin_list plugins = plugin_mgr->Plugins(); - plugin::Manager::plugin_list::const_iterator it; - - for ( it = plugins.begin(); it != plugins.end(); ++it ) - { - if ( ! ComponentsMatch(*it, plugin::component::ANALYZER, true) ) - continue; - - WritePluginSectionHeading(f, *it); - WritePluginComponents(f, *it); - WritePluginBifItems(f, *it, plugin::BifItem::CONSTANT, - "Options/Constants"); - WritePluginBifItems(f, *it, plugin::BifItem::GLOBAL, "Globals"); - WritePluginBifItems(f, *it, plugin::BifItem::TYPE, "Types"); - WritePluginBifItems(f, *it, plugin::BifItem::EVENT, "Events"); - WritePluginBifItems(f, *it, plugin::BifItem::FUNCTION, "Functions"); - } - - fclose(f); - } - -void CreateFileAnalyzerDoc(const char* filename) - { - FILE* f = fopen(filename, "w"); - - fprintf(f, "File Analyzers\n"); - fprintf(f, "==============\n\n"); - fprintf(f, ".. contents::\n"); - fprintf(f, " :depth: 1\n\n"); - - WriteAnalyzerTagDefn(f, file_mgr->GetTagEnumType(), "Files"); - - plugin::Manager::plugin_list plugins = plugin_mgr->Plugins(); - plugin::Manager::plugin_list::const_iterator it; - - for ( it = plugins.begin(); it != plugins.end(); ++it ) - { - if ( ! ComponentsMatch(*it, plugin::component::FILE_ANALYZER) ) - continue; - - WritePluginSectionHeading(f, *it); - WritePluginComponents(f, *it); - WritePluginBifItems(f, *it, plugin::BifItem::CONSTANT, - "Options/Constants"); - WritePluginBifItems(f, *it, plugin::BifItem::GLOBAL, "Globals"); - WritePluginBifItems(f, *it, plugin::BifItem::TYPE, "Types"); - WritePluginBifItems(f, *it, plugin::BifItem::EVENT, "Events"); - WritePluginBifItems(f, *it, plugin::BifItem::FUNCTION, "Functions"); - } - - fclose(f); - } diff --git a/src/Func.cc b/src/Func.cc index 2b1a44f33a..37a6b55f3b 100644 --- a/src/Func.cc +++ b/src/Func.cc @@ -277,7 +277,7 @@ int BroFunc::IsPure() const return 1; } -Val* BroFunc::HandlePluginResult(Val* plugin_resul, tval_list* args) +Val* BroFunc::HandlePluginResult(Val* plugin_result, val_list* args) const { // Helper function factoring out this code from BroFunc:Call() for better // readability. diff --git a/src/Func.h b/src/Func.h index 280e31be61..4f46957029 100644 --- a/src/Func.h +++ b/src/Func.h @@ -100,7 +100,7 @@ public: protected: BroFunc() : Func(BRO_FUNC) {} Stmt* AddInits(Stmt* body, id_list* inits); - Val* HandlePluginResult(Val* plugin_result, val_list* args); + Val* HandlePluginResult(Val* plugin_result, val_list* args) const; DECLARE_SERIAL(BroFunc); diff --git a/src/analyzer/Component.cc b/src/analyzer/Component.cc index 932e0c06a3..9f12759640 100644 --- a/src/analyzer/Component.cc +++ b/src/analyzer/Component.cc @@ -28,7 +28,7 @@ void Component::DoDescribe(ODesc* d) const if ( factory ) { d->Add("ANALYZER_"); - d->Add(canon_name); + d->Add(CanonicalName()); d->Add(", "); } diff --git a/src/file_analysis/Component.cc b/src/file_analysis/Component.cc index 52ac8fe894..7869116392 100644 --- a/src/file_analysis/Component.cc +++ b/src/file_analysis/Component.cc @@ -26,6 +26,6 @@ void Component::DoDescribe(ODesc* d) const if ( factory ) { d->Add("ANALYZER_"); - d->Add(canon_name); + d->Add(CanonicalName()); } } diff --git a/src/file_analysis/file_analysis.bif b/src/file_analysis/file_analysis.bif index 8205b870c1..43efd8ba0f 100644 --- a/src/file_analysis/file_analysis.bif +++ b/src/file_analysis/file_analysis.bif @@ -60,6 +60,13 @@ function Files::__analyzer_name%(tag: Files::Tag%) : string return new StringVal(file_mgr->GetComponentName(tag)); %} +## :bro:see:`Files::register_for_mime_type`. +function Files::__register_for_mime_type%(id: Analyzer::Tag, mt: string%) : bool + %{ + bool result = file_mgr->RegisterAnalyzerForMIMEType(id->AsEnumVal(), mt); + return new Val(result, TYPE_BOOL); + %} + module GLOBAL; ## For use within a :bro:see:`get_file_handle` handler to set a unique diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.register_mime_type/files.log b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.register_mime_type/files.log new file mode 100644 index 0000000000..44a90b9ee6 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.register_mime_type/files.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path files +#open 2014-07-21-14-26-07 +#fields ts fuid tx_hosts rx_hosts conn_uids source depth analyzers mime_type filename duration local_orig is_orig seen_bytes total_bytes missing_bytes overflow_bytes timedout parent_fuid md5 sha1 sha256 extracted +#types time string set[addr] set[addr] set[string] string count set[string] string string interval bool bool count count count count bool string string string string string +1362692527.009721 FakNcS1Jfe01uljb3 192.150.187.43 141.142.228.5 CXWv6p3arKYeMETxOg HTTP 0 MD5 text/plain - 0.000054 - F 4705 4705 0 0 F - 397168fd09991a0e712254df7bc639ac - - - +#close 2014-07-21-14-26-07 diff --git a/testing/btest/scripts/base/frameworks/file-analysis/bifs/register_mime_type.bro b/testing/btest/scripts/base/frameworks/file-analysis/bifs/register_mime_type.bro new file mode 100644 index 0000000000..9b6d11ce0d --- /dev/null +++ b/testing/btest/scripts/base/frameworks/file-analysis/bifs/register_mime_type.bro @@ -0,0 +1,9 @@ +# @TEST-EXEC: bro -r $TRACES/http/get.trace %INPUT +# @TEST-EXEC: btest-diff files.log + +event bro_init() + { + Files::register_for_mime_type(Files::ANALYZER_MD5, "text/plain"); + }; + +