<commit_before>/* jslint node: true */
'use strict';

//	ENiGMA½
const baseClient		= require('../../client.js');
const Log				= require('../../logger.js').log;
const LoginServerModule	= require('../../login_server_module.js');
const Config			= require('../../config.js').config;

//	deps
const net 			= require('net');
const buffers		= require('buffers');
const binary		= require('binary');
const assert		= require('assert');
const util			= require('util');

//var debug	= require('debug')('telnet');

const ModuleInfo = exports.moduleInfo = {
	name		: 'Telnet',
	desc		: 'Telnet Server',
	author		: 'NuSkooler',
	isSecure	: false,
	packageName	: 'codes.l33t.enigma.telnet.server',
};

//
//	Telnet Protocol Resources
//	* http://pcmicro.com/netfoss/telnet.html
//	* http://mud-dev.wikidot.com/telnet:negotiation
//

/*
	TODO:
	* Document COMMANDS -- add any missing
	* Document OPTIONS -- add any missing
	* Internally handle OPTIONS:
		* Some should be emitted generically
		* Some shoudl be handled internally -- denied, handled, etc. 
		* 

	* Allow term (ttype) to be set by environ sub negotiation

	* Process terms in loop.... research needed

	* Handle will/won't
	* Handle do's, ..
	* Some won't should close connection

	* Options/Commands we don't understand shouldn't crash the server!!


*/

const COMMANDS = {
	SE		: 240,	//	End of Sub-Negotation Parameters
	NOP		: 241,	//	No Operation
	DM		: 242,	//	Data Mark
	BRK		: 243,	//	Break
	IP		: 244,	//	Interrupt Process
	AO		: 245,	//	Abort Output
	AYT		: 246,	//	Are You There?
	EC		: 247,	//	Erase Character
	EL		: 248,	//	Erase Line
	GA		: 249,	//	Go Ahead
	SB		: 250,	//	Start Sub-Negotiation Parameters
	WILL	: 251,	//	
	WONT	: 252,
	DO		: 253,
	DONT	: 254,
	IAC		: 255,	//	(Data Byte)
};

//
//	Resources:
//		* http://www.faqs.org/rfcs/rfc1572.html
//
const SB_COMMANDS = {
	IS		: 0,
	SEND	: 1,
	INFO	: 2,
};

