22

I have a javascript variable called "list". I need to send it as a POST data to another page and open that page in a new tab (with the POST data present).

This code:

jQuery.post('datadestination.php', list);

sends the data all right, but ofcourse it opens the page in the same tab.

I saw some solutions to similar problems using invisible form and things like that, but I could not get them to work. Is there any simple solution?

zorza
  • 2,814
  • 3
  • 27
  • 41
  • 1
    The solution described in http://stackoverflow.com/questions/7024040/jquery-open-page-in-a-tab-and-pass-some-post-values appears to work. Have you any specific problems with that? What happens? – LSerni Jul 23 '14 at 11:03
  • 1
    You can also call a javascript function that dynamically creates a form with a `target='_blank'` attribute: http://stackoverflow.com/questions/7013109/submit-is-not-a-function-error-in-firefox-in-dynamically-created-form-without – Stefan Jul 23 '14 at 11:06

3 Answers3

24

You can send a form using the target="_blank" attribute.

<form action="datadestination.php" method="POST" target="_blank" id="myform">
  <input type="hidden" name="list" id="list-data"/>
  <input type="submit" value="Submit">
</form>

Then in JS:

jQuery('#list-data').val(list);
jQuery('#myform').submit();
Mark Lowe
  • 1,056
  • 8
  • 16
18

This is an implementation of Sergey's solution.

<?php // this is save.php
    session_start();
    // DO NOT just copy from _POST to _SESSION,
    // as it could allow a malicious user to override security.
    // Use a disposable variable key, such as "data" here.
    // So even if someone passed _POST[isAdmin]=true, all that he would do
    // is populate _SESSION[data][isAuthenticated], which nobody reads,
    // not the all-important _SESSION[isAuthenticated] key.
    if (array_key_exists('data', $_POST)) {
        $_SESSION['data']             = $_POST['data'];
        $_SESSION['data.timestamp']   = time();
        // Let us let the client know what happened
        $msg = 'OK';
    } else {
        $msg = 'No data was supplied';
    }
    Header('Content-Type: application/json; charset=utf8');
    die(json_encode(array('status' => $msg)));
?>

In the first page:

$.post('save.php', { data: list }, function(response){
    if (!response.status) {
        alert("Error calling save");
        return;
    }
    if (response.status !== 'OK') {
        alert(response.status);
        return;
    }
    // We had a response and it was "OK". We're good.
    window.open('datadestination.php');
});

And in datadestination.php add the fix:

if (!array_key_exists('data', $_SESSION)) {
   die("Problems? Did you perchance attempt to reload the page and resubmit?"); 
   // For if he did, then yes, $_SESSION would have been cleared.

   // Same if he is operating on more than one window or browser tab.
}
// Do something to validate data. For example we can use data.timestamp
// to assure data isn't stale.
$age = time();
if (array_key_exists($ts = 'data.timestamp', $_SESSION)) {
    $age -= $_SESSION[$ts];
}
if ($age > 3600) {
    die("Data is more than one hour old. Did someone change server time?!?");
    // I actually had ${PFY} do that to me using NTP + --hctosys, once.
    // My own time zone is (most of the year) exactly one hour past GMT.
}

// This is safe (we move unsecurity-ward):
$_POST = $_SESSION['data'];
unset($_SESSION['data'], $_SESSION['data.timestamp']);
// keep things clean.

// From here on, the script behaves "as if" it got a _POST.

Update

You can actually merge save.php and datadestination.php and use a "saving stub" savepost.php that you can recycle in other pages:

<?php
    session_start();

    // DO NOT just copy from _POST to _SESSION,
    // as it could allow a malicious user to override security.
    // Use a disposable variable key, such as "data" here.
    if (array_key_exists('data', $_POST)) {
        // Timestamp sent by AJAX
        if (array_key_exists('ts', $_POST)) {
            // TODO: verify ts, but beware of time zones!
            $_SESSION['data'] = $_POST['data'];
            Header("Content-Type: application/json;charset=UTF-8");
            die(json_encode(array('status' => 'OK')));
        }
        die("Error");
    }
    // This is safe (we move unsecurity-ward):
    $_POST = $_SESSION['data'];
    unset($_SESSION['data']); // keep things clean.
?>

Now your call becomes

$.post('datadestination.php', { data: list, ts: Date.now() }, function(){
    window.open('datadestination.php');
});

and in your datadestination.php (or anywhere else) you add

require 'savepost.php';
LSerni
  • 55,617
  • 10
  • 65
  • 107
  • Kudos! I'd write it myself, but it's good for others who run into the same problem to see the working solution. – zorza Jul 23 '14 at 11:17
  • 1
    Och, I had somehow forgotten you wanted it to open in a *new* tab. Fixed. – LSerni Jul 23 '14 at 11:24
17

I suggest:

  1. Pass that list with the jquery.post() function and save it in the SESSION array.
  2. Open a new tab with the same file/address/URL with the window.open() function.
  3. Retrieve saved data from the SESSION array.

This seems straightforward and clean to me.

James Risner
  • 5,451
  • 11
  • 25
  • 47