diff --git a/src/logging/writers/SQLite.cc b/src/logging/writers/SQLite.cc index c529fbfe3c..23d7799b1e 100644 --- a/src/logging/writers/SQLite.cc +++ b/src/logging/writers/SQLite.cc @@ -22,17 +22,17 @@ SQLite::SQLite(WriterFrontend* frontend) : WriterBackend(frontend) { set_separator.assign( (const char*) BifConst::LogSQLite::set_separator->Bytes(), - BifConst::LogAscii::set_separator->Len() + BifConst::LogSQLite::set_separator->Len() ); unset_field.assign( (const char*) BifConst::LogSQLite::unset_field->Bytes(), - BifConst::LogAscii::unset_field->Len() + BifConst::LogSQLite::unset_field->Len() ); empty_field.assign( (const char*) BifConst::LogSQLite::empty_field->Bytes(), - BifConst::LogAscii::empty_field->Len() + BifConst::LogSQLite::empty_field->Len() ); db = 0; @@ -247,7 +247,7 @@ char* SQLite::FS(const char* format, ...) int SQLite::AddParams(Value* val, int pos) { - if ( ! val->present ) + if ( ! val->present ) return sqlite3_bind_null(st, pos); switch ( val->type ) { @@ -296,18 +296,25 @@ int SQLite::AddParams(Value* val, int pos) { ODesc desc; desc.Clear(); + desc.EnableEscaping(); desc.AddEscapeSequence(set_separator); - for ( int j = 0; j < val->val.set_val.size; j++ ) + if ( ! val->val.set_val.size ) { - if ( j > 0 ) - desc.AddRaw(set_separator); - - io->Describe(&desc, val->val.set_val.vals[j], fields[pos]->name); - // yes, giving NULL here is not really really pretty.... - // it works however, because tables cannot contain tables... - // or vectors. + desc.Add(empty_field); } + else + for ( int j = 0; j < val->val.set_val.size; j++ ) + { + if ( j > 0 ) + desc.AddRaw(set_separator); + + io->Describe(&desc, val->val.set_val.vals[j], fields[pos]->name); + // yes, giving NULL here is not really really pretty.... + // it works however, because tables cannot contain tables... + // or vectors. + } + desc.RemoveEscapeSequence(set_separator); return sqlite3_bind_text(st, pos, (const char*) desc.Bytes(), desc.Len(), SQLITE_TRANSIENT); } @@ -316,15 +323,21 @@ int SQLite::AddParams(Value* val, int pos) { ODesc desc; desc.Clear(); + desc.EnableEscaping(); desc.AddEscapeSequence(set_separator); - - for ( int j = 0; j < val->val.vector_val.size; j++ ) + + if ( ! val->val.vector_val.size ) { - if ( j > 0 ) - desc.AddRaw(set_separator); - - io->Describe(&desc, val->val.vector_val.vals[j], fields[pos]->name); + desc.Add(empty_field); } + else + for ( int j = 0; j < val->val.vector_val.size; j++ ) + { + if ( j > 0 ) + desc.AddRaw(set_separator); + + io->Describe(&desc, val->val.vector_val.vals[j], fields[pos]->name); + } desc.RemoveEscapeSequence(set_separator); diff --git a/testing/btest/Baseline/scripts.base.frameworks.input.sqlite.types/out b/testing/btest/Baseline/scripts.base.frameworks.input.sqlite.types/out new file mode 100644 index 0000000000..9b4aa6e207 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.input.sqlite.types/out @@ -0,0 +1,15 @@ +[b=T, i=-42, e=SSH::LOG, c=21, p=123/unknown, sn=10.0.0.0/24, a=1.2.3.4, d=3.14, t=1358376849.393854, iv=100.0, s=hurz, sc={ +2, +4, +1, +3 +}, ss={ +CC, +AA, +BB +}, se={ + +}, vc=[10, 20, 30], vs=[], vn=] +0 +1 +End of data diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.sqlite.types/ssh.select b/testing/btest/Baseline/scripts.base.frameworks.logging.sqlite.types/ssh.select new file mode 100644 index 0000000000..7b92f10d65 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.sqlite.types/ssh.select @@ -0,0 +1,8 @@ +1|-42|SSH::LOG|21|123|10.0.0.0/24|1.2.3.4|3.14|1363036624.07106|100.0|hurz|2,4,1,3|CC,AA,BB|(empty)|10,20,30|(empty)|SSH::foo +{ +if (0 < SSH::i) + return (Foo); +else + return (Bar); + +} diff --git a/testing/btest/scripts/base/frameworks/input/sqlite/types.bro b/testing/btest/scripts/base/frameworks/input/sqlite/types.bro new file mode 100644 index 0000000000..a325100964 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/input/sqlite/types.bro @@ -0,0 +1,87 @@ +# @TEST-EXEC: cat ssh.sql | sqlite3 ssh.sqlite +# @TEST-EXEC: btest-bg-run bro bro -b %INPUT +# @TEST-EXEC: btest-bg-wait -k 5 +# @TEST-EXEC: btest-diff out + +@TEST-START-FILE ssh.sql +PRAGMA foreign_keys=OFF; +BEGIN TRANSACTION; +CREATE TABLE ssh ( +'b' boolean, +'i' integer, +'e' text, +'c' integer, +'p' integer, +'sn' text, +'a' text, +'d' double precision, +'t' double precision, +'iv' double precision, +'s' text, +'sc' text, +'ss' text, +'se' text, +'vc' text, +'vs' text, +'vn' text +); +INSERT INTO "ssh" VALUES(1,-42,'SSH::LOG',21,123,'10.0.0.0/24','1.2.3.4',3.14,1.35837684939385390286e+09,100.0,'hurz','2,4,1,3','CC,AA,BB','(empty)','10,20,30','', null); +COMMIT; +@TEST-END-FILE + +redef exit_only_after_terminate = T; + +module SSH; + +export { + redef enum Log::ID += { LOG }; + + type Log: record { + b: bool; + i: int; + e: Log::ID; + c: count; + p: port; + sn: subnet; + a: addr; + d: double; + t: time; + iv: interval; + s: string; + sc: set[count]; + ss: set[string]; + se: set[string]; + vc: vector of count; + vs: vector of string; + vn: vector of string &optional; + } &log; +} + + +global outfile: file; + +event line(description: Input::EventDescription, tpe: Input::Event, p: SSH::Log) + { + print outfile, p; + + print outfile, |p$se|; + print outfile, |p$vs|; + } + +event bro_init() + { + local config_strings: table[string] of string = { + ["query"] = "select * from ssh;", + ["dbname"] = "ssh" + }; + + outfile = open("../out"); + Input::add_event([$source="../ssh", $name="ssh", $fields=SSH::Log, $ev=line, $reader=Input::READER_SQLITE, $want_record=T, $config=config_strings]); + } + +event Input::end_of_data(name: string, source:string) + { + print outfile, "End of data"; + close(outfile); + terminate(); + } diff --git a/testing/btest/scripts/base/frameworks/logging/sqlite/types.bro b/testing/btest/scripts/base/frameworks/logging/sqlite/types.bro new file mode 100644 index 0000000000..24fcf7362b --- /dev/null +++ b/testing/btest/scripts/base/frameworks/logging/sqlite/types.bro @@ -0,0 +1,77 @@ +# +# @TEST-GROUP: sqlite +# +# @TEST-EXEC: bro -b %INPUT +# @TEST-EXEC: sqlite3 ssh.sqlite 'select * from ssh' > ssh.select +# @TEST-EXEC: btest-diff ssh.select +# +# Testing all possible types. + +redef LogSQLite::unset_field = "(unset)"; + +module SSH; + +export { + redef enum Log::ID += { LOG }; + + type Log: record { + b: bool; + i: int; + e: Log::ID; + c: count; + p: port; + sn: subnet; + a: addr; + d: double; + t: time; + iv: interval; + s: string; + sc: set[count]; + ss: set[string]; + se: set[string]; + vc: vector of count; + ve: vector of string; + f: function(i: count) : string; + } &log; +} + +function foo(i : count) : string + { + if ( i > 0 ) + return "Foo"; + else + return "Bar"; + } + +event bro_init() +{ + Log::create_stream(SSH::LOG, [$columns=Log]); + Log::remove_filter(SSH::LOG, "default"); + + local filter: Log::Filter = [$name="sqlite", $path="ssh", $writer=Log::WRITER_SQLITE]; + Log::add_filter(SSH::LOG, filter); + + local empty_set: set[string]; + local empty_vector: vector of string; + + Log::write(SSH::LOG, [ + $b=T, + $i=-42, + $e=SSH::LOG, + $c=21, + $p=123/tcp, + $sn=10.0.0.1/24, + $a=1.2.3.4, + $d=3.14, + $t=network_time(), + $iv=100secs, + $s="hurz", + $sc=set(1,2,3,4), + $ss=set("AA", "BB", "CC"), + $se=empty_set, + $vc=vector(10, 20, 30), + $ve=empty_vector, + $f=foo + ]); +} +