//
//	Telnet Options
//
//	Resources
//		* http://mars.netanya.ac.il/~unesco/cdrom/booklet/HTML/NETWORKING/node300.html
//
const OPTIONS = {
	TRANSMIT_BINARY			: 0,	// http://tools.ietf.org/html/rfc856
	ECHO					: 1,	//	http://tools.ietf.org/html/rfc857
	//	RECONNECTION : 2
	SUPPRESS_GO_AHEAD		: 3,	// aka 'SGA': RFC 858 @ http://tools.ietf.org/html/rfc858
	//APPROX_MESSAGE_SIZE 	: 4
	STATUS					: 5,	// http://tools.ietf.org/html/rfc859
	TIMING_MARK				: 6, // http://tools.ietf.org/html/rfc860
	//RC_TRANS_AND_ECHO		: 7,	//	aka 'RCTE' @ http://www.rfc-base.org/txt/rfc-726.txt
	//OUPUT_LINE_WIDTH		: 8,
	//OUTPUT_PAGE_SIZE		: 9,	//	
	//OUTPUT_CARRIAGE_RETURN_DISP	: 10,	//	RFC 652
	//OUTPUT_HORIZ_TABSTOPS	: 11,	//	RFC 653
	//OUTPUT_HORIZ_TAB_DISP	: 12,	//	RFC 654
	//OUTPUT_FORMFEED_DISP	: 13,	//	RFC 655
	//OUTPUT_VERT_TABSTOPS	: 14,	//	RFC 656
	//OUTPUT_VERT_TAB_DISP	: 15,	//	RFC 657
	//OUTPUT_LF_DISP		: 16,	//	RFC 658
	//EXTENDED_ASCII		: 17,	//	RFC 659
	//LOGOUT				: 18,	//	RFC 727
	//BYTE_MACRO			: 19,	//	RFC 753
	//DATA_ENTRY_TERMINAL	: 20,	//	RFC 1043
	//SUPDUP				: 21,	//	RFC 736
	//SUPDUP_OUTPUT			: 22,	//	RFC 749
	SEND_LOCATION			: 23,	//	RFC 779
	TERMINAL_TYPE			: 24,	//	aka 'TTYPE': RFC 1091 @ http://tools.ietf.org/html/rfc1091
	//END_OF_RECORD			: 25,	//	RFC 885
	//TACACS_USER_ID		: 26,	//	RFC 927
	//OUTPUT_MARKING		: 27,	//	RFC 933
	//TERMINCAL_LOCATION_NUMBER	: 28,	//	RFC 946
	//TELNET_3270_REGIME	: 29,	//	RFC 1041
	WINDOW_SIZE				: 31,	//	aka 'NAWS': RFC 1073 @ http://tools.ietf.org/html/rfc1073
	TERMINAL_SPEED			: 32,	//	RFC 1079 @ http://tools.ietf.org/html/rfc1079
	REMOTE_FLOW_CONTROL		: 33,	//	RFC 1072 @ http://tools.ietf.org/html/rfc1372
	LINEMODE				: 34,	//	RFC 1184 @ http://tools.ietf.org/html/rfc1184
	X_DISPLAY_LOCATION		: 35,	//	aka 'XDISPLOC': RFC 1096 @ http://tools.ietf.org/html/rfc1096
	NEW_ENVIRONMENT_DEP		: 36,	//	aka 'NEW-ENVIRON': RFC 1408 @ http://tools.ietf.org/html/rfc1408 (note: RFC 1572 is an update to this)
	AUTHENTICATION			: 37,	//	RFC 2941 @ http://tools.ietf.org/html/rfc2941
	ENCRYPT					: 38,	//	RFC 2946 @ http://tools.ietf.org/html/rfc2946
	NEW_ENVIRONMENT			: 39,	//	aka 'NEW-ENVIRON': RFC 1572 @ http://tools.ietf.org/html/rfc1572 (note: update to RFC 1408)
	//TN3270E					: 40,	//	RFC 2355
	//XAUTH					: 41,
	//CHARSET				: 42,	//	RFC 2066
	//REMOTE_SERIAL_PORT	: 43,
	//COM_PORT_CONTROL		: 44,	//	RFC 2217
	//SUPRESS_LOCAL_ECHO	: 45,
	//START_TLS				: 46,
	//KERMIT				: 47,	//	RFC 2840
	//SEND_URL				: 48,
	//FORWARD_X				: 49,

	//PRAGMA_LOGON			: 138,
	//SSPI_LOGON			: 139,
	//PRAGMA_HEARTBEAT		: 140

	EXTENDED_OPTIONS_LIST	: 255,	//	RFC 861 (STD 32)
};

//	Commands used within NEW_ENVIRONMENT[_DEP]
const NEW_ENVIRONMENT_COMMANDS = {
	VAR		: 0,
	VALUE	: 1,
	ESC		: 2,
	USERVAR	: 3,
};

const IAC_BUF 		= new Buffer([ COMMANDS.IAC ]);
const IAC_SE_BUF	= new Buffer([ COMMANDS.IAC, COMMANDS.SE ]);

const COMMAND_NAMES = Object.keys(COMMANDS).reduce(function(names, name) {
	names[COMMANDS[name]] = name.toLowerCase();
	return names;
}, {});

const COMMAND_IMPLS = {};
[ 'do', 'dont', 'will', 'wont', 'sb' ].forEach(function(command) {
	const code = COMMANDS[command.toUpperCase()];
	COMMAND_IMPLS[code] = function(bufs, i, event) {
		if(bufs.length < (i + 1)) {
			return MORE_DATA_REQUIRED;
		}
		return parseOption(bufs, i, event);
	};
});

//	:TODO: See TooTallNate's telnet.js: Handle COMMAND_IMPL for IAC in binary mode

