<commit_before><!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Node client virtual machine</title>
</head>
<body>
	<h1>Node client virtual machine</h1>
	<h2>Running Node.js modules in the browser!</h2>

	<ul>
		<li><a href="https://github.com/emersion/node-client-vm">Github project</a></li>
		<li><a href="https://github.com/emersion">Author</a></li>
	</ul>

	<p>The aim of this project is to run any Node.js module in the browser.</p>

	<p>Here is a simple demo: e-mail sending using <a href="https://github.com/substack/node-smtp-protocol">a pure Javascript implementation of the SMTP protocol</a>. The <code>smtp-protocol</code> module is run right in the browser, using pure Javascript core modules if available (such as <code>events</code>, <code>path</code>...), browser versions (<code>stream</code>, <code>buffer</code>...) or custom polyfills (<code>net</code>, <code>tls</code>). In this demo, we a re opening a TCP socket to the SMTP server. As we cannot open raw TCP connections from the browser directly, we are using a WebSocket connection to send the TCP data through a Node.js server (something like <em>SMTP-over-WebSockets</em>). Then the connection is upgraded to a secure TSL connection, using <a href="https://github.com/digitalbazaar/forge">a client-side TLS library</a>. We are now able to send SMTP commands to the server (<code>HELO</code>, <code>AUTH</code> and so on).</p>

	<form id="send-email-form">
		<label>SMTP server: <input type="text" name="hostname" value="smtp.gmail.com"></label><br>
		<label>Port: <input type="number" name="port" value="587"></label><br>
		<label>Username: <input type="text" name="username"></label><br>
		<label>Password: <input type="password" name="password"></label><br><br>

		<label>From: <input type="email" name="from"></label><br>
		<label>To: <input type="email" name="to"></label><br>
		<label>Body:<br><textarea name="body" cols="50" rows="10">From: the browser <<EMAIL>>
To: you <<EMAIL>>
Subject: hello world

Hello from your web browser!</textarea></label>

		<p>
			<button type="submit">Send an e-mail</button>
		</p>

		<small>Note that we're using an end-to-end encryption so the server cannot retrieve your username and password. If you don't trust us, read the source! ;-)</small>
	</form>

	<pre id="status" style="height: 300px; overflow: auto; background-color: black; color: lightgray;"></pre>

	<script src="/bower_components/jquery/dist/jquery.min.js"></script>
	<script src="/js/node-client-vm.js"></script>
	<script>
	function uiStatus(msg) {
		$('#status').append(msg+'\n');
	}
	function uiReceived(msg) {
		return uiStatus('<span style="color:aqua;">'+msg+'</span>');
	}
	function uiError(msg) {
		return uiStatus('<span style="color:red;">'+msg+'</span>');
	}

	function sendEmail(options) {
		$('#status').empty();
		uiStatus('Loading core modules and smtp-protocol...');

		var startTime = (new Date()).getTime();
		Node.Module.load('smtp-protocol').then(function (module) {
			var smtp = module.run();
			uiStatus('SMTP module initialized!');

			uiStatus('Connecting to SMTP server '+options.hostname+':'+options.port);
			smtp.connect(options.hostname, options.port, function (client) {
				uiStatus('Connected with TCP!');

				client.on('error', function (err) {
					console.warn('[smtp] error:', err);
					uiError(err);
				});

				client.on('greeting', function (code, lines) {
					uiReceived(code+' '+lines.join('\n'));
				});

				uiStatus('Saying HELO...');
				client.helo(options.servername, function (err) {
					uiStatus('Upgrading to a secure TLS connection...');
					client.on('tls', function () {
						uiStatus('Connected with TLS!');

						client.stream.on('data', function (data) {
							uiReceived(data);
						});
						client.stream.on('end', function (data) {
							uiStatus('Socket closed.');
						});

						uiStatus('Logging in...');
						client.login(options.username, options.password, options.authType, function (err, status, lines) {
							if (err) {
								console.error(err);
								uiError(err);
								return;
							}

							if (status == 235) {
								uiStatus('Logged in!');

								uiStatus('Now sending a message...');
								client.from(options.from, function (err) {
									client.to(options.to, function (err) {
										client.data(function (err) {
											var stream = client.message();
											stream.write(options.body);
											stream.end();

											uiStatus('Sent! Now disconnecting...');
											client.quit();

											var endTime = (new Date()).getTime();
											uiStatus('Time: '+(endTime - startTime)+'ms');
										});
									});
								});
							} else {
								if (status == 535) {
									console.error('Auth error');
								} else {
									console.error('Unknown error', status, lines);
								}
								uiError('['+status+'] Login failed: '+lines.join('\n'));
							}
						});
					});
					client.startTLS({
						servername: options.hostname,
						rejectUnauthorized: true
					});
				});

				// Export client to let the user play with it from the web console
				window.client = client;
			});
		}, function (err) {
			uiError(err);
		});
	}

	$('#send-email-form').submit(function (e) {
		e.preventDefault();

		var options = {
			hostname: '',
			port: 25,
			servername: window.location.hostname,
			username: '',
			password: '',
			authType: 'PLAIN',

			from: '<EMAIL>',
			to: '<EMAIL>',
			body: 'From: the browser <<EMAIL>>\n'+
				'To: you <<EMAIL>>\n'+
				'Subject: hello world\n\n'+
				'Hello from your web browser!'
		};

		$(this).find('input,select,textarea').each(function () {
			var name = $(this).attr('name');

			if (name) {
				var value = $(this).val();
				switch ($(this).attr('type')) {
					case 'number':
						value = parseInt(value, 10);
						break;
				}

				if (value) {
					options[name] = value;
				}
			}
		});

		sendEmail(options);
	});
	</script>
