1+ using Fiddler ;
2+ using MAPIInspector . Parsers ;
13using System ;
24using System . Text ;
35using System . Windows . Forms ;
@@ -6,6 +8,10 @@ namespace MapiInspector
68{
79 public partial class MAPIControl
810 {
11+ public static readonly string SearchDefaultText = "Search (Ctrl+F) F3 to search. Hold SHIFT to search backwards. Hold CTRL to search across frames." ;
12+ private readonly System . Drawing . Color SearchDefaultColor = System . Drawing . Color . Gray ;
13+ private readonly System . Drawing . Color SearchNormalColor = System . Drawing . Color . Black ;
14+
915 private void InitializeContextMenus ( )
1016 {
1117 // TreeView context menu
@@ -69,6 +75,7 @@ private string GetNodeText(TreeNode node)
6975 {
7076 return CleanString ( position . SourceBlock . Text ) ;
7177 }
78+
7279 return CleanString ( node . Text ) ;
7380 }
7481
@@ -207,43 +214,47 @@ private void CropsHexBox_CopyHex_Click(object sender, EventArgs e)
207214
208215 private void SearchButton_Click ( object sender , EventArgs e )
209216 {
210- bool bIsShift = ( ModifierKeys & Keys . Shift ) == Keys . Shift ;
211- PerformSearch ( bIsShift ) ;
217+ var isCtrl = ( ModifierKeys & Keys . Control ) == Keys . Control ;
218+ var isShift = ( ModifierKeys & Keys . Shift ) == Keys . Shift ;
219+ PerformSearch ( isShift , isCtrl ) ;
220+
212221 }
213222
214223 private void SearchTextBox_KeyDown ( object sender , KeyEventArgs e )
215224 {
216225 bool bEnter = e . KeyCode == Keys . Enter ;
217- bool bShiftEnter = ( e . KeyCode == Keys . Enter ) && ( e . Modifiers == Keys . Shift ) ;
226+ bool isCtrl = ( ModifierKeys & Keys . Control ) == Keys . Control ;
227+ bool isShift = ( ModifierKeys & Keys . Shift ) == Keys . Shift ;
218228
219- if ( bEnter || bShiftEnter )
229+ if ( bEnter )
220230 {
221- PerformSearch ( e . Modifiers == Keys . Shift ) ;
231+ PerformSearch ( isShift , isCtrl ) ;
222232 e . Handled = true ;
223233 e . SuppressKeyPress = true ;
224234 }
225235 }
226236
227237 private void SearchTextBox_GotFocus ( object sender , EventArgs e )
228238 {
229- if ( searchTextBox . Text == "Search (Ctrl+F)" )
239+ if ( searchTextBox . Text == SearchDefaultText )
230240 {
231241 searchTextBox . Text = "" ;
242+ searchTextBox . ForeColor = SearchNormalColor ;
232243 }
233244 }
234245
235246 private void SearchTextBox_LostFocus ( object sender , EventArgs e )
236247 {
237248 if ( string . IsNullOrWhiteSpace ( searchTextBox . Text ) )
238249 {
239- searchTextBox . Text = "Search (Ctrl+F)" ;
250+ searchTextBox . Text = SearchDefaultText ;
251+ searchTextBox . ForeColor = SearchDefaultColor ;
240252 }
241253 }
242254
243- protected override bool ProcessCmdKey ( ref Message msg , Keys keyData )
255+ protected override bool ProcessCmdKey ( ref System . Windows . Forms . Message msg , Keys keyData )
244256 {
245- bool isF3 = keyData == Keys . F3 ;
246- bool isShiftF3 = keyData == ( Keys . Shift | Keys . F3 ) ;
257+ bool isF3 = keyData . HasFlag ( Keys . F3 ) ;
247258 bool isCtrlF = keyData == ( Keys . Control | Keys . F ) ;
248259 bool isCtrlRight = keyData == ( Keys . Control | Keys . Right ) ;
249260
@@ -287,43 +298,74 @@ protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
287298 return true ;
288299 }
289300
290- if ( isF3 || isShiftF3 )
301+ if ( isF3 )
291302 {
292- PerformSearch ( keyData . HasFlag ( Keys . Shift ) ) ;
303+ PerformSearch ( keyData . HasFlag ( Keys . Shift ) , keyData . HasFlag ( Keys . Control ) ) ;
293304 return true ;
294305 }
295306
296307 return base . ProcessCmdKey ( ref msg , keyData ) ;
297308 }
298309
299- private void PerformSearch ( bool searchUp )
310+ // Combined search logic for single and multi-frame search
311+ private void PerformSearch ( bool searchUp , bool searchFrames )
300312 {
301- string searchText = searchTextBox . Text . Trim ( ) ;
302- if ( mapiTreeView . Nodes . Count == 0 ||
303- string . IsNullOrEmpty ( searchText ) ||
304- searchText == "Search (Ctrl+F)" )
313+ var searchText = searchTextBox . Text . Trim ( ) ;
314+ if ( string . IsNullOrEmpty ( searchText ) || searchText == SearchDefaultText ) return ;
315+
316+ FiddlerApplication . UI . SetStatusText ( $ "Searching for { searchText } ") ;
317+ var startNode = mapiTreeView ? . SelectedNode ;
318+ if ( startNode == null && mapiTreeView ? . Nodes . Count > 0 )
305319 {
306- return ;
320+ startNode = mapiTreeView . Nodes [ 0 ] ;
307321 }
308322
309- var startNode = mapiTreeView . SelectedNode ?? mapiTreeView . Nodes [ 0 ] ;
310- if ( startNode == null )
311- return ;
323+ if ( startNode != null )
324+ {
325+ var nodes = mapiTreeView . Nodes ;
326+ TreeNode foundNode = searchUp
327+ ? FindPrevNode ( nodes , startNode , searchText , ! searchFrames )
328+ : FindNextNode ( nodes , startNode , searchText , ! searchFrames ) ;
312329
313- var foundNode = searchUp
314- ? FindPrevNode ( mapiTreeView . Nodes , startNode , searchText )
315- : FindNextNode ( mapiTreeView . Nodes , startNode , searchText ) ;
330+ if ( foundNode != null )
331+ {
332+ mapiTreeView . SelectedNode = foundNode ;
333+ mapiTreeView . Focus ( ) ;
334+ foundNode . EnsureVisible ( ) ;
335+ return ;
336+ }
337+ }
316338
317- if ( foundNode != null )
339+ if ( searchFrames )
318340 {
319- mapiTreeView . SelectedNode = foundNode ;
320- mapiTreeView . Focus ( ) ;
321- foundNode . EnsureVisible ( ) ;
341+ var currentSession = Inspector . session ;
342+ while ( currentSession != null )
343+ {
344+ var nextSession = searchUp ? currentSession ? . Previous ( ) : currentSession ? . Next ( ) ;
345+ if ( nextSession == null ) break ;
346+ var parseResult = MAPIParser . ParseHTTPPayload ( nextSession , Inspector . Direction , out var bytes ) ;
347+ var rootNode = new TreeNode ( ) ;
348+ var node = BaseStructure . AddBlock ( parseResult , false ) ;
349+ rootNode . Nodes . Add ( node ) ;
350+ var foundMatch = searchUp
351+ ? FindPrevNode ( rootNode . Nodes , node , searchText , true )
352+ : FindNextNode ( rootNode . Nodes , node , searchText , true ) ;
353+ if ( foundMatch != null )
354+ {
355+ FiddlerApplication . UI . SelectSessionsMatchingCriteria ( s => s . id == nextSession . id ) ;
356+ nextSession . ViewItem . EnsureVisible ( ) ;
357+ return ;
358+ }
359+
360+ currentSession = nextSession ;
361+ }
322362 }
363+
364+ FiddlerApplication . UI . SetStatusText ( "No match found" ) ;
323365 }
324366
325367 // Find next node (downwards, wraps around)
326- private TreeNode FindNextNode ( TreeNodeCollection nodes , TreeNode startNode , string searchText )
368+ private TreeNode FindNextNode ( TreeNodeCollection nodes , TreeNode startNode , string searchText , bool wrap )
327369 {
328370 bool foundStart = false ;
329371 TreeNode firstMatch = null ;
@@ -335,18 +377,20 @@ private TreeNode FindNextNode(TreeNodeCollection nodes, TreeNode startNode, stri
335377 continue ;
336378 }
337379
338- if ( foundStart && GetNodeText ( node ) . IndexOf ( searchText , StringComparison . OrdinalIgnoreCase ) >= 0 )
339- return node ;
340- if ( firstMatch == null && GetNodeText ( node ) . IndexOf ( searchText , StringComparison . OrdinalIgnoreCase ) >= 0 )
341- firstMatch = node ;
380+ if ( GetNodeText ( node ) . IndexOf ( searchText , StringComparison . OrdinalIgnoreCase ) >= 0 )
381+ {
382+ if ( foundStart )
383+ return node ;
384+ if ( firstMatch == null )
385+ firstMatch = node ;
386+ }
342387 }
343388
344- // Wrap around
345- return firstMatch ;
389+ return wrap ? firstMatch : null ;
346390 }
347391
348392 // Find previous node (upwards, wraps around)
349- private TreeNode FindPrevNode ( TreeNodeCollection nodes , TreeNode startNode , string searchText )
393+ private TreeNode FindPrevNode ( TreeNodeCollection nodes , TreeNode startNode , string searchText , bool wrap )
350394 {
351395 TreeNode lastMatch = null ;
352396 foreach ( var node in FlattenNodes ( nodes ) )
@@ -357,8 +401,7 @@ private TreeNode FindPrevNode(TreeNodeCollection nodes, TreeNode startNode, stri
357401 lastMatch = node ;
358402 }
359403
360- // Wrap around: if nothing before, search from end
361- if ( lastMatch == null )
404+ if ( lastMatch == null && wrap )
362405 {
363406 foreach ( var node in FlattenNodes ( nodes ) )
364407 {
0 commit comments