Skip to content

Commit 454ffc8

Browse files
committed
Improve echo probe to recognize CUB+EL instead of BS+SPACE+BS. Issue 6878
1 parent 9b0e95e commit 454ffc8

File tree

4 files changed

+97
-52
lines changed

4 files changed

+97
-52
lines changed

sources/PTYSession.m

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2603,10 +2603,6 @@ - (void)taskWasDeregistered {
26032603
// This is run in PTYTask's thread. It parses the input here and then queues an async task to run
26042604
// in the main thread to execute the parsed tokens.
26052605
- (void)threadedReadTask:(char *)buffer length:(int)length {
2606-
@synchronized (self) {
2607-
[_echoProbe updateEchoProbeStateWithBuffer:buffer length:length];
2608-
}
2609-
26102606
// Pass the input stream to the parser.
26112607
[_terminal.parser putStreamData:buffer length:length];
26122608

@@ -2620,6 +2616,10 @@ - (void)threadedReadTask:(char *)buffer length:(int)length {
26202616
return;
26212617
}
26222618

2619+
@synchronized (self) {
2620+
[_echoProbe updateEchoProbeStateWithTokenCVector:&vector];
2621+
}
2622+
26232623
// This limits the number of outstanding execution blocks to prevent the main thread from
26242624
// getting bogged down.
26252625
dispatch_semaphore_wait(_executionSemaphore, DISPATCH_TIME_FOREVER);

sources/iTermEchoProbe.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//
77

88
#import <Foundation/Foundation.h>
9+
#import "CVector.h"
910

1011
NS_ASSUME_NONNULL_BEGIN
1112

@@ -25,7 +26,7 @@ NS_ASSUME_NONNULL_BEGIN
2526

2627
- (void)beginProbeWithBackspace:(NSData *)backspaceData
2728
password:(NSString *)password;
28-
- (void)updateEchoProbeStateWithBuffer:(char *)buffer length:(int)length;
29+
- (void)updateEchoProbeStateWithTokenCVector:(CVector *)vector;
2930
- (void)enterPassword;
3031

3132
@end

sources/iTermEchoProbe.m

Lines changed: 51 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#import "iTermEchoProbe.h"
99

1010
#import "iTermAdvancedSettingsModel.h"
11+
#import "VT100Token.h"
1112

1213
typedef NS_ENUM(NSUInteger, iTermEchoProbeState) {
1314
iTermEchoProbeOff = 0,
@@ -47,61 +48,64 @@ - (void)beginProbeWithBackspace:(NSData *)backspace
4748
}
4849
}
4950

50-
- (void)updateEchoProbeStateWithBuffer:(char *)buffer length:(int)length {
51+
- (void)updateEchoProbeStateWithTokenCVector:(CVector *)vector {
5152
@synchronized(self) {
52-
if (_state == iTermEchoProbeOff) {
53+
if (_state == iTermEchoProbeOff || _state == iTermEchoProbeFailed) {
5354
return;
5455
}
55-
for (int i = 0; i < length; i++) {
56-
switch (_state) {
57-
case iTermEchoProbeOff:
58-
case iTermEchoProbeFailed:
59-
return;
60-
61-
case iTermEchoProbeWaiting:
62-
if (buffer[i] == '*') {
63-
_state = iTermEchoProbeOneAsterisk;
64-
} else {
65-
_state = iTermEchoProbeFailed;
66-
return;
67-
}
68-
break;
69-
70-
case iTermEchoProbeOneAsterisk:
71-
if (buffer[i] == '\b') {
72-
_state = iTermEchoProbeBackspaceOverAsterisk;
73-
} else {
74-
_state = iTermEchoProbeFailed;
75-
return;
76-
}
77-
break;
78-
79-
case iTermEchoProbeBackspaceOverAsterisk:
80-
if (buffer[i] == ' ') {
81-
_state = iTermEchoProbeSpaceOverAsterisk;
82-
} else {
83-
_state = iTermEchoProbeFailed;
84-
return;
85-
}
86-
break;
87-
88-
case iTermEchoProbeSpaceOverAsterisk:
89-
if (buffer[i] == '\b') {
90-
_state = iTermEchoProbeBackspaceOverSpace;
91-
} else {
92-
_state = iTermEchoProbeFailed;
93-
return;
94-
}
95-
break;
96-
97-
case iTermEchoProbeBackspaceOverSpace:
98-
_state = iTermEchoProbeFailed;
99-
return;
56+
const int count = CVectorCount(vector);
57+
for (int i = 0; i < count; i++) {
58+
VT100Token *token = CVectorGetObject(vector, i);
59+
_state = iTermEchoProbeGetNextState(_state, token);
60+
if (_state == iTermEchoProbeOff || _state == iTermEchoProbeFailed) {
61+
break;
10062
}
10163
}
10264
}
10365
}
10466

67+
iTermEchoProbeState iTermEchoProbeGetNextState(iTermEchoProbeState state, VT100Token *token) {
68+
switch (state) {
69+
case iTermEchoProbeOff:
70+
case iTermEchoProbeFailed:
71+
return state;
72+
73+
case iTermEchoProbeWaiting:
74+
if (token->type == VT100_ASCIISTRING && [[token stringForAsciiData] isEqualToString:@"*"]) {
75+
return iTermEchoProbeOneAsterisk;
76+
} else {
77+
return iTermEchoProbeFailed;
78+
}
79+
80+
case iTermEchoProbeOneAsterisk:
81+
if (token->type == VT100CC_BS ||
82+
(token->type == VT100CSI_CUB && token.csi->p[0] == 1)) {
83+
return iTermEchoProbeBackspaceOverAsterisk;
84+
} else {
85+
return iTermEchoProbeFailed;
86+
}
87+
88+
case iTermEchoProbeBackspaceOverAsterisk:
89+
if (token->type == VT100_ASCIISTRING && [[token stringForAsciiData] isEqualToString:@" "]) {
90+
return iTermEchoProbeSpaceOverAsterisk;
91+
} else if (token->type == VT100CSI_EL && token.csi->p[0] == 0) {
92+
return iTermEchoProbeBackspaceOverSpace;
93+
} else {
94+
return iTermEchoProbeFailed;
95+
}
96+
97+
case iTermEchoProbeSpaceOverAsterisk:
98+
if (token->type == VT100CC_BS) {
99+
return iTermEchoProbeBackspaceOverSpace;
100+
} else {
101+
return iTermEchoProbeFailed;
102+
}
103+
104+
case iTermEchoProbeBackspaceOverSpace:
105+
return iTermEchoProbeFailed;
106+
}
107+
}
108+
105109
- (void)enterPassword {
106110
[self.delegate echoProbeWriteString:_password];
107111
[self.delegate echoProbeWriteString:@"\n"];

tests/echo_probe_test.sh

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/bin/bash
2+
3+
unset PASSWORD
4+
unset CHARCOUNT
5+
6+
echo -n "Enter password: "
7+
8+
stty -echo
9+
10+
CHARCOUNT=0
11+
while IFS= read -p "$PROMPT" -r -s -n 1 CHAR
12+
do
13+
# Enter - accept password
14+
if [[ $CHAR == $'\0' ]] ; then
15+
break
16+
fi
17+
# Backspace
18+
if [[ $CHAR == $'\177' ]] ; then
19+
if [ $CHARCOUNT -gt 0 ] ; then
20+
CHARCOUNT=$((CHARCOUNT-1))
21+
PROMPT=$'\b \b'
22+
# Alternate way of erasing a character that the echo probe understands:
23+
# PROMPT=$''
24+
PASSWORD="${PASSWORD%?}"
25+
else
26+
PROMPT=''
27+
fi
28+
else
29+
CHARCOUNT=$((CHARCOUNT+1))
30+
PROMPT='*'
31+
PASSWORD+="$CHAR"
32+
fi
33+
done
34+
35+
stty echo
36+
37+
echo ""
38+
echo Your password is:
39+
echo $PASSWORD
40+

0 commit comments

Comments
 (0)