diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..b5cc2de
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..ccdce42
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/sonarlint/issuestore/8/e/8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d b/.idea/sonarlint/issuestore/8/e/8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d
new file mode 100644
index 0000000..e69de29
diff --git a/.idea/sonarlint/issuestore/index.pb b/.idea/sonarlint/issuestore/index.pb
new file mode 100644
index 0000000..841e6b6
--- /dev/null
+++ b/.idea/sonarlint/issuestore/index.pb
@@ -0,0 +1,3 @@
+
+9
+ README.md,8/e/8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d
\ No newline at end of file
diff --git a/.idea/sonarlint/securityhotspotstore/8/e/8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d b/.idea/sonarlint/securityhotspotstore/8/e/8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d
new file mode 100644
index 0000000..e69de29
diff --git a/.idea/sonarlint/securityhotspotstore/index.pb b/.idea/sonarlint/securityhotspotstore/index.pb
new file mode 100644
index 0000000..841e6b6
--- /dev/null
+++ b/.idea/sonarlint/securityhotspotstore/index.pb
@@ -0,0 +1,3 @@
+
+9
+ README.md,8/e/8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/webssh.iml b/.idea/webssh.iml
new file mode 100644
index 0000000..53ff249
--- /dev/null
+++ b/.idea/webssh.iml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..3e7f579
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ "associatedIndex": 7
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1696093060393
+
+
+ 1696093060393
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/webssh/handler.py b/webssh/handler.py
index 6cfc822..0d8677c 100644
--- a/webssh/handler.py
+++ b/webssh/handler.py
@@ -6,6 +6,7 @@ import struct
import traceback
import weakref
import paramiko
+import socks
import tornado.web
from concurrent.futures import ThreadPoolExecutor
@@ -29,7 +30,6 @@ try:
except ImportError:
from urlparse import urlparse
-
DEFAULT_PORT = 22
swallow_http_errors = True
@@ -101,7 +101,6 @@ class SSHClient(paramiko.SSHClient):
class PrivateKey(object):
-
max_length = 16384 # rough number
tag_to_name = {
@@ -143,7 +142,7 @@ class PrivateKey(object):
logging.debug('Reset offset to {}.'.format(offset))
logging.debug('Try parsing it as {} type key'.format(name))
- pkeycls = getattr(paramiko, name+'Key')
+ pkeycls = getattr(paramiko, name + 'Key')
pkey = None
try:
@@ -179,12 +178,11 @@ class PrivateKey(object):
msg = 'Invalid key'
if self.password:
msg += ' or wrong passphrase "{}" for decrypting it.'.format(
- self.password)
+ self.password)
raise InvalidValueError(msg)
class MixinHandler(object):
-
custom_headers = {
'Server': 'TornadoServer'
}
@@ -313,8 +311,7 @@ class NotFoundHandler(MixinHandler, tornado.web.ErrorHandler):
class IndexHandler(MixinHandler, tornado.web.RequestHandler):
-
- executor = ThreadPoolExecutor(max_workers=cpu_count()*5)
+ executor = ThreadPoolExecutor(max_workers=cpu_count() * 5)
def initialize(self, loop, policy, host_keys_settings):
super(IndexHandler, self).initialize(loop)
@@ -383,9 +380,9 @@ class IndexHandler(MixinHandler, tornado.web.RequestHandler):
if self.ssh_client._system_host_keys.lookup(key) is None:
if self.ssh_client._host_keys.lookup(key) is None:
raise tornado.web.HTTPError(
- 403, 'Connection to {}:{} is not allowed.'.format(
- hostname, port)
- )
+ 403, 'Connection to {}:{} is not allowed.'.format(
+ hostname, port)
+ )
def get_args(self):
hostname = self.get_hostname()
@@ -396,6 +393,19 @@ class IndexHandler(MixinHandler, tornado.web.RequestHandler):
passphrase = self.get_argument('passphrase', u'')
totp = self.get_argument('totp', u'')
+ # proxyType, proxyIp, proxyPort, proxyRdns = true, proxyUser, proxyPass
+
+ proxyType = self.get_argument('proxytype', None)
+ if proxyType is not None and proxyType != '':
+ proxyType = int(proxyType)
+ proxyIp = self.get_argument('proxyip', u'')
+ proxyPort = self.get_argument('proxyport', None)
+ if proxyPort is not None and proxyPort != '':
+ proxyPort = int(proxyPort)
+ proxyRdns = self.get_argument('proxyrdns', u'')
+ proxyUser = self.get_argument('proxyuser', u'')
+ proxyPass = self.get_argument('proxypass', u'')
+
if isinstance(self.policy, paramiko.RejectPolicy):
self.lookup_hostname(hostname, port)
@@ -405,7 +415,8 @@ class IndexHandler(MixinHandler, tornado.web.RequestHandler):
pkey = None
self.ssh_client.totp = totp
- args = (hostname, port, username, password, pkey)
+ args = (
+ hostname, port, username, password, pkey, proxyType, proxyIp, proxyPort, proxyRdns, proxyUser, proxyPass)
logging.debug(args)
return args
@@ -446,13 +457,33 @@ class IndexHandler(MixinHandler, tornado.web.RequestHandler):
logging.warning('Could not detect the default encoding.')
return 'utf-8'
+ def http_proxy_tunnel_connect(self, proxy, target, timeout=None):
+ logging.info('Connecting to proxy {}'.format(proxy))
+ logging.info('Connecting to target {}'.format(target))
+ sock = socks.socksocket()
+ sock.set_proxy(*proxy)
+ sock.connect(target)
+ sock.settimeout(timeout)
+ return sock
+
def ssh_connect(self, args):
ssh = self.ssh_client
dst_addr = args[:2]
+ logging.info(args)
logging.info('Connecting to {}:{}'.format(*dst_addr))
+ sock = None
+ if len(args) > 5:
+ if args[6] is not None and args[6] != '':
+ # 从args中获取代理信息
+ sock = self.http_proxy_tunnel_connect(
+ proxy=args[5:],
+ target=dst_addr,
+ timeout=5000
+ )
+
try:
- ssh.connect(*args, timeout=options.timeout)
+ ssh.connect(*args[:5], timeout=options.timeout, sock=sock)
except socket.error:
raise ValueError('Unable to connect to {}:{}'.format(*dst_addr))
except paramiko.BadAuthenticationType:
@@ -503,6 +534,7 @@ class IndexHandler(MixinHandler, tornado.web.RequestHandler):
self.check_origin()
+ logging.info('Connected from {}'.format(self.get_args()))
try:
args = self.get_args()
except InvalidValueError as exc:
diff --git a/webssh/static/js/main.js b/webssh/static/js/main.js
index 6f79643..4228acc 100644
--- a/webssh/static/js/main.js
+++ b/webssh/static/js/main.js
@@ -4,856 +4,847 @@ var jQuery;
var wssh = {};
-(function() {
- // For FormData without getter and setter
- var proto = FormData.prototype,
- data = {};
+(function () {
+ // For FormData without getter and setter
+ var proto = FormData.prototype, data = {};
- if (!proto.get) {
- proto.get = function (name) {
- if (data[name] === undefined) {
- var input = document.querySelector('input[name="' + name + '"]'),
- value;
- if (input) {
- if (input.type === 'file') {
- value = input.files[0];
- } else {
- value = input.value;
- }
- data[name] = value;
- }
- }
- return data[name];
- };
- }
+ if (!proto.get) {
+ proto.get = function (name) {
+ if (data[name] === undefined) {
+ var input = document.querySelector('input[name="' + name + '"]'), value;
+ if (input) {
+ if (input.type === 'file') {
+ value = input.files[0];
+ } else {
+ value = input.value;
+ }
+ data[name] = value;
+ }
+ }
+ return data[name];
+ };
+ }
- if (!proto.set) {
- proto.set = function (name, value) {
- data[name] = value;
- };
- }
+ if (!proto.set) {
+ proto.set = function (name, value) {
+ data[name] = value;
+ };
+ }
}());
-jQuery(function($){
- var status = $('#status'),
- button = $('.btn-primary'),
- form_container = $('.form-container'),
- waiter = $('#waiter'),
- term_type = $('#term'),
- style = {},
- default_title = 'WebSSH',
- title_element = document.querySelector('title'),
- form_id = '#connect',
- debug = document.querySelector(form_id).noValidate,
- custom_font = document.fonts ? document.fonts.values().next().value : undefined,
- default_fonts,
- DISCONNECTED = 0,
- CONNECTING = 1,
- CONNECTED = 2,
- state = DISCONNECTED,
- messages = {1: 'This client is connecting ...', 2: 'This client is already connnected.'},
- key_max_size = 16384,
- fields = ['hostname', 'port', 'username'],
- form_keys = fields.concat(['password', 'totp']),
- opts_keys = ['bgcolor', 'title', 'encoding', 'command', 'term', 'fontsize', 'fontcolor', 'cursor'],
- url_form_data = {},
- url_opts_data = {},
- validated_form_data,
- event_origin,
- hostname_tester = /((^\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$))|(^\s*((?=.{1,255}$)(?=.*[A-Za-z].*)[0-9A-Za-z](?:(?:[0-9A-Za-z]|\b-){0,61}[0-9A-Za-z])?(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|\b-){0,61}[0-9A-Za-z])?)*)\s*$)/;
+jQuery(function ($) {
+ var status = $('#status'), button = $('.btn-primary'), form_container = $('.form-container'), waiter = $('#waiter'),
+ term_type = $('#term'), style = {}, default_title = 'WebSSH', title_element = document.querySelector('title'),
+ form_id = '#connect', debug = document.querySelector(form_id).noValidate,
+ custom_font = document.fonts ? document.fonts.values().next().value : undefined, default_fonts,
+ DISCONNECTED = 0, CONNECTING = 1, CONNECTED = 2, state = DISCONNECTED,
+ messages = {1: 'This client is connecting ...', 2: 'This client is already connnected.'}, key_max_size = 16384,
+ fields = ['hostname', 'port', 'username'],
+ form_keys = fields.concat(['password', 'totp', 'proxytype', 'proxyip', 'proxyport', 'proxyrdns', 'proxyuser', 'proxypass']),
+ opts_keys = ['bgcolor', 'title', 'encoding', 'command', 'term', 'fontsize', 'fontcolor', 'cursor'],
+ url_form_data = {}, url_opts_data = {}, validated_form_data, event_origin,
+ hostname_tester = /((^\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$))|(^\s*((?=.{1,255}$)(?=.*[A-Za-z].*)[0-9A-Za-z](?:(?:[0-9A-Za-z]|\b-){0,61}[0-9A-Za-z])?(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|\b-){0,61}[0-9A-Za-z])?)*)\s*$)/;
- function store_items(names, data) {
- var i, name, value;
+ function store_items(names, data) {
+ var i, name, value;
- for (i = 0; i < names.length; i++) {
- name = names[i];
- value = data.get(name);
- if (value){
- window.localStorage.setItem(name, value);
- }
- }
- }
-
-
- function restore_items(names) {
- var i, name, value;
-
- for (i=0; i < names.length; i++) {
- name = names[i];
- value = window.localStorage.getItem(name);
- if (value) {
- $('#'+name).val(value);
- }
- }
- }
-
-
- function populate_form(data) {
- var names = form_keys.concat(['passphrase']),
- i, name;
-
- for (i=0; i < names.length; i++) {
- name = names[i];
- $('#'+name).val(data.get(name));
- }
- }
-
-
- function get_object_length(object) {
- return Object.keys(object).length;
- }
-
-
- function decode_uri_component(uri) {
- try {
- return decodeURIComponent(uri);
- } catch(e) {
- console.error(e);
- }
- return '';
- }
-
-
- function decode_password(encoded) {
- try {
- return window.atob(encoded);
- } catch (e) {
- console.error(e);
- }
- return null;
- }
-
-
- function parse_url_data(string, form_keys, opts_keys, form_map, opts_map) {
- var i, pair, key, val,
- arr = string.split('&');
-
- for (i = 0; i < arr.length; i++) {
- pair = arr[i].split('=');
- key = pair[0].trim().toLowerCase();
- val = pair.slice(1).join('=').trim();
-
- if (form_keys.indexOf(key) >= 0) {
- form_map[key] = val;
- } else if (opts_keys.indexOf(key) >=0) {
- opts_map[key] = val;
- }
- }
-
- if (form_map.password) {
- form_map.password = decode_password(form_map.password);
- }
- }
-
-
- function parse_xterm_style() {
- var text = $('.xterm-helpers style').text();
- var arr = text.split('xterm-normal-char{width:');
- style.width = parseFloat(arr[1]);
- arr = text.split('div{height:');
- style.height = parseFloat(arr[1]);
- }
-
-
- function get_cell_size(term) {
- style.width = term._core._renderService._renderer.dimensions.actualCellWidth;
- style.height = term._core._renderService._renderer.dimensions.actualCellHeight;
- }
-
-
- function toggle_fullscreen(term) {
- $('#terminal .terminal').toggleClass('fullscreen');
- term.fitAddon.fit();
- }
-
-
- function current_geometry(term) {
- if (!style.width || !style.height) {
- try {
- get_cell_size(term);
- } catch (TypeError) {
- parse_xterm_style();
- }
- }
-
- var cols = parseInt(window.innerWidth / style.width, 10) - 1;
- var rows = parseInt(window.innerHeight / style.height, 10);
- return {'cols': cols, 'rows': rows};
- }
-
-
- function resize_terminal(term) {
- var geometry = current_geometry(term);
- term.on_resize(geometry.cols, geometry.rows);
- }
-
-
- function set_backgound_color(term, color) {
- term.setOption('theme', {
- background: color
- });
- }
-
- function set_font_color(term, color) {
- term.setOption('theme', {
- foreground: color
- });
- }
-
- function custom_font_is_loaded() {
- if (!custom_font) {
- console.log('No custom font specified.');
- } else {
- console.log('Status of custom font ' + custom_font.family + ': ' + custom_font.status);
- if (custom_font.status === 'loaded') {
- return true;
- }
- if (custom_font.status === 'unloaded') {
- return false;
- }
- }
- }
-
- function update_font_family(term) {
- if (term.font_family_updated) {
- console.log('Already using custom font family');
- return;
- }
-
- if (!default_fonts) {
- default_fonts = term.getOption('fontFamily');
- }
-
- if (custom_font_is_loaded()) {
- var new_fonts = custom_font.family + ', ' + default_fonts;
- term.setOption('fontFamily', new_fonts);
- term.font_family_updated = true;
- console.log('Using custom font family ' + new_fonts);
- }
- }
-
-
- function reset_font_family(term) {
- if (!term.font_family_updated) {
- console.log('Already using default font family');
- return;
- }
-
- if (default_fonts) {
- term.setOption('fontFamily', default_fonts);
- term.font_family_updated = false;
- console.log('Using default font family ' + default_fonts);
- }
- }
-
-
- function format_geometry(cols, rows) {
- return JSON.stringify({'cols': cols, 'rows': rows});
- }
-
-
- function read_as_text_with_decoder(file, callback, decoder) {
- var reader = new window.FileReader();
-
- if (decoder === undefined) {
- decoder = new window.TextDecoder('utf-8', {'fatal': true});
- }
-
- reader.onload = function() {
- var text;
- try {
- text = decoder.decode(reader.result);
- } catch (TypeError) {
- console.log('Decoding error happened.');
- } finally {
- if (callback) {
- callback(text);
+ for (i = 0; i < names.length; i++) {
+ name = names[i];
+ value = data.get(name);
+ if (value) {
+ window.localStorage.setItem(name, value);
+ }
}
- }
- };
-
- reader.onerror = function (e) {
- console.error(e);
- };
-
- reader.readAsArrayBuffer(file);
- }
-
-
- function read_as_text_with_encoding(file, callback, encoding) {
- var reader = new window.FileReader();
-
- if (encoding === undefined) {
- encoding = 'utf-8';
}
- reader.onload = function() {
- if (callback) {
- callback(reader.result);
- }
- };
- reader.onerror = function (e) {
- console.error(e);
- };
+ function restore_items(names) {
+ var i, name, value;
- reader.readAsText(file, encoding);
- }
-
-
- function read_file_as_text(file, callback, decoder) {
- if (!window.TextDecoder) {
- read_as_text_with_encoding(file, callback, decoder);
- } else {
- read_as_text_with_decoder(file, callback, decoder);
- }
- }
-
-
- function reset_wssh() {
- var name;
-
- for (name in wssh) {
- if (wssh.hasOwnProperty(name) && name !== 'connect') {
- delete wssh[name];
- }
- }
- }
-
-
- function log_status(text, to_populate) {
- console.log(text);
- status.html(text.split('\n').join('
'));
-
- if (to_populate && validated_form_data) {
- populate_form(validated_form_data);
- validated_form_data = undefined;
- }
-
- if (waiter.css('display') !== 'none') {
- waiter.hide();
- }
-
- if (form_container.css('display') === 'none') {
- form_container.show();
- }
- }
-
-
- function ajax_complete_callback(resp) {
- button.prop('disabled', false);
-
- if (resp.status !== 200) {
- log_status(resp.status + ': ' + resp.statusText, true);
- state = DISCONNECTED;
- return;
- }
-
- var msg = resp.responseJSON;
- if (!msg.id) {
- log_status(msg.status, true);
- state = DISCONNECTED;
- return;
- }
-
- var ws_url = window.location.href.split(/\?|#/, 1)[0].replace('http', 'ws'),
- join = (ws_url[ws_url.length-1] === '/' ? '' : '/'),
- url = ws_url + join + 'ws?id=' + msg.id,
- sock = new window.WebSocket(url),
- encoding = 'utf-8',
- decoder = window.TextDecoder ? new window.TextDecoder(encoding) : encoding,
- terminal = document.getElementById('terminal'),
- termOptions = {
- cursorBlink: true,
- theme: {
- background: url_opts_data.bgcolor || 'black',
- foreground: url_opts_data.fontcolor || 'white',
- cursor: url_opts_data.cursor || url_opts_data.fontcolor || 'white'
- }
- };
-
- if (url_opts_data.fontsize) {
- var fontsize = window.parseInt(url_opts_data.fontsize);
- if (fontsize && fontsize > 0) {
- termOptions.fontSize = fontsize;
- }
- }
-
- var term = new window.Terminal(termOptions);
-
- term.fitAddon = new window.FitAddon.FitAddon();
- term.loadAddon(term.fitAddon);
-
- console.log(url);
- if (!msg.encoding) {
- console.log('Unable to detect the default encoding of your server');
- msg.encoding = encoding;
- } else {
- console.log('The deault encoding of your server is ' + msg.encoding);
- }
-
- function term_write(text) {
- if (term) {
- term.write(text);
- if (!term.resized) {
- resize_terminal(term);
- term.resized = true;
+ for (i = 0; i < names.length; i++) {
+ name = names[i];
+ value = window.localStorage.getItem(name);
+ if (value) {
+ $('#' + name).val(value);
+ }
}
- }
}
- function set_encoding(new_encoding) {
- // for console use
- if (!new_encoding) {
- console.log('An encoding is required');
- return;
- }
- if (!window.TextDecoder) {
- decoder = new_encoding;
- encoding = decoder;
- console.log('Set encoding to ' + encoding);
- } else {
+ function populate_form(data) {
+ var names = form_keys.concat(['passphrase']), i, name;
+
+ for (i = 0; i < names.length; i++) {
+ name = names[i];
+ $('#' + name).val(data.get(name));
+ }
+ }
+
+
+ function get_object_length(object) {
+ return Object.keys(object).length;
+ }
+
+
+ function decode_uri_component(uri) {
try {
- decoder = new window.TextDecoder(new_encoding);
- encoding = decoder.encoding;
- console.log('Set encoding to ' + encoding);
- } catch (RangeError) {
- console.log('Unknown encoding ' + new_encoding);
- return false;
+ return decodeURIComponent(uri);
+ } catch (e) {
+ console.error(e);
}
- }
- }
-
- wssh.set_encoding = set_encoding;
-
- if (url_opts_data.encoding) {
- if (set_encoding(url_opts_data.encoding) === false) {
- set_encoding(msg.encoding);
- }
- } else {
- set_encoding(msg.encoding);
+ return '';
}
- wssh.geometry = function() {
- // for console use
- var geometry = current_geometry(term);
- console.log('Current window geometry: ' + JSON.stringify(geometry));
- };
+ function decode_password(encoded) {
+ try {
+ return window.atob(encoded);
+ } catch (e) {
+ console.error(e);
+ }
+ return null;
+ }
- wssh.send = function(data) {
- // for console use
- if (!sock) {
- console.log('Websocket was already closed');
- return;
- }
- if (typeof data !== 'string') {
- console.log('Only string is allowed');
- return;
- }
+ function parse_url_data(string, form_keys, opts_keys, form_map, opts_map) {
+ var i, pair, key, val, arr = string.split('&');
- try {
- JSON.parse(data);
- sock.send(data);
- } catch (SyntaxError) {
- data = data.trim() + '\r';
- sock.send(JSON.stringify({'data': data}));
- }
- };
+ for (i = 0; i < arr.length; i++) {
+ pair = arr[i].split('=');
+ key = pair[0].trim().toLowerCase();
+ val = pair.slice(1).join('=').trim();
- wssh.reset_encoding = function() {
- // for console use
- if (encoding === msg.encoding) {
- console.log('Already reset to ' + msg.encoding);
- } else {
- set_encoding(msg.encoding);
- }
- };
+ if (form_keys.indexOf(key) >= 0) {
+ form_map[key] = val;
+ } else if (opts_keys.indexOf(key) >= 0) {
+ console.log(key, val)
+ opts_map[key] = val;
+ }
+ }
- wssh.resize = function(cols, rows) {
- // for console use
- if (term === undefined) {
- console.log('Terminal was already destroryed');
- return;
- }
+ if (form_map.password) {
+ form_map.password = decode_password(form_map.password);
+ }
+ }
- var valid_args = false;
- if (cols > 0 && rows > 0) {
+ function parse_xterm_style() {
+ var text = $('.xterm-helpers style').text();
+ var arr = text.split('xterm-normal-char{width:');
+ style.width = parseFloat(arr[1]);
+ arr = text.split('div{height:');
+ style.height = parseFloat(arr[1]);
+ }
+
+
+ function get_cell_size(term) {
+ style.width = term._core._renderService._renderer.dimensions.actualCellWidth;
+ style.height = term._core._renderService._renderer.dimensions.actualCellHeight;
+ }
+
+
+ function toggle_fullscreen(term) {
+ $('#terminal .terminal').toggleClass('fullscreen');
+ term.fitAddon.fit();
+ }
+
+
+ function current_geometry(term) {
+ if (!style.width || !style.height) {
+ try {
+ get_cell_size(term);
+ } catch (TypeError) {
+ parse_xterm_style();
+ }
+ }
+
+ var cols = parseInt(window.innerWidth / style.width, 10) - 1;
+ var rows = parseInt(window.innerHeight / style.height, 10);
+ return {'cols': cols, 'rows': rows};
+ }
+
+
+ function resize_terminal(term) {
var geometry = current_geometry(term);
- if (cols <= geometry.cols && rows <= geometry.rows) {
- valid_args = true;
- }
- }
-
- if (!valid_args) {
- console.log('Unable to resize terminal to geometry: ' + format_geometry(cols, rows));
- } else {
- term.on_resize(cols, rows);
- }
- };
-
- wssh.set_bgcolor = function(color) {
- set_backgound_color(term, color);
- };
-
- wssh.set_fontcolor = function(color) {
- set_font_color(term, color);
- };
-
- wssh.custom_font = function() {
- update_font_family(term);
- };
-
- wssh.default_font = function() {
- reset_font_family(term);
- };
-
- term.on_resize = function(cols, rows) {
- if (cols !== this.cols || rows !== this.rows) {
- console.log('Resizing terminal to geometry: ' + format_geometry(cols, rows));
- this.resize(cols, rows);
- sock.send(JSON.stringify({'resize': [cols, rows]}));
- }
- };
-
- term.onData(function(data) {
- // console.log(data);
- sock.send(JSON.stringify({'data': data}));
- });
-
- sock.onopen = function() {
- term.open(terminal);
- toggle_fullscreen(term);
- update_font_family(term);
- term.focus();
- state = CONNECTED;
- title_element.text = url_opts_data.title || default_title;
- if (url_opts_data.command) {
- setTimeout(function () {
- sock.send(JSON.stringify({'data': url_opts_data.command+'\r'}));
- }, 500);
- }
- };
-
- sock.onmessage = function(msg) {
- read_file_as_text(msg.data, term_write, decoder);
- };
-
- sock.onerror = function(e) {
- console.error(e);
- };
-
- sock.onclose = function(e) {
- term.dispose();
- term = undefined;
- sock = undefined;
- reset_wssh();
- log_status(e.reason, true);
- state = DISCONNECTED;
- default_title = 'WebSSH';
- title_element.text = default_title;
- };
-
- $(window).resize(function(){
- if (term) {
- resize_terminal(term);
- }
- });
- }
-
-
- function wrap_object(opts) {
- var obj = {};
-
- obj.get = function(attr) {
- return opts[attr] || '';
- };
-
- obj.set = function(attr, val) {
- opts[attr] = val;
- };
-
- return obj;
- }
-
-
- function clean_data(data) {
- var i, attr, val;
- var attrs = form_keys.concat(['privatekey', 'passphrase']);
-
- for (i = 0; i < attrs.length; i++) {
- attr = attrs[i];
- val = data.get(attr);
- if (typeof val === 'string') {
- data.set(attr, val.trim());
- }
- }
- }
-
-
- function validate_form_data(data) {
- clean_data(data);
-
- var hostname = data.get('hostname'),
- port = data.get('port'),
- username = data.get('username'),
- pk = data.get('privatekey'),
- result = {
- valid: false,
- data: data,
- title: ''
- },
- errors = [], size;
-
- if (!hostname) {
- errors.push('Value of hostname is required.');
- } else {
- if (!hostname_tester.test(hostname)) {
- errors.push('Invalid hostname: ' + hostname);
- }
+ term.on_resize(geometry.cols, geometry.rows);
}
- if (!port) {
- port = 22;
- } else {
- if (!(port > 0 && port <= 65535)) {
- errors.push('Invalid port: ' + port);
- }
+
+ function set_backgound_color(term, color) {
+ term.setOption('theme', {
+ background: color
+ });
}
- if (!username) {
- errors.push('Value of username is required.');
+ function set_font_color(term, color) {
+ term.setOption('theme', {
+ foreground: color
+ });
}
- if (pk) {
- size = pk.size || pk.length;
- if (size > key_max_size) {
- errors.push('Invalid private key: ' + pk.name || '');
- }
- }
-
- if (!errors.length || debug) {
- result.valid = true;
- result.title = username + '@' + hostname + ':' + port;
- }
- result.errors = errors;
-
- return result;
- }
-
- // Fix empty input file ajax submission error for safari 11.x
- function disable_file_inputs(inputs) {
- var i, input;
-
- for (i = 0; i < inputs.length; i++) {
- input = inputs[i];
- if (input.files.length === 0) {
- input.setAttribute('disabled', '');
- }
- }
- }
-
-
- function enable_file_inputs(inputs) {
- var i;
-
- for (i = 0; i < inputs.length; i++) {
- inputs[i].removeAttribute('disabled');
- }
- }
-
-
- function connect_without_options() {
- // use data from the form
- var form = document.querySelector(form_id),
- inputs = form.querySelectorAll('input[type="file"]'),
- url = form.action,
- data, pk;
-
- disable_file_inputs(inputs);
- data = new FormData(form);
- pk = data.get('privatekey');
- enable_file_inputs(inputs);
-
- function ajax_post() {
- status.text('');
- button.prop('disabled', true);
-
- $.ajax({
- url: url,
- type: 'post',
- data: data,
- complete: ajax_complete_callback,
- cache: false,
- contentType: false,
- processData: false
- });
- }
-
- var result = validate_form_data(data);
- if (!result.valid) {
- log_status(result.errors.join('\n'));
- return;
- }
-
- if (pk && pk.size && !debug) {
- read_file_as_text(pk, function(text) {
- if (text === undefined) {
- log_status('Invalid private key: ' + pk.name);
+ function custom_font_is_loaded() {
+ if (!custom_font) {
+ console.log('No custom font specified.');
} else {
- ajax_post();
+ console.log('Status of custom font ' + custom_font.family + ': ' + custom_font.status);
+ if (custom_font.status === 'loaded') {
+ return true;
+ }
+ if (custom_font.status === 'unloaded') {
+ return false;
+ }
}
- });
- } else {
- ajax_post();
}
- return result;
- }
+ function update_font_family(term) {
+ if (term.font_family_updated) {
+ console.log('Already using custom font family');
+ return;
+ }
+ if (!default_fonts) {
+ default_fonts = term.getOption('fontFamily');
+ }
- function connect_with_options(data) {
- // use data from the arguments
- var form = document.querySelector(form_id),
- url = data.url || form.action,
- _xsrf = form.querySelector('input[name="_xsrf"]');
-
- var result = validate_form_data(wrap_object(data));
- if (!result.valid) {
- log_status(result.errors.join('\n'));
- return;
+ if (custom_font_is_loaded()) {
+ var new_fonts = custom_font.family + ', ' + default_fonts;
+ term.setOption('fontFamily', new_fonts);
+ term.font_family_updated = true;
+ console.log('Using custom font family ' + new_fonts);
+ }
}
- data.term = term_type.val();
- data._xsrf = _xsrf.value;
- if (event_origin) {
- data._origin = event_origin;
+
+ function reset_font_family(term) {
+ if (!term.font_family_updated) {
+ console.log('Already using default font family');
+ return;
+ }
+
+ if (default_fonts) {
+ term.setOption('fontFamily', default_fonts);
+ term.font_family_updated = false;
+ console.log('Using default font family ' + default_fonts);
+ }
}
- status.text('');
- button.prop('disabled', true);
- $.ajax({
- url: url,
- type: 'post',
- data: data,
- complete: ajax_complete_callback
+ function format_geometry(cols, rows) {
+ return JSON.stringify({'cols': cols, 'rows': rows});
+ }
+
+
+ function read_as_text_with_decoder(file, callback, decoder) {
+ var reader = new window.FileReader();
+
+ if (decoder === undefined) {
+ decoder = new window.TextDecoder('utf-8', {'fatal': true});
+ }
+
+ reader.onload = function () {
+ var text;
+ try {
+ text = decoder.decode(reader.result);
+ } catch (TypeError) {
+ console.log('Decoding error happened.');
+ } finally {
+ if (callback) {
+ callback(text);
+ }
+ }
+ };
+
+ reader.onerror = function (e) {
+ console.error(e);
+ };
+
+ reader.readAsArrayBuffer(file);
+ }
+
+
+ function read_as_text_with_encoding(file, callback, encoding) {
+ var reader = new window.FileReader();
+
+ if (encoding === undefined) {
+ encoding = 'utf-8';
+ }
+
+ reader.onload = function () {
+ if (callback) {
+ callback(reader.result);
+ }
+ };
+
+ reader.onerror = function (e) {
+ console.error(e);
+ };
+
+ reader.readAsText(file, encoding);
+ }
+
+
+ function read_file_as_text(file, callback, decoder) {
+ if (!window.TextDecoder) {
+ read_as_text_with_encoding(file, callback, decoder);
+ } else {
+ read_as_text_with_decoder(file, callback, decoder);
+ }
+ }
+
+
+ function reset_wssh() {
+ var name;
+
+ for (name in wssh) {
+ if (wssh.hasOwnProperty(name) && name !== 'connect') {
+ delete wssh[name];
+ }
+ }
+ }
+
+
+ function log_status(text, to_populate) {
+ console.log(text);
+ status.html(text.split('\n').join('
'));
+
+ if (to_populate && validated_form_data) {
+ populate_form(validated_form_data);
+ validated_form_data = undefined;
+ }
+
+ if (waiter.css('display') !== 'none') {
+ waiter.hide();
+ }
+
+ if (form_container.css('display') === 'none') {
+ form_container.show();
+ }
+ }
+
+
+ function ajax_complete_callback(resp) {
+ button.prop('disabled', false);
+
+ if (resp.status !== 200) {
+ log_status(resp.status + ': ' + resp.statusText, true);
+ state = DISCONNECTED;
+ return;
+ }
+
+ var msg = resp.responseJSON;
+ if (!msg.id) {
+ log_status(msg.status, true);
+ state = DISCONNECTED;
+ return;
+ }
+
+ var ws_url = window.location.href.split(/\?|#/, 1)[0].replace('http', 'ws'),
+ join = (ws_url[ws_url.length - 1] === '/' ? '' : '/'), url = ws_url + join + 'ws?id=' + msg.id,
+ sock = new window.WebSocket(url), encoding = 'utf-8',
+ decoder = window.TextDecoder ? new window.TextDecoder(encoding) : encoding,
+ terminal = document.getElementById('terminal'), termOptions = {
+ cursorBlink: true,
+ theme: {
+ background: url_opts_data.bgcolor || 'black',
+ foreground: url_opts_data.fontcolor || 'white',
+ cursor: url_opts_data.cursor || url_opts_data.fontcolor || 'white'
+ }
+ };
+
+ window.sock = sock;
+
+ if (url_opts_data.fontsize) {
+ var fontsize = window.parseInt(url_opts_data.fontsize);
+ if (fontsize && fontsize > 0) {
+ termOptions.fontSize = fontsize;
+ }
+ }
+
+ var term = new window.Terminal(termOptions);
+
+ term.fitAddon = new window.FitAddon.FitAddon();
+ term.loadAddon(term.fitAddon);
+
+ console.log(url);
+ if (!msg.encoding) {
+ console.log('Unable to detect the default encoding of your server');
+ msg.encoding = encoding;
+ } else {
+ console.log('The deault encoding of your server is ' + msg.encoding);
+ }
+
+ function term_write(text) {
+ if (term) {
+ term.write(text);
+ window.parent.postMessage({event: 'command', data: text}, '*')
+ if (!term.resized) {
+ resize_terminal(term);
+ term.resized = true;
+ }
+ }
+ }
+
+ function set_encoding(new_encoding) {
+ // for console use
+ if (!new_encoding) {
+ console.log('An encoding is required');
+ return;
+ }
+
+ if (!window.TextDecoder) {
+ decoder = new_encoding;
+ encoding = decoder;
+ console.log('Set encoding to ' + encoding);
+ } else {
+ try {
+ decoder = new window.TextDecoder(new_encoding);
+ encoding = decoder.encoding;
+ console.log('Set encoding to ' + encoding);
+ } catch (RangeError) {
+ console.log('Unknown encoding ' + new_encoding);
+ return false;
+ }
+ }
+ }
+
+ wssh.set_encoding = set_encoding;
+
+ if (url_opts_data.encoding) {
+ if (set_encoding(url_opts_data.encoding) === false) {
+ set_encoding(msg.encoding);
+ }
+ } else {
+ set_encoding(msg.encoding);
+ }
+
+
+ wssh.geometry = function () {
+ // for console use
+ var geometry = current_geometry(term);
+ console.log('Current window geometry: ' + JSON.stringify(geometry));
+ };
+
+ wssh.send = function (data) {
+ // for console use
+ if (!sock) {
+ console.log('Websocket was already closed');
+ return;
+ }
+
+ if (typeof data !== 'string') {
+ console.log('Only string is allowed');
+ return;
+ }
+
+ try {
+ JSON.parse(data);
+ sock.send(data);
+ } catch (SyntaxError) {
+ data = data.trim() + '\r';
+ sock.send(JSON.stringify({'data': data}));
+ }
+ };
+
+ wssh.reset_encoding = function () {
+ // for console use
+ if (encoding === msg.encoding) {
+ console.log('Already reset to ' + msg.encoding);
+ } else {
+ set_encoding(msg.encoding);
+ }
+ };
+
+ wssh.resize = function (cols, rows) {
+ // for console use
+ if (term === undefined) {
+ console.log('Terminal was already destroryed');
+ return;
+ }
+
+ var valid_args = false;
+
+ if (cols > 0 && rows > 0) {
+ var geometry = current_geometry(term);
+ if (cols <= geometry.cols && rows <= geometry.rows) {
+ valid_args = true;
+ }
+ }
+
+ if (!valid_args) {
+ console.log('Unable to resize terminal to geometry: ' + format_geometry(cols, rows));
+ } else {
+ term.on_resize(cols, rows);
+ }
+ };
+
+ wssh.set_bgcolor = function (color) {
+ set_backgound_color(term, color);
+ };
+
+ wssh.set_fontcolor = function (color) {
+ set_font_color(term, color);
+ };
+
+ wssh.custom_font = function () {
+ update_font_family(term);
+ };
+
+ wssh.default_font = function () {
+ reset_font_family(term);
+ };
+
+ term.on_resize = function (cols, rows) {
+ if (cols !== this.cols || rows !== this.rows) {
+ console.log('Resizing terminal to geometry: ' + format_geometry(cols, rows));
+ this.resize(cols, rows);
+ sock.send(JSON.stringify({'resize': [cols, rows]}));
+ }
+ };
+
+ term.onData(function (data) {
+ // console.log(data);
+ sock.send(JSON.stringify({'data': data}));
+ });
+
+ sock.onopen = function () {
+ term.open(terminal);
+ toggle_fullscreen(term);
+ update_font_family(term);
+ term.focus();
+ state = CONNECTED;
+ title_element.text = url_opts_data.title || default_title;
+ if (url_opts_data.command) {
+ setTimeout(function () {
+ sock.send(JSON.stringify({'data': url_opts_data.command + '\r'}));
+ }, 500);
+ }
+ };
+
+ sock.onmessage = function (msg) {
+ read_file_as_text(msg.data, term_write, decoder);
+ };
+
+ sock.onerror = function (e) {
+ console.error(e);
+ window.parent.postMessage({event: 'disconnected'}, '*')
+ };
+
+ sock.onclose = function (e) {
+ term.dispose();
+ term = undefined;
+ sock = undefined;
+ reset_wssh();
+ log_status(e.reason, true);
+ state = DISCONNECTED;
+ default_title = 'WebSSH';
+ title_element.text = default_title;
+ window.parent.postMessage({event: 'disconnected'}, '*')
+ };
+
+ $(window).resize(function () {
+ if (term) {
+ resize_terminal(term);
+ }
+ });
+ }
+
+
+ function wrap_object(opts) {
+ var obj = {};
+
+ obj.get = function (attr) {
+ return opts[attr] || '';
+ };
+
+ obj.set = function (attr, val) {
+ opts[attr] = val;
+ };
+
+ return obj;
+ }
+
+
+ function clean_data(data) {
+ var i, attr, val;
+ var attrs = form_keys.concat(['privatekey', 'passphrase']);
+
+ for (i = 0; i < attrs.length; i++) {
+ attr = attrs[i];
+ val = data.get(attr);
+ if (typeof val === 'string') {
+ data.set(attr, val.trim());
+ }
+ }
+ }
+
+
+ function validate_form_data(data) {
+ clean_data(data);
+
+ var hostname = data.get('hostname'), port = data.get('port'), username = data.get('username'),
+ pk = data.get('privatekey'), result = {
+ valid: false, data: data, title: ''
+ }, errors = [], size;
+
+ if (!hostname) {
+ errors.push('Value of hostname is required.');
+ } else {
+ if (!hostname_tester.test(hostname)) {
+ errors.push('Invalid hostname: ' + hostname);
+ }
+ }
+
+ if (!port) {
+ port = 22;
+ } else {
+ if (!(port > 0 && port <= 65535)) {
+ errors.push('Invalid port: ' + port);
+ }
+ }
+
+ if (!username) {
+ errors.push('Value of username is required.');
+ }
+
+ if (pk) {
+ size = pk.size || pk.length;
+ if (size > key_max_size) {
+ errors.push('Invalid private key: ' + pk.name || '');
+ }
+ }
+
+ if (!errors.length || debug) {
+ result.valid = true;
+ result.title = username + '@' + hostname + ':' + port;
+ }
+ result.errors = errors;
+
+ return result;
+ }
+
+ // Fix empty input file ajax submission error for safari 11.x
+ function disable_file_inputs(inputs) {
+ var i, input;
+
+ for (i = 0; i < inputs.length; i++) {
+ input = inputs[i];
+ if (input.files.length === 0) {
+ input.setAttribute('disabled', '');
+ }
+ }
+ }
+
+
+ function enable_file_inputs(inputs) {
+ var i;
+
+ for (i = 0; i < inputs.length; i++) {
+ inputs[i].removeAttribute('disabled');
+ }
+ }
+
+
+ function connect_without_options() {
+ // use data from the form
+ var form = document.querySelector(form_id), inputs = form.querySelectorAll('input[type="file"]'),
+ url = form.action, data, pk;
+
+ disable_file_inputs(inputs);
+ data = new FormData(form);
+ pk = data.get('privatekey');
+ enable_file_inputs(inputs);
+
+ function ajax_post() {
+ status.text('');
+ button.prop('disabled', true);
+
+ $.ajax({
+ url: url,
+ type: 'post',
+ data: data,
+ complete: ajax_complete_callback,
+ cache: false,
+ contentType: false,
+ processData: false
+ });
+ }
+
+ var result = validate_form_data(data);
+ if (!result.valid) {
+ log_status(result.errors.join('\n'));
+ window.parent.postMessage({event: 'connected'}, '*')
+ return;
+ }
+
+ if (pk && pk.size && !debug) {
+ read_file_as_text(pk, function (text) {
+ if (text === undefined) {
+ log_status('Invalid private key: ' + pk.name);
+ } else {
+ ajax_post();
+ }
+ });
+ } else {
+ ajax_post();
+ }
+
+ return result;
+ }
+
+
+ function connect_with_options(data) {
+ // use data from the arguments
+ var form = document.querySelector(form_id), url = data.url || form.action,
+ _xsrf = form.querySelector('input[name="_xsrf"]');
+
+ var result = validate_form_data(wrap_object(data));
+ if (!result.valid) {
+ log_status(result.errors.join('\n'));
+ window.parent.postMessage({event: 'connected'}, '*')
+ return;
+ }
+
+ data.term = term_type.val();
+ data._xsrf = _xsrf.value;
+ if (event_origin) {
+ data._origin = event_origin;
+ }
+
+ status.text('');
+ button.prop('disabled', true);
+
+ $.ajax({
+ url: url, type: 'post', data: data, complete: ajax_complete_callback,
+ }).then(() => {
+ window.parent.postMessage({event: 'connected'}, '*')
+ }).catch(() => {
+ window.parent.postMessage({event: 'connected'}, '*')
+ })
+
+ return result;
+ }
+
+
+ function connect(hostname, port, username, password, privatekey, passphrase, totp, proxyType, proxyIp, proxyPort, proxyRdns = true, proxyUser, proxyPass) {
+ var result, opts;
+ if (state !== DISCONNECTED) {
+ console.log(messages[state]);
+ return;
+ }
+
+ if (hostname === undefined) {
+ result = connect_without_options();
+ } else {
+ if (typeof hostname === 'string') {
+ opts = {
+ hostname: hostname,
+ port: port,
+ username: username,
+ password: password,
+ privatekey: privatekey,
+ passphrase: passphrase,
+ totp: totp,
+ proxyType: proxyType,
+ proxyIp: proxyIp,
+ proxyPort: proxyPort,
+ proxyRdns: proxyRdns,
+ proxyUser: proxyUser,
+ proxyPass: proxyPass
+ };
+ } else {
+ opts = hostname;
+ }
+
+ result = connect_with_options(opts);
+ }
+
+ if (result) {
+ state = CONNECTING;
+ default_title = result.title;
+ if (hostname) {
+ validated_form_data = result.data;
+ }
+ store_items(fields, result.data);
+ }
+
+
+ }
+
+ window.onmessage = function (event) {
+ //如果是command则执行
+ if (event.data.command) {
+ console.log('command', event.data.command);
+ window.sock.send(JSON.stringify({'data': event.data.command + '\r'}));
+ }
+ }
+
+ wssh.connect = connect;
+
+ $(form_id).submit(function (event) {
+ event.preventDefault();
+ connect();
});
- return result;
- }
+ function cross_origin_connect(event) {
+ console.log(event.origin);
+ var prop = 'connect', args;
- function connect(hostname, port, username, password, privatekey, passphrase, totp) {
- // for console use
- var result, opts;
-
- if (state !== DISCONNECTED) {
- console.log(messages[state]);
- return;
- }
-
- if (hostname === undefined) {
- result = connect_without_options();
- } else {
- if (typeof hostname === 'string') {
- opts = {
- hostname: hostname,
- port: port,
- username: username,
- password: password,
- privatekey: privatekey,
- passphrase: passphrase,
- totp: totp
- };
- } else {
- opts = hostname;
- }
-
- result = connect_with_options(opts);
- }
-
- if (result) {
- state = CONNECTING;
- default_title = result.title;
- if (hostname) {
- validated_form_data = result.data;
- }
- store_items(fields, result.data);
- }
- }
-
- wssh.connect = connect;
-
- $(form_id).submit(function(event){
- event.preventDefault();
- connect();
- });
-
-
- function cross_origin_connect(event)
- {
- console.log(event.origin);
- var prop = 'connect',
- args;
-
- try {
- args = JSON.parse(event.data);
- } catch (SyntaxError) {
- args = event.data.split('|');
- }
-
- if (!Array.isArray(args)) {
- args = [args];
- }
-
- try {
- event_origin = event.origin;
- wssh[prop].apply(wssh, args);
- } finally {
- event_origin = undefined;
- }
- }
-
- window.addEventListener('message', cross_origin_connect, false);
-
- if (document.fonts) {
- document.fonts.ready.then(
- function () {
- if (custom_font_is_loaded() === false) {
- document.body.style.fontFamily = custom_font.family;
+ try {
+ args = JSON.parse(event.data);
+ } catch (SyntaxError) {
+ args = event.data.split('|');
}
- }
- );
- }
+ if (!Array.isArray(args)) {
+ args = [args];
+ }
- parse_url_data(
- decode_uri_component(window.location.search.substring(1)) + '&' + decode_uri_component(window.location.hash.substring(1)),
- form_keys, opts_keys, url_form_data, url_opts_data
- );
- // console.log(url_form_data);
- // console.log(url_opts_data);
-
- if (url_opts_data.term) {
- term_type.val(url_opts_data.term);
- }
-
- if (url_form_data.password === null) {
- log_status('Password via url must be encoded in base64.');
- } else {
- if (get_object_length(url_form_data)) {
- waiter.show();
- connect(url_form_data);
- } else {
- restore_items(fields);
- form_container.show();
+ try {
+ event_origin = event.origin;
+ wssh[prop].apply(wssh, args);
+ } finally {
+ event_origin = undefined;
+ }
+ }
+
+ window.addEventListener('message', cross_origin_connect, false);
+
+ if (document.fonts) {
+ document.fonts.ready.then(function () {
+ if (custom_font_is_loaded() === false) {
+ document.body.style.fontFamily = custom_font.family;
+ }
+ });
+ }
+
+ document.addEventListener("dragenter", (e) => {
+ console.log("dragenter事件触发");
+ e.target.style.backgroundColor = "green"
+ console.log("颜色改变");
+ })
+
+
+ parse_url_data(decode_uri_component(window.location.search.substring(1)) + '&' + decode_uri_component(window.location.hash.substring(1)), form_keys, opts_keys, url_form_data, url_opts_data);
+ console.log(url_form_data);
+ console.log("url_opts_data:", url_opts_data);
+ if (url_opts_data.term) {
+ term_type.val(url_opts_data.term);
+ }
+
+ if (url_form_data.password === null) {
+ log_status('Password via url must be encoded in base64.');
+ } else {
+ if (get_object_length(url_form_data)) {
+ waiter.show();
+ connect(url_form_data);
+ console.log('Connecting ...', url_form_data)
+ } else {
+ restore_items(fields);
+ form_container.show();
+ }
}
- }
});