@@ -17,26 +17,160 @@ function curlToGo(curl) {
17
17
// List of curl flags that are boolean typed; this helps with parsing
18
18
// a command like `curl -abc value` to know whether 'value' belongs to '-c'
19
19
// or is just a positional argument instead.
20
- var boolOptions = [ '#' , 'progress-bar' , '-' , 'next' , '0' , 'http1.0' , 'http1.1' , 'http2' ,
21
- 'no-npn' , 'no-alpn' , '1' , 'tlsv1' , '2' , 'sslv2' , '3' , 'sslv3' , '4' , 'ipv4' , '6' , 'ipv6' ,
22
- 'a' , 'append' , 'anyauth' , 'B' , 'use-ascii' , 'basic' , 'compressed' , 'create-dirs' ,
23
- 'crlf' , 'digest' , 'disable-eprt' , 'disable-epsv' , 'environment' , 'cert-status' ,
24
- 'false-start' , 'f' , 'fail' , 'ftp-create-dirs' , 'ftp-pasv' , 'ftp-skip-pasv-ip' ,
25
- 'ftp-pret' , 'ftp-ssl-ccc' , 'ftp-ssl-control' , 'g' , 'globoff' , 'G' , 'get' ,
26
- 'ignore-content-length' , 'i' , 'include' , 'I' , 'head' , 'j' , 'junk-session-cookies' ,
27
- 'J' , 'remote-header-name' , 'k' , 'insecure' , 'l' , 'list-only' , 'L' , 'location' ,
28
- 'location-trusted' , 'metalink' , 'n' , 'netrc' , 'N' , 'no-buffer' , 'netrc-file' ,
29
- 'netrc-optional' , 'negotiate' , 'no-keepalive' , 'no-sessionid' , 'ntlm' , 'O' ,
30
- 'remote-name' , 'oauth2-bearer' , 'p' , 'proxy-tunnel' , 'path-as-is' , 'post301' , 'post302' ,
31
- 'post303' , 'proxy-anyauth' , 'proxy-basic' , 'proxy-digest' , 'proxy-negotiate' ,
32
- 'proxy-ntlm' , 'q' , 'raw' , 'remote-name-all' , 's' , 'silent' , 'sasl-ir' , 'S' , 'show-error' ,
33
- 'ssl' , 'ssl-reqd' , 'ssl-allow-beast' , 'ssl-no-revoke' , 'socks5-gssapi-nec' , 'tcp-nodelay' ,
34
- 'tlsv1.0' , 'tlsv1.1' , 'tlsv1.2' , 'tr-encoding' , 'trace-time' , 'v' , 'verbose' , 'xattr' ,
35
- 'h' , 'help' , 'M' , 'manual' , 'V' , 'version' ] ;
20
+ // https://github.com/curl/curl/blob/f410b9e538129e77607fef1894f96c684a7c8c3b/src/tool_getparam.c#L73-L341
21
+ var boolOptions = new Set ( [
22
+ 'disable-epsv' , 'no-disable-epsv' , 'disallow-username-in-url' , 'no-disallow-username-in-url' ,
23
+ 'epsv' , 'no-epsv' , 'npn' , 'no-npn' , 'alpn' , 'no-alpn' , 'compressed' , 'no-compressed' ,
24
+ 'tr-encoding' , 'no-tr-encoding' , 'digest' , 'no-digest' , 'negotiate' , 'no-negotiate' ,
25
+ 'ntlm' , 'no-ntlm' , 'ntlm-wb' , 'no-ntlm-wb' , 'basic' , 'no-basic' , 'anyauth' , 'no-anyauth' ,
26
+ 'wdebug' , 'no-wdebug' , 'ftp-create-dirs' , 'no-ftp-create-dirs' ,
27
+ 'create-dirs' , 'no-create-dirs' , 'proxy-ntlm' , 'no-proxy-ntlm' , 'crlf' , 'no-crlf' ,
28
+ 'haproxy-protocol' , 'no-haproxy-protocol' , 'disable-eprt' , 'no-disable-eprt' ,
29
+ 'eprt' , 'no-eprt' , 'xattr' , 'no-xattr' , 'ftp-ssl' , 'no-ftp-ssl' , 'ssl' , 'no-ssl' ,
30
+ 'ftp-pasv' , 'no-ftp-pasv' , 'tcp-nodelay' , 'no-tcp-nodelay' , 'proxy-digest' , 'no-proxy-digest' ,
31
+ 'proxy-basic' , 'no-proxy-basic' , 'retry-connrefused' , 'no-retry-connrefused' ,
32
+ 'proxy-negotiate' , 'no-proxy-negotiate' , 'proxy-anyauth' , 'no-proxy-anyauth' ,
33
+ 'trace-time' , 'no-trace-time' , 'ignore-content-length' , 'no-ignore-content-length' ,
34
+ 'ftp-skip-pasv-ip' , 'no-ftp-skip-pasv-ip' , 'ftp-ssl-reqd' , 'no-ftp-ssl-reqd' ,
35
+ 'ssl-reqd' , 'no-ssl-reqd' , 'sessionid' , 'no-sessionid' , 'ftp-ssl-control' , 'no-ftp-ssl-control' ,
36
+ 'ftp-ssl-ccc' , 'no-ftp-ssl-ccc' , 'raw' , 'no-raw' , 'post301' , 'no-post301' ,
37
+ 'keepalive' , 'no-keepalive' , 'post302' , 'no-post302' ,
38
+ 'socks5-gssapi-nec' , 'no-socks5-gssapi-nec' , 'ftp-pret' , 'no-ftp-pret' , 'post303' , 'no-post303' ,
39
+ 'metalink' , 'no-metalink' , 'sasl-ir' , 'no-sasl-ir' , 'test-event' , 'no-test-event' ,
40
+ 'path-as-is' , 'no-path-as-is' , 'tftp-no-options' , 'no-tftp-no-options' ,
41
+ 'suppress-connect-headers' , 'no-suppress-connect-headers' , 'compressed-ssh' , 'no-compressed-ssh' ,
42
+ 'retry-all-errors' , 'no-retry-all-errors' ,
43
+ 'http1.0' , 'http1.1' , 'http2' , 'http2-prior-knowledge' , 'http3' , 'http0.9' , 'no-http0.9' ,
44
+ 'tlsv1' , 'tlsv1.0' , 'tlsv1.1' , 'tlsv1.2' , 'tlsv1.3' , 'sslv2' , 'sslv3' ,
45
+ 'ipv4' , 'ipv6' ,
46
+ 'append' , 'no-append' , 'use-ascii' , 'no-use-ascii' , 'ssl-allow-beast' , 'no-ssl-allow-beast' ,
47
+ 'ssl-auto-client-cert' , 'no-ssl-auto-client-cert' ,
48
+ 'proxy-ssl-auto-client-cert' , 'no-proxy-ssl-auto-client-cert' , 'cert-status' , 'no-cert-status' ,
49
+ 'doh-cert-status' , 'no-doh-cert-status' , 'false-start' , 'no-false-start' ,
50
+ 'ssl-no-revoke' , 'no-ssl-no-revoke' , 'ssl-revoke-best-effort' , 'no-ssl-revoke-best-effort' ,
51
+ 'tcp-fastopen' , 'no-tcp-fastopen' , 'proxy-ssl-allow-beast' , 'no-proxy-ssl-allow-beast' ,
52
+ 'proxy-insecure' , 'no-proxy-insecure' , 'proxy-tlsv1' , 'socks5-basic' , 'no-socks5-basic' ,
53
+ 'socks5-gssapi' , 'no-socks5-gssapi' , 'fail' , 'no-fail' , 'fail-early' , 'no-fail-early' ,
54
+ 'styled-output' , 'no-styled-output' , 'mail-rcpt-allowfails' , 'no-mail-rcpt-allowfails' ,
55
+ 'fail-with-body' , 'no-fail-with-body' , 'globoff' , 'no-globoff' , 'get' , 'help' , 'no-help' ,
56
+ 'include' , 'no-include' , 'head' , 'no-head' , 'junk-session-cookies' , 'no-junk-session-cookies' ,
57
+ 'remote-header-name' , 'no-remote-header-name' , 'insecure' , 'no-insecure' ,
58
+ 'doh-insecure' , 'no-doh-insecure' , 'list-only' , 'no-list-only' , 'location' , 'no-location' ,
59
+ 'location-trusted' , 'no-location-trusted' , 'manual' , 'no-manual' , 'netrc' , 'no-netrc' ,
60
+ 'netrc-optional' , 'no-netrc-optional' , 'buffer' , 'no-buffer' , 'remote-name' ,
61
+ 'remote-name-all' , 'no-remote-name-all' , 'proxytunnel' , 'no-proxytunnel' , 'disable' , 'no-disable' ,
62
+ 'remote-time' , 'no-remote-time' , 'silent' , 'no-silent' , 'show-error' , 'no-show-error' ,
63
+ 'verbose' , 'no-verbose' , 'version' , 'no-version' , 'parallel' , 'no-parallel' ,
64
+ 'parallel-immediate' , 'no-parallel-immediate' , 'progress-bar' , 'no-progress-bar' ,
65
+ 'progress-meter' , 'no-progress-meter' , 'next' ,
66
+ // renamed to --http3 in https://github.com/curl/curl/commit/026840e3
67
+ 'http3-direct' ,
68
+ // replaced by --request-target in https://github.com/curl/curl/commit/9b167fd0
69
+ 'strip-path-slash' , 'no-strip-path-slash' ,
70
+ // removed in https://github.com/curl/curl/commit/a8e388dd
71
+ 'environment' , 'no-environment' ,
72
+ // curl technically accepted these non-sensical options, they were removed in
73
+ // https://github.com/curl/curl/commit/913c3c8f
74
+ 'no-http1.0' , 'no-http1.1' , 'no-http2' , 'no-http2-prior-knowledge' ,
75
+ 'no-tlsv1' , 'no-tlsv1.0' , 'no-tlsv1.1' , 'no-tlsv1.2' , 'no-tlsv1.3' , 'no-sslv2' , 'no-sslv3' ,
76
+ 'no-ipv4' , 'no-ipv6' , 'no-proxy-tlsv1' , 'no-get' , 'no-remote-name' , 'no-next' ,
77
+ // removed in https://github.com/curl/curl/commit/720ea577
78
+ 'proxy-sslv2' , 'no-proxy-sslv2' , 'proxy-sslv3' , 'no-proxy-sslv3' ,
79
+ // removed in https://github.com/curl/curl/commit/388c6b5e
80
+ // I don't think this was ever a real short option
81
+ // '~',
82
+ // renamed to --http2 in https://github.com/curl/curl/commit/0952c9ab
83
+ 'http2.0' , 'no-http2.0' ,
84
+ // removed in https://github.com/curl/curl/commit/ebf31389
85
+ // I don't think this option was ever released, it was renamed the same day
86
+ // it was introduced
87
+ // 'ssl-no-empty-fragments', 'no-ssl-no-empty-fragments',
88
+ // renamed to --ntlm-wb in https://github.com/curl/curl/commit/b4f6319c
89
+ 'ntlm-sso' , 'no-ntlm-sso' ,
90
+ // all options got "--no-" versions in https://github.com/curl/curl/commit/5abfdc01
91
+ // renamed to --no-keepalive in https://github.com/curl/curl/commit/f866af91
92
+ 'no-keep-alive' ,
93
+ // may've been short for --crlf until https://github.com/curl/curl/commit/16643faa
94
+ // '9',
95
+ // removed in https://github.com/curl/curl/commit/07660eea
96
+ // -@ used to be short for --create-dirs
97
+ 'ftp-ascii' , // '@',
98
+ // removed in https://github.com/curl/curl/commit/c13dbf7b
99
+ // 'c', 'continue',
100
+ // removed in https://github.com/curl/curl/commit/a1d6ad26
101
+ // -t used to be short for --upload
102
+ // 't', 'upload',
103
+ // https://github.com/mholt/curl-to-go/pull/47#issuecomment-879485938
104
+ '-' ,
105
+ ] ) ;
106
+
107
+ // all of curl's short options have a long form
108
+ var optionAliases = {
109
+ '0' : 'http1.0' ,
110
+ '1' : 'tlsv1' ,
111
+ '2' : 'sslv2' ,
112
+ '3' : 'sslv3' ,
113
+ '4' : 'ipv4' ,
114
+ '6' : 'ipv6' ,
115
+ 'a' : 'append' ,
116
+ 'A' : 'user-agent' ,
117
+ 'b' : 'cookie' ,
118
+ 'B' : 'use-ascii' ,
119
+ 'c' : 'cookie-jar' ,
120
+ 'C' : 'continue-at' ,
121
+ 'd' : 'data' ,
122
+ 'D' : 'dump-header' ,
123
+ 'e' : 'referer' ,
124
+ 'E' : 'cert' ,
125
+ 'f' : 'fail' ,
126
+ 'F' : 'form' ,
127
+ 'g' : 'globoff' ,
128
+ 'G' : 'get' ,
129
+ 'h' : 'help' ,
130
+ 'H' : 'header' ,
131
+ 'i' : 'include' ,
132
+ 'I' : 'head' ,
133
+ 'j' : 'junk-session-cookies' ,
134
+ 'J' : 'remote-header-name' ,
135
+ 'k' : 'insecure' ,
136
+ 'K' : 'config' ,
137
+ 'l' : 'list-only' ,
138
+ 'L' : 'location' ,
139
+ 'm' : 'max-time' ,
140
+ 'M' : 'manual' ,
141
+ 'n' : 'netrc' ,
142
+ // N is an alias for --no-buffer, not --buffer
143
+ 'N' : 'no-buffer' ,
144
+ 'o' : 'output' ,
145
+ 'O' : 'remote-name' ,
146
+ 'p' : 'proxytunnel' ,
147
+ 'P' : 'ftp-port' ,
148
+ 'q' : 'disable' ,
149
+ 'Q' : 'quote' ,
150
+ 'r' : 'range' ,
151
+ 'R' : 'remote-time' ,
152
+ 's' : 'silent' ,
153
+ 'S' : 'show-error' ,
154
+ 't' : 'telnet-option' ,
155
+ 'T' : 'upload-file' ,
156
+ 'u' : 'user' ,
157
+ 'U' : 'proxy-user' ,
158
+ 'v' : 'verbose' ,
159
+ 'V' : 'version' ,
160
+ 'w' : 'write-out' ,
161
+ 'x' : 'proxy' ,
162
+ 'X' : 'request' ,
163
+ 'Y' : 'speed-limit' ,
164
+ 'y' : 'speed-time' ,
165
+ 'z' : 'time-cond' ,
166
+ 'Z' : 'parallel' ,
167
+ '#' : 'progress-bar' ,
168
+ ':' : 'next' ,
169
+ } ;
36
170
37
171
if ( ! curl . trim ( ) )
38
172
return ;
39
- var cmd = parseCommand ( curl , { boolFlags : boolOptions } ) ;
173
+ var cmd = parseCommand ( curl , { boolFlags : boolOptions , aliases : optionAliases } ) ;
40
174
41
175
if ( cmd . _ [ 0 ] != "curl" )
42
176
throw "Not a curl command" ;
@@ -196,21 +330,16 @@ function curlToGo(curl) {
196
330
relevant . url = cmd . _ [ 1 ] ; // position 1 because index 0 is the curl command itself
197
331
198
332
// gather the headers together
199
- if ( cmd . H )
200
- relevant . headers = relevant . headers . concat ( cmd . H ) ;
201
333
if ( cmd . header )
202
334
relevant . headers = relevant . headers . concat ( cmd . header ) ;
203
335
relevant . headers = parseHeaders ( relevant . headers )
204
336
205
337
// set method to HEAD?
206
- if ( cmd . I || cmd . head )
338
+ if ( cmd . head )
207
339
relevant . method = "HEAD" ;
208
340
209
- // between -X and --request, prefer the long form I guess
210
341
if ( cmd . request && cmd . request . length > 0 )
211
- relevant . method = cmd . request [ cmd . request . length - 1 ] . toUpperCase ( ) ;
212
- else if ( cmd . X && cmd . X . length > 0 )
213
- relevant . method = cmd . X [ cmd . X . length - 1 ] . toUpperCase ( ) ; // if multiple, use last (according to curl docs)
342
+ relevant . method = cmd . request [ cmd . request . length - 1 ] . toUpperCase ( ) ; // if multiple, use last (according to curl docs)
214
343
else if (
215
344
( cmd [ "data-binary" ] && cmd [ "data-binary" ] . length > 0 )
216
345
|| ( cmd [ "data-raw" ] && cmd [ "data-raw" ] . length > 0 )
@@ -243,8 +372,6 @@ function curlToGo(curl) {
243
372
}
244
373
}
245
374
} ;
246
- if ( cmd . d )
247
- loadData ( cmd . d ) ;
248
375
if ( cmd . data )
249
376
loadData ( cmd . data ) ;
250
377
if ( cmd [ "data-binary" ] )
@@ -256,12 +383,9 @@ function curlToGo(curl) {
256
383
if ( dataFiles . length > 0 )
257
384
relevant . data . files = dataFiles ;
258
385
259
- // between -u and --user, choose the long form...
260
386
var basicAuthString = "" ;
261
387
if ( cmd . user && cmd . user . length > 0 )
262
388
basicAuthString = cmd . user [ cmd . user . length - 1 ] ;
263
- else if ( cmd . u && cmd . u . length > 0 )
264
- basicAuthString = cmd . u [ cmd . u . length - 1 ] ;
265
389
// if the -u or --user flags haven't been set then don't set the
266
390
// basicauth property.
267
391
if ( basicAuthString ) {
@@ -281,7 +405,7 @@ function curlToGo(curl) {
281
405
if ( ! relevant . method )
282
406
relevant . method = "GET" ;
283
407
284
- if ( cmd . k || cmd . insecure ) {
408
+ if ( cmd . insecure ) {
285
409
relevant . insecure = true ;
286
410
}
287
411
@@ -378,13 +502,13 @@ function parseCommand(input, options) {
378
502
cursor ++ ; // skip leading dash
379
503
while ( cursor < input . length && ! whitespace ( input [ cursor ] ) )
380
504
{
381
- var flagName = input [ cursor ] ;
505
+ var flagName = fullName ( input [ cursor ] ) ;
382
506
if ( typeof result [ flagName ] == 'undefined' ) {
383
507
result [ flagName ] = [ ] ;
384
508
}
385
509
cursor ++ ; // skip the flag name
386
510
if ( boolFlag ( flagName ) )
387
- result [ flagName ] = true ;
511
+ result [ flagName ] = toBool ( flagName ) ;
388
512
else if ( Array . isArray ( result [ flagName ] ) )
389
513
result [ flagName ] . push ( nextString ( ) ) ;
390
514
}
@@ -396,7 +520,7 @@ function parseCommand(input, options) {
396
520
cursor += 2 ; // skip leading dashes
397
521
var flagName = nextString ( "=" ) ;
398
522
if ( boolFlag ( flagName ) )
399
- result [ flagName ] = true ;
523
+ result [ flagName ] = toBool ( flagName ) ;
400
524
else {
401
525
if ( typeof result [ flagName ] == 'undefined' ) {
402
526
result [ flagName ] = [ ] ;
@@ -413,8 +537,17 @@ function parseCommand(input, options) {
413
537
result . _ . push ( nextString ( ) ) ;
414
538
}
415
539
540
+ // fullName returns the long name of a short flag
541
+ function fullName ( flag ) {
542
+ var alias = options . aliases [ flag ]
543
+ return alias ? alias : flag ;
544
+ }
545
+
416
546
// boolFlag returns whether a flag is known to be boolean type
417
547
function boolFlag ( flag ) {
548
+ if ( options . boolFlags instanceof Set ) {
549
+ return options . boolFlags . has ( flag ) ;
550
+ }
418
551
if ( Array . isArray ( options . boolFlags ) ) {
419
552
for ( var i = 0 ; i < options . boolFlags . length ; i ++ ) {
420
553
if ( options . boolFlags [ i ] == flag )
@@ -424,6 +557,13 @@ function parseCommand(input, options) {
424
557
return false ;
425
558
}
426
559
560
+ // toBool converts a long flag name to a boolean value.
561
+ // --verbose -> true
562
+ // --no-verbose -> false
563
+ function toBool ( flag ) {
564
+ return ! ( flag . startsWith ( 'no-' ) || flag . startsWith ( 'disable-' ) ) ;
565
+ }
566
+
427
567
// nextString skips any leading whitespace and consumes the next
428
568
// space-delimited string value and returns it. If endChar is set,
429
569
// it will be used to determine the end of the string. Normally just
0 commit comments