UNPKG

curlconverter

Version:

convert curl commands to Python, JavaScript, Go, PHP and more

1,000 lines 47.5 kB
import { CCError, has } from "../utils.js"; import { eq, firstShellToken } from "../shell/Word.js"; import { warnf, underlineNode } from "../Warnings.js"; import { CURLAUTH_BASIC, CURLAUTH_DIGEST, CURLAUTH_NEGOTIATE, CURLAUTH_NTLM, CURLAUTH_NTLM_WB, CURLAUTH_BEARER, CURLAUTH_AWS_SIGV4, CURLAUTH_ANY, } from "./auth.js"; // prettier-ignore export const curlLongOpts = { // BEGIN EXTRACTED OPTIONS "url": { type: "string", name: "url" }, "dns-ipv4-addr": { type: "string", name: "dns-ipv4-addr" }, "dns-ipv6-addr": { type: "string", name: "dns-ipv6-addr" }, "random-file": { type: "string", name: "random-file" }, "egd-file": { type: "string", name: "egd-file" }, "oauth2-bearer": { type: "string", name: "oauth2-bearer" }, "connect-timeout": { type: "string", name: "connect-timeout" }, "doh-url": { type: "string", name: "doh-url" }, "ciphers": { type: "string", name: "ciphers" }, "dns-interface": { type: "string", name: "dns-interface" }, "disable-epsv": { type: "bool", name: "disable-epsv" }, "no-disable-epsv": { type: "bool", name: "disable-epsv", expand: false }, "disallow-username-in-url": { type: "bool", name: "disallow-username-in-url" }, "no-disallow-username-in-url": { type: "bool", name: "disallow-username-in-url", expand: false }, "epsv": { type: "bool", name: "epsv" }, "no-epsv": { type: "bool", name: "epsv", expand: false }, "dns-servers": { type: "string", name: "dns-servers" }, "trace": { type: "string", name: "trace" }, "npn": { type: "bool", name: "npn" }, "no-npn": { type: "bool", name: "npn", expand: false }, "trace-ascii": { type: "string", name: "trace-ascii" }, "alpn": { type: "bool", name: "alpn" }, "no-alpn": { type: "bool", name: "alpn", expand: false }, "limit-rate": { type: "string", name: "limit-rate" }, "rate": { type: "string", name: "rate" }, "compressed": { type: "bool", name: "compressed" }, "no-compressed": { type: "bool", name: "compressed", expand: false }, "tr-encoding": { type: "bool", name: "tr-encoding" }, "no-tr-encoding": { type: "bool", name: "tr-encoding", expand: false }, "digest": { type: "bool", name: "digest" }, "no-digest": { type: "bool", name: "digest", expand: false }, "negotiate": { type: "bool", name: "negotiate" }, "no-negotiate": { type: "bool", name: "negotiate", expand: false }, "ntlm": { type: "bool", name: "ntlm" }, "no-ntlm": { type: "bool", name: "ntlm", expand: false }, "ntlm-wb": { type: "bool", name: "ntlm-wb" }, "no-ntlm-wb": { type: "bool", name: "ntlm-wb", expand: false }, "basic": { type: "bool", name: "basic" }, "no-basic": { type: "bool", name: "basic", expand: false }, "anyauth": { type: "bool", name: "anyauth" }, "no-anyauth": { type: "bool", name: "anyauth", expand: false }, "wdebug": { type: "bool", name: "wdebug" }, "no-wdebug": { type: "bool", name: "wdebug", expand: false }, "ftp-create-dirs": { type: "bool", name: "ftp-create-dirs" }, "no-ftp-create-dirs": { type: "bool", name: "ftp-create-dirs", expand: false }, "create-dirs": { type: "bool", name: "create-dirs" }, "no-create-dirs": { type: "bool", name: "create-dirs", expand: false }, "create-file-mode": { type: "string", name: "create-file-mode" }, "max-redirs": { type: "string", name: "max-redirs" }, "proxy-ntlm": { type: "bool", name: "proxy-ntlm" }, "no-proxy-ntlm": { type: "bool", name: "proxy-ntlm", expand: false }, "crlf": { type: "bool", name: "crlf" }, "no-crlf": { type: "bool", name: "crlf", expand: false }, "stderr": { type: "string", name: "stderr" }, "aws-sigv4": { type: "string", name: "aws-sigv4" }, "interface": { type: "string", name: "interface" }, "krb": { type: "string", name: "krb" }, "krb4": { type: "string", name: "krb" }, "haproxy-protocol": { type: "bool", name: "haproxy-protocol" }, "no-haproxy-protocol": { type: "bool", name: "haproxy-protocol", expand: false }, "haproxy-clientip": { type: "string", name: "haproxy-clientip" }, "max-filesize": { type: "string", name: "max-filesize" }, "disable-eprt": { type: "bool", name: "disable-eprt" }, "no-disable-eprt": { type: "bool", name: "disable-eprt", expand: false }, "eprt": { type: "bool", name: "eprt" }, "no-eprt": { type: "bool", name: "eprt", expand: false }, "xattr": { type: "bool", name: "xattr" }, "no-xattr": { type: "bool", name: "xattr", expand: false }, "ftp-ssl": { type: "bool", name: "ssl" }, "no-ftp-ssl": { type: "bool", name: "ssl", expand: false }, "ssl": { type: "bool", name: "ssl" }, "no-ssl": { type: "bool", name: "ssl", expand: false }, "ftp-pasv": { type: "bool", name: "ftp-pasv" }, "no-ftp-pasv": { type: "bool", name: "ftp-pasv", expand: false }, "socks5": { type: "string", name: "socks5" }, "tcp-nodelay": { type: "bool", name: "tcp-nodelay" }, "no-tcp-nodelay": { type: "bool", name: "tcp-nodelay", expand: false }, "proxy-digest": { type: "bool", name: "proxy-digest" }, "no-proxy-digest": { type: "bool", name: "proxy-digest", expand: false }, "proxy-basic": { type: "bool", name: "proxy-basic" }, "no-proxy-basic": { type: "bool", name: "proxy-basic", expand: false }, "retry": { type: "string", name: "retry" }, "retry-connrefused": { type: "bool", name: "retry-connrefused" }, "no-retry-connrefused": { type: "bool", name: "retry-connrefused", expand: false }, "retry-delay": { type: "string", name: "retry-delay" }, "retry-max-time": { type: "string", name: "retry-max-time" }, "proxy-negotiate": { type: "bool", name: "proxy-negotiate" }, "no-proxy-negotiate": { type: "bool", name: "proxy-negotiate", expand: false }, "form-escape": { type: "bool", name: "form-escape" }, "no-form-escape": { type: "bool", name: "form-escape", expand: false }, "ftp-account": { type: "string", name: "ftp-account" }, "proxy-anyauth": { type: "bool", name: "proxy-anyauth" }, "no-proxy-anyauth": { type: "bool", name: "proxy-anyauth", expand: false }, "trace-time": { type: "bool", name: "trace-time" }, "no-trace-time": { type: "bool", name: "trace-time", expand: false }, "ignore-content-length": { type: "bool", name: "ignore-content-length" }, "no-ignore-content-length": { type: "bool", name: "ignore-content-length", expand: false }, "ftp-skip-pasv-ip": { type: "bool", name: "ftp-skip-pasv-ip" }, "no-ftp-skip-pasv-ip": { type: "bool", name: "ftp-skip-pasv-ip", expand: false }, "ftp-method": { type: "string", name: "ftp-method" }, "local-port": { type: "string", name: "local-port" }, "socks4": { type: "string", name: "socks4" }, "socks4a": { type: "string", name: "socks4a" }, "ftp-alternative-to-user": { type: "string", name: "ftp-alternative-to-user" }, "ftp-ssl-reqd": { type: "bool", name: "ssl-reqd" }, "no-ftp-ssl-reqd": { type: "bool", name: "ssl-reqd", expand: false }, "ssl-reqd": { type: "bool", name: "ssl-reqd" }, "no-ssl-reqd": { type: "bool", name: "ssl-reqd", expand: false }, "sessionid": { type: "bool", name: "sessionid" }, "no-sessionid": { type: "bool", name: "sessionid", expand: false }, "ftp-ssl-control": { type: "bool", name: "ftp-ssl-control" }, "no-ftp-ssl-control": { type: "bool", name: "ftp-ssl-control", expand: false }, "ftp-ssl-ccc": { type: "bool", name: "ftp-ssl-ccc" }, "no-ftp-ssl-ccc": { type: "bool", name: "ftp-ssl-ccc", expand: false }, "ftp-ssl-ccc-mode": { type: "string", name: "ftp-ssl-ccc-mode" }, "libcurl": { type: "string", name: "libcurl" }, "raw": { type: "bool", name: "raw" }, "no-raw": { type: "bool", name: "raw", expand: false }, "post301": { type: "bool", name: "post301" }, "no-post301": { type: "bool", name: "post301", expand: false }, "keepalive": { type: "bool", name: "keepalive" }, "no-keepalive": { type: "bool", name: "keepalive", expand: false }, "socks5-hostname": { type: "string", name: "socks5-hostname" }, "keepalive-time": { type: "string", name: "keepalive-time" }, "post302": { type: "bool", name: "post302" }, "no-post302": { type: "bool", name: "post302", expand: false }, "noproxy": { type: "string", name: "noproxy" }, "socks5-gssapi-nec": { type: "bool", name: "socks5-gssapi-nec" }, "no-socks5-gssapi-nec": { type: "bool", name: "socks5-gssapi-nec", expand: false }, "proxy1.0": { type: "string", name: "proxy1.0" }, "tftp-blksize": { type: "string", name: "tftp-blksize" }, "mail-from": { type: "string", name: "mail-from" }, "mail-rcpt": { type: "string", name: "mail-rcpt" }, "ftp-pret": { type: "bool", name: "ftp-pret" }, "no-ftp-pret": { type: "bool", name: "ftp-pret", expand: false }, "proto": { type: "string", name: "proto" }, "proto-redir": { type: "string", name: "proto-redir" }, "resolve": { type: "string", name: "resolve" }, "delegation": { type: "string", name: "delegation" }, "mail-auth": { type: "string", name: "mail-auth" }, "post303": { type: "bool", name: "post303" }, "no-post303": { type: "bool", name: "post303", expand: false }, "metalink": { type: "bool", name: "metalink" }, "no-metalink": { type: "bool", name: "metalink", expand: false }, "sasl-authzid": { type: "string", name: "sasl-authzid" }, "sasl-ir": { type: "bool", name: "sasl-ir" }, "no-sasl-ir": { type: "bool", name: "sasl-ir", expand: false }, "test-event": { type: "bool", name: "test-event" }, "no-test-event": { type: "bool", name: "test-event", expand: false }, "unix-socket": { type: "string", name: "unix-socket" }, "path-as-is": { type: "bool", name: "path-as-is" }, "no-path-as-is": { type: "bool", name: "path-as-is", expand: false }, "socks5-gssapi-service": { type: "string", name: "proxy-service-name" }, "proxy-service-name": { type: "string", name: "proxy-service-name" }, "service-name": { type: "string", name: "service-name" }, "proto-default": { type: "string", name: "proto-default" }, "expect100-timeout": { type: "string", name: "expect100-timeout" }, "tftp-no-options": { type: "bool", name: "tftp-no-options" }, "no-tftp-no-options": { type: "bool", name: "tftp-no-options", expand: false }, "connect-to": { type: "string", name: "connect-to" }, "abstract-unix-socket": { type: "string", name: "abstract-unix-socket" }, "tls-max": { type: "string", name: "tls-max" }, "suppress-connect-headers": { type: "bool", name: "suppress-connect-headers" }, "no-suppress-connect-headers": { type: "bool", name: "suppress-connect-headers", expand: false }, "compressed-ssh": { type: "bool", name: "compressed-ssh" }, "no-compressed-ssh": { type: "bool", name: "compressed-ssh", expand: false }, "happy-eyeballs-timeout-ms": { type: "string", name: "happy-eyeballs-timeout-ms" }, "retry-all-errors": { type: "bool", name: "retry-all-errors" }, "no-retry-all-errors": { type: "bool", name: "retry-all-errors", expand: false }, "trace-ids": { type: "bool", name: "trace-ids" }, "no-trace-ids": { type: "bool", name: "trace-ids", expand: false }, "http1.0": { type: "bool", name: "http1.0" }, "http1.1": { type: "bool", name: "http1.1" }, "http2": { type: "bool", name: "http2" }, "http2-prior-knowledge": { type: "bool", name: "http2-prior-knowledge" }, "http3": { type: "bool", name: "http3" }, "http3-only": { type: "bool", name: "http3-only" }, "http0.9": { type: "bool", name: "http0.9" }, "no-http0.9": { type: "bool", name: "http0.9", expand: false }, "proxy-http2": { type: "bool", name: "proxy-http2" }, "no-proxy-http2": { type: "bool", name: "proxy-http2", expand: false }, "tlsv1": { type: "bool", name: "tlsv1" }, "tlsv1.0": { type: "bool", name: "tlsv1.0" }, "tlsv1.1": { type: "bool", name: "tlsv1.1" }, "tlsv1.2": { type: "bool", name: "tlsv1.2" }, "tlsv1.3": { type: "bool", name: "tlsv1.3" }, "tls13-ciphers": { type: "string", name: "tls13-ciphers" }, "proxy-tls13-ciphers": { type: "string", name: "proxy-tls13-ciphers" }, "sslv2": { type: "bool", name: "sslv2" }, "sslv3": { type: "bool", name: "sslv3" }, "ipv4": { type: "bool", name: "ipv4" }, "ipv6": { type: "bool", name: "ipv6" }, "append": { type: "bool", name: "append" }, "no-append": { type: "bool", name: "append", expand: false }, "user-agent": { type: "string", name: "user-agent" }, "cookie": { type: "string", name: "cookie" }, "alt-svc": { type: "string", name: "alt-svc" }, "hsts": { type: "string", name: "hsts" }, "use-ascii": { type: "bool", name: "use-ascii" }, "no-use-ascii": { type: "bool", name: "use-ascii", expand: false }, "cookie-jar": { type: "string", name: "cookie-jar" }, "continue-at": { type: "string", name: "continue-at" }, "data": { type: "string", name: "data" }, "data-raw": { type: "string", name: "data-raw" }, "data-ascii": { type: "string", name: "data-ascii" }, "data-binary": { type: "string", name: "data-binary" }, "data-urlencode": { type: "string", name: "data-urlencode" }, "json": { type: "string", name: "json" }, "url-query": { type: "string", name: "url-query" }, "dump-header": { type: "string", name: "dump-header" }, "referer": { type: "string", name: "referer" }, "cert": { type: "string", name: "cert" }, "cacert": { type: "string", name: "cacert" }, "cert-type": { type: "string", name: "cert-type" }, "key": { type: "string", name: "key" }, "key-type": { type: "string", name: "key-type" }, "pass": { type: "string", name: "pass" }, "engine": { type: "string", name: "engine" }, "ca-native": { type: "bool", name: "ca-native" }, "no-ca-native": { type: "bool", name: "ca-native", expand: false }, "proxy-ca-native": { type: "bool", name: "proxy-ca-native" }, "no-proxy-ca-native": { type: "bool", name: "proxy-ca-native", expand: false }, "capath": { type: "string", name: "capath" }, "pubkey": { type: "string", name: "pubkey" }, "hostpubmd5": { type: "string", name: "hostpubmd5" }, "hostpubsha256": { type: "string", name: "hostpubsha256" }, "crlfile": { type: "string", name: "crlfile" }, "tlsuser": { type: "string", name: "tlsuser" }, "tlspassword": { type: "string", name: "tlspassword" }, "tlsauthtype": { type: "string", name: "tlsauthtype" }, "ssl-allow-beast": { type: "bool", name: "ssl-allow-beast" }, "no-ssl-allow-beast": { type: "bool", name: "ssl-allow-beast", expand: false }, "ssl-auto-client-cert": { type: "bool", name: "ssl-auto-client-cert" }, "no-ssl-auto-client-cert": { type: "bool", name: "ssl-auto-client-cert", expand: false }, "proxy-ssl-auto-client-cert": { type: "bool", name: "proxy-ssl-auto-client-cert" }, "no-proxy-ssl-auto-client-cert": { type: "bool", name: "proxy-ssl-auto-client-cert", expand: false }, "pinnedpubkey": { type: "string", name: "pinnedpubkey" }, "proxy-pinnedpubkey": { type: "string", name: "proxy-pinnedpubkey" }, "cert-status": { type: "bool", name: "cert-status" }, "no-cert-status": { type: "bool", name: "cert-status", expand: false }, "doh-cert-status": { type: "bool", name: "doh-cert-status" }, "no-doh-cert-status": { type: "bool", name: "doh-cert-status", expand: false }, "false-start": { type: "bool", name: "false-start" }, "no-false-start": { type: "bool", name: "false-start", expand: false }, "ssl-no-revoke": { type: "bool", name: "ssl-no-revoke" }, "no-ssl-no-revoke": { type: "bool", name: "ssl-no-revoke", expand: false }, "ssl-revoke-best-effort": { type: "bool", name: "ssl-revoke-best-effort" }, "no-ssl-revoke-best-effort": { type: "bool", name: "ssl-revoke-best-effort", expand: false }, "tcp-fastopen": { type: "bool", name: "tcp-fastopen" }, "no-tcp-fastopen": { type: "bool", name: "tcp-fastopen", expand: false }, "proxy-tlsuser": { type: "string", name: "proxy-tlsuser" }, "proxy-tlspassword": { type: "string", name: "proxy-tlspassword" }, "proxy-tlsauthtype": { type: "string", name: "proxy-tlsauthtype" }, "proxy-cert": { type: "string", name: "proxy-cert" }, "proxy-cert-type": { type: "string", name: "proxy-cert-type" }, "proxy-key": { type: "string", name: "proxy-key" }, "proxy-key-type": { type: "string", name: "proxy-key-type" }, "proxy-pass": { type: "string", name: "proxy-pass" }, "proxy-ciphers": { type: "string", name: "proxy-ciphers" }, "proxy-crlfile": { type: "string", name: "proxy-crlfile" }, "proxy-ssl-allow-beast": { type: "bool", name: "proxy-ssl-allow-beast" }, "no-proxy-ssl-allow-beast": { type: "bool", name: "proxy-ssl-allow-beast", expand: false }, "login-options": { type: "string", name: "login-options" }, "proxy-cacert": { type: "string", name: "proxy-cacert" }, "proxy-capath": { type: "string", name: "proxy-capath" }, "proxy-insecure": { type: "bool", name: "proxy-insecure" }, "no-proxy-insecure": { type: "bool", name: "proxy-insecure", expand: false }, "proxy-tlsv1": { type: "bool", name: "proxy-tlsv1" }, "socks5-basic": { type: "bool", name: "socks5-basic" }, "no-socks5-basic": { type: "bool", name: "socks5-basic", expand: false }, "socks5-gssapi": { type: "bool", name: "socks5-gssapi" }, "no-socks5-gssapi": { type: "bool", name: "socks5-gssapi", expand: false }, "etag-save": { type: "string", name: "etag-save" }, "etag-compare": { type: "string", name: "etag-compare" }, "curves": { type: "string", name: "curves" }, "fail": { type: "bool", name: "fail" }, "no-fail": { type: "bool", name: "fail", expand: false }, "fail-early": { type: "bool", name: "fail-early" }, "no-fail-early": { type: "bool", name: "fail-early", expand: false }, "styled-output": { type: "bool", name: "styled-output" }, "no-styled-output": { type: "bool", name: "styled-output", expand: false }, "mail-rcpt-allowfails": { type: "bool", name: "mail-rcpt-allowfails" }, "no-mail-rcpt-allowfails": { type: "bool", name: "mail-rcpt-allowfails", expand: false }, "fail-with-body": { type: "bool", name: "fail-with-body" }, "no-fail-with-body": { type: "bool", name: "fail-with-body", expand: false }, "remove-on-error": { type: "bool", name: "remove-on-error" }, "no-remove-on-error": { type: "bool", name: "remove-on-error", expand: false }, "form": { type: "string", name: "form" }, "form-string": { type: "string", name: "form-string" }, "globoff": { type: "bool", name: "globoff" }, "no-globoff": { type: "bool", name: "globoff", expand: false }, "get": { type: "bool", name: "get" }, "no-get": { type: "bool", name: "get", expand: false }, "request-target": { type: "string", name: "request-target" }, "help": { type: "bool", name: "help" }, "no-help": { type: "bool", name: "help", expand: false }, "header": { type: "string", name: "header" }, "proxy-header": { type: "string", name: "proxy-header" }, "include": { type: "bool", name: "include" }, "no-include": { type: "bool", name: "include", expand: false }, "head": { type: "bool", name: "head" }, "no-head": { type: "bool", name: "head", expand: false }, "junk-session-cookies": { type: "bool", name: "junk-session-cookies" }, "no-junk-session-cookies": { type: "bool", name: "junk-session-cookies", expand: false }, "remote-header-name": { type: "bool", name: "remote-header-name" }, "no-remote-header-name": { type: "bool", name: "remote-header-name", expand: false }, "insecure": { type: "bool", name: "insecure" }, "no-insecure": { type: "bool", name: "insecure", expand: false }, "doh-insecure": { type: "bool", name: "doh-insecure" }, "no-doh-insecure": { type: "bool", name: "doh-insecure", expand: false }, "config": { type: "string", name: "config" }, "list-only": { type: "bool", name: "list-only" }, "no-list-only": { type: "bool", name: "list-only", expand: false }, "location": { type: "bool", name: "location" }, "no-location": { type: "bool", name: "location", expand: false }, "location-trusted": { type: "bool", name: "location-trusted" }, "no-location-trusted": { type: "bool", name: "location-trusted", expand: false }, "max-time": { type: "string", name: "max-time" }, "manual": { type: "bool", name: "manual" }, "no-manual": { type: "bool", name: "manual", expand: false }, "netrc": { type: "bool", name: "netrc" }, "no-netrc": { type: "bool", name: "netrc", expand: false }, "netrc-optional": { type: "bool", name: "netrc-optional" }, "no-netrc-optional": { type: "bool", name: "netrc-optional", expand: false }, "netrc-file": { type: "string", name: "netrc-file" }, "buffer": { type: "bool", name: "buffer" }, "no-buffer": { type: "bool", name: "buffer", expand: false }, "output": { type: "string", name: "output" }, "remote-name": { type: "bool", name: "remote-name" }, "no-remote-name": { type: "bool", name: "remote-name", expand: false }, "remote-name-all": { type: "bool", name: "remote-name-all" }, "no-remote-name-all": { type: "bool", name: "remote-name-all", expand: false }, "output-dir": { type: "string", name: "output-dir" }, "clobber": { type: "bool", name: "clobber" }, "no-clobber": { type: "bool", name: "clobber", expand: false }, "proxytunnel": { type: "bool", name: "proxytunnel" }, "no-proxytunnel": { type: "bool", name: "proxytunnel", expand: false }, "ftp-port": { type: "string", name: "ftp-port" }, "disable": { type: "bool", name: "disable" }, "no-disable": { type: "bool", name: "disable", expand: false }, "quote": { type: "string", name: "quote" }, "range": { type: "string", name: "range" }, "remote-time": { type: "bool", name: "remote-time" }, "no-remote-time": { type: "bool", name: "remote-time", expand: false }, "silent": { type: "bool", name: "silent" }, "no-silent": { type: "bool", name: "silent", expand: false }, "show-error": { type: "bool", name: "show-error" }, "no-show-error": { type: "bool", name: "show-error", expand: false }, "telnet-option": { type: "string", name: "telnet-option" }, "upload-file": { type: "string", name: "upload-file" }, "user": { type: "string", name: "user" }, "proxy-user": { type: "string", name: "proxy-user" }, "verbose": { type: "bool", name: "verbose" }, "no-verbose": { type: "bool", name: "verbose", expand: false }, "version": { type: "bool", name: "version" }, "no-version": { type: "bool", name: "version", expand: false }, "write-out": { type: "string", name: "write-out" }, "proxy": { type: "string", name: "proxy" }, "preproxy": { type: "string", name: "preproxy" }, "request": { type: "string", name: "request" }, "speed-limit": { type: "string", name: "speed-limit" }, "speed-time": { type: "string", name: "speed-time" }, "time-cond": { type: "string", name: "time-cond" }, "parallel": { type: "bool", name: "parallel" }, "no-parallel": { type: "bool", name: "parallel", expand: false }, "parallel-max": { type: "string", name: "parallel-max" }, "parallel-immediate": { type: "bool", name: "parallel-immediate" }, "no-parallel-immediate": { type: "bool", name: "parallel-immediate", expand: false }, "progress-bar": { type: "bool", name: "progress-bar" }, "no-progress-bar": { type: "bool", name: "progress-bar", expand: false }, "progress-meter": { type: "bool", name: "progress-meter" }, "no-progress-meter": { type: "bool", name: "progress-meter", expand: false }, "next": { type: "bool", name: "next" }, // END EXTRACTED OPTIONS // These are options that curl used to have. // Those that don't conflict with the current options are supported by curlconverter. // TODO: curl's --long-options can be shortened. // For example if curl used to only have a single option, "--blah" then // "--bla" "--bl" and "--b" all used to be valid options as well. If later // "--blaz" was added, suddenly those 3 shortened options are removed (because // they are now ambiguous). // https://github.com/curlconverter/curlconverter/pull/280#issuecomment-931241328 port: { type: "string", name: "port", removed: "7.3" }, // These are now shoretened forms of --upload-file and --continue-at //upload: { type: "bool", name: "upload", removed: "7.7" }, //continue: { type: "bool", name: "continue", removed: "7.9" }, "ftp-ascii": { type: "bool", name: "use-ascii", removed: "7.10.7" }, "3p-url": { type: "string", name: "3p-url", removed: "7.16.0" }, "3p-user": { type: "string", name: "3p-user", removed: "7.16.0" }, "3p-quote": { type: "string", name: "3p-quote", removed: "7.16.0" }, "http2.0": { type: "bool", name: "http2", removed: "7.36.0" }, "no-http2.0": { type: "bool", name: "http2", removed: "7.36.0" }, "telnet-options": { type: "string", name: "telnet-option", removed: "7.49.0" }, "http-request": { type: "string", name: "request", removed: "7.49.0" }, // --socks is now an ambiguous shortening of --socks4, --socks5 and a bunch more //socks: { type: "string", name: "socks5", removed: "7.49.0" }, "capath ": { type: "string", name: "capath", removed: "7.49.0" }, // trailing space ftpport: { type: "string", name: "ftp-port", removed: "7.49.0" }, environment: { type: "bool", name: "environment", removed: "7.54.1" }, // These never had any effect "no-tlsv1": { type: "bool", name: "tlsv1", removed: "7.54.1" }, "no-tlsv1.2": { type: "bool", name: "tlsv1.2", removed: "7.54.1" }, "no-http2-prior-knowledge": { type: "bool", name: "http2-prior-knowledge", removed: "7.54.1" }, "no-ipv6": { type: "bool", name: "ipv6", removed: "7.54.1" }, "no-ipv4": { type: "bool", name: "ipv4", removed: "7.54.1" }, "no-sslv2": { type: "bool", name: "sslv2", removed: "7.54.1" }, "no-tlsv1.0": { type: "bool", name: "tlsv1.0", removed: "7.54.1" }, "no-tlsv1.1": { type: "bool", name: "tlsv1.1", removed: "7.54.1" }, "no-sslv3": { type: "bool", name: "sslv3", removed: "7.54.1" }, "no-http1.0": { type: "bool", name: "http1.0", removed: "7.54.1" }, "no-next": { type: "bool", name: "next", removed: "7.54.1" }, "no-tlsv1.3": { type: "bool", name: "tlsv1.3", removed: "7.54.1" }, "no-environment": { type: "bool", name: "environment", removed: "7.54.1" }, "no-http1.1": { type: "bool", name: "http1.1", removed: "7.54.1" }, "no-proxy-tlsv1": { type: "bool", name: "proxy-tlsv1", removed: "7.54.1" }, "no-http2": { type: "bool", name: "http2", removed: "7.54.1" }, }; // curl lets you not type the full argument as long as it's unambiguous. // So --sil instead of --silent is okay, --s is not. export const curlLongOptsShortened = {}; for (const [opt, val] of Object.entries(curlLongOpts)) { const expand = "expand" in val ? val.expand : true; const removed = "removed" in val ? val.removed : false; if (expand && !removed) { for (let i = 1; i < opt.length; i++) { const shortenedOpt = opt.slice(0, i); if (!Object.prototype.hasOwnProperty.call(curlLongOptsShortened, shortenedOpt)) { if (!Object.prototype.hasOwnProperty.call(curlLongOpts, shortenedOpt)) { curlLongOptsShortened[shortenedOpt] = val; } } else { // If more than one option shortens to this, it's ambiguous curlLongOptsShortened[shortenedOpt] = null; } } } } // Arguments which are supported by all generators, because they're // easy to implement or because they're handled by upstream code and // affect something that's easy to implement. export const COMMON_SUPPORTED_ARGS = [ "url", "proto-default", // Controls whether or not backslash-escaped [] {} will have the backslash removed. "globoff", // curl will exit if it finds auth credentials in the URL with this option, // we remove it from the URL and emit a warning instead. "disallow-username-in-url", // Method "request", "get", "head", "no-head", // Headers "header", // TODO: can be a file "user-agent", "referer", "range", "time-cond", "cookie", // TODO: can be a file "oauth2-bearer", // Basic Auth "user", "basic", "no-basic", // Data "data", "data-raw", "data-ascii", "data-binary", "data-urlencode", "json", "url-query", // TODO: --compressed is already the default for some runtimes, in // which case we might have to only warn that --no-compressed isn't supported. ]; export function toBoolean(opt) { if (opt.startsWith("no-disable-")) { return true; } if (opt.startsWith("disable-") || opt.startsWith("no-")) { return false; } return true; } // prettier-ignore export const curlShortOpts = { // BEGIN EXTRACTED SHORT OPTIONS "0": "http1.0", "1": "tlsv1", "2": "sslv2", "3": "sslv3", "4": "ipv4", "6": "ipv6", "a": "append", "A": "user-agent", "b": "cookie", "B": "use-ascii", "c": "cookie-jar", "C": "continue-at", "d": "data", "D": "dump-header", "e": "referer", "E": "cert", "f": "fail", "F": "form", "g": "globoff", "G": "get", "h": "help", "H": "header", "i": "include", "I": "head", "j": "junk-session-cookies", "J": "remote-header-name", "k": "insecure", "K": "config", "l": "list-only", "L": "location", "m": "max-time", "M": "manual", "n": "netrc", "N": "no-buffer", "o": "output", "O": "remote-name", "p": "proxytunnel", "P": "ftp-port", "q": "disable", "Q": "quote", "r": "range", "R": "remote-time", "s": "silent", "S": "show-error", "t": "telnet-option", "T": "upload-file", "u": "user", "U": "proxy-user", "v": "verbose", "V": "version", "w": "write-out", "x": "proxy", "X": "request", "Y": "speed-limit", "y": "speed-time", "z": "time-cond", "Z": "parallel", "#": "progress-bar", ":": "next", // END EXTRACTED SHORT OPTIONS }; export const changedShortOpts = { p: "used to be short for --port <port> (a since-deleted flag) until curl 7.3", // TODO: some of these might be renamed options t: "used to be short for --upload (a since-deleted boolean flag) until curl 7.7", c: "used to be short for --continue (a since-deleted boolean flag) until curl 7.9", // TODO: did -@ actually work? "@": "used to be short for --create-dirs until curl 7.10.7", Z: "used to be short for --max-redirs <num> until curl 7.10.7", 9: "used to be short for --crlf until curl 7.10.8", 8: "used to be short for --stderr <file> until curl 7.10.8", 7: "used to be short for --interface <name> until curl 7.10.8", 6: "used to be short for --krb <level> (which itself used to be --krb4 <level>) until curl 7.10.8", // TODO: did these short options ever actually work? 5: "used to be another way to specify the url until curl 7.10.8", "*": "used to be another way to specify the url until curl 7.49.0", "~": "used to be short for --xattr until curl 7.49.0", }; // type Satisfies<T, U extends T> = void; // type AssertSubsetKeys = Satisfies< // keyof typeof curlLongOpts | "authtype" | "proxyauthtype", // keyof OperationConfig // >; // These options can be specified more than once, they // are always returned as a list. // For all other options, if you specify it more than once // curl will use the last one. const canBeList = new Set([ "connect-to", "cookie", "data", "form", "header", "hsts", "mail-rcpt", "output", "proxy-header", "quote", "resolve", "telnet-option", "upload-file", "url-query", "url", ]); function checkSupported(global_, lookup, longArg, supportedOpts) { if (supportedOpts && !supportedOpts.has(longArg.name)) { // TODO: better message. include generator name? warnf(global_, [ longArg.name, lookup + " is not a supported option" + (longArg.removed ? ", it was removed in curl " + longArg.removed : ""), ]); } } export function pushProp(obj, prop, value) { if (!Object.prototype.hasOwnProperty.call(obj, prop)) { obj[prop] = []; } obj[prop].push(value); return obj; } function pushArgValue(global_, config, argName, value) { // Note: cli.ts assumes that the property names on OperationConfig // are the same as the passed in argument in an error message, so // if you do something like // echo curl example.com | curlconverter - --data-raw foo // The error message will say // "if you pass --stdin or -, you can't also pass --data" // instead of "--data-raw". switch (argName) { case "data": case "data-ascii": return pushProp(config, "data", ["data", value]); case "data-binary": return pushProp(config, "data", [ // Unless it's a file, --data-binary works the same as --data value.startsWith("@") ? "binary" : "data", value, ]); case "data-raw": return pushProp(config, "data", [ // Unless it's a file, --data-raw works the same as --data value.startsWith("@") ? "raw" : "data", value, ]); case "data-urlencode": return pushProp(config, "data", ["urlencode", value]); case "json": config.json = true; return pushProp(config, "data", ["json", value]); case "url-query": if (value.startsWith("+")) { return pushProp(config, "url-query", ["raw", value.slice(1)]); } return pushProp(config, "url-query", ["urlencode", value]); case "form": return pushProp(config, "form", { value, type: "form" }); case "form-string": return pushProp(config, "form", { value, type: "string" }); case "aws-sigv4": config.authtype |= CURLAUTH_AWS_SIGV4; break; case "oauth2-bearer": config.authtype |= CURLAUTH_BEARER; break; case "unix-socket": case "abstract-unix-socket": // Ignore distinction // TODO: this makes the error message wrong // TODO: what's the difference? pushProp(config, "unix-socket", value); break; case "trace": case "trace-ascii": case "stderr": case "libcurl": case "config": case "parallel-max": global_[argName] = value; break; case "language": // --language is a curlconverter specific option global_[argName] = value.toString(); return; } return pushProp(config, argName, value); } // Might create a new config function setArgValue(global_, config, argName, toggle) { switch (argName) { case "digest": if (toggle) { config.authtype |= CURLAUTH_DIGEST; } else { config.authtype &= ~CURLAUTH_DIGEST; } break; case "proxy-digest": if (toggle) { config.proxyauthtype |= CURLAUTH_DIGEST; } else { config.proxyauthtype &= ~CURLAUTH_DIGEST; } break; case "negotiate": if (toggle) { config.authtype |= CURLAUTH_NEGOTIATE; } else { config.authtype &= ~CURLAUTH_NEGOTIATE; } break; case "proxy-negotiate": if (toggle) { config.proxyauthtype |= CURLAUTH_NEGOTIATE; } else { config.proxyauthtype &= ~CURLAUTH_NEGOTIATE; } break; case "ntlm": if (toggle) { config.authtype |= CURLAUTH_NTLM; } else { config.authtype &= ~CURLAUTH_NTLM; } break; case "proxy-ntlm": if (toggle) { config.proxyauthtype |= CURLAUTH_NTLM; } else { config.proxyauthtype &= ~CURLAUTH_NTLM; } break; case "ntlm-wb": if (toggle) { config.authtype |= CURLAUTH_NTLM_WB; } else { config.authtype &= ~CURLAUTH_NTLM_WB; } break; case "basic": if (toggle) { config.authtype |= CURLAUTH_BASIC; } else { config.authtype &= ~CURLAUTH_BASIC; } break; case "proxy-basic": if (toggle) { config.proxyauthtype |= CURLAUTH_BASIC; } else { config.proxyauthtype &= ~CURLAUTH_BASIC; } break; case "anyauth": if (toggle) { config.authtype = CURLAUTH_ANY; } break; case "proxy-anyauth": if (toggle) { config.proxyauthtype = CURLAUTH_ANY; } break; case "location": config["location"] = toggle; break; case "location-trusted": config["location"] = toggle; config["location-trusted"] = toggle; break; case "http1.0": config.httpVersion = "1.0"; break; case "http1.1": config.httpVersion = "1.1"; break; case "http2": config.httpVersion = "2"; break; case "http2-prior-knowledge": config.httpVersion = "2-prior-knowledge"; break; case "http3": config.httpVersion = "3"; break; case "http3-only": config.httpVersion = "3-only"; break; case "tlsv1": config.tlsVersion = "1"; break; case "tlsv1.0": config.tlsVersion = "1.0"; break; case "tlsv1.1": config.tlsVersion = "1.1"; break; case "tlsv1.2": config.tlsVersion = "1.2"; break; case "tlsv1.3": config.tlsVersion = "1.3"; break; case "verbose": case "version": case "trace-time": case "test-event": case "progress-bar": case "progress-meter": case "fail-early": case "styled-output": case "help": case "silent": case "show-error": case "parallel": case "parallel-immediate": case "stdin": // --stdin or - is a curlconverter specific option global_[argName] = toggle; break; case "next": // curl ignores --next if the last url node doesn't have a url if (toggle && config.url && config.url.length > 0 && config.url.length >= (config["upload-file"] || []).length && config.url.length >= (config.output || []).length) { config = { authtype: CURLAUTH_BASIC, proxyauthtype: CURLAUTH_BASIC }; global_.configs.push(config); } break; default: config[argName] = toggle; } return config; } export function parseArgs(args, longOpts = curlLongOpts, shortenedLongOpts = curlLongOptsShortened, shortOpts = curlShortOpts, supportedOpts, warnings = []) { let config = { authtype: CURLAUTH_BASIC, proxyauthtype: CURLAUTH_BASIC, }; const global_ = { configs: [config], warnings }; const seen = []; for (let i = 1, stillflags = true; i < args.length; i++) { const arg = args[i]; if (stillflags && arg.startsWith("-")) { if (eq(arg, "--")) { /* This indicates the end of the flags and thus enables the following (URL) argument to start with -. */ stillflags = false; } else if (arg.startsWith("--")) { const shellToken = firstShellToken(arg); if (shellToken) { // TODO: if there's any text after the "--" or after the variable // we could narrow it down. throw new CCError("this " + shellToken.type + " could " + (shellToken.type === "command" ? "return" : "be") + " anything\n" + underlineNode(shellToken.syntaxNode)); } const argStr = arg.toString(); const lookup = argStr.slice(2); let longArg = shortenedLongOpts[lookup]; if (typeof longArg === "undefined") { longArg = longOpts[lookup]; } if (longArg === null) { throw new CCError("option " + argStr + ": is ambiguous"); } if (typeof longArg === "undefined") { // TODO: extract a list of deleted arguments to check here throw new CCError("option " + argStr + ": is unknown"); } if (longArg.type === "string") { i++; if (i >= args.length) { throw new CCError("option " + argStr + ": requires parameter"); } pushArgValue(global_, config, longArg.name, args[i]); } else { config = setArgValue(global_, config, longArg.name, toBoolean(argStr.slice(2))); // TODO: all shortened args work correctly? } checkSupported(global_, argStr, longArg, supportedOpts); seen.push([longArg.name, argStr]); } else { // Short option. These can look like // -X POST -> {request: 'POST'} // or // -XPOST -> {request: 'POST'} // or multiple options // -ABCX POST -> {A: true, B: true, C: true, request: 'POST'} // or multiple options and a value for the last one // -ABCXPOST -> {A: true, B: true, C: true, request: 'POST'} // "-" passed to curl as an argument raises an error, // curlconverter's command line uses it to read from stdin if (arg.length === 1) { if (Object.prototype.hasOwnProperty.call(shortOpts, "")) { const shortFor = shortOpts[""]; const longArg = longOpts[shortFor]; if (longArg === null) { throw new CCError("option -: is unknown"); } config = setArgValue(global_, config, longArg.name, toBoolean(shortFor)); seen.push([longArg.name, "-"]); } else { throw new CCError("option -: is unknown"); } } for (let j = 1; j < arg.length; j++) { const jthChar = arg.get(j); if (typeof jthChar !== "string") { // A bash variable in the middle of a short option throw new CCError("this " + jthChar.type + " could " + (jthChar.type === "command" ? "return" : "be") + " anything\n" + underlineNode(jthChar.syntaxNode)); } if (!has(shortOpts, jthChar)) { if (has(changedShortOpts, jthChar)) { throw new CCError("option " + arg + ": " + changedShortOpts[jthChar]); } // TODO: there are a few deleted short options we could report throw new CCError("option " + arg + ": is unknown"); } const lookup = jthChar; const shortFor = shortOpts[lookup]; const longArg = longOpts[shortFor]; if (longArg === null) { // This could happen if curlShortOpts points to a renamed option or has a typo throw new CCError("ambiguous short option -" + jthChar); } if (longArg.type === "string") { let val; if (j + 1 < arg.length) { // treat -XPOST as -X POST val = arg.slice(j + 1); j = arg.length; } else if (i + 1 < args.length) { i++; val = args[i]; } else { throw new CCError("option " + arg.toString() + ": requires parameter"); } pushArgValue(global_, config, longArg.name, val); } else { // Use shortFor because -N is short for --no-buffer // and we want to end up with {buffer: false} config = setArgValue(global_, config, longArg.name, toBoolean(shortFor)); } if (lookup) { checkSupported(global_, "-" + lookup, longArg, supportedOpts); seen.push([longArg.name, "-" + lookup]); } } } } else { if (typeof arg !== "string" && arg.tokens.length && typeof arg.tokens[0] !== "string") { const isOrBeginsWith = arg.tokens.length === 1 ? "is" : "begins with"; warnings.push([ "ambiguous argument", "argument " + isOrBeginsWith + " a " + arg.tokens[0].type + ", assuming it's a URL\n" + underlineNode(arg.tokens[0].syntaxNode), ]); } pushArgValue(global_, config, "url", arg); seen.push(["url", "--url"]); } } for (const cfg of global_.configs) { for (const [arg, values] of Object.entries(cfg)) { if (Array.isArray(values) && !canBeList.has(arg)) { cfg[arg] = values[values.length - 1]; } } } return [global_, seen]; } //# sourceMappingURL=opts.js.map