@@ -22,13 +22,35 @@ pub(crate) struct YaraResult {
2222}
2323
2424/// Yara data
25- #[ cfg_attr( target_arch = "wasm32" , allow( unused) ) ]
26- #[ derive( Debug ) ]
25+ #[ derive( Debug , serde:: Deserialize , serde:: Serialize ) ]
2726pub ( crate ) struct YaraData {
2827 /// rule string
2928 rule : String ,
29+
3030 /// results - matching and non-matching rules
31+ #[ serde( skip) ]
32+ #[ cfg_attr( target_arch = "wasm32" , allow( unused) ) ]
3133 results : Option < YaraResult > ,
34+
35+ /// Error
36+ #[ serde( skip) ]
37+ error : Option < String > ,
38+ }
39+
40+ impl Default for YaraData {
41+ fn default ( ) -> Self {
42+ Self {
43+ rule : r#"rule lorem_ipsum {
44+ strings:
45+ $ = "Lorem ipsum"
46+ condition:
47+ all of them
48+ }"#
49+ . to_string ( ) ,
50+ results : None ,
51+ error : None ,
52+ }
53+ }
3254}
3355
3456/// Yara data
@@ -37,13 +59,8 @@ pub(crate) struct Yara {
3759 /// is open
3860 pub ( crate ) is_open : bool ,
3961
40- #[ serde( skip) ]
4162 /// optional data
4263 data : Option < YaraData > ,
43-
44- /// Error
45- #[ serde( skip) ]
46- error : Option < String > ,
4764}
4865
4966impl Yara {
@@ -57,13 +74,12 @@ impl Yara {
5774
5875 /// Window title
5976 pub ( crate ) fn window_title ( ) -> & ' static str {
60- "Yara"
77+ "Yara-X "
6178 }
6279
6380 /// reset data
6481 pub ( crate ) fn reset ( & mut self ) {
6582 self . data = None ;
66- self . error = None ;
6783 }
6884
6985 /// Extract a rule result
@@ -74,108 +90,78 @@ impl Yara {
7490
7591 /// Window UI
7692 #[ cfg( target_arch = "wasm32" ) ]
77- pub ( crate ) fn window_ui (
78- & mut self ,
79- _binary_data : & [ u8 ] ,
80- ui : & mut egui:: Ui ,
81- _error_manager : & mut ErrorManager ,
82- ) {
93+ pub ( crate ) fn window_ui ( _binary_data : & [ u8 ] , _data : & mut YaraData , ui : & mut egui:: Ui ) {
8394 ui. label ( "Yara is not enabled in wasm32" ) ;
8495 }
8596
8697 /// Window UI
8798 #[ cfg( not( target_arch = "wasm32" ) ) ]
88- pub ( crate ) fn window_ui (
89- & mut self ,
90- binary_data : & [ u8 ] ,
91- ui : & mut egui:: Ui ,
92- _error_manager : & mut ErrorManager ,
93- ) {
99+ pub ( crate ) fn window_ui ( binary_data : & [ u8 ] , data : & mut YaraData , ui : & mut egui:: Ui ) {
94100 use bladvak:: egui_extras:: { Column , TableBuilder } ;
95101 use yara_x:: Compiler ;
96- if let Some ( data) = & mut self . data {
97- ui. text_edit_multiline ( & mut data. rule ) ;
98- if ui. button ( "Run rules" ) . clicked ( ) {
99- self . error = None ;
100- let mut compiler = Compiler :: new ( ) ;
101- match compiler. add_source ( & * data. rule ) {
102- Ok ( _) => {
103- let rules = compiler. build ( ) ;
104- let mut scanner = yara_x:: Scanner :: new ( & rules) ;
105- match scanner. scan ( binary_data) {
106- Ok ( results) => {
107- let matching_rules = results
108- . matching_rules ( )
109- . map ( |r| Self :: extract_result ( & r) )
110- . collect ( ) ;
111- let non_matching_rules = results
112- . non_matching_rules ( )
113- . map ( |r| Self :: extract_result ( & r) )
114- . collect ( ) ;
115- data. results = Some ( YaraResult {
116- matching_rules,
117- non_matching_rules,
118- } ) ;
119- }
120- Err ( e) => {
121- data. results = None ;
122- self . error = Some ( e. to_string ( ) ) ;
123- }
102+
103+ if ui. button ( "Run rules" ) . clicked ( ) {
104+ let mut compiler = Compiler :: new ( ) ;
105+ match compiler. add_source ( & * data. rule ) {
106+ Ok ( _) => {
107+ let rules = compiler. build ( ) ;
108+ let mut scanner = yara_x:: Scanner :: new ( & rules) ;
109+ match scanner. scan ( binary_data) {
110+ Ok ( results) => {
111+ let matching_rules = results
112+ . matching_rules ( )
113+ . map ( |r| Self :: extract_result ( & r) )
114+ . collect ( ) ;
115+ let non_matching_rules = results
116+ . non_matching_rules ( )
117+ . map ( |r| Self :: extract_result ( & r) )
118+ . collect ( ) ;
119+ data. results = Some ( YaraResult {
120+ matching_rules,
121+ non_matching_rules,
122+ } ) ;
123+ }
124+ Err ( e) => {
125+ data. results = None ;
126+ data. error = Some ( e. to_string ( ) ) ;
124127 }
125- }
126- Err ( e) => {
127- data. results = None ;
128- self . error = Some ( e. to_string ( ) ) ;
129128 }
130129 }
130+ Err ( e) => {
131+ data. results = None ;
132+ data. error = Some ( e. to_string ( ) ) ;
133+ }
131134 }
132- if let Some ( res) = & data. results {
133- TableBuilder :: new ( ui)
134- . striped ( true )
135- . column ( Column :: auto ( ) )
136- . column ( Column :: auto ( ) )
137- . header ( 20.0 , |mut header| {
138- header. col ( |ui| {
139- ui. label ( "Matching Rules" ) ;
140- } ) ;
141- header. col ( |ui| {
142- ui. label ( "Non matching rules" ) ;
135+ }
136+ if let Some ( res) = & data. results {
137+ TableBuilder :: new ( ui)
138+ . striped ( true )
139+ . column ( Column :: auto ( ) )
140+ . column ( Column :: auto ( ) )
141+ . header ( 20.0 , |mut header| {
142+ header. col ( |ui| {
143+ ui. label ( "Matching Rules" ) ;
144+ } ) ;
145+ header. col ( |ui| {
146+ ui. label ( "Non matching rules" ) ;
147+ } ) ;
148+ } )
149+ . body ( |mut body| {
150+ body. row ( 30.0 , |mut row| {
151+ row. col ( |ui| {
152+ for one_res in & res. matching_rules {
153+ ui. label ( & one_res. 0 ) ;
154+ }
143155 } ) ;
144- } )
145- . body ( |mut body| {
146- body. row ( 30.0 , |mut row| {
147- row. col ( |ui| {
148- for one_res in & res. matching_rules {
149- ui. label ( & one_res. 0 ) ;
150- }
151- } ) ;
152- row. col ( |ui| {
153- for one_res in & res. non_matching_rules {
154- ui. label ( & one_res. 0 ) ;
155- }
156- } ) ;
156+ row. col ( |ui| {
157+ for one_res in & res. non_matching_rules {
158+ ui. label ( & one_res. 0 ) ;
159+ }
157160 } ) ;
158161 } ) ;
159- } else if self . error . is_none ( ) {
160- ui. label ( "No result - click to Run rules" ) ;
161- }
162-
163- if let Some ( e) = & self . error {
164- ui. colored_label ( egui:: Color32 :: RED , "Error: " ) ;
165- ui. colored_label ( egui:: Color32 :: RED , e) ;
166- }
167- } else {
168- let yara_data = YaraData {
169- rule : r#"rule lorem_ipsum {
170- strings:
171- $ = "Lorem ipsum"
172- condition:
173- all of them
174- }"#
175- . to_string ( ) ,
176- results : None ,
177- } ;
178- self . data = Some ( yara_data) ;
162+ } ) ;
163+ } else if data. error . is_none ( ) {
164+ ui. label ( "No result - click to Run rules" ) ;
179165 }
180166 }
181167
@@ -184,15 +170,28 @@ impl Yara {
184170 & mut self ,
185171 binary_data : & [ u8 ] ,
186172 ui : & mut egui:: Ui ,
187- error_manager : & mut ErrorManager ,
173+ _error_manager : & mut ErrorManager ,
188174 ) {
189175 if self . is_open {
190176 let mut is_open = self . is_open ;
191177 egui:: Window :: new ( Self :: window_title ( ) )
192178 . open ( & mut is_open)
193179 . vscroll ( true )
194180 . show ( ui. ctx ( ) , |ui| {
195- self . window_ui ( binary_data, ui, error_manager) ;
181+ if let Some ( data) = & mut self . data {
182+ let is_wasm = cfg ! ( target_arch = "wasm32" ) ;
183+ ui. add_enabled_ui ( !is_wasm, |ui| {
184+ ui. text_edit_multiline ( & mut data. rule ) ;
185+ } ) ;
186+ Self :: window_ui ( binary_data, data, ui) ;
187+ if let Some ( e) = & data. error {
188+ ui. colored_label ( egui:: Color32 :: RED , "Error: " ) ;
189+ ui. colored_label ( egui:: Color32 :: RED , e) ;
190+ }
191+ } else {
192+ let yara_data = YaraData :: default ( ) ;
193+ self . data = Some ( yara_data) ;
194+ }
196195 } ) ;
197196 self . is_open = is_open;
198197 }
0 commit comments