</body>
</html><commit_msg>Rollback - wait for the greeting.<commit_after><!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Node client virtual machine</title>
</head>
<body>
	<h1>Node client virtual machine</h1>
	<h2>Running Node.js modules in the browser!</h2>

	<ul>
		<li><a href="https://github.com/emersion/node-client-vm">Github project</a></li>
		<li><a href="https://github.com/emersion">Author</a></li>
	</ul>

	<p>The aim of this project is to run any Node.js module in the browser.</p>

	<p>Here is a simple demo: e-mail sending using <a href="https://github.com/substack/node-smtp-protocol">a pure Javascript implementation of the SMTP protocol</a>. The <code>smtp-protocol</code> module is run right in the browser, using pure Javascript core modules if available (such as <code>events</code>, <code>path</code>...), browser versions (<code>stream</code>, <code>buffer</code>...) or custom polyfills (<code>net</code>, <code>tls</code>). In this demo, we a re opening a TCP socket to the SMTP server. As we cannot open raw TCP connections from the browser directly, we are using a WebSocket connection to send the TCP data through a Node.js server (something like <em>SMTP-over-WebSockets</em>). Then the connection is upgraded to a secure TSL connection, using <a href="https://github.com/digitalbazaar/forge">a client-side TLS library</a>. We are now able to send SMTP commands to the server (<code>HELO</code>, <code>AUTH</code> and so on).</p>

	<form id="send-email-form">
		<label>SMTP server: <input type="text" name="hostname" value="smtp.gmail.com"></label><br>
		<label>Port: <input type="number" name="port" value="587"></label><br>
		<label>Username: <input type="text" name="username"></label><br>
		<label>Password: <input type="password" name="password"></label><br><br>

		<label>From: <input type="email" name="from"></label><br>
		<label>To: <input type="email" name="to"></label><br>
		<label>Body:<br><textarea name="body" cols="50" rows="10">From: the browser <<EMAIL>>
To: you <<EMAIL>>
Subject: hello world