//	Create option names such as 'transmit binary' -> OPTIONS.TRANSMIT_BINARY
const OPTION_NAMES = Object.keys(OPTIONS).reduce(function(names, name) {
	names[OPTIONS[name]] = name.toLowerCase().replace(/_/g, ' ');
	return names;
}, {});

const OPTION_IMPLS = {};
//	:TODO: fill in the rest...
OPTION_IMPLS.NO_ARGS						=
OPTION_IMPLS[OPTIONS.ECHO]					= 
OPTION_IMPLS[OPTIONS.STATUS]				=
OPTION_IMPLS[OPTIONS.LINEMODE]				= 
OPTION_IMPLS[OPTIONS.TRANSMIT_BINARY]		=	
OPTION_IMPLS[OPTIONS.AUTHENTICATION]		=
OPTION_IMPLS[OPTIONS.TERMINAL_SPEED]		=
OPTION_IMPLS[OPTIONS.REMOTE_FLOW_CONTROL]	=
OPTION_IMPLS[OPTIONS.X_DISPLAY_LOCATION]	=
OPTION_IMPLS[OPTIONS.SEND_LOCATION]			= 

OPTION_IMPLS[OPTIONS.SUPPRESS_GO_AHEAD]		= function(bufs, i, event) {
	event.buf = bufs.splice(0, i).toBuffer();
	return event;
};

