@@ -44,6 +44,44 @@ def __init__(self, timeout = default, level = None, *a, **kw):
44
44
self ._newline = None
45
45
atexit .register (self .close )
46
46
47
+ def _normalize_drop_keepends (self , drop , keepends , drop_default ):
48
+ '''
49
+ >>> t = tube()
50
+ >>> t._normalize_drop_keepends(None, None, True)
51
+ True
52
+ >>> t._normalize_drop_keepends(None, None, False)
53
+ False
54
+ >>> t._normalize_drop_keepends(True, None, True)
55
+ True
56
+ >>> t._normalize_drop_keepends(True, None, False)
57
+ True
58
+ >>> t._normalize_drop_keepends(None, True, True)
59
+ False
60
+ >>> t._normalize_drop_keepends(None, True, False)
61
+ False
62
+ >>> t._normalize_drop_keepends(False, None, True)
63
+ False
64
+ >>> t._normalize_drop_keepends(False, None, False)
65
+ False
66
+ >>> t._normalize_drop_keepends(None, False, True)
67
+ True
68
+ >>> t._normalize_drop_keepends(None, False, False)
69
+ True
70
+ >>> t._normalize_drop_keepends(True, False, False)
71
+ Traceback (most recent call last):
72
+ ...
73
+ pwnlib.exception.PwnlibException: 'drop' and 'keepends' arguments cannot be used together.
74
+ '''
75
+ if keepends is not None :
76
+ self .warn_once ("'keepends' argument is deprecated. Use 'drop' instead." )
77
+ if drop is None and keepends is None :
78
+ return drop_default
79
+ elif drop is not None :
80
+ if keepends is not None :
81
+ self .error ("'drop' and 'keepends' arguments cannot be used together." )
82
+ return drop
83
+ return not keepends
84
+
47
85
@property
48
86
def newline (self ):
49
87
r'''Character sent with methods like sendline() or used for recvline().
@@ -99,7 +137,7 @@ def recv(self, numb = None, timeout = default):
99
137
True
100
138
>>> with context.local(log_level='debug'):
101
139
... _ = t.recv() # doctest: +ELLIPSIS
102
- [... ] Received 0xc bytes:
140
+ [DEBUG ] Received 0xc bytes:
103
141
b'Hello, world'
104
142
"""
105
143
numb = self .buffer .get_fill_size (numb )
@@ -368,8 +406,8 @@ def recvuntil(self, delims, drop=False, timeout=default):
368
406
369
407
return b''
370
408
371
- def recvlines (self , numlines = 2 ** 20 , keepends = False , timeout = default ):
372
- r"""recvlines(numlines, keepends=False , timeout=default) -> list of bytes objects
409
+ def recvlines (self , numlines = 2 ** 20 , drop = None , keepends = None , timeout = default ):
410
+ r"""recvlines(numlines, drop=True , timeout=default) -> list of bytes objects
373
411
374
412
Receive up to ``numlines`` lines.
375
413
@@ -381,7 +419,7 @@ def recvlines(self, numlines=2**20, keepends=False, timeout=default):
381
419
382
420
Arguments:
383
421
numlines(int): Maximum number of lines to receive
384
- keepends (bool): Keep newlines at the end of each line (:const:`False `).
422
+ drop (bool): Drop newlines at the end of each line (:const:`True `).
385
423
timeout(int): Maximum timeout
386
424
387
425
Raises:
@@ -400,17 +438,20 @@ def recvlines(self, numlines=2**20, keepends=False, timeout=default):
400
438
>>> t.recv_raw = lambda n: b'Foo\nBar\nBaz\n'
401
439
>>> t.recvlines(3)
402
440
[b'Foo', b'Bar', b'Baz']
403
- >>> t.recvlines(3, True )
441
+ >>> t.recvlines(3, drop=False )
404
442
[b'Foo\n', b'Bar\n', b'Baz\n']
405
443
"""
444
+ drop = self ._normalize_drop_keepends (drop , keepends , True )
445
+ del keepends
446
+
406
447
lines = []
407
448
with self .countdown (timeout ):
408
449
for _ in range (numlines ):
409
450
try :
410
- # We must set 'keepends ' to True here so that we can
451
+ # We must set 'drop ' to False here so that we can
411
452
# restore the original, unmodified data to the buffer
412
453
# in the event of a timeout.
413
- res = self .recvline (keepends = True , timeout = timeout )
454
+ res = self .recvline (drop = False , timeout = timeout )
414
455
except Exception :
415
456
self .unrecv (b'' .join (lines ))
416
457
raise
@@ -420,13 +461,13 @@ def recvlines(self, numlines=2**20, keepends=False, timeout=default):
420
461
else :
421
462
break
422
463
423
- if not keepends :
424
- lines = [line . rstrip (self .newline ) for line in lines ]
464
+ if drop :
465
+ lines = [line [: - len (self .newline )] for line in lines ]
425
466
426
467
return lines
427
468
428
- def recvlinesS (self , numlines = 2 ** 20 , keepends = False , timeout = default ):
429
- r"""recvlinesS(numlines, keepends=False , timeout=default) -> str list
469
+ def recvlinesS (self , numlines = 2 ** 20 , drop = None , keepends = None , timeout = default ):
470
+ r"""recvlinesS(numlines, drop=True , timeout=default) -> str list
430
471
431
472
This function is identical to :meth:`recvlines`, but decodes
432
473
the received bytes into string using :func:`context.encoding`.
@@ -442,10 +483,10 @@ def recvlinesS(self, numlines=2**20, keepends=False, timeout=default):
442
483
>>> t.recvlinesS(3)
443
484
['Foo', 'Bar', 'Baz']
444
485
"""
445
- return [packing ._decode (x ) for x in self .recvlines (numlines , keepends , timeout )]
486
+ return [packing ._decode (x ) for x in self .recvlines (numlines , drop = drop , keepends = keepends , timeout = timeout )]
446
487
447
- def recvlinesb (self , numlines = 2 ** 20 , keepends = False , timeout = default ):
448
- r"""recvlinesb(numlines, keepends=False , timeout=default) -> bytearray list
488
+ def recvlinesb (self , numlines = 2 ** 20 , drop = None , keepends = None , timeout = default ):
489
+ r"""recvlinesb(numlines, drop=True , timeout=default) -> bytearray list
449
490
450
491
This function is identical to :meth:`recvlines`, but returns a bytearray.
451
492
@@ -459,10 +500,10 @@ def recvlinesb(self, numlines=2**20, keepends=False, timeout=default):
459
500
>>> t.recvlinesb(3)
460
501
[bytearray(b'Foo'), bytearray(b'Bar'), bytearray(b'Baz')]
461
502
"""
462
- return [bytearray (x ) for x in self .recvlines (numlines , keepends , timeout )]
503
+ return [bytearray (x ) for x in self .recvlines (numlines , drop = drop , keepends = keepends , timeout = timeout )]
463
504
464
- def recvline (self , keepends = True , timeout = default ):
465
- r"""recvline(keepends=True , timeout=default) -> bytes
505
+ def recvline (self , drop = None , keepends = None , timeout = default ):
506
+ r"""recvline(drop=False , timeout=default) -> bytes
466
507
467
508
Receive a single line from the tube.
468
509
@@ -478,7 +519,7 @@ def recvline(self, keepends=True, timeout=default):
478
519
all data is buffered and an empty byte string (``b''``) is returned.
479
520
480
521
Arguments:
481
- keepends (bool): Keep the line ending (:const:`True `).
522
+ drop (bool): Drop the line ending (:const:`False `).
482
523
timeout(int): Timeout
483
524
484
525
Raises:
@@ -501,10 +542,10 @@ def recvline(self, keepends=True, timeout=default):
501
542
b'Foo\n'
502
543
>>> t.recvline()
503
544
b'Bar\r\n'
504
- >>> t.recvline(keepends = False )
545
+ >>> t.recvline(drop=True )
505
546
b'Baz'
506
547
>>> t.newline = b'\r\n'
507
- >>> t.recvline(keepends = False )
548
+ >>> t.recvline(drop=True )
508
549
b'Foo\nBar'
509
550
>>> t = tube()
510
551
>>> def _recv_eof(n):
@@ -520,20 +561,23 @@ def recvline(self, keepends=True, timeout=default):
520
561
b'trailing data'
521
562
>>> t.recvline() # doctest: +ELLIPSIS
522
563
Traceback (most recent call last):
523
- ...
564
+ ...
524
565
EOFError
525
566
"""
567
+ drop = self ._normalize_drop_keepends (drop , keepends , False )
568
+ del keepends
569
+
526
570
try :
527
- return self .recvuntil (self .newline , drop = not keepends , timeout = timeout )
571
+ return self .recvuntil (self .newline , drop = drop , timeout = timeout )
528
572
except EOFError :
529
573
if not context .throw_eof_on_incomplete_line and self .buffer .size > 0 :
530
574
if context .throw_eof_on_incomplete_line is None :
531
575
self .warn_once ('EOFError during recvline. Returning buffered data without trailing newline.' )
532
576
return self .buffer .get ()
533
577
raise
534
578
535
- def recvline_pred (self , pred , keepends = False , timeout = default ):
536
- r"""recvline_pred(pred, keepends=False ) -> bytes
579
+ def recvline_pred (self , pred , drop = None , keepends = None , timeout = default ):
580
+ r"""recvline_pred(pred, drop=True, timeout=default ) -> bytes
537
581
538
582
Receive data until ``pred(line)`` returns a truthy value.
539
583
Drop all other data.
@@ -544,25 +588,28 @@ def recvline_pred(self, pred, keepends=False, timeout=default):
544
588
Arguments:
545
589
pred(callable): Function to call. Returns the line for which
546
590
this function returns :const:`True`.
591
+ drop(bool): Drop the line ending (:const:`True`).
547
592
548
593
Examples:
549
594
550
595
>>> t = tube()
551
596
>>> t.recv_raw = lambda n: b"Foo\nBar\nBaz\n"
552
597
>>> t.recvline_pred(lambda line: line == b"Bar\n")
553
598
b'Bar'
554
- >>> t.recvline_pred(lambda line: line == b"Bar\n", keepends=True )
599
+ >>> t.recvline_pred(lambda line: line == b"Bar\n", drop=False )
555
600
b'Bar\n'
556
601
>>> t.recvline_pred(lambda line: line == b'Nope!', timeout=0.1)
557
602
b''
558
603
"""
604
+ drop = self ._normalize_drop_keepends (drop , keepends , True )
605
+ del keepends
559
606
560
607
tmpbuf = Buffer ()
561
608
line = b''
562
609
with self .countdown (timeout ):
563
610
while self .countdown_active ():
564
611
try :
565
- line = self .recvline (keepends = True )
612
+ line = self .recvline (drop = False )
566
613
except Exception :
567
614
self .buffer .unget (tmpbuf )
568
615
raise
@@ -572,22 +619,23 @@ def recvline_pred(self, pred, keepends=False, timeout=default):
572
619
return b''
573
620
574
621
if pred (line ):
575
- if not keepends :
622
+ if drop :
576
623
line = line [:- len (self .newline )]
577
624
return line
578
625
else :
579
626
tmpbuf .add (line )
580
627
581
628
return b''
582
629
583
- def recvline_contains (self , items , keepends = False , timeout = default ):
584
- r"""
630
+ def recvline_contains (self , items , drop = None , keepends = None , timeout = default ):
631
+ r"""recvline_contains(items, drop=True, timeout=default) -> bytes
632
+
585
633
Receive lines until one line is found which contains at least
586
634
one of `items`.
587
635
588
636
Arguments:
589
637
items(str,tuple): List of strings to search for, or a single string.
590
- keepends (bool): Return lines with newlines if :const:`True`
638
+ drop (bool): Drop the line ending ( :const:`True`).
591
639
timeout(int): Timeout, in seconds
592
640
593
641
Examples:
@@ -613,10 +661,10 @@ def recvline_contains(self, items, keepends = False, timeout = default):
613
661
def pred (line ):
614
662
return any (d in line for d in items )
615
663
616
- return self .recvline_pred (pred , keepends , timeout )
664
+ return self .recvline_pred (pred , drop = drop , keepends = keepends , timeout = timeout )
617
665
618
- def recvline_startswith (self , delims , keepends = False , timeout = default ):
619
- r"""recvline_startswith(delims, keepends=False , timeout=default) -> bytes
666
+ def recvline_startswith (self , delims , drop = None , keepends = None , timeout = default ):
667
+ r"""recvline_startswith(delims, drop=True , timeout=default) -> bytes
620
668
621
669
Keep receiving lines until one is found that starts with one of
622
670
`delims`. Returns the last line received.
@@ -626,7 +674,7 @@ def recvline_startswith(self, delims, keepends=False, timeout=default):
626
674
627
675
Arguments:
628
676
delims(str,tuple): List of strings to search for, or string of single characters
629
- keepends (bool): Return lines with newlines if :const:`True`
677
+ drop (bool): Drop the line ending ( :const:`True`).
630
678
timeout(int): Timeout, in seconds
631
679
632
680
Returns:
@@ -638,7 +686,7 @@ def recvline_startswith(self, delims, keepends=False, timeout=default):
638
686
>>> t.recv_raw = lambda n: b"Hello\nWorld\nXylophone\n"
639
687
>>> t.recvline_startswith((b'W',b'X',b'Y',b'Z'))
640
688
b'World'
641
- >>> t.recvline_startswith((b'W',b'X',b'Y',b'Z'), True )
689
+ >>> t.recvline_startswith((b'W',b'X',b'Y',b'Z'), drop=False )
642
690
b'Xylophone\n'
643
691
>>> t.recvline_startswith(b'Wo')
644
692
b'World'
@@ -649,11 +697,12 @@ def recvline_startswith(self, delims, keepends=False, timeout=default):
649
697
delims = tuple (map (packing ._need_bytes , delims ))
650
698
651
699
return self .recvline_pred (lambda line : any (map (line .startswith , delims )),
700
+ drop = drop ,
652
701
keepends = keepends ,
653
702
timeout = timeout )
654
703
655
- def recvline_endswith (self , delims , keepends = False , timeout = default ):
656
- r"""recvline_endswith(delims, keepends=False , timeout=default) -> bytes
704
+ def recvline_endswith (self , delims , drop = None , keepends = None , timeout = default ):
705
+ r"""recvline_endswith(delims, drop=True , timeout=default) -> bytes
657
706
658
707
Keep receiving lines until one is found that ends with one of
659
708
`delims`. Returns the last line received.
@@ -669,7 +718,7 @@ def recvline_endswith(self, delims, keepends=False, timeout=default):
669
718
>>> t.recv_raw = lambda n: b'Foo\nBar\nBaz\nKaboodle\n'
670
719
>>> t.recvline_endswith(b'r')
671
720
b'Bar'
672
- >>> t.recvline_endswith((b'a',b'b',b'c',b'd',b'e'), True )
721
+ >>> t.recvline_endswith((b'a',b'b',b'c',b'd',b'e'), drop=False )
673
722
b'Kaboodle\n'
674
723
>>> t.recvline_endswith(b'oodle')
675
724
b'Kaboodle'
@@ -681,6 +730,7 @@ def recvline_endswith(self, delims, keepends=False, timeout=default):
681
730
delims = tuple (packing ._need_bytes (delim ) + self .newline for delim in delims )
682
731
683
732
return self .recvline_pred (lambda line : any (map (line .endswith , delims )),
733
+ drop = drop ,
684
734
keepends = keepends ,
685
735
timeout = timeout )
686
736
@@ -724,8 +774,8 @@ def recvregex(self, regex, exact=False, timeout=default, capture=False):
724
774
else :
725
775
return self .recvpred (pred , timeout = timeout )
726
776
727
- def recvline_regex (self , regex , exact = False , keepends = False , timeout = default ):
728
- """recvline_regex(regex, exact=False, keepends=False , timeout=default) -> bytes
777
+ def recvline_regex (self , regex , exact = False , drop = None , keepends = None , timeout = default ):
778
+ """recvline_regex(regex, exact=False, drop=True , timeout=default) -> bytes
729
779
730
780
Wrapper around :func:`recvline_pred`, which will return when a regex
731
781
matches a line.
@@ -746,7 +796,7 @@ def recvline_regex(self, regex, exact=False, keepends=False, timeout=default):
746
796
else :
747
797
pred = regex .search
748
798
749
- return self .recvline_pred (pred , keepends = keepends , timeout = timeout )
799
+ return self .recvline_pred (pred , drop = drop , keepends = keepends , timeout = timeout )
750
800
751
801
def recvrepeat (self , timeout = default ):
752
802
"""recvrepeat(timeout=default) -> bytes
@@ -1062,7 +1112,7 @@ def clean_and_log(self, timeout = 0.05):
1062
1112
>>> t.connected_raw = lambda d: True
1063
1113
>>> t.fileno = lambda: 1234
1064
1114
>>> with context.local(log_level='info'):
1065
- ... data = t.clean_and_log() #doctest: +ELLIPSIS
1115
+ ... data = t.clean_and_log()
1066
1116
[DEBUG] Received 0xb bytes:
1067
1117
b'hooray_data'
1068
1118
>>> data
0 commit comments