Hello from your web browser!</textarea></label>

		<p>
			<button type="submit">Send an e-mail</button>
		</p>

		<small>Note that we're using an end-to-end encryption so the server cannot retrieve your username and password. If you don't trust us, read the source! ;-)</small>
	</form>

	<pre id="status" style="height: 300px; overflow: auto; background-color: black; color: lightgray;"></pre>

	<script src="/bower_components/jquery/dist/jquery.min.js"></script>
	<script src="/js/node-client-vm.js"></script>
	<script>
	function uiStatus(msg) {
		$('#status').append(msg+'\n');
	}
	function uiReceived(msg) {
		return uiStatus('<span style="color:aqua;">'+msg+'</span>');
	}
	function uiError(msg) {
		return uiStatus('<span style="color:red;">'+msg+'</span>');
	}

	function sendEmail(options) {
		$('#status').empty();
		uiStatus('Loading core modules and smtp-protocol...');

		var startTime = (new Date()).getTime();
		Node.Module.load('smtp-protocol').then(function (module) {
			var smtp = module.run();
			uiStatus('SMTP module initialized!');

			uiStatus('Connecting to SMTP server '+options.hostname+':'+options.port);
			smtp.connect(options.hostname, options.port, function (client) {
				uiStatus('Connected with TCP!');

				client.on('error', function (err) {
					console.warn('[smtp] error:', err);
					uiError(err);
				});

				uiStatus('Waiting for greeting...');
				client.on('greeting', function (code, lines) {
					uiReceived(code+' '+lines.join('\n'));

					uiStatus('Saying HELO...');
					client.helo(options.servername, function (err) {
						uiStatus('Upgrading to a secure TLS connection...');
						client.on('tls', function () {
							uiStatus('Connected with TLS!');

							client.stream.on('data', function (data) {
								uiReceived(data);
							});
							client.stream.on('end', function (data) {
								uiStatus('Socket closed.');
							});

							uiStatus('Logging in...');
							client.login(options.username, options.password, options.authType, function (err, status, lines) {
								if (err) {
									console.error(err);
									uiError(err);
									return;
								}

								if (status == 235) {
									uiStatus('Logged in!');

									uiStatus('Now sending a message...');
									client.from(options.from, function (err) {
										client.to(options.to, function (err) {
											client.data(function (err) {
												var stream = client.message();
												stream.write(options.body);
												stream.end();

												uiStatus('Sent! Now disconnecting...');
												client.quit();

												var endTime = (new Date()).getTime();
												uiStatus('Time: '+(endTime - startTime)+'ms');
											});
										});
									});
								} else {
									if (status == 535) {
										console.error('Auth error');
									} else {
										console.error('Unknown error', status, lines);
									}
									uiError('['+status+'] Login failed: '+lines.join('\n'));
								}
							});
						});
						client.startTLS({
							servername: options.hostname,
							rejectUnauthorized: true
						});
					});
				});

				// Export client to let the user play with it from the web console
				window.client = client;
			});
		}, function (err) {
			uiError(err);
		});
	}

	$('#send-email-form').submit(function (e) {
		e.preventDefault();

		var options = {
			hostname: '',
			port: 25,
			servername: window.location.hostname,
			username: '',
			password: '',
			authType: 'PLAIN',

			from: '<EMAIL>',
			to: '<EMAIL>',
			body: 'From: the browser <<EMAIL>>\n'+
				'To: you <<EMAIL>>\n'+
				'Subject: hello world\n\n'+
				'Hello from your web browser!'
		};

		$(this).find('input,select,textarea').each(function () {
			var name = $(this).attr('name');

			if (name) {
				var value = $(this).val();
				switch ($(this).attr('type')) {
					case 'number':
						value = parseInt(value, 10);
						break;
				}

				if (value) {
					options[name] = value;
				}
			}
		});

		sendEmail(options);
	});
	</script>
</body>
</html>
{'fraction_non_alphanumeric': 0.1815159574468085, 'fraction_numerical': 0.004155585106382979, 'mean_word_length': 3.235480464625132, 'pattern_counts': {'":': 0, '<': 227, '<?xml version=': 0, '>': 227, 'https://': 8, 'lorem ipsum': 0, 'www.': 0, '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': '474612', 'n_tokens_mistral': 4877, 'n_tokens_neox': 3796, 'n_words': 982}