OPTION_IMPLS[OPTIONS.TERMINAL_TYPE] = function(bufs, i, event) {
	if(event.commandCode !== COMMANDS.SB) {
		OPTION_IMPLS.NO_ARGS(bufs, i, event);
	} else {
		//	We need 4 bytes header + data + IAC SE
		if(bufs.length < 7) {
			return MORE_DATA_REQUIRED;
		}<commit_msg>Crash on Telnet Bridge connecting to Tradewars server #105<commit_after>/* jslint node: true */
'use strict';

//	ENiGMA½
const baseClient		= require('../../client.js');
const Log				= require('../../logger.js').log;
const LoginServerModule	= require('../../login_server_module.js');
const Config			= require('../../config.js').config;

//	deps
const net 			= require('net');
const buffers		= require('buffers');
const binary		= require('binary');
const assert		= require('assert');
const util			= require('util');

//var debug	= require('debug')('telnet');

const ModuleInfo = exports.moduleInfo = {
	name		: 'Telnet',
	desc		: 'Telnet Server',
	author		: 'NuSkooler',
	isSecure	: false,
	packageName	: 'codes.l33t.enigma.telnet.server',
};

//
//	Telnet Protocol Resources
//	* http://pcmicro.com/netfoss/telnet.html
//	* http://mud-dev.wikidot.com/telnet:negotiation
//

/*
	TODO:
	* Document COMMANDS -- add any missing
	* Document OPTIONS -- add any missing
	* Internally handle OPTIONS:
		* Some should be emitted generically
		* Some shoudl be handled internally -- denied, handled, etc. 
		* 

	* Allow term (ttype) to be set by environ sub negotiation

	* Process terms in loop.... research needed

	* Handle will/won't
	* Handle do's, ..
	* Some won't should close connection

	* Options/Commands we don't understand shouldn't crash the server!!


*/

const COMMANDS = {
	SE		: 240,	//	End of Sub-Negotation Parameters
	NOP		: 241,	//	No Operation
	DM		: 242,	//	Data Mark
	BRK		: 243,	//	Break
	IP		: 244,	//	Interrupt Process
	AO		: 245,	//	Abort Output
	AYT		: 246,	//	Are You There?
	EC		: 247,	//	Erase Character
	EL		: 248,	//	Erase Line
	GA		: 249,	//	Go Ahead
	SB		: 250,	//	Start Sub-Negotiation Parameters
	WILL	: 251,	//	
	WONT	: 252,
	DO		: 253,
	DONT	: 254,
	IAC		: 255,	//	(Data Byte)
};

//
//	Resources:
//		* http://www.faqs.org/rfcs/rfc1572.html
//
const SB_COMMANDS = {
	IS		: 0,
	SEND	: 1,
	INFO	: 2,
};

//
//	Telnet Options
//
//	Resources
//		* http://mars.netanya.ac.il/~unesco/cdrom/booklet/HTML/NETWORKING/node300.html
//
const OPTIONS = {
	TRANSMIT_BINARY			: 0,	// http://tools.ietf.org/html/rfc856
	ECHO					: 1,	//	http://tools.ietf.org/html/rfc857
	//	RECONNECTION : 2
	SUPPRESS_GO_AHEAD		: 3,	// aka 'SGA': RFC 858 @ http://tools.ietf.org/html/rfc858
	//APPROX_MESSAGE_SIZE 	: 4
	STATUS					: 5,	// http://tools.ietf.org/html/rfc859
	TIMING_MARK				: 6, // http://tools.ietf.org/html/rfc860
	//RC_TRANS_AND_ECHO		: 7,	//	aka 'RCTE' @ http://www.rfc-base.org/txt/rfc-726.txt
	//OUPUT_LINE_WIDTH		: 8,
	//OUTPUT_PAGE_SIZE		: 9,	//	
	//OUTPUT_CARRIAGE_RETURN_DISP	: 10,	//	RFC 652
	//OUTPUT_HORIZ_TABSTOPS	: 11,	//	RFC 653
	//OUTPUT_HORIZ_TAB_DISP	: 12,	//	RFC 654
	//OUTPUT_FORMFEED_DISP	: 13,	//	RFC 655
	//OUTPUT_VERT_TABSTOPS	: 14,	//	RFC 656
	//OUTPUT_VERT_TAB_DISP	: 15,	//	RFC 657
	//OUTPUT_LF_DISP		: 16,	//	RFC 658
	//EXTENDED_ASCII		: 17,	//	RFC 659
	//LOGOUT				: 18,	//	RFC 727
	//BYTE_MACRO			: 19,	//	RFC 753
	//DATA_ENTRY_TERMINAL	: 20,	//	RFC 1043
	//SUPDUP				: 21,	//	RFC 736
	//SUPDUP_OUTPUT			: 22,	//	RFC 749
	SEND_LOCATION			: 23,	//	RFC 779
	TERMINAL_TYPE			: 24,	//	aka 'TTYPE': RFC 1091 @ http://tools.ietf.org/html/rfc1091
	//END_OF_RECORD			: 25,	//	RFC 885
	//TACACS_USER_ID		: 26,	//	RFC 927
	//OUTPUT_MARKING		: 27,	//	RFC 933
	//TERMINCAL_LOCATION_NUMBER	: 28,	//	RFC 946
	//TELNET_3270_REGIME	: 29,	//	RFC 1041
	WINDOW_SIZE				: 31,	//	aka 'NAWS': RFC 1073 @ http://tools.ietf.org/html/rfc1073
	TERMINAL_SPEED			: 32,	//	RFC 1079 @ http://tools.ietf.org/html/rfc1079
	REMOTE_FLOW_CONTROL		: 33,	//	RFC 1072 @ http://tools.ietf.org/html/rfc1372
	LINEMODE				: 34,	//	RFC 1184 @ http://tools.ietf.org/html/rfc1184
	X_DISPLAY_LOCATION		: 35,	//	aka 'XDISPLOC': RFC 1096 @ http://tools.ietf.org/html/rfc1096
	NEW_ENVIRONMENT_DEP		: 36,	//	aka 'NEW-ENVIRON': RFC 1408 @ http://tools.ietf.org/html/rfc1408 (note: RFC 1572 is an update to this)
	AUTHENTICATION			: 37,	//	RFC 2941 @ http://tools.ietf.org/html/rfc2941
	ENCRYPT					: 38,	//	RFC 2946 @ http://tools.ietf.org/html/rfc2946
	NEW_ENVIRONMENT			: 39,	//	aka 'NEW-ENVIRON': RFC 1572 @ http://tools.ietf.org/html/rfc1572 (note: update to RFC 1408)
	//TN3270E					: 40,	//	RFC 2355
	//XAUTH					: 41,
	//CHARSET				: 42,	//	RFC 2066
	//REMOTE_SERIAL_PORT	: 43,
	//COM_PORT_CONTROL		: 44,	//	RFC 2217
	//SUPRESS_LOCAL_ECHO	: 45,
	//START_TLS				: 46,
	//KERMIT				: 47,	//	RFC 2840
	//SEND_URL				: 48,
	//FORWARD_X				: 49,

	//PRAGMA_LOGON			: 138,
	//SSPI_LOGON			: 139,
	//PRAGMA_HEARTBEAT		: 140

	ARE_YOU_THERE			: 246,	//	aka 'AYT' RFC 854 @ https://tools.ietf.org/html/rfc854

	EXTENDED_OPTIONS_LIST	: 255,	//	RFC 861 (STD 32)
};

//	Commands used within NEW_ENVIRONMENT[_DEP]
const NEW_ENVIRONMENT_COMMANDS = {
	VAR		: 0,
	VALUE	: 1,
	ESC		: 2,
	USERVAR	: 3,
};

const IAC_BUF 		= new Buffer([ COMMANDS.IAC ]);
const IAC_SE_BUF	= new Buffer([ COMMANDS.IAC, COMMANDS.SE ]);

const COMMAND_NAMES = Object.keys(COMMANDS).reduce(function(names, name) {
	names[COMMANDS[name]] = name.toLowerCase();
	return names;
}, {});

const COMMAND_IMPLS = {};
[ 'do', 'dont', 'will', 'wont', 'sb' ].forEach(function(command) {
	const code = COMMANDS[command.toUpperCase()];
	COMMAND_IMPLS[code] = function(bufs, i, event) {
		if(bufs.length < (i + 1)) {
			return MORE_DATA_REQUIRED;
		}
		return parseOption(bufs, i, event);
	};
});

//	:TODO: See TooTallNate's telnet.js: Handle COMMAND_IMPL for IAC in binary mode

//	Create option names such as 'transmit binary' -> OPTIONS.TRANSMIT_BINARY
const OPTION_NAMES = Object.keys(OPTIONS).reduce(function(names, name) {
	names[OPTIONS[name]] = name.toLowerCase().replace(/_/g, ' ');
	return names;
}, {});

const OPTION_IMPLS = {};
//	:TODO: fill in the rest...
OPTION_IMPLS.NO_ARGS						=
OPTION_IMPLS[OPTIONS.ECHO]					= 
OPTION_IMPLS[OPTIONS.STATUS]				=
OPTION_IMPLS[OPTIONS.LINEMODE]				= 
OPTION_IMPLS[OPTIONS.TRANSMIT_BINARY]		=	
OPTION_IMPLS[OPTIONS.AUTHENTICATION]		=
OPTION_IMPLS[OPTIONS.TERMINAL_SPEED]		=
OPTION_IMPLS[OPTIONS.REMOTE_FLOW_CONTROL]	=
OPTION_IMPLS[OPTIONS.X_DISPLAY_LOCATION]	=
OPTION_IMPLS[OPTIONS.SEND_LOCATION]			= 
OPTION_IMPLS[OPTIONS.ARE_YOU_THERE]			=
OPTION_IMPLS[OPTIONS.SUPPRESS_GO_AHEAD]		= function(bufs, i, event) {
	event.buf = bufs.splice(0, i).toBuffer();
	return event;
};

OPTION_IMPLS[OPTIONS.TERMINAL_TYPE] = function(bufs, i, event) {
	if(event.commandCode !== COMMANDS.SB) {
		OPTION_IMPLS.NO_ARGS(bufs, i, event);
	} else {
		//	We need 4 bytes header + data + IAC SE
		if(bufs.length < 7) {
			return MORE_DATA_REQUIRED;
		}
{'fraction_non_alphanumeric': 0.16022013797380047, 'fraction_numerical': 0.05751492132392838, 'mean_word_length': 3.0331353547983744, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 1, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5741183', 'n_tokens_mistral': 6556, 'n_tokens_neox': 5712, 'n_words': 1110}