Advertisement
alfps

Untitled

Apr 4th, 2014
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <html>
  2. <!-- Windows HTA application "Text Stream Host". Copyright (©) 2014 Alf P. Steinbach -->
  3. <head id="head-element">
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta http-equiv="MSThemeCompatible" content="yes">
  7.  
  8. <title id="title-element"></title>
  9.  
  10. <style>
  11. * { font: 10pt 'MS Shell Dlg 2'; }
  12.  
  13. code { font: 10pt 'Courier new'; }
  14.  
  15. body {
  16. padding: 0; margin: 0; overflow: hidden;
  17. background-color: #F0F0F0;
  18. }
  19.  
  20. #text-stream-display p { margin: 0; padding: 0; color: #000080; }
  21.  
  22. #control-area {
  23. padding-top: 0; padding-left: 0; padding-right: 0.5em; padding-bottom: 0;
  24. overflow: none;
  25. margin: 0;
  26. position: absolute;
  27. left: 0; top: 0;
  28. /*background-color: #FF0000;*/
  29. width: 30em; height: 2em; left: -14em; top: +14em;
  30. transform: rotate(-90deg);
  31. }
  32.  
  33. #info-area {
  34. background-color: white;
  35. overflow: none;
  36. position: absolute;
  37. left: 2.5em; top: 0; right: 0; bottom: 0px;
  38. }
  39.  
  40. #commandline-display {
  41. color: gray;
  42. overflow: auto;
  43. white-space: nowrap;
  44. padding: 0.5em;
  45. border-bottom: 1px solid gray;
  46. margin-bottom: 0.5em;
  47. position: absolute; left: 0; top: 0; right: 0;
  48. height: 7em;
  49. }
  50.  
  51. .command-line { background-color: #F0FFF0; }
  52.  
  53. #text-stream-display {
  54. overflow: auto;
  55. white-space: nowrap;
  56. padding: 0.5em;
  57. position: absolute;
  58. left: 0; top: 0px; right: 0; bottom: 0px;
  59. }
  60.  
  61. .checkbox-div {
  62. border: 1px black solid;
  63. border-radius: 5px;
  64. padding-bottom: 0.2em; margin-bottom: 0.1em;
  65. padding-right: 0.5em;
  66. display: inline-block;
  67. cursor: pointer;
  68. }
  69.  
  70. .checkbox-div:hover {
  71. background: #D0E0FF;
  72. }
  73. </style>
  74.  
  75. <!-- Namespace js_util
  76. JavaScript utilities -->
  77. <script type="text/javascript">
  78. js_util = new function()
  79. {
  80. this.is_whitespace_character = function( ch )
  81. {
  82. return (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t');
  83. };
  84.  
  85. this.is_whitespace = function( s )
  86. {
  87. with( this )
  88. {
  89. var n = s.length;
  90. for( var i = 0; i < n; ++i )
  91. {
  92. if( !is_whitespace_character( s.substr( i, 1 ) ) )
  93. {
  94. return false;
  95. }
  96. }
  97. }
  98. return true;
  99. };
  100.  
  101. this.hex_digits = '0123456789ABCDEF';
  102.  
  103. this.hex_from_int = function( number, n_digits )
  104. {
  105. if( n_digits == undefined ) { n_digits = 8; }
  106. var digits = new Array();
  107. for( var i = 1; i <= n_digits; ++i )
  108. {
  109. digits.push( number & 0xF );
  110. number >>>= 4;
  111. }
  112. var result = '';
  113. for( var i = n_digits - 1; i >= 0; --i )
  114. {
  115. result += this.hex_digits.substr( digits[i], 1 );
  116. }
  117. return result;
  118. }
  119.  
  120. this.add_class = function( html_elem, classname )
  121. {
  122. var classname_set = html_elem.classList;
  123. if( !classname_set.contains( classname ) )
  124. {
  125. classname_set.toggle( classname );
  126. return true;
  127. }
  128. return false;
  129. }
  130.  
  131. this.unquoted = function( s )
  132. {
  133. var quote = '"';
  134. var n = s.length;
  135. if( n <= 1 )
  136. {
  137. return s;
  138. }
  139. if( s.substr( 0, 1 ) == quote && s.substr( n - 1, 1 ) == quote )
  140. {
  141. return s.substring( 1, n - 1 );
  142. }
  143. return s;
  144. }
  145.  
  146. this.local_file_url = function( filespec )
  147. {
  148. with( this )
  149. {
  150. var url = 'file:///' + unquoted( filespec ).replace( /\\/g, '/' );
  151. return url;
  152. }
  153. }
  154. };
  155. </script>
  156.  
  157. <!-- Namespace windows.wsh
  158. Windows Script Host (shell functionality only). -->
  159. <script type="text/javascript">
  160. var windows = windows || {};
  161. windows.wsh = new function()
  162. {
  163. this.shell = new ActiveXObject( 'WScript.Shell' );
  164.  
  165. this.sleep = function( millisecs )
  166. {
  167. with( this )
  168. {
  169. var nowindow = 0;
  170. var wait = true;
  171. shell.Run( 'ping 1.1.1.1 -n 1 -w ' + millisecs, nowindow, wait );
  172. }
  173. };
  174.  
  175. this.is_running = function( wsh_execution )
  176. {
  177. return (wsh_execution.Status == 0);
  178. };
  179.  
  180. this.run_hidden = function( command )
  181. {
  182. var hidden_window = 0;
  183. var wait_for_completion = true;
  184. with( this )
  185. {
  186. return shell.Run( command, hidden_window, wait_for_completion );
  187. }
  188. }
  189. };
  190. </script>
  191.  
  192. <!-- Namespace windows.fs
  193. File System Object (part of Window's script support). -->
  194. <script type="text/javascript">
  195. var windows = windows || {};
  196. windows.fs = new function()
  197. {
  198. this.fso = new ActiveXObject( "Scripting.FileSystemObject" );
  199.  
  200. this.tempfolder = this.fso.GetSpecialFolder( 2 );
  201. this.tempfolder_path = this.tempfolder.Path;
  202.  
  203. this.open_for_reading = function( textfile_spec )
  204. {
  205. var for_reading = 1;
  206.  
  207. var do_not_create = false;
  208.  
  209. var ascii_encoding = 0;
  210. var utf16_encoding = -1;
  211. var default_encoding = -2;
  212.  
  213. with( this )
  214. {
  215. return fso.OpenTextFile(
  216. textfile_spec,
  217. for_reading, do_not_create, default_encoding
  218. );
  219. }
  220. }
  221.  
  222. this.joined_paths = function( folder_path, filename )
  223. {
  224. with( this ) return fso.BuildPath( folder_path, filename );
  225. }
  226.  
  227. this.temp_filename = function()
  228. {
  229. with( this ) return fso.GetTempName();
  230. }
  231.  
  232. this.temp_filepath = function()
  233. {
  234. with( this ) return joined_paths( tempfolder_path, temp_filename() );
  235. }
  236.  
  237. this.quoted = function( path )
  238. {
  239. var quote = '"';
  240. var is_quoted = (path.length > 0 && path.substr( 0, 1 ) == quote);
  241. return (is_quoted? path : quote + path + quote);
  242. }
  243. };
  244. </script>
  245.  
  246. <!-- Namespace windows.process_info
  247. Windows process information. -->
  248. <script type="text/javascript">
  249. var windows = windows || {};
  250. windows.process_info = new function()
  251. {
  252. var pg = {}; // "private globals" namespace, to make that explicit.
  253.  
  254. pg.Record = function()
  255. {
  256. this._add_item = function( spec )
  257. {
  258. i_delimiter = spec.indexOf( '=' );
  259. if( i_delimiter != -1 )
  260. {
  261. var property_name = spec.substring( 0, i_delimiter );
  262. var value = spec.substr( i_delimiter + 1 );
  263. this[property_name] = value;
  264. }
  265. }
  266. };
  267.  
  268. this.new_records = function()
  269. {
  270. var filepath = windows.fs.temp_filepath();
  271. var exitcode = windows.wsh.run_hidden(
  272. 'cmd /c wmic process list full >' + windows.fs.quoted( filepath )
  273. );
  274. if( exitcode != 0 )
  275. {
  276. return null; // TODO: exception
  277. }
  278.  
  279. var records = new Array();
  280. var current_record = null;
  281.  
  282. var f = windows.fs.open_for_reading( filepath );
  283. while( !f.AtEndOfStream )
  284. {
  285. var line = f.ReadLine();
  286.  
  287. var i_end = line.length - 1;
  288. while( i_end >= 0 && line.substr( i_end, 1 ) < ' ' )
  289. {
  290. --i_end;
  291. }
  292. if( 0 <= i_end && i_end < line.length - 1 )
  293. {
  294. line = line.substr( 0, i_end + 1 );
  295. }
  296.  
  297. if( js_util.is_whitespace( line ) )
  298. {
  299. if( current_record != null )
  300. {
  301. records.push( current_record );
  302. current_record = null;
  303. }
  304. }
  305. else // line.length > 0
  306. {
  307. if( current_record == null )
  308. {
  309. current_record = new pg.Record();
  310. }
  311. current_record._add_item( line );
  312. }
  313. }
  314.  
  315. // Complete a possible last record.
  316. if( current_record != null )
  317. {
  318. records.push( current_record );
  319. }
  320.  
  321. f.Close();
  322. windows.fs.fso.DeleteFile( filepath );
  323.  
  324. return records;
  325. };
  326. };
  327. </script>
  328.  
  329. <!-- Namespace ts_host
  330. Text Stream Host (this HTA application). -->
  331. <script type="text/javascript">
  332. var ts_host = new function()
  333. {
  334. var pg = {}; // "private globals" namespace, to make that explicit.
  335.  
  336. // Assumption: records from a call near the start of this process.
  337. // It this ever should become unreliable, then add check of hta name.
  338. pg.record_for_this_process = function( records )
  339. {
  340. var this_process = null;
  341. var this_usertime = null;
  342. var n = records.length;
  343. for( var i = 0; i != n; ++i )
  344. {
  345. var process = records[i];
  346. if( process.Name == 'mshta.exe' )
  347. {
  348. var usertime = parseInt( process.UserModeTime );
  349. if( this_usertime == null || usertime < this_usertime )
  350. {
  351. this_process = process;
  352. this_usertime = usertime;
  353. }
  354. }
  355. }
  356. return this_process;
  357. }
  358.  
  359. pg.folder_path_of = function( s )
  360. {
  361. return s.substr( 0, 1 + s.lastIndexOf( '\\' ) );
  362. }
  363.  
  364. pg.Span = function( _start, _end )
  365. {
  366. this.start = _start;
  367. this.end = _end;
  368. };
  369.  
  370. pg.commandline_argument_spans_of = function( s )
  371. {
  372. function is_whitespace( s ) { return js_util.is_whitespace( s ); }
  373.  
  374. var spans = new Array();
  375.  
  376. var n = s.length;
  377. var unquoted = true;
  378. var in_argument = false;
  379. var i_span_start;
  380. for( var i = 0; i < n; ++i )
  381. {
  382. var ch = s.substr( i, 1 );
  383. if( ch == '"' )
  384. {
  385. unquoted = !unquoted;
  386. }
  387.  
  388. if( in_argument )
  389. {
  390. if( unquoted && is_whitespace( ch ) )
  391. {
  392. spans.push( new pg.Span( i_span_start, i ) );
  393. in_argument = false;
  394. }
  395. }
  396. else
  397. {
  398. if( !is_whitespace( ch ) )
  399. {
  400. in_argument = true;
  401. i_span_start = i;
  402. }
  403. }
  404. }
  405.  
  406. if( in_argument )
  407. {
  408. spans.push( new pg.Span( i_span_start, n ) );
  409. }
  410.  
  411. return spans;
  412. }
  413.  
  414. pg.commandline_arguments_of = function( s )
  415. {
  416. var spans = pg.commandline_argument_spans_of( s );
  417. var arguments = new Array();
  418. var n = spans.length;
  419. for( var i = 0; i < n; ++i )
  420. {
  421. var span = spans[i];
  422. arguments.push( s.substring( span.start, span.end ) );
  423. }
  424. return arguments;
  425. }
  426.  
  427. pg.script_commandline_part_of = function( process_commandline )
  428. {
  429. var spans = pg.commandline_argument_spans_of( process_commandline );
  430. return (spans.length <= 3? '' : process_commandline.substr( spans[3].start ) );
  431. }
  432.  
  433. pg.drophandler = new function()
  434. {
  435. // Final backslash specifies that the last item is a key name not value name.
  436. var registry_key = 'HKEY_CLASSES_ROOT\\HTAFile\\ShellEx\\DropHandler\\';
  437. var type_spec = 'REG_SZ';
  438. var handler_uuid = '{60254CA5-953B-11CF-8C96-00AA00B8708C}';
  439.  
  440. this.value = function()
  441. {
  442. try
  443. {
  444. return windows.wsh.shell.RegRead( registry_key );
  445. }
  446. catch( e )
  447. {
  448. return null;
  449. }
  450. }
  451.  
  452. this.is_installed = function()
  453. {
  454. with( this )
  455. {
  456. var v = value();
  457. //alert( 'Checking is_installed(), value = ' + v );
  458. return (v == null? false : v.toUpperCase() == handler_uuid);
  459. }
  460. }
  461.  
  462. this.install = function()
  463. {
  464. try
  465. {
  466. //windows.wsh.shell.RegWrite( registry_key, handler_uuid, type_spec ); // Fails.
  467. alert( 'To enable file drop on HTML application files say YES in the following intent checking box.' );
  468. var reg_arguments = ''
  469. + 'add ' + registry_key
  470. + ' /ve' // Add empty value name (default value).
  471. + ' /t ' + type_spec
  472. + ' /d ' + handler_uuid
  473. + ' /f'; // Force, if some value already exists.
  474. var winshell = new ActiveXObject( 'Shell.Application' );
  475. var exitcode = winshell.ShellExecute(
  476. 'reg.exe',
  477. reg_arguments,
  478. '', // Directory
  479. 'runas', // This verb requests elevation.
  480. 0 // Hidden window.
  481. );
  482. // Here exitcode is undefined! So.
  483. this.is_installed(); // This call is needed to flush a cache somewhere.
  484. windows.wsh.sleep( 200 ); // Ditto, we're in Microsoft non-deterministic country.
  485. return this.is_installed();
  486. }
  487. catch( e )
  488. {
  489. alert( 'Exception:\n' + e );
  490. return false;
  491. }
  492. }
  493. }
  494.  
  495. pg.buffered_output = '';
  496.  
  497. pg.writeline = function( s )
  498. {
  499. if( s != undefined ) { pg.buffered_output += s; }
  500. if( js_util.is_whitespace( pg.buffered_output ) )
  501. {
  502. var nbsp = '\xA0';
  503. pg.buffered_output = nbsp;
  504. }
  505. var para = document.createElement( 'p' )
  506. var text = document.createTextNode( pg.buffered_output );
  507. para.appendChild( text );
  508. pg.ui.text_stream_display.appendChild( para );
  509. //trace_doc.body.scrollTop = 99999;
  510. para.scrollIntoView( false ); // false => align with bottom of scroll area.
  511. pg.buffered_output = '';
  512. };
  513.  
  514. pg.write = function( s )
  515. {
  516. if( s.length == 0 ) { return; }
  517. pg.buffered_output += s;
  518. };
  519.  
  520. pg.flush = function()
  521. {
  522. if( pg.buffered_output.length == 0 )
  523. {
  524. return;
  525. }
  526. var last_para = pg.ui.text_stream_display.lastChild;
  527. // TODO:
  528. }
  529.  
  530. pg.records = windows.process_info.new_records();
  531. pg.this_process = pg.record_for_this_process( pg.records );
  532. pg.process_commandline = (pg.this_process == null? '' : pg.this_process.CommandLine);
  533. pg.script_commandline = pg.script_commandline_part_of( pg.process_commandline );
  534. pg.command_arguments = pg.commandline_arguments_of( pg.script_commandline );
  535. pg.ui = {}; // Attributes are added by document loaded event.
  536. pg.basic_title = "Text Stream Host";
  537.  
  538. this.hta_path = window.location.pathname.substr( 1 );
  539. this.hta_folder_path = pg.folder_path_of( this.hta_path );
  540. this.raw_commandline = pg.process_commandline;
  541. this.commandline = pg.script_commandline;
  542. this.command_arguments = pg.command_arguments;
  543.  
  544. this.commandline_argument_spans_of = pg.commandline_argument_spans_of;
  545. this.commandline_arguments_of = pg.commandline_arguments_of;
  546.  
  547. this._on_show_arguments_choice = function( checkbox )
  548. {
  549. function number_part( s ) { return parseFloat( s ); }
  550.  
  551. with( this )
  552. {
  553. var astyle = pg.ui.commandline_display.style;
  554. var ainfo = getComputedStyle( pg.ui.commandline_display, null );
  555. var aheight = 0
  556. + number_part( ainfo.height )
  557. + number_part( ainfo.marginBottom )
  558. + number_part( ainfo.paddingBottom )
  559. + number_part( ainfo.borderBottomWidth );
  560. var tstyle = pg.ui.text_stream_display.style;
  561.  
  562. tstyle.top = (checkbox.checked? aheight + 'px' : 0);
  563. astyle.display = (checkbox.checked? 'block' : 'none');
  564. scrollTo( 0, 0 ); // Counter automatic scroll-checkbox-into-view.
  565. }
  566. }
  567.  
  568. this._on_wrapping_choice = function( checkbox )
  569. {
  570. function set_wrapping( elem )
  571. {
  572. elem.style.whiteSpace = (checkbox.checked? 'normal' : 'nowrap');
  573. }
  574.  
  575. with( this )
  576. {
  577. set_wrapping( pg.ui.commandline_display );
  578. set_wrapping( pg.ui.text_stream_display );
  579. }
  580. }
  581.  
  582. pg.install_drophandler = function()
  583. {
  584. function replacement_okayed()
  585. {
  586. return window.confirm( ''
  587. + 'The registry key that specifices the file drop handler for '
  588. + 'HTML application files already has a value (different from the standard one), '
  589. + '“' + current_value + '”. Should that be replaced with the '
  590. + ' standard value? Say OK,replace, if dropping scripts on HTML application files '
  591. + ' doesn’t work, but perhaps say CANCEL if it appears to already work.'
  592. );
  593. }
  594.  
  595. var current_value = pg.drophandler.value();
  596. if( current_value == null || replacement_okayed() )
  597. {
  598. var ok = pg.drophandler.install();
  599. if( ok )
  600. {
  601. pg.writeline( '☺ Enabled Windows dropping of scripts on HTA files.' );
  602. pg.writeline( ' ' );
  603. pg.writeline( 'After rebooting the machine you can now run a JavaScript script' );
  604. pg.writeline( 'by just dropping it on the ' + pg.basic_title + ' HTML application file.' );
  605. }
  606. else
  607. {
  608. pg.writeline( '(。・_・。) Oh! Apparently failed to enable Windows dropping of scripts on HTA files...' );
  609. pg.writeline();
  610. pg.writeline( 'It may help to be logged in as administrator, if you’re not already.' );
  611. }
  612. }
  613. }
  614.  
  615. this._on_document_loaded = function()
  616. {
  617. function elem( id ) { return document.getElementById( id ); }
  618.  
  619. with( this )
  620. {
  621. pg.ui.commandline_display = elem( 'commandline-display' );
  622. pg.ui.text_stream_display = elem( 'text-stream-display' );
  623. pg.ui.text_stream_display.focus();
  624. elem( 'title-element' ).innerText = pg.basic_title;
  625. elem( 'process-command-line' ).innerText = pg.process_commandline;
  626. elem( 'script-command-line' ).innerText = pg.script_commandline;
  627.  
  628. if( pg.script_commandline.length > 0 )
  629. {
  630. elem( 'no-script-info' ).innerText = '';
  631. }
  632.  
  633. if( pg.script_commandline.length == 0 )
  634. {
  635. elem( 'arguments-display' ).style.display = 'none';
  636.  
  637. writeline( '☺ No script was specified.' );
  638. if( pg.drophandler.is_installed() )
  639. {
  640. writeline( '☺ Dropping of files on HTML Application files is enabled.' );
  641. }
  642. else
  643. {
  644. pg.install_drophandler();
  645. }
  646. }
  647. else
  648. {
  649. var n = pg.command_arguments.length;
  650. elem( 'argument-list-count' ).innerText =
  651. n + ' command line ' + (n == 1? 'argument' : 'arguments');
  652. var list = elem( 'argument-list' );
  653. for( var i = 0; i < n; ++i )
  654. {
  655. var item = document.createElement( 'li' );
  656. var span = document.createElement( 'span' );
  657. var text = document.createTextNode( pg.command_arguments[i] );
  658. js_util.add_class( span, 'command-line' );
  659. span.appendChild( text );
  660. item.appendChild( span );
  661. list.appendChild( item );
  662. }
  663. }
  664.  
  665. if( pg.command_arguments.length > 0 )
  666. {
  667. var filespec = js_util.unquoted( pg.command_arguments[0] );
  668. try
  669. {
  670. elem( 'title-element' ).innerText = pg.basic_title + ' ‒ “' + filespec + '”';
  671. windows.fs.open_for_reading( filespec ).close(); // Check availability.
  672. var head_elem = elem( 'head-element' );
  673. var head_elem = elem( 'head-element' );
  674. var script_elem = document.createElement( 'script' );
  675. script_elem.setAttribute( 'type', 'text/javascript' );
  676. script_elem.setAttribute( 'src', js_util.local_file_url( filespec ) );
  677. head_elem.appendChild( script_elem );
  678. }
  679. catch( e )
  680. {
  681. alert( ''
  682. + '“' + e.description + '” error\n'
  683. + 'while attempting to load and execute script “' + filespec + '”\n'
  684. + '(error code 0x' + js_util.hex_from_int( e.number ) + ')' );
  685. window.close();
  686. }
  687. }
  688.  
  689. //writeline( '"' + htaelem.commandLine + '"' );
  690. //for( var i = 1; i <= 42; ++i ) { writeline( i ); }
  691. //write( 'Ufinished line... ' );
  692. //flush();
  693. } // with( this )
  694. };
  695.  
  696. this.writeline = pg.writeline;
  697. this.write = pg.write;
  698. this.flush = pg.flush;
  699. };
  700. </script>
  701. </head>
  702.  
  703. <body onload="ts_host._on_document_loaded()">
  704. <div id="control-area">
  705. <div id="buttons-bar" style="float: right;">
  706. <div class="checkbox-div" title="Show command line">
  707. <label>
  708. <input type="checkbox" onchange="ts_host._on_show_arguments_choice(this)"/>
  709. Command line
  710. </label>
  711. </div>
  712. <div class="checkbox-div" title="Show line-numbers">
  713. <label>
  714. <input type="checkbox"/>
  715. Line-numbers
  716. </label>
  717. </div>
  718. <div class="checkbox-div" title="Wrap lines">
  719. <label>
  720. <input type="checkbox" onchange="ts_host._on_wrapping_choice(this)"/>
  721. Wrap lines
  722. </label>
  723. </div>
  724. </div>
  725. </div>
  726. <div id="info-area">
  727. <div id="commandline-display" style="display: none">
  728. <p style="margin-top: 0;">
  729. <label for="process-command-line" title="ts_host.raw_commandline">
  730. Process command line:
  731. </label><br>
  732. <span id="process-command-line" class="command-line"></span>
  733. </p>
  734. <p>
  735. <label for="script-command-line" title="ts_host.commandline">
  736. Script command line (part of the above):
  737. </label>
  738. <span id="no-script-info" style="font-style: italic">Not specified</span><br>
  739. <span id="script-command-line" class="command-line"></span>
  740. </p>
  741. <div id="arguments-display" title="ts_host.command_arguments">
  742. <span id="argument-list-count">n arguments</span>:
  743. <ol id="argument-list" start="0">
  744. </ol>
  745. </div>
  746. </div>
  747. <div id="text-stream-display">
  748. <!-- p>
  749. Blah blah this is the text stream display area.</p -->
  750. <div>
  751. </div>
  752. </body>
  753. </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement