CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/spec/lib/msf/ui/text/dispatcher_shell_spec.rb
Views: 11766
1
require 'spec_helper'
2
require 'readline'
3
4
RSpec.describe Rex::Ui::Text::DispatcherShell do
5
let(:prompt) { '%undmsf6%clr' }
6
let(:prompt_char) { '%clr>' }
7
let(:subject) do
8
dummy_class = Class.new
9
dummy_class.include described_class
10
dummy_class.new(prompt, prompt_char)
11
end
12
13
def mock_dispatcher_for(completions:)
14
dispatcher = double :mock_dispatcher
15
allow(dispatcher).to receive(:tab_complete_helper) do |_current_word, _preceding_words|
16
completions
17
end
18
dispatcher
19
end
20
21
describe '#tab_complete' do
22
let(:dispatcher_stack) do
23
[
24
mock_dispatcher_for(completions: completions)
25
]
26
end
27
28
before(:each) do
29
allow(subject).to receive(:dispatcher_stack).and_return(dispatcher_stack)
30
end
31
32
context 'when tab completing options' do
33
let(:completions) { ['username=', 'password='] }
34
[
35
{ input: '', expected: nil },
36
{ input: ' ', expected: [' username=', ' password='] },
37
{ input: ' u', expected: [' username='] },
38
{ input: 'password=abc user', expected: ['password=abc username='] },
39
{ input: 'password=a\\ b\\ c user', expected: ['password=a\\ b\\ c username='] },
40
{ input: "'password=a b c' user", expected: ["'password=a b c' username="] },
41
{ input: "password='a b c' user", expected: ["password='a b c' username="] },
42
{ input: "password='a b c' user", expected: ["password='a b c' username="] },
43
{ input: 'username=', expected: ['username='] },
44
{ input: 'password=abc ', expected: ['password=abc username=', 'password=abc password='] }
45
].each do |test|
46
it "provides completion for #{test[:input].inspect}" do
47
expect(subject.tab_complete(test[:input])).to eql(test[:expected])
48
end
49
end
50
end
51
52
context 'when tab completing paths' do
53
context 'when the paths are relative' do
54
let(:completions) { ['$Recycle.Bin', 'Program Files (x86)', 'Program Files', 'Documents and Settings'] }
55
56
[
57
{ input: '', expected: nil },
58
{ input: 'cd ', expected: ['cd $Recycle.Bin', 'cd Program\\ Files\\ (x86)', 'cd Program\\ Files', 'cd Documents\\ and\\ Settings'] },
59
{ input: 'cd P', expected: ['cd Program\\ Files\\ (x86)', 'cd Program\\ Files'] },
60
{ input: "cd 'Progra", expected: ["cd 'Program Files (x86)'", "cd 'Program Files'"] },
61
{ input: 'cd "Program"', expected: ['cd "Program Files (x86)"', 'cd "Program Files"'] },
62
{ input: "cd 'Program Files", expected: ["cd 'Program Files (x86)'", "cd 'Program Files'"] },
63
{ input: "cd 'Program\\ Files", expected: [] },
64
{ input: "cd 'Program\\\\ Files", expected: [] },
65
{ input: 'cd Program\\ Files', expected: ['cd Program\\ Files\\ (x86)', 'cd Program\\ Files'] },
66
].each do |test|
67
it "provides completion for #{test[:input].inspect}" do
68
expect(subject.tab_complete(test[:input])).to eql(test[:expected])
69
end
70
end
71
end
72
73
context 'when the paths are absolute' do
74
let(:completions) { ['C:\\$Recycle.Bin', 'C:\\Program Files (x86)', 'C:\\Program Files', 'C:\\Documents and Settings'] }
75
76
[
77
{ input: '', expected: nil },
78
{ input: 'cd ', expected: ['cd C:\\\\$Recycle.Bin', 'cd C:\\\\Program\\ Files\\ (x86)', 'cd C:\\\\Program\\ Files', 'cd C:\\\\Documents\\ and\\ Settings'] },
79
{ input: 'cd C:', expected: ['cd C:\\\\$Recycle.Bin', 'cd C:\\\\Program\\ Files\\ (x86)', 'cd C:\\\\Program\\ Files', 'cd C:\\\\Documents\\ and\\ Settings'] },
80
{ input: "cd 'C:\\Progra", expected: ["cd 'C:\\Program Files (x86)'", "cd 'C:\\Program Files'"] },
81
{ input: 'cd "C:\\Program"', expected: ['cd "C:\\Program Files (x86)"', 'cd "C:\\Program Files"'] },
82
{ input: "cd 'C:\\Program Files", expected: ["cd 'C:\\Program Files (x86)'", "cd 'C:\\Program Files'"] },
83
{ input: "cd 'C:\\Program\\ Files", expected: [] },
84
{ input: "cd 'C:\\Program\\\\ Files", expected: [] },
85
{ input: 'cd C:\\\\Program\\ Files', expected: ['cd C:\\\\Program\\ Files\\ (x86)', 'cd C:\\\\Program\\ Files'] },
86
].each do |test|
87
it "provides completion for #{test[:input].inspect}" do
88
expect(subject.tab_complete(test[:input])).to eql(test[:expected])
89
end
90
end
91
end
92
end
93
end
94
95
describe '#shellsplitex' do
96
[
97
{
98
input: '',
99
expected: {
100
tokens: [
101
]
102
}
103
},
104
105
{
106
input: ' ',
107
focus: true,
108
expected: {
109
tokens: [
110
]
111
}
112
},
113
114
{
115
input: 'foo bar',
116
focus: true,
117
expected: {
118
tokens: [
119
{ begin: 0, value: 'foo', quote: nil },
120
{ begin: 10, value: 'bar', quote: nil }
121
]
122
}
123
},
124
125
{
126
input: 'dir',
127
expected: {
128
tokens: [
129
{ begin: 0, value: 'dir', quote: nil }
130
]
131
}
132
},
133
134
{
135
input: 'dir "/"',
136
expected: {
137
tokens: [
138
{ begin: 0, value: 'dir', quote: nil },
139
{ begin: 4, value: '/', quote: '"' }
140
]
141
}
142
},
143
144
{
145
input: 'dir "/',
146
expected: {
147
tokens: [
148
{ begin: 0, value: 'dir', quote: nil },
149
{ begin: 4, value: '/', quote: '"' }
150
]
151
}
152
},
153
154
{
155
input: 'dir "/Program',
156
expected: {
157
tokens: [
158
{ begin: 0, value: 'dir', quote: nil },
159
{ begin: 4, value: '/Program', quote: '"' }
160
]
161
}
162
},
163
164
{
165
input: 'dir "/Program/',
166
expected: {
167
tokens: [
168
{ begin: 0, value: 'dir', quote: nil },
169
{ begin: 4, value: '/Program/', quote: '"' }
170
]
171
}
172
},
173
174
{
175
input: 'dir C:\\Pro',
176
expected: {
177
tokens: [
178
{ begin: 0, value: 'dir', quote: nil },
179
{ begin: 4, value: 'C:Pro', quote: nil }
180
]
181
}
182
},
183
184
{
185
input: 'dir "C:\\Pro"',
186
expected: {
187
tokens: [
188
{ begin: 0, value: 'dir', quote: nil },
189
{ begin: 4, value: 'C:\\Pro', quote: '"' }
190
]
191
}
192
},
193
194
{
195
input: "dir 'C:\\Pro'",
196
expected: {
197
tokens: [
198
{ begin: 0, value: 'dir', quote: nil },
199
{ begin: 4, value: 'C:\\Pro', quote: "'" }
200
]
201
}
202
},
203
204
{
205
input: "dir 'C:\\ProgramData\\jim\\bob.rb'",
206
expected: {
207
tokens: [
208
{ begin: 0, value: 'dir', quote: nil },
209
{ begin: 4, value: 'C:\\ProgramData\\jim\\bob.rb', quote: "'" }
210
]
211
}
212
},
213
214
{
215
input: "dir 'C:\\ProgramData\\jim\\'",
216
expected: {
217
tokens: [
218
{ begin: 0, value: 'dir', quote: nil },
219
{ begin: 4, value: 'C:\\ProgramData\\jim\\', quote: "'" }
220
]
221
}
222
},
223
224
{
225
input: 'dir "C:\\Pro',
226
expected: {
227
tokens: [
228
{ begin: 0, value: 'dir', quote: nil },
229
{ begin: 4, value: 'C:\\Pro', quote: '"' }
230
]
231
}
232
},
233
234
{
235
input: 'dir "C: \\Pro',
236
expected: {
237
tokens: [
238
{ begin: 0, value: 'dir', quote: nil },
239
{ begin: 4, value: 'C: \\Pro', quote: '"' }
240
]
241
}
242
},
243
244
{
245
input: 'dir "C:\\Program F',
246
expected: {
247
tokens: [
248
{ begin: 0, value: 'dir', quote: nil },
249
{ begin: 4, value: 'C:\\Program F', quote: '"' },
250
]
251
}
252
},
253
254
{
255
input: 'cd C:\\\\Program\\ F',
256
expected: {
257
tokens: [
258
{ begin: 0, value: 'cd', quote: nil },
259
{ begin: 4, value: 'C:\\Program F', quote: nil },
260
]
261
}
262
},
263
264
{
265
input: 'cd "C:\\Program F',
266
expected: {
267
tokens: [
268
{ begin: 0, value: 'cd', quote: nil },
269
{ begin: 4, value: 'C:\\Program F', quote: '"' },
270
]
271
}
272
},
273
274
{
275
input: "cd 'C:\\\\Program F",
276
expected: {
277
tokens: [
278
{ begin: 0, value: 'cd', quote: nil },
279
{ begin: 4, value: 'C:\\Program F', quote: "'" },
280
]
281
}
282
},
283
284
{
285
input: "cd 'Progra",
286
expected: {
287
tokens: [
288
{ begin: 0, value: 'cd', quote: nil },
289
{ begin: 4, value: 'Progra', quote: "'" },
290
]
291
}
292
},
293
294
{
295
input: 'pass=a\\ b\\ c user',
296
expected: {
297
tokens: [
298
{ begin: 0, value: 'pass=a b c', quote: nil },
299
{ begin: 13, value: 'user', quote: nil },
300
]
301
}
302
},
303
304
{
305
input: "'pass=a b' username=\"",
306
expected: {
307
tokens: [
308
{ begin: 0, value: 'pass=a b', quote: "'" },
309
{ begin: 11, value: 'username=', quote: '"' },
310
]
311
}
312
},
313
314
{
315
input: "pass='a b' user",
316
expected: {
317
tokens: [
318
{ begin: 0, value: 'pass=a b', quote: "'" },
319
{ begin: 11, value: 'user', quote: nil },
320
]
321
}
322
},
323
].each do |test|
324
it "correctly parses #{test[:input]}" do
325
expect(subject.shellsplitex(test[:input])).to eql(test[:expected])
326
end
327
end
328
end
329
end
330
331