5

Using Ajax, I've created a sort of console that allows me to execute some PHP functions dynamically.

It looks like this screenshot

The problem is that after a bunch of commands, the console becomes hard to read. So I've created a javascript function, named "wipe();", which clears the <div> containing the console.

I tested this function with the developpers tools of chrome (the javascript console) and it works perfectly.

But when I try to call this function by making the PHP-AJAX return a "<script>wipe();</script>", it doesn't work. It does nothing.

I've read on the internet that all the "<script></script>" works independently from each other, but that you can call a <script>function</script> from another <script></script> block.

So why is it failing to do that ?

here is the php code :

    echo '<script>wipe();</script>';

and here is the the first <script> block:

        var xmlhttp = new XMLHttpRequest();
        var span = document.getElementById("screen");

     function send(data) {
        window.setInterval(function() {
        var elem = document.getElementById('screen');
           xmlhttp = new XMLHttpRequest();
           xmlhttp.open("GET", "./_rcons-transmetter.php?data="+data, true)
           xmlhttp.onloadend = function() {
             span.innerHTML = span.innerHTML+escapeHtml(data)+'<br>'+xmlhttp.responseText+'<br><br>';
           }
           xmlhttp.send();
         }

    function wipe(){
             span.innerHTML = '';
        }
Mr Lister
  • 45,515
  • 15
  • 108
  • 150
Rackover
  • 91
  • 1
  • 15

5 Answers5

2

To avoid security issues ( like a cross-site scripting attack) HTML5 specifies that a <script> tag inserted via innerHTML should not execute.

A way to execute the script is to evaluate the html using eval() . Be warned: using eval can be dangerous.

var xmlhttp = new XMLHttpRequest();
var span = document.getElementById("screen");

function send(data) {
  window.setInterval(function() {
      var elem = document.getElementById('screen');
      xmlhttp = new XMLHttpRequest();
      xmlhttp.open("GET", "./_rcons-transmetter.php?data=" + data, true)
      xmlhttp.onloadend = function() {
        span.innerHTML = span.innerHTML + escapeHtml(data) + '<br>' + xmlhttp.responseText + '<br><br>';
        evalJSFromHtml(span.innerHTML);
      }
      xmlhttp.send();
    }

    function wipe() {
      span.innerHTML = '';
    }

    function evalJSFromHtml(html) {
      var newElement = document.createElement('div');
      newElement.innerHTML = html;

      var scripts = newElement.getElementsByTagName("script");
      for (var i = 0; i < scripts.length; ++i) {
        var script = scripts[i];
        eval(script.innerHTML);
      }
    }

  }
Mr Lister
  • 45,515
  • 15
  • 108
  • 150
Vladu Ionut
  • 8,075
  • 1
  • 19
  • 30
  • In case is not used properly it can generate security issues (ex: xss ) . There are a lot of threads regarding this ( http://stackoverflow.com/questions/197769/when-is-javascripts-eval-not-evil ) – Vladu Ionut Sep 21 '16 at 09:17
  • I'm very surprised this answer is accepted - evalJSFromHtml has no access to `wipe` function within the send function! – Jaromanda X Sep 21 '16 at 10:00
  • @JaromandaX - I believe "eval" function only don't have access to the global function if it's in strict mode. Since he's not in strict mode it should be fine. – Robert Parham Sep 30 '16 at 20:20
  • 1
    `eval` can be used inside strict functions and still have access to the global environment, one just has to use a weird syntax to do an *indirect eval* -- `(null, eval)("alert(1)")` – Jeremy J Starcher Sep 30 '16 at 20:26
0

Call the 'wipe' function as a callback function directly from the 'send' function. Check status = 200 for a success response.

var xmlhttp = new XMLHttpRequest();
    var span = document.getElementById("screen");

 function send(data) {
    window.setInterval(function() {
    var elem = document.getElementById('screen');
       xmlhttp = new XMLHttpRequest();
       xmlhttp.open("GET", "./_rcons-transmetter.php?data="+data, true)
       xmlhttp.onloadend = function() {
         span.innerHTML = span.innerHTML+escapeHtml(data)+'<br>'+xmlhttp.responseText+'<br><br>';
       }

    xmlhttp.onreadystatechange = function()
    {
     if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
      {
        wipe(); // 'Wipe' callback function
      }
    }
       xmlhttp.send();
     }


function wipe(){
         span.innerHTML = '';
    }
Nikz
  • 1,346
  • 1
  • 18
  • 24
0

But when I try to call this function by making the PHP-AJAX return a "wipe();", it doesn't work. It does nothing.

try create script tag and add to document rather than change inner html.

var spaScript = document.getElementById("spaScript");
var wraper = document.createElement("div");
wraper.innerHTML = xmlhttp.responseText;
var script = document.createElement("script");
script.innerHTML = wraper.getElementsByTagName("script")[0].innerHTML;
spaScript.appendChild(script);
alireza.salemian
  • 536
  • 5
  • 21
0

Test if wipe() is in the input and if it is trigger it instead of the ajax call

    var xmlhttp = new XMLHttpRequest();
    var span = document.getElementById("screen");

    function send(data) {
      if (data.indexOf('wipe()') == -1) {

        window.setInterval(function() {
            var elem = document.getElementById('screen');
            xmlhttp = new XMLHttpRequest();
            xmlhttp.open("GET", "./_rcons-transmetter.php?data=" + data, true)
            xmlhttp.onloadend = function() {
              span.innerHTML = span.innerHTML + escapeHtml(data) + '<br>' + xmlhttp.responseText + '<br><br>';
            }
            xmlhttp.send();
          }
        } else {
          wipe();
        };
      }

      function wipe() {
        span.innerHTML = '';
      }
madalinivascu
  • 32,064
  • 4
  • 39
  • 55
-1

inserting a script tag directly inside an element should not work (and by the way generating an error in the console).

Using the native eval() function on the response text without speciying the tag attribute should solve the problem.

on server side

echo 'wipe()';

on client side

eval(xmlhttp.responseText)
OBDM
  • 177
  • 3