Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <html>
- <!-- Windows HTA application "Text Stream Host". Copyright (©) 2014 Alf P. Steinbach -->
- <head id="head-element">
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta http-equiv="MSThemeCompatible" content="yes">
- <title id="title-element"></title>
- <style>
- * { font: 10pt 'MS Shell Dlg 2'; }
- code { font: 10pt 'Courier new'; }
- body {
- padding: 0; margin: 0; overflow: hidden;
- background-color: #F0F0F0;
- }
- #text-stream-display p { margin: 0; padding: 0; color: #000080; }
- #control-area {
- padding-top: 0; padding-left: 0; padding-right: 0.5em; padding-bottom: 0;
- overflow: none;
- margin: 0;
- position: absolute;
- left: 0; top: 0;
- /*background-color: #FF0000;*/
- width: 30em; height: 2em; left: -14em; top: +14em;
- transform: rotate(-90deg);
- }
- #info-area {
- background-color: white;
- overflow: none;
- position: absolute;
- left: 2.5em; top: 0; right: 0; bottom: 0px;
- }
- #commandline-display {
- color: gray;
- overflow: auto;
- white-space: nowrap;
- padding: 0.5em;
- border-bottom: 1px solid gray;
- margin-bottom: 0.5em;
- position: absolute; left: 0; top: 0; right: 0;
- height: 7em;
- }
- .command-line { background-color: #F0FFF0; }
- #text-stream-display {
- overflow: auto;
- white-space: nowrap;
- padding: 0.5em;
- position: absolute;
- left: 0; top: 0px; right: 0; bottom: 0px;
- }
- .checkbox-div {
- border: 1px black solid;
- border-radius: 5px;
- padding-bottom: 0.2em; margin-bottom: 0.1em;
- padding-right: 0.5em;
- display: inline-block;
- cursor: pointer;
- }
- .checkbox-div:hover {
- background: #D0E0FF;
- }
- </style>
- <!-- Namespace js_util
- JavaScript utilities -->
- <script type="text/javascript">
- js_util = new function()
- {
- this.is_whitespace_character = function( ch )
- {
- return (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t');
- };
- this.is_whitespace = function( s )
- {
- with( this )
- {
- var n = s.length;
- for( var i = 0; i < n; ++i )
- {
- if( !is_whitespace_character( s.substr( i, 1 ) ) )
- {
- return false;
- }
- }
- }
- return true;
- };
- this.hex_digits = '0123456789ABCDEF';
- this.hex_from_int = function( number, n_digits )
- {
- if( n_digits == undefined ) { n_digits = 8; }
- var digits = new Array();
- for( var i = 1; i <= n_digits; ++i )
- {
- digits.push( number & 0xF );
- number >>>= 4;
- }
- var result = '';
- for( var i = n_digits - 1; i >= 0; --i )
- {
- result += this.hex_digits.substr( digits[i], 1 );
- }
- return result;
- }
- this.add_class = function( html_elem, classname )
- {
- var classname_set = html_elem.classList;
- if( !classname_set.contains( classname ) )
- {
- classname_set.toggle( classname );
- return true;
- }
- return false;
- }
- this.unquoted = function( s )
- {
- var quote = '"';
- var n = s.length;
- if( n <= 1 )
- {
- return s;
- }
- if( s.substr( 0, 1 ) == quote && s.substr( n - 1, 1 ) == quote )
- {
- return s.substring( 1, n - 1 );
- }
- return s;
- }
- this.local_file_url = function( filespec )
- {
- with( this )
- {
- var url = 'file:///' + unquoted( filespec ).replace( /\\/g, '/' );
- return url;
- }
- }
- };
- </script>
- <!-- Namespace windows.wsh
- Windows Script Host (shell functionality only). -->
- <script type="text/javascript">
- var windows = windows || {};
- windows.wsh = new function()
- {
- this.shell = new ActiveXObject( 'WScript.Shell' );
- this.sleep = function( millisecs )
- {
- with( this )
- {
- var nowindow = 0;
- var wait = true;
- shell.Run( 'ping 1.1.1.1 -n 1 -w ' + millisecs, nowindow, wait );
- }
- };
- this.is_running = function( wsh_execution )
- {
- return (wsh_execution.Status == 0);
- };
- this.run_hidden = function( command )
- {
- var hidden_window = 0;
- var wait_for_completion = true;
- with( this )
- {
- return shell.Run( command, hidden_window, wait_for_completion );
- }
- }
- };
- </script>
- <!-- Namespace windows.fs
- File System Object (part of Window's script support). -->
- <script type="text/javascript">
- var windows = windows || {};
- windows.fs = new function()
- {
- this.fso = new ActiveXObject( "Scripting.FileSystemObject" );
- this.tempfolder = this.fso.GetSpecialFolder( 2 );
- this.tempfolder_path = this.tempfolder.Path;
- this.open_for_reading = function( textfile_spec )
- {
- var for_reading = 1;
- var do_not_create = false;
- var ascii_encoding = 0;
- var utf16_encoding = -1;
- var default_encoding = -2;
- with( this )
- {
- return fso.OpenTextFile(
- textfile_spec,
- for_reading, do_not_create, default_encoding
- );
- }
- }
- this.joined_paths = function( folder_path, filename )
- {
- with( this ) return fso.BuildPath( folder_path, filename );
- }
- this.temp_filename = function()
- {
- with( this ) return fso.GetTempName();
- }
- this.temp_filepath = function()
- {
- with( this ) return joined_paths( tempfolder_path, temp_filename() );
- }
- this.quoted = function( path )
- {
- var quote = '"';
- var is_quoted = (path.length > 0 && path.substr( 0, 1 ) == quote);
- return (is_quoted? path : quote + path + quote);
- }
- };
- </script>
- <!-- Namespace windows.process_info
- Windows process information. -->
- <script type="text/javascript">
- var windows = windows || {};
- windows.process_info = new function()
- {
- var pg = {}; // "private globals" namespace, to make that explicit.
- pg.Record = function()
- {
- this._add_item = function( spec )
- {
- i_delimiter = spec.indexOf( '=' );
- if( i_delimiter != -1 )
- {
- var property_name = spec.substring( 0, i_delimiter );
- var value = spec.substr( i_delimiter + 1 );
- this[property_name] = value;
- }
- }
- };
- this.new_records = function()
- {
- var filepath = windows.fs.temp_filepath();
- var exitcode = windows.wsh.run_hidden(
- 'cmd /c wmic process list full >' + windows.fs.quoted( filepath )
- );
- if( exitcode != 0 )
- {
- return null; // TODO: exception
- }
- var records = new Array();
- var current_record = null;
- var f = windows.fs.open_for_reading( filepath );
- while( !f.AtEndOfStream )
- {
- var line = f.ReadLine();
- var i_end = line.length - 1;
- while( i_end >= 0 && line.substr( i_end, 1 ) < ' ' )
- {
- --i_end;
- }
- if( 0 <= i_end && i_end < line.length - 1 )
- {
- line = line.substr( 0, i_end + 1 );
- }
- if( js_util.is_whitespace( line ) )
- {
- if( current_record != null )
- {
- records.push( current_record );
- current_record = null;
- }
- }
- else // line.length > 0
- {
- if( current_record == null )
- {
- current_record = new pg.Record();
- }
- current_record._add_item( line );
- }
- }
- // Complete a possible last record.
- if( current_record != null )
- {
- records.push( current_record );
- }
- f.Close();
- windows.fs.fso.DeleteFile( filepath );
- return records;
- };
- };
- </script>
- <!-- Namespace ts_host
- Text Stream Host (this HTA application). -->
- <script type="text/javascript">
- var ts_host = new function()
- {
- var pg = {}; // "private globals" namespace, to make that explicit.
- // Assumption: records from a call near the start of this process.
- // It this ever should become unreliable, then add check of hta name.
- pg.record_for_this_process = function( records )
- {
- var this_process = null;
- var this_usertime = null;
- var n = records.length;
- for( var i = 0; i != n; ++i )
- {
- var process = records[i];
- if( process.Name == 'mshta.exe' )
- {
- var usertime = parseInt( process.UserModeTime );
- if( this_usertime == null || usertime < this_usertime )
- {
- this_process = process;
- this_usertime = usertime;
- }
- }
- }
- return this_process;
- }
- pg.folder_path_of = function( s )
- {
- return s.substr( 0, 1 + s.lastIndexOf( '\\' ) );
- }
- pg.Span = function( _start, _end )
- {
- this.start = _start;
- this.end = _end;
- };
- pg.commandline_argument_spans_of = function( s )
- {
- function is_whitespace( s ) { return js_util.is_whitespace( s ); }
- var spans = new Array();
- var n = s.length;
- var unquoted = true;
- var in_argument = false;
- var i_span_start;
- for( var i = 0; i < n; ++i )
- {
- var ch = s.substr( i, 1 );
- if( ch == '"' )
- {
- unquoted = !unquoted;
- }
- if( in_argument )
- {
- if( unquoted && is_whitespace( ch ) )
- {
- spans.push( new pg.Span( i_span_start, i ) );
- in_argument = false;
- }
- }
- else
- {
- if( !is_whitespace( ch ) )
- {
- in_argument = true;
- i_span_start = i;
- }
- }
- }
- if( in_argument )
- {
- spans.push( new pg.Span( i_span_start, n ) );
- }
- return spans;
- }
- pg.commandline_arguments_of = function( s )
- {
- var spans = pg.commandline_argument_spans_of( s );
- var arguments = new Array();
- var n = spans.length;
- for( var i = 0; i < n; ++i )
- {
- var span = spans[i];
- arguments.push( s.substring( span.start, span.end ) );
- }
- return arguments;
- }
- pg.script_commandline_part_of = function( process_commandline )
- {
- var spans = pg.commandline_argument_spans_of( process_commandline );
- return (spans.length <= 3? '' : process_commandline.substr( spans[3].start ) );
- }
- pg.drophandler = new function()
- {
- // Final backslash specifies that the last item is a key name not value name.
- var registry_key = 'HKEY_CLASSES_ROOT\\HTAFile\\ShellEx\\DropHandler\\';
- var type_spec = 'REG_SZ';
- var handler_uuid = '{60254CA5-953B-11CF-8C96-00AA00B8708C}';
- this.value = function()
- {
- try
- {
- return windows.wsh.shell.RegRead( registry_key );
- }
- catch( e )
- {
- return null;
- }
- }
- this.is_installed = function()
- {
- with( this )
- {
- var v = value();
- //alert( 'Checking is_installed(), value = ' + v );
- return (v == null? false : v.toUpperCase() == handler_uuid);
- }
- }
- this.install = function()
- {
- try
- {
- //windows.wsh.shell.RegWrite( registry_key, handler_uuid, type_spec ); // Fails.
- alert( 'To enable file drop on HTML application files say YES in the following intent checking box.' );
- var reg_arguments = ''
- + 'add ' + registry_key
- + ' /ve' // Add empty value name (default value).
- + ' /t ' + type_spec
- + ' /d ' + handler_uuid
- + ' /f'; // Force, if some value already exists.
- var winshell = new ActiveXObject( 'Shell.Application' );
- var exitcode = winshell.ShellExecute(
- 'reg.exe',
- reg_arguments,
- '', // Directory
- 'runas', // This verb requests elevation.
- 0 // Hidden window.
- );
- // Here exitcode is undefined! So.
- this.is_installed(); // This call is needed to flush a cache somewhere.
- windows.wsh.sleep( 200 ); // Ditto, we're in Microsoft non-deterministic country.
- return this.is_installed();
- }
- catch( e )
- {
- alert( 'Exception:\n' + e );
- return false;
- }
- }
- }
- pg.buffered_output = '';
- pg.writeline = function( s )
- {
- if( s != undefined ) { pg.buffered_output += s; }
- if( js_util.is_whitespace( pg.buffered_output ) )
- {
- var nbsp = '\xA0';
- pg.buffered_output = nbsp;
- }
- var para = document.createElement( 'p' )
- var text = document.createTextNode( pg.buffered_output );
- para.appendChild( text );
- pg.ui.text_stream_display.appendChild( para );
- //trace_doc.body.scrollTop = 99999;
- para.scrollIntoView( false ); // false => align with bottom of scroll area.
- pg.buffered_output = '';
- };
- pg.write = function( s )
- {
- if( s.length == 0 ) { return; }
- pg.buffered_output += s;
- };
- pg.flush = function()
- {
- if( pg.buffered_output.length == 0 )
- {
- return;
- }
- var last_para = pg.ui.text_stream_display.lastChild;
- // TODO:
- }
- pg.records = windows.process_info.new_records();
- pg.this_process = pg.record_for_this_process( pg.records );
- pg.process_commandline = (pg.this_process == null? '' : pg.this_process.CommandLine);
- pg.script_commandline = pg.script_commandline_part_of( pg.process_commandline );
- pg.command_arguments = pg.commandline_arguments_of( pg.script_commandline );
- pg.ui = {}; // Attributes are added by document loaded event.
- pg.basic_title = "Text Stream Host";
- this.hta_path = window.location.pathname.substr( 1 );
- this.hta_folder_path = pg.folder_path_of( this.hta_path );
- this.raw_commandline = pg.process_commandline;
- this.commandline = pg.script_commandline;
- this.command_arguments = pg.command_arguments;
- this.commandline_argument_spans_of = pg.commandline_argument_spans_of;
- this.commandline_arguments_of = pg.commandline_arguments_of;
- this._on_show_arguments_choice = function( checkbox )
- {
- function number_part( s ) { return parseFloat( s ); }
- with( this )
- {
- var astyle = pg.ui.commandline_display.style;
- var ainfo = getComputedStyle( pg.ui.commandline_display, null );
- var aheight = 0
- + number_part( ainfo.height )
- + number_part( ainfo.marginBottom )
- + number_part( ainfo.paddingBottom )
- + number_part( ainfo.borderBottomWidth );
- var tstyle = pg.ui.text_stream_display.style;
- tstyle.top = (checkbox.checked? aheight + 'px' : 0);
- astyle.display = (checkbox.checked? 'block' : 'none');
- scrollTo( 0, 0 ); // Counter automatic scroll-checkbox-into-view.
- }
- }
- this._on_wrapping_choice = function( checkbox )
- {
- function set_wrapping( elem )
- {
- elem.style.whiteSpace = (checkbox.checked? 'normal' : 'nowrap');
- }
- with( this )
- {
- set_wrapping( pg.ui.commandline_display );
- set_wrapping( pg.ui.text_stream_display );
- }
- }
- pg.install_drophandler = function()
- {
- function replacement_okayed()
- {
- return window.confirm( ''
- + 'The registry key that specifices the file drop handler for '
- + 'HTML application files already has a value (different from the standard one), '
- + '“' + current_value + '”. Should that be replaced with the '
- + ' standard value? Say OK,replace, if dropping scripts on HTML application files '
- + ' doesn’t work, but perhaps say CANCEL if it appears to already work.'
- );
- }
- var current_value = pg.drophandler.value();
- if( current_value == null || replacement_okayed() )
- {
- var ok = pg.drophandler.install();
- if( ok )
- {
- pg.writeline( '☺ Enabled Windows dropping of scripts on HTA files.' );
- pg.writeline( ' ' );
- pg.writeline( 'After rebooting the machine you can now run a JavaScript script' );
- pg.writeline( 'by just dropping it on the ' + pg.basic_title + ' HTML application file.' );
- }
- else
- {
- pg.writeline( '(。・_・。) Oh! Apparently failed to enable Windows dropping of scripts on HTA files...' );
- pg.writeline();
- pg.writeline( 'It may help to be logged in as administrator, if you’re not already.' );
- }
- }
- }
- this._on_document_loaded = function()
- {
- function elem( id ) { return document.getElementById( id ); }
- with( this )
- {
- pg.ui.commandline_display = elem( 'commandline-display' );
- pg.ui.text_stream_display = elem( 'text-stream-display' );
- pg.ui.text_stream_display.focus();
- elem( 'title-element' ).innerText = pg.basic_title;
- elem( 'process-command-line' ).innerText = pg.process_commandline;
- elem( 'script-command-line' ).innerText = pg.script_commandline;
- if( pg.script_commandline.length > 0 )
- {
- elem( 'no-script-info' ).innerText = '';
- }
- if( pg.script_commandline.length == 0 )
- {
- elem( 'arguments-display' ).style.display = 'none';
- writeline( '☺ No script was specified.' );
- if( pg.drophandler.is_installed() )
- {
- writeline( '☺ Dropping of files on HTML Application files is enabled.' );
- }
- else
- {
- pg.install_drophandler();
- }
- }
- else
- {
- var n = pg.command_arguments.length;
- elem( 'argument-list-count' ).innerText =
- n + ' command line ' + (n == 1? 'argument' : 'arguments');
- var list = elem( 'argument-list' );
- for( var i = 0; i < n; ++i )
- {
- var item = document.createElement( 'li' );
- var span = document.createElement( 'span' );
- var text = document.createTextNode( pg.command_arguments[i] );
- js_util.add_class( span, 'command-line' );
- span.appendChild( text );
- item.appendChild( span );
- list.appendChild( item );
- }
- }
- if( pg.command_arguments.length > 0 )
- {
- var filespec = js_util.unquoted( pg.command_arguments[0] );
- try
- {
- elem( 'title-element' ).innerText = pg.basic_title + ' ‒ “' + filespec + '”';
- windows.fs.open_for_reading( filespec ).close(); // Check availability.
- var head_elem = elem( 'head-element' );
- var head_elem = elem( 'head-element' );
- var script_elem = document.createElement( 'script' );
- script_elem.setAttribute( 'type', 'text/javascript' );
- script_elem.setAttribute( 'src', js_util.local_file_url( filespec ) );
- head_elem.appendChild( script_elem );
- }
- catch( e )
- {
- alert( ''
- + '“' + e.description + '” error\n'
- + 'while attempting to load and execute script “' + filespec + '”\n'
- + '(error code 0x' + js_util.hex_from_int( e.number ) + ')' );
- window.close();
- }
- }
- //writeline( '"' + htaelem.commandLine + '"' );
- //for( var i = 1; i <= 42; ++i ) { writeline( i ); }
- //write( 'Ufinished line... ' );
- //flush();
- } // with( this )
- };
- this.writeline = pg.writeline;
- this.write = pg.write;
- this.flush = pg.flush;
- };
- </script>
- </head>
- <body onload="ts_host._on_document_loaded()">
- <div id="control-area">
- <div id="buttons-bar" style="float: right;">
- <div class="checkbox-div" title="Show command line">
- <label>
- <input type="checkbox" onchange="ts_host._on_show_arguments_choice(this)"/>
- Command line
- </label>
- </div>
- <div class="checkbox-div" title="Show line-numbers">
- <label>
- <input type="checkbox"/>
- Line-numbers
- </label>
- </div>
- <div class="checkbox-div" title="Wrap lines">
- <label>
- <input type="checkbox" onchange="ts_host._on_wrapping_choice(this)"/>
- Wrap lines
- </label>
- </div>
- </div>
- </div>
- <div id="info-area">
- <div id="commandline-display" style="display: none">
- <p style="margin-top: 0;">
- <label for="process-command-line" title="ts_host.raw_commandline">
- Process command line:
- </label><br>
- <span id="process-command-line" class="command-line"></span>
- </p>
- <p>
- <label for="script-command-line" title="ts_host.commandline">
- Script command line (part of the above):
- </label>
- <span id="no-script-info" style="font-style: italic">Not specified</span><br>
- <span id="script-command-line" class="command-line"></span>
- </p>
- <div id="arguments-display" title="ts_host.command_arguments">
- <span id="argument-list-count">n arguments</span>:
- <ol id="argument-list" start="0">
- </ol>
- </div>
- </div>
- <div id="text-stream-display">
- <!-- p>
- Blah blah this is the text stream display area.</p -->
- <div>
- </div>
- </body>
- </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement