summaryrefslogtreecommitdiff
path: root/home/.oh-my-zsh/plugins/shell-proxy
diff options
context:
space:
mode:
Diffstat (limited to 'home/.oh-my-zsh/plugins/shell-proxy')
-rw-r--r--home/.oh-my-zsh/plugins/shell-proxy/.editorconfig3
-rw-r--r--home/.oh-my-zsh/plugins/shell-proxy/README.md67
-rwxr-xr-xhome/.oh-my-zsh/plugins/shell-proxy/proxy.py91
-rw-r--r--home/.oh-my-zsh/plugins/shell-proxy/shell-proxy.plugin.zsh44
-rwxr-xr-xhome/.oh-my-zsh/plugins/shell-proxy/ssh-agent.py16
-rwxr-xr-xhome/.oh-my-zsh/plugins/shell-proxy/ssh-proxy.py37
6 files changed, 258 insertions, 0 deletions
diff --git a/home/.oh-my-zsh/plugins/shell-proxy/.editorconfig b/home/.oh-my-zsh/plugins/shell-proxy/.editorconfig
new file mode 100644
index 0000000..b7c70d1
--- /dev/null
+++ b/home/.oh-my-zsh/plugins/shell-proxy/.editorconfig
@@ -0,0 +1,3 @@
+[*.py]
+indent_size = 4
+indent_style = space
diff --git a/home/.oh-my-zsh/plugins/shell-proxy/README.md b/home/.oh-my-zsh/plugins/shell-proxy/README.md
new file mode 100644
index 0000000..102e46b
--- /dev/null
+++ b/home/.oh-my-zsh/plugins/shell-proxy/README.md
@@ -0,0 +1,67 @@
+# shell-proxy plugin
+
+This a pure user-space program, shell-proxy setter, written in Python3 and Zsh.
+
+To use it, add `shell-proxy` to the plugins array in your zshrc file:
+
+```zsh
+plugins=(... shell-proxy)
+```
+
+## Key features
+
+- Supports macOS and Linux (Ubuntu, Archlinux, etc.)
+- Supports git via setting `$GIT_SSH`
+- Supports ssh, sftp, scp, slogin and ssh-copy-id via setting aliases
+- Built-in autocomplete
+
+## Usage
+
+### Method 1
+
+Set `SHELLPROXY_URL` environment variable to the URL of the proxy server:
+
+```sh
+SHELLPROXY_URL="http://127.0.0.1:8123"
+SHELLPROXY_NO_PROXY="localhost,127.0.0.1"
+proxy enable
+```
+
+### Method 2
+
+Write a program file in `$HOME/.config/proxy` so that the proxy URL is defined dynamically.
+Note that the program file must be executable.
+
+Example:
+
+```sh
+#!/bin/bash
+
+# HTTP Proxy
+if [[ "$(uname)" = Darwin ]]; then
+ echo "http://127.0.0.1:6152" # Surge Mac
+else
+ echo "http://127.0.0.1:8123" # polipo
+fi
+
+# No Proxy
+echo "localhost,127.0.0.1"
+```
+
+### Method 3
+
+Use [method 2](#method-2) but define the location of the program file by setting the
+`SHELLPROXY_CONFIG` environment variable:
+
+```sh
+SHELLPROXY_CONFIG="$HOME/.dotfiles/proxy-config"
+```
+
+## Reference
+
+- `$GIT_SSH`: <https://www.git-scm.com/docs/git#Documentation/git.txt-codeGITSSHcode>
+- OpenSSH manual: <https://man.openbsd.org/ssh>
+
+## Maintainer
+
+- [@septs](https://github.com/septs)
diff --git a/home/.oh-my-zsh/plugins/shell-proxy/proxy.py b/home/.oh-my-zsh/plugins/shell-proxy/proxy.py
new file mode 100755
index 0000000..8c2aaf9
--- /dev/null
+++ b/home/.oh-my-zsh/plugins/shell-proxy/proxy.py
@@ -0,0 +1,91 @@
+#!/usr/bin/env python3
+import os
+import sys
+from subprocess import check_output, list2cmdline
+
+cwd = os.path.dirname(__file__)
+ssh_agent = os.path.join(cwd, "ssh-agent.py")
+proxy_env = "SHELLPROXY_URL"
+no_proxy_env = "SHELLPROXY_NO_PROXY"
+proxy_config = os.environ.get("SHELLPROXY_CONFIG") or os.path.expandvars("$HOME/.config/proxy")
+
+usage="""shell-proxy: no proxy configuration found.
+
+Set `{env}` or create a config file at `{config}`
+See the plugin README for more information.""".format(env=proxy_env, config=proxy_config)
+
+def get_http_proxy():
+ default_proxy = os.environ.get(proxy_env)
+ no_proxy = os.environ.get(no_proxy_env)
+ if default_proxy and no_proxy:
+ return default_proxy, no_proxy
+
+ if os.path.isfile(proxy_config):
+ proxy_configdata = [line.strip() for line in check_output(proxy_config).decode("utf-8").splitlines()]
+ if len(proxy_configdata) >= 1:
+ if not default_proxy:
+ default_proxy = proxy_configdata[0]
+ if len(proxy_configdata) == 2 and not no_proxy:
+ no_proxy = proxy_configdata[1]
+
+ if default_proxy:
+ return default_proxy, no_proxy
+ print(usage, file=sys.stderr)
+ sys.exit(1)
+
+
+def make_proxies(url: str, no_proxy: str):
+ proxies = {"%s_PROXY" % _: url for _ in ("HTTP", "HTTPS", "FTP", "RSYNC", "ALL")}
+ proxies.update({name.lower(): value for (name, value) in proxies.items()})
+ proxies["GIT_SSH"] = ssh_agent
+ if no_proxy:
+ proxies.update({"NO_PROXY": no_proxy, "no_proxy": no_proxy})
+ return proxies
+
+
+def merge(mapping: dict):
+ return ("%s=%s" % _ for _ in mapping.items())
+
+
+class CommandSet:
+ proxies = make_proxies(*get_http_proxy())
+ aliases = {
+ _: "env __SSH_PROGRAM_NAME__=%s %s" % (_, ssh_agent)
+ for _ in ("ssh", "sftp", "scp", "slogin", "ssh-copy-id")
+ }
+
+ def enable(self):
+ cmdline("export", *merge(self.proxies))
+ cmdline("alias", *merge(self.aliases))
+
+ def disable(self):
+ cmdline("unset", *self.proxies.keys())
+ cmdline("unalias", *self.aliases.keys())
+
+ def status(self):
+ proxies = (
+ "%11s = %s" % (name, os.environ[name])
+ for name in self.proxies.keys()
+ if name in os.environ
+ )
+ for _ in proxies:
+ cmdline("echo", _)
+
+ def usage(self):
+ print("usage: proxy {enable,disable,status}", file=sys.stderr)
+
+
+def cmdline(*items):
+ print(list2cmdline(items))
+
+
+def main():
+ command = CommandSet()
+ if len(sys.argv) == 1:
+ command.usage()
+ sys.exit(1)
+ getattr(command, sys.argv[1], command.usage)()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/home/.oh-my-zsh/plugins/shell-proxy/shell-proxy.plugin.zsh b/home/.oh-my-zsh/plugins/shell-proxy/shell-proxy.plugin.zsh
new file mode 100644
index 0000000..f6c31da
--- /dev/null
+++ b/home/.oh-my-zsh/plugins/shell-proxy/shell-proxy.plugin.zsh
@@ -0,0 +1,44 @@
+#!/usr/bin/bash
+# shellcheck disable=SC1090,SC2154
+
+# Handle $0 according to the standard:
+# https://zdharma-continuum.github.io/Zsh-100-Commits-Club/Zsh-Plugin-Standard.html
+0="${${ZERO:-${0:#$ZSH_ARGZERO}}:-${(%):-%N}}"
+0="${${(M)0:#/*}:-$PWD/$0}"
+
+eval '
+ proxy() {
+ # deprecate $DEFAULT_PROXY, use SHELLPROXY_URL instead
+ if [[ -n "$DEFAULT_PROXY" && -z "$SHELLPROXY_URL" ]]; then
+ echo >&2 "proxy: DEFAULT_PROXY is deprecated, use SHELLPROXY_URL instead"
+ SHELLPROXY_URL="$DEFAULT_PROXY"
+ unset DEFAULT_PROXY
+ fi
+
+ # deprecate CONFIG_PROXY, use SHELLPROXY_CONFIG instead
+ if [[ -n "$CONFIG_PROXY" && -z "$SHELLPROXY_CONFIG" ]]; then
+ echo >&2 "proxy: CONFIG_PROXY is deprecated, use SHELLPROXY_CONFIG instead"
+ SHELLPROXY_CONFIG="$CONFIG_PROXY"
+ unset CONFIG_PROXY
+ fi
+
+ # the proxy.py script is in the same directory as this function
+ local proxy="'"${0:h}"'/proxy.py"
+
+ # capture the output of the proxy script and bail out if it fails
+ local output
+ output="$(SHELLPROXY_URL="$SHELLPROXY_URL" SHELLPROXY_NO_PROXY="$SHELLPROXY_NO_PROXY" SHELLPROXY_CONFIG="$SHELLPROXY_CONFIG" "$proxy" "$1")" ||
+ return $?
+
+ # evaluate the output generated by the proxy script
+ source <(echo "$output")
+ }
+'
+
+_proxy() {
+ local -r commands=('enable' 'disable' 'status')
+ compset -P '*,'
+ compadd -S '' "${commands[@]}"
+}
+
+compdef _proxy proxy
diff --git a/home/.oh-my-zsh/plugins/shell-proxy/ssh-agent.py b/home/.oh-my-zsh/plugins/shell-proxy/ssh-agent.py
new file mode 100755
index 0000000..4ee24b7
--- /dev/null
+++ b/home/.oh-my-zsh/plugins/shell-proxy/ssh-agent.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python3
+import os
+import subprocess
+import sys
+
+ssh_proxy = os.path.join(os.path.dirname(__file__), "ssh-proxy.py")
+
+argv = [
+ os.environ.get("__SSH_PROGRAM_NAME__", "ssh"),
+ "-o",
+ "ProxyCommand={} %h %p".format(ssh_proxy),
+ "-o",
+ "Compression=yes",
+]
+
+subprocess.call(argv + sys.argv[1:], env=os.environ)
diff --git a/home/.oh-my-zsh/plugins/shell-proxy/ssh-proxy.py b/home/.oh-my-zsh/plugins/shell-proxy/ssh-proxy.py
new file mode 100755
index 0000000..4b692f9
--- /dev/null
+++ b/home/.oh-my-zsh/plugins/shell-proxy/ssh-proxy.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python3
+import os
+import subprocess
+import sys
+from urllib.parse import urlparse
+
+proxy = next(os.environ[_] for _ in ("HTTP_PROXY", "HTTPS_PROXY") if _ in os.environ)
+
+parsed = urlparse(proxy)
+
+proxy_protocols = {
+ "http": "connect",
+ "https": "connect",
+ "socks": "5",
+ "socks5": "5",
+ "socks4": "4",
+ "socks4a": "4",
+}
+
+if parsed.scheme not in proxy_protocols:
+ raise TypeError('unsupported proxy protocol: "{}"'.format(parsed.scheme))
+
+def make_argv():
+ yield "nc"
+ if sys.platform in {'linux', 'cygwin'}:
+ # caveats: the built-in netcat of most linux distributions and cygwin support proxy type
+ # caveats: macOS built-in netcat command not supported proxy-type
+ yield "-X" # --proxy-type
+ # Supported protocols are 4 (SOCKS v4), 5 (SOCKS v5) and connect (HTTP proxy).
+ # Default SOCKS v5 is used.
+ yield proxy_protocols[parsed.scheme]
+ yield "-x" # --proxy
+ yield parsed.netloc # proxy-host:proxy-port
+ yield sys.argv[1] # host
+ yield sys.argv[2] # port
+
+subprocess.call(make_argv())