What’s keeping my php session from saving data added within a wordpress plugin?

I’ve written a wordpress plugin that allows pages of the wordpress site to host data from a separate php/MySQL app on the server.

One function of the plugin is to give the website visitor a token in their session that allows them to download a file from the other app.

Read More

AFAIK, this has been functioning properly for several years. But after a recent server upgrade (which included PHP 5.4.43) several session-related bugs popped up. I solved those issues by introducing a custom save_path which is being used via php.ini in the custom app, and set manually in my wordpress plugin.

Here’s the operative code from the plugin initialization:

function myStartSession() {
  if(!session_id()) {
    session_save_path("/my/custom/save/path");
    session_start();
  }
}
add_shortcode( 'mypluginname', 'print_gadget' );
add_action('init', 'myStartSession', 1);

Here’s the operative code from when the plugin is triggered by a shortcode:

//make a call to the external app
$request = new RestRequest($apis['Playlist'], 'POST',$requestArgs);
$request->execute();
$data = json_decode($request->getResponseBody(),true);

//set the token in the session
$_SESSION['gueststamp'] = time();
//extract valid mediaIDs
$playlist = $data['Results'];
$validIDs = array();
foreach($playlist['Items'] as $row){
    $validIDs[] = $row['ID'];
}
$_SESSION['guestvalidIDs'] = $validIDs;

//print out playlist template into buffered output
ob_start();
//DEBUG: print out session variable
print "<!--";
print_r($_SESSION);
print "-->" //END DEBUG
include 'playlistgadget.php'; //renders output text
$contents = ob_get_contents();
ob_end_clean();

//return the buffer
return $contents;

Note the debug code. When a user visits the wordpress page with this plugin’s shortcode, everything seems to work fine, and the page source includes the token in the HTML comment that I added for debugging purposes.

Next, the visitor can click on a button which links to download.php from the external app (on the same domain). Download.php checks for a valid token in the session and delivers a file if the token is found. The bug is that download.php executes the following codepath even though the user should have a valid token in their session:

//note: download.php actually references several utility functions, but I've simplified it to show only the codepath that is actually getting executed
session_start();
$mediaID = $_REQUEST['mediaID'];
if($mediaID == "" || !is_numeric($mediaID)){
    print "invalid media ID";
    die;
}

if(!isset($_SESSION['gueststamp']) || (time() - $_SESSION['gueststamp'] > 36000)){
    print "no such media found.";
    print session_id(); //debug
    print_r($_SESSION); //debug
    die;
}

When I run the download page, the session_id matches the ID from the wordpress page with the plugin, but the $_SESSION variable is empty.

I’ve tried a bunch of things, and I’m pretty stumped. Any ideas?

Related posts

1 comment

  1. OK- I finally figured it out.
    In the original post, I mentioned some weird session bugs I fixed last month by changing the session.save_path. I used php.ini files to do that, and in order to get something that seemed to work, I updated php.ini in the public root directory, and in the root directory of the app.

    For mysterious reasons, PHP was unhappy with having multiple nested php.ini files. Additionally, the shared hosting I’m using seems to really dislike using any folder other than the default /tmp for sessions. I’m guessing this latter bit is a permissioning issue due to shared hosting.

    As best I can tell the problem chain was:

    1. Hosting company had messed up the root php config (they stopped including php libraries that had previously been included)
    2. I put patched php.ini files in place while the host’s config was broken, this messed up sessions
    3. To fix the session issue, I added a session.save_path config to my custom php.ini files
    4. Despite my best understanding, some php scripts on the server were pulling session.save_path values from my php.ini config files, and others were pulling from the root config.
    5. For some further reason I don’t understand, phpinfo() did not indicate that any scripts were referencing the root config.

    At one point, I managed to get all of the scripts reading from my shiny new session.save_path only to discover that new path was not saving ANY session data (probably due to permissions issues).

    Fortunately, my hosting company has since fixed the original problem with their config files. My fix was to remove ALL of the custom php.ini files so that all scripts are once again reading only the root config and using the same session.save_path

Comments are closed.