1import {Terminal} from 'xterm';
2import style from 'xterm/dist/xterm.css';
3import * as attach from 'xterm/lib/addons/attach/attach';
4import * as fit from 'xterm/lib/addons/fit/fit';
5var configJSON = require('../../../config.json');
6if (configJSON.keyType == 'VT100+') {
7  var vt100PlusKey = require('./vt100plus');
8}
9
10var customKeyHandlers = function(ev) {
11  if (configJSON.keyType == 'VT100+') {
12    return vt100PlusKey.customVT100PlusKey(ev, this);
13  }
14  return true;
15};
16
17function measureChar(term) {
18  var span = document.createElement('span');
19  var fontFamily = 'courier-new';
20  var fontSize = 15;
21  var rect;
22
23  span.textContent = 'W';
24  try {
25    fontFamily = term.getOption('fontFamily');
26    fontSize = term.getOption('fontSize');
27  } catch (err) {
28    console.log('get option failure');
29  }
30  span.style.fontFamily = fontFamily;
31  span.style.fontSize = fontSize + 'px';
32  document.body.appendChild(span);
33  rect = span.getBoundingClientRect();
34  document.body.removeChild(span);
35  return rect;
36}
37
38// Add a TextEncoder polyfill to handle ie9 properly.  (does anyone still use
39// that anymore? Grabbed from
40// https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder#Polyfill
41if (typeof TextEncoder === 'undefined') {
42  let TextEncoder = function TextEncoder() {};
43  TextEncoder.prototype.encode = function encode(str) {
44    var Len = str.length, resPos = -1;
45    // The Uint8Array's length must be at least 3x the length of the string
46    // because an invalid UTF-16
47    //  takes up the equivelent space of 3 UTF-8 characters to encode it
48    //  properly. However, Array's have an auto expanding length and 1.5x should
49    //  be just the right balance for most uses.
50    var resArr = typeof Uint8Array === 'undefined' ? new Array(Len * 1.5) :
51                                                     new Uint8Array(Len * 3);
52    for (var point = 0, nextcode = 0, i = 0; i !== Len;) {
53      point = str.charCodeAt(i), i += 1;
54      if (point >= 0xD800 && point <= 0xDBFF) {
55        if (i === Len) {
56          resArr[resPos += 1] = 0xef /*0b11101111*/;
57          resArr[resPos += 1] = 0xbf /*0b10111111*/;
58          resArr[resPos += 1] = 0xbd /*0b10111101*/;
59          break;
60        }
61        // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
62        nextcode = str.charCodeAt(i);
63        if (nextcode >= 0xDC00 && nextcode <= 0xDFFF) {
64          point = (point - 0xD800) * 0x400 + nextcode - 0xDC00 + 0x10000;
65          i += 1;
66          if (point > 0xffff) {
67            resArr[resPos += 1] = (0x1e /*0b11110*/ << 3) | (point >>> 18);
68            resArr[resPos += 1] =
69                (0x2 /*0b10*/ << 6) | ((point >>> 12) & 0x3f /*0b00111111*/);
70            resArr[resPos += 1] =
71                (0x2 /*0b10*/ << 6) | ((point >>> 6) & 0x3f /*0b00111111*/);
72            resArr[resPos += 1] =
73                (0x2 /*0b10*/ << 6) | (point & 0x3f /*0b00111111*/);
74            continue;
75          }
76        } else {
77          resArr[resPos += 1] = 0xef /*0b11101111*/;
78          resArr[resPos += 1] = 0xbf /*0b10111111*/;
79          resArr[resPos += 1] = 0xbd /*0b10111101*/;
80          continue;
81        }
82      }
83      if (point <= 0x007f) {
84        resArr[resPos += 1] = (0x0 /*0b0*/ << 7) | point;
85      } else if (point <= 0x07ff) {
86        resArr[resPos += 1] = (0x6 /*0b110*/ << 5) | (point >>> 6);
87        resArr[resPos += 1] =
88            (0x2 /*0b10*/ << 6) | (point & 0x3f /*0b00111111*/);
89      } else {
90        resArr[resPos += 1] = (0xe /*0b1110*/ << 4) | (point >>> 12);
91        resArr[resPos += 1] =
92            (0x2 /*0b10*/ << 6) | ((point >>> 6) & 0x3f /*0b00111111*/);
93        resArr[resPos += 1] =
94            (0x2 /*0b10*/ << 6) | (point & 0x3f /*0b00111111*/);
95      }
96    }
97    if (typeof Uint8Array !== 'undefined')
98      return resArr.subarray(0, resPos + 1);
99    // else // IE 6-9
100    resArr.length = resPos + 1;  // trim off extra weight
101    return resArr;
102  };
103  TextEncoder.prototype.toString = function() {
104    return '[object TextEncoder]'
105  };
106  try {  // Object.defineProperty only works on DOM prototypes in IE8
107    Object.defineProperty(TextEncoder.prototype, 'encoding', {
108      get: function() {
109        if (TextEncoder.prototype.isPrototypeOf(this))
110          return 'utf-8';
111        else
112          throw TypeError('Illegal invocation');
113      }
114    });
115  } catch (e) { /*IE6-8 fallback*/
116    TextEncoder.prototype.encoding = 'utf-8';
117  }
118  if (typeof Symbol !== 'undefined')
119    TextEncoder.prototype[Symbol.toStringTag] = 'TextEncoder';
120}
121
122window.angular && (function(angular) {
123  'use strict';
124
125  angular.module('app.common.directives').directive('serialConsole', [
126    function() {
127      return {
128        'restrict': 'E',
129        'template': require('./serial-console.html'),
130        'scope': {'path': '=', 'showTabBtn': '=?'},
131        'controller': [
132          '$scope', '$cookies', '$window', 'dataService', '$element',
133          function($scope, $cookies, $window, dataService, $element) {
134            $scope.dataService = dataService;
135
136            // See https://github.com/xtermjs/xterm.js/ for available xterm
137            // options
138
139            Terminal.applyAddon(attach);  // Apply the `attach` addon
140            Terminal.applyAddon(fit);     // Apply the `fit` addon
141
142            var border = 10;
143            var term = new Terminal();
144            // Should be a reference to <div id="terminal"></div>
145            var terminal = $element[0].firstElementChild.firstElementChild;
146            var customConsole;
147            var charSize;
148            var termContainer;
149
150            term.open(terminal);
151            term.fit();
152            if (configJSON.customKeyEnable == true) {
153              term.attachCustomKeyEventHandler(customKeyHandlers);
154            }
155            var SOL_THEME = {
156              background: '#19273c',
157              cursor: 'rgba(83, 146, 255, .5)',
158              scrollbar: 'rgba(83, 146, 255, .5)'
159            };
160            term.setOption('theme', SOL_THEME);
161            var hostname = dataService.getHost().replace('https://', '');
162            var host = 'wss://' + hostname + '/console0';
163            var token = $cookies.get('XSRF-TOKEN');
164            try {
165              var ws = new WebSocket(host, [token]);
166              term.attach(ws);
167              ws.onopen = function() {
168                console.log('websocket opened');
169              };
170              ws.onclose = function(event) {
171                console.log(
172                    'websocket closed. code: ' + event.code +
173                    ' reason: ' + event.reason);
174              };
175            } catch (error) {
176              console.log(JSON.stringify(error));
177            }
178
179            $window.onresize = function() {
180              termContainer = document.getElementById('term-container');
181              termContainer.style.width = window.innerWidth;
182              termContainer.style.height = window.innerHeight;
183              term.fit();
184            };
185
186            $scope.openTerminalWindow = function() {
187              var sol_window = $window.open(
188                  '#/server-control/remote-console-window',
189                  'Remote Console Window',
190                  'directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=yes,width=600,height=550');
191
192              sol_window.onresize = function() {
193                termContainer = document.getElementById('term-container');
194                termContainer.style.width = sol_window.innerWidth;
195                termContainer.style.height = sol_window.innerHeight;
196                term.fit();
197              };
198            };
199          }
200        ]
201      };
202    }
203  ]);
204})(window.angular);
205