net-ssh 5.0.2 → 7.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.dockerignore +6 -0
- data/.github/config/rubocop_linter_action.yml +4 -0
- data/.github/workflows/ci-with-docker.yml +44 -0
- data/.github/workflows/ci.yml +87 -0
- data/.github/workflows/rubocop.yml +13 -0
- data/.gitignore +3 -0
- data/.rubocop.yml +19 -2
- data/.rubocop_todo.yml +623 -511
- data/CHANGES.txt +76 -0
- data/Dockerfile +27 -0
- data/Dockerfile.openssl3 +17 -0
- data/Gemfile +2 -0
- data/Gemfile.noed25519 +2 -0
- data/Manifest +0 -1
- data/README.md +293 -0
- data/Rakefile +6 -2
- data/appveyor.yml +4 -2
- data/docker-compose.yml +23 -0
- data/lib/net/ssh/authentication/agent.rb +36 -14
- data/lib/net/ssh/authentication/certificate.rb +19 -7
- data/lib/net/ssh/authentication/constants.rb +0 -1
- data/lib/net/ssh/authentication/ed25519.rb +83 -50
- data/lib/net/ssh/authentication/ed25519_loader.rb +5 -8
- data/lib/net/ssh/authentication/key_manager.rb +74 -33
- data/lib/net/ssh/authentication/methods/abstract.rb +12 -3
- data/lib/net/ssh/authentication/methods/hostbased.rb +3 -5
- data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +5 -3
- data/lib/net/ssh/authentication/methods/none.rb +6 -9
- data/lib/net/ssh/authentication/methods/password.rb +2 -3
- data/lib/net/ssh/authentication/methods/publickey.rb +58 -16
- data/lib/net/ssh/authentication/pageant.rb +97 -97
- data/lib/net/ssh/authentication/pub_key_fingerprint.rb +2 -3
- data/lib/net/ssh/authentication/session.rb +27 -23
- data/lib/net/ssh/buffer.rb +91 -40
- data/lib/net/ssh/buffered_io.rb +24 -26
- data/lib/net/ssh/config.rb +99 -53
- data/lib/net/ssh/connection/channel.rb +101 -87
- data/lib/net/ssh/connection/constants.rb +0 -4
- data/lib/net/ssh/connection/event_loop.rb +30 -25
- data/lib/net/ssh/connection/keepalive.rb +12 -12
- data/lib/net/ssh/connection/session.rb +115 -111
- data/lib/net/ssh/connection/term.rb +56 -58
- data/lib/net/ssh/errors.rb +12 -12
- data/lib/net/ssh/key_factory.rb +108 -22
- data/lib/net/ssh/known_hosts.rb +120 -36
- data/lib/net/ssh/loggable.rb +10 -11
- data/lib/net/ssh/packet.rb +1 -1
- data/lib/net/ssh/prompt.rb +9 -11
- data/lib/net/ssh/proxy/command.rb +1 -2
- data/lib/net/ssh/proxy/errors.rb +2 -4
- data/lib/net/ssh/proxy/http.rb +18 -20
- data/lib/net/ssh/proxy/https.rb +8 -10
- data/lib/net/ssh/proxy/jump.rb +8 -10
- data/lib/net/ssh/proxy/socks4.rb +2 -4
- data/lib/net/ssh/proxy/socks5.rb +3 -6
- data/lib/net/ssh/service/forward.rb +9 -8
- data/lib/net/ssh/test/channel.rb +24 -26
- data/lib/net/ssh/test/extensions.rb +37 -35
- data/lib/net/ssh/test/kex.rb +6 -8
- data/lib/net/ssh/test/local_packet.rb +0 -2
- data/lib/net/ssh/test/packet.rb +3 -3
- data/lib/net/ssh/test/remote_packet.rb +6 -8
- data/lib/net/ssh/test/script.rb +25 -27
- data/lib/net/ssh/test/socket.rb +12 -15
- data/lib/net/ssh/test.rb +12 -12
- data/lib/net/ssh/transport/algorithms.rb +177 -118
- data/lib/net/ssh/transport/cipher_factory.rb +34 -50
- data/lib/net/ssh/transport/constants.rb +13 -9
- data/lib/net/ssh/transport/ctr.rb +8 -14
- data/lib/net/ssh/transport/hmac/abstract.rb +20 -5
- data/lib/net/ssh/transport/hmac/md5.rb +0 -2
- data/lib/net/ssh/transport/hmac/md5_96.rb +0 -2
- data/lib/net/ssh/transport/hmac/none.rb +0 -2
- data/lib/net/ssh/transport/hmac/ripemd160.rb +0 -2
- data/lib/net/ssh/transport/hmac/sha1.rb +0 -2
- data/lib/net/ssh/transport/hmac/sha1_96.rb +0 -2
- data/lib/net/ssh/transport/hmac/sha2_256.rb +7 -11
- data/lib/net/ssh/transport/hmac/sha2_256_96.rb +4 -8
- data/lib/net/ssh/transport/hmac/sha2_256_etm.rb +12 -0
- data/lib/net/ssh/transport/hmac/sha2_512.rb +6 -9
- data/lib/net/ssh/transport/hmac/sha2_512_96.rb +4 -8
- data/lib/net/ssh/transport/hmac/sha2_512_etm.rb +12 -0
- data/lib/net/ssh/transport/hmac.rb +13 -11
- data/lib/net/ssh/transport/identity_cipher.rb +11 -13
- data/lib/net/ssh/transport/kex/abstract.rb +130 -0
- data/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
- data/lib/net/ssh/transport/kex/curve25519_sha256.rb +39 -0
- data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +5 -19
- data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +30 -139
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +1 -8
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +5 -9
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +20 -81
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +5 -4
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +5 -4
- data/lib/net/ssh/transport/kex.rb +15 -10
- data/lib/net/ssh/transport/key_expander.rb +7 -8
- data/lib/net/ssh/transport/openssl.rb +149 -111
- data/lib/net/ssh/transport/packet_stream.rb +53 -22
- data/lib/net/ssh/transport/server_version.rb +17 -16
- data/lib/net/ssh/transport/session.rb +35 -11
- data/lib/net/ssh/transport/state.rb +44 -44
- data/lib/net/ssh/verifiers/accept_new.rb +7 -2
- data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +1 -2
- data/lib/net/ssh/verifiers/always.rb +10 -4
- data/lib/net/ssh/verifiers/never.rb +4 -2
- data/lib/net/ssh/version.rb +2 -2
- data/lib/net/ssh.rb +17 -9
- data/net-ssh-public_cert.pem +18 -19
- data/net-ssh.gemspec +9 -7
- data/support/ssh_tunnel_bug.rb +3 -3
- data.tar.gz.sig +0 -0
- metadata +65 -41
- metadata.gz.sig +0 -0
- data/.travis.yml +0 -52
- data/Gemfile.noed25519.lock +0 -41
- data/README.rdoc +0 -169
- data/lib/net/ssh/ruby_compat.rb +0 -13
- data/support/arcfour_check.rb +0 -20
data/lib/net/ssh/test/script.rb
CHANGED
|
@@ -2,10 +2,9 @@ require 'net/ssh/test/channel'
|
|
|
2
2
|
require 'net/ssh/test/local_packet'
|
|
3
3
|
require 'net/ssh/test/remote_packet'
|
|
4
4
|
|
|
5
|
-
module Net
|
|
6
|
-
module SSH
|
|
5
|
+
module Net
|
|
6
|
+
module SSH
|
|
7
7
|
module Test
|
|
8
|
-
|
|
9
8
|
# Represents a sequence of scripted events that identify the behavior that
|
|
10
9
|
# a test expects. Methods named "sends_*" create events for packets being
|
|
11
10
|
# sent from the local to the remote host, and methods named "gets_*" create
|
|
@@ -22,41 +21,41 @@ module Net
|
|
|
22
21
|
# The list of scripted events. These will be Net::SSH::Test::LocalPacket
|
|
23
22
|
# and Net::SSH::Test::RemotePacket instances.
|
|
24
23
|
attr_reader :events
|
|
25
|
-
|
|
24
|
+
|
|
26
25
|
# Create a new, empty script.
|
|
27
26
|
def initialize
|
|
28
27
|
@events = []
|
|
29
28
|
end
|
|
30
|
-
|
|
29
|
+
|
|
31
30
|
# Scripts the opening of a channel by adding a local packet sending the
|
|
32
31
|
# channel open request, and if +confirm+ is true (the default), also
|
|
33
32
|
# adding a remote packet confirming the new channel.
|
|
34
33
|
#
|
|
35
34
|
# A new Net::SSH::Test::Channel instance is returned, which can be used
|
|
36
35
|
# to script additional channel operations.
|
|
37
|
-
def opens_channel(confirm=true)
|
|
36
|
+
def opens_channel(confirm = true)
|
|
38
37
|
channel = Channel.new(self)
|
|
39
38
|
channel.remote_id = 5555
|
|
40
|
-
|
|
39
|
+
|
|
41
40
|
events << LocalPacket.new(:channel_open) { |p| channel.local_id = p[:remote_id] }
|
|
42
|
-
|
|
41
|
+
|
|
43
42
|
events << RemotePacket.new(:channel_open_confirmation, channel.local_id, channel.remote_id, 0x20000, 0x10000) if confirm
|
|
44
|
-
|
|
43
|
+
|
|
45
44
|
channel
|
|
46
45
|
end
|
|
47
|
-
|
|
46
|
+
|
|
48
47
|
# A convenience method for adding an arbitrary local packet to the events
|
|
49
48
|
# list.
|
|
50
49
|
def sends(type, *args, &block)
|
|
51
50
|
events << LocalPacket.new(type, *args, &block)
|
|
52
51
|
end
|
|
53
|
-
|
|
52
|
+
|
|
54
53
|
# A convenience method for adding an arbitrary remote packet to the events
|
|
55
54
|
# list.
|
|
56
55
|
def gets(type, *args)
|
|
57
56
|
events << RemotePacket.new(type, *args)
|
|
58
57
|
end
|
|
59
|
-
|
|
58
|
+
|
|
60
59
|
# Scripts the sending of a new channel request packet to the remote host.
|
|
61
60
|
# +channel+ should be an instance of Net::SSH::Test::Channel. +request+
|
|
62
61
|
# is a string naming the request type to send, +reply+ is a boolean
|
|
@@ -71,7 +70,7 @@ module Net
|
|
|
71
70
|
#
|
|
72
71
|
# This will typically be called via Net::SSH::Test::Channel#sends_exec or
|
|
73
72
|
# Net::SSH::Test::Channel#sends_subsystem.
|
|
74
|
-
def sends_channel_request(channel, request, reply, data, success=true)
|
|
73
|
+
def sends_channel_request(channel, request, reply, data, success = true)
|
|
75
74
|
if data.is_a? Array
|
|
76
75
|
events << LocalPacket.new(:channel_request, channel.remote_id, request, reply, *data)
|
|
77
76
|
else
|
|
@@ -85,7 +84,7 @@ module Net
|
|
|
85
84
|
end
|
|
86
85
|
end
|
|
87
86
|
end
|
|
88
|
-
|
|
87
|
+
|
|
89
88
|
# Scripts the sending of a channel data packet. +channel+ must be a
|
|
90
89
|
# Net::SSH::Test::Channel object, and +data+ is the (string) data to
|
|
91
90
|
# expect will be sent.
|
|
@@ -94,21 +93,21 @@ module Net
|
|
|
94
93
|
def sends_channel_data(channel, data)
|
|
95
94
|
events << LocalPacket.new(:channel_data, channel.remote_id, data)
|
|
96
95
|
end
|
|
97
|
-
|
|
96
|
+
|
|
98
97
|
# Scripts the sending of a channel EOF packet from the given
|
|
99
98
|
# Net::SSH::Test::Channel +channel+. This will typically be called via
|
|
100
99
|
# Net::SSH::Test::Channel#sends_eof.
|
|
101
100
|
def sends_channel_eof(channel)
|
|
102
101
|
events << LocalPacket.new(:channel_eof, channel.remote_id)
|
|
103
102
|
end
|
|
104
|
-
|
|
103
|
+
|
|
105
104
|
# Scripts the sending of a channel close packet from the given
|
|
106
105
|
# Net::SSH::Test::Channel +channel+. This will typically be called via
|
|
107
106
|
# Net::SSH::Test::Channel#sends_close.
|
|
108
107
|
def sends_channel_close(channel)
|
|
109
108
|
events << LocalPacket.new(:channel_close, channel.remote_id)
|
|
110
109
|
end
|
|
111
|
-
|
|
110
|
+
|
|
112
111
|
# Scripts the sending of a channel request pty packets from the given
|
|
113
112
|
# Net::SSH::Test::Channel +channel+. This will typically be called via
|
|
114
113
|
# Net::SSH::Test::Channel#sends_request_pty.
|
|
@@ -117,14 +116,14 @@ module Net
|
|
|
117
116
|
data += Net::SSH::Connection::Channel::VALID_PTY_OPTIONS.merge(modes: "\0").values
|
|
118
117
|
events << LocalPacket.new(:channel_request, channel.remote_id, *data)
|
|
119
118
|
end
|
|
120
|
-
|
|
119
|
+
|
|
121
120
|
# Scripts the reception of a channel data packet from the remote host by
|
|
122
121
|
# the given Net::SSH::Test::Channel +channel+. This will typically be
|
|
123
122
|
# called via Net::SSH::Test::Channel#gets_data.
|
|
124
123
|
def gets_channel_data(channel, data)
|
|
125
124
|
events << RemotePacket.new(:channel_data, channel.local_id, data)
|
|
126
125
|
end
|
|
127
|
-
|
|
126
|
+
|
|
128
127
|
# Scripts the reception of a channel extended data packet from the remote
|
|
129
128
|
# host by the given Net::SSH::Test::Channel +channel+. This will typically
|
|
130
129
|
# be called via Net::SSH::Test::Channel#gets_extended_data.
|
|
@@ -133,28 +132,28 @@ module Net
|
|
|
133
132
|
def gets_channel_extended_data(channel, data)
|
|
134
133
|
events << RemotePacket.new(:channel_extended_data, channel.local_id, 1, data)
|
|
135
134
|
end
|
|
136
|
-
|
|
135
|
+
|
|
137
136
|
# Scripts the reception of a channel request packet from the remote host by
|
|
138
137
|
# the given Net::SSH::Test::Channel +channel+. This will typically be
|
|
139
138
|
# called via Net::SSH::Test::Channel#gets_exit_status.
|
|
140
139
|
def gets_channel_request(channel, request, reply, data)
|
|
141
140
|
events << RemotePacket.new(:channel_request, channel.local_id, request, reply, data)
|
|
142
141
|
end
|
|
143
|
-
|
|
142
|
+
|
|
144
143
|
# Scripts the reception of a channel EOF packet from the remote host by
|
|
145
144
|
# the given Net::SSH::Test::Channel +channel+. This will typically be
|
|
146
145
|
# called via Net::SSH::Test::Channel#gets_eof.
|
|
147
146
|
def gets_channel_eof(channel)
|
|
148
147
|
events << RemotePacket.new(:channel_eof, channel.local_id)
|
|
149
148
|
end
|
|
150
|
-
|
|
149
|
+
|
|
151
150
|
# Scripts the reception of a channel close packet from the remote host by
|
|
152
151
|
# the given Net::SSH::Test::Channel +channel+. This will typically be
|
|
153
152
|
# called via Net::SSH::Test::Channel#gets_close.
|
|
154
153
|
def gets_channel_close(channel)
|
|
155
154
|
events << RemotePacket.new(:channel_close, channel.local_id)
|
|
156
155
|
end
|
|
157
|
-
|
|
156
|
+
|
|
158
157
|
# By default, removes the next event in the list and returns it. However,
|
|
159
158
|
# this can also be used to non-destructively peek at the next event in the
|
|
160
159
|
# list, by passing :first as the argument.
|
|
@@ -164,10 +163,10 @@ module Net
|
|
|
164
163
|
#
|
|
165
164
|
# # peek at the next event
|
|
166
165
|
# event = script.next(:first)
|
|
167
|
-
def next(mode
|
|
166
|
+
def next(mode = :shift)
|
|
168
167
|
events.send(mode)
|
|
169
168
|
end
|
|
170
|
-
|
|
169
|
+
|
|
171
170
|
# Compare the given packet against the next event in the list. If there is
|
|
172
171
|
# no next event, an exception will be raised. This is called by
|
|
173
172
|
# Net::SSH::Test::Extensions::PacketStream#test_enqueue_packet.
|
|
@@ -176,7 +175,6 @@ module Net
|
|
|
176
175
|
event.process(packet)
|
|
177
176
|
end
|
|
178
177
|
end
|
|
179
|
-
|
|
180
178
|
end
|
|
181
179
|
end
|
|
182
|
-
end
|
|
180
|
+
end
|
data/lib/net/ssh/test/socket.rb
CHANGED
|
@@ -3,66 +3,63 @@ require 'stringio'
|
|
|
3
3
|
require 'net/ssh/test/extensions'
|
|
4
4
|
require 'net/ssh/test/script'
|
|
5
5
|
|
|
6
|
-
module Net
|
|
7
|
-
module SSH
|
|
6
|
+
module Net
|
|
7
|
+
module SSH
|
|
8
8
|
module Test
|
|
9
|
-
|
|
10
9
|
# A mock socket implementation for use in testing. It implements the minimum
|
|
11
10
|
# necessary interface for interacting with the rest of the Net::SSH::Test
|
|
12
11
|
# system.
|
|
13
12
|
class Socket < StringIO
|
|
14
13
|
attr_reader :host, :port
|
|
15
|
-
|
|
14
|
+
|
|
16
15
|
# The Net::SSH::Test::Script object in use by this socket. This is the
|
|
17
16
|
# canonical script instance that should be used for any test depending on
|
|
18
17
|
# this socket instance.
|
|
19
18
|
attr_reader :script
|
|
20
|
-
|
|
19
|
+
|
|
21
20
|
# Create a new test socket. This will also instantiate a new Net::SSH::Test::Script
|
|
22
21
|
# and seed it with the necessary events to power the initialization of the
|
|
23
22
|
# connection.
|
|
24
23
|
def initialize
|
|
25
24
|
extend(Net::SSH::Transport::PacketStream)
|
|
26
25
|
super "SSH-2.0-Test\r\n"
|
|
27
|
-
|
|
26
|
+
|
|
28
27
|
@script = Script.new
|
|
29
|
-
|
|
28
|
+
|
|
30
29
|
script.sends(:kexinit)
|
|
31
30
|
script.gets(:kexinit, 1, 2, 3, 4, "test", "ssh-rsa", "none", "none", "none", "none", "none", "none", "", "", false)
|
|
32
31
|
script.sends(:newkeys)
|
|
33
32
|
script.gets(:newkeys)
|
|
34
33
|
end
|
|
35
|
-
|
|
34
|
+
|
|
36
35
|
# This doesn't actually do anything, since we don't really care what gets
|
|
37
36
|
# written.
|
|
38
37
|
def write(data)
|
|
39
38
|
# black hole, because we don't actually care about what gets written
|
|
40
39
|
end
|
|
41
|
-
|
|
40
|
+
|
|
42
41
|
# Allows the socket to also mimic a socket factory, simply returning
|
|
43
42
|
# +self+.
|
|
44
|
-
def open(host, port, options={})
|
|
43
|
+
def open(host, port, options = {})
|
|
45
44
|
@host, @port = host, port
|
|
46
45
|
self
|
|
47
46
|
end
|
|
48
|
-
|
|
47
|
+
|
|
49
48
|
# Returns a sockaddr struct for the port and host that were used when the
|
|
50
49
|
# socket was instantiated.
|
|
51
50
|
def getpeername
|
|
52
51
|
::Socket.sockaddr_in(port, host)
|
|
53
52
|
end
|
|
54
|
-
|
|
53
|
+
|
|
55
54
|
# Alias to #read, but never returns nil (returns an empty string instead).
|
|
56
55
|
def recv(n)
|
|
57
56
|
read(n) || ""
|
|
58
57
|
end
|
|
59
|
-
|
|
58
|
+
|
|
60
59
|
def readpartial(n)
|
|
61
60
|
recv(n)
|
|
62
61
|
end
|
|
63
|
-
|
|
64
62
|
end
|
|
65
|
-
|
|
66
63
|
end
|
|
67
64
|
end
|
|
68
65
|
end
|
data/lib/net/ssh/test.rb
CHANGED
|
@@ -3,9 +3,8 @@ require 'net/ssh/connection/session'
|
|
|
3
3
|
require 'net/ssh/test/kex'
|
|
4
4
|
require 'net/ssh/test/socket'
|
|
5
5
|
|
|
6
|
-
module Net
|
|
6
|
+
module Net
|
|
7
7
|
module SSH
|
|
8
|
-
|
|
9
8
|
# This module may be used in unit tests, for when you want to test that your
|
|
10
9
|
# SSH state machines are really doing what you expect they are doing. You will
|
|
11
10
|
# typically include this module in your unit test class, and then build a
|
|
@@ -54,30 +53,30 @@ module Net
|
|
|
54
53
|
Net::SSH::Test::Extensions::IO.with_test_extension { yield socket.script if block_given? }
|
|
55
54
|
return socket.script
|
|
56
55
|
end
|
|
57
|
-
|
|
56
|
+
|
|
58
57
|
# Returns the test socket instance to use for these tests (see
|
|
59
58
|
# Net::SSH::Test::Socket).
|
|
60
|
-
def socket(options={})
|
|
59
|
+
def socket(options = {})
|
|
61
60
|
@socket ||= Net::SSH::Test::Socket.new
|
|
62
61
|
end
|
|
63
|
-
|
|
62
|
+
|
|
64
63
|
# Returns the connection session (Net::SSH::Connection::Session) for use
|
|
65
64
|
# in these tests. It is a fully functional SSH session, operating over
|
|
66
65
|
# a mock socket (#socket).
|
|
67
|
-
def connection(options={})
|
|
66
|
+
def connection(options = {})
|
|
68
67
|
@connection ||= Net::SSH::Connection::Session.new(transport(options), options)
|
|
69
68
|
end
|
|
70
|
-
|
|
69
|
+
|
|
71
70
|
# Returns the transport session (Net::SSH::Transport::Session) for use
|
|
72
71
|
# in these tests. It is a fully functional SSH transport session, operating
|
|
73
72
|
# over a mock socket (#socket).
|
|
74
|
-
def transport(options={})
|
|
73
|
+
def transport(options = {})
|
|
75
74
|
@transport ||= Net::SSH::Transport::Session.new(
|
|
76
75
|
options[:host] || "localhost",
|
|
77
|
-
options.merge(kex: "test", host_key: "ssh-rsa", verify_host_key:
|
|
76
|
+
options.merge(kex: "test", host_key: "ssh-rsa", append_all_supported_algorithms: true, verify_host_key: :never, proxy: socket(options))
|
|
78
77
|
)
|
|
79
78
|
end
|
|
80
|
-
|
|
79
|
+
|
|
81
80
|
# First asserts that a story has been described (see #story). Then yields,
|
|
82
81
|
# and then asserts that all items described in the script have been
|
|
83
82
|
# processed. Typically, this is called immediately after a story has
|
|
@@ -85,10 +84,11 @@ module Net
|
|
|
85
84
|
# the block passed to this assertion.
|
|
86
85
|
def assert_scripted
|
|
87
86
|
raise "there is no script to be processed" if socket.script.events.empty?
|
|
87
|
+
|
|
88
88
|
Net::SSH::Test::Extensions::IO.with_test_extension { yield }
|
|
89
|
-
assert socket.script.events.empty?, "there should not be any remaining scripted events, but there are still
|
|
89
|
+
assert socket.script.events.empty?, "there should not be any remaining scripted events, but there are still" \
|
|
90
|
+
"#{socket.script.events.length} pending"
|
|
90
91
|
end
|
|
91
92
|
end
|
|
92
|
-
|
|
93
93
|
end
|
|
94
94
|
end
|