I have a WP plugin that sends a link to an email to download a file in hidden location. User selects a file, then a token containing the file ID etc. is written to a database, and a link is sent. Upon clicking the link (ex. mysite.com/thank-you/?id=asd687asd68as7d6a8sdd7sd768as7d6, the "thank you" page makes a request to a php function to donload the file.
There's also a dummy "download engine" page with a shortcode [download_page] that initiates the download.
Weird thing is that while this setup works just fine at test environment, and has worked for over a year at production site, it suddenly stopped working: call for DownloadFile() returns 0KB and correct headers at test site, and initiates the download, but returns full HTML file and, of course, no download.
I cannot spot any changes in configuration (both sites run WP 4.2.7). Only difference seems to be the WooCommerce plugin, and Google Analytics snippet included in production site.And that test site runs PHP 5.3 while productiopn site runs 5.6.
I'd be very grateful if somebody had an insight of what's happening.. Why are headers ignored? (There's no "Headers already sent" error.) Why is full HTML of the dummy "download engine" page displayed?
BTW it's an out-of-the-box theme, but I cannot spot no faults in it. But still, maybe.. Where I'm to look for a culprit lines? What could force a page to show full HTML instead of headers sent by php?
Relevant code is such: (download manager.php):
<?php
/*
Plugin Name: Hidden Download Manager
Description: Bla bla
*/
include_once('add_meta_boxes.php');
include_once('mfdm_frontend_functions.php');
add_action( 'init', 'program_register' );
add_shortcode( 'download_page', 'downloadFile' );
?>
(thank_you.tpl.php)
<?php
/**
Template Name: Thank You
*/
$HOST = get_option('mfdm_dbhost');
$USER = get_option('mfdm_dbuser');
$PWORD = get_option('mfdm_dbpwd');
$DB = get_option('mfdm_dbname');
$connect_db = mysqli_connect($HOST,$USER,$PWORD,$DB) or die("Some error occurred during connection " . mysqli_error($connect_db));
if(get_magic_quotes_gpc()) {
$id = stripslashes($_GET['id']);
} else {
$id = $_GET['id'];
}
$result = $connect_db->query("SELECT * FROM 3_downloadkey WHERE uniqueid = '$id'");
$row = resultToArray($result);
$redirect = '';
if (!$row) {
// redirect to 'invalid' page
$redirect = get_option('mfdm_link_invalid_page');
wp_redirect($redirect);
exit;
}
get_header();
$plugindir = plugin_dir_url(0).'mouseful_download/';
// embed the javascript file that makes the AJAX request
wp_enqueue_script( 'processLink_request', $plugindir . 'mf_downloads.js', array( 'jquery' ) );
// declare the URL to the file that handles the AJAX request (wp-admin/admin-ajax.php)
wp_localize_script('processLink_request', 'ProcessLink', array(
'ajaxurl' => admin_url('admin-ajax.php'),
'postCommentNonce' => wp_create_nonce( 'ProcessLink-post-comment-nonce' ),
'downloadHiddenPage' => get_option('mfdm_download_hidden_page')
)
);
?>
<link rel="stylesheet" type="text/css" media="all" href="<?=$plugindir;?>mf_downloads.css">
<body onLoad="setTimeout('downloadLink()', 1000)"></body>
<div class="contents about">
<div class="row">
<div class="col banner">
<p><?php the_title(); ?></p>
</div>
</div>
<div class="row2"><div class="col">
<?php
while ( have_posts() ) : the_post();
the_content();
endwhile;
?>
</div></div></div>
<?php
get_footer();
?>
(mfdm_frontend_functions.php):
<?php
add_action( 'wp_ajax_nopriv_downloadLink-submit', 'downloadFile' );
add_action( 'wp_ajax_downloadLink-submit', 'downloadFile' );
function downloadFile() {
$HOST = get_option('mfdm_dbhost');
$USER = get_option('mfdm_dbuser');
$PWORD = get_option('mfdm_dbpwd');
$DB = get_option('mfdm_dbname');
$id = $_POST['app'];
$connect_db = mysqli_connect($HOST,$USER,$PWORD,$DB);
$result = $connect_db->query("SELECT * FROM 3_downloadkey WHERE uniqueid = '$id'");
$row = resultToArray($result);
$app_ID = $row[0]['app_ID'];
ob_start();
// get app name
$base_dir = get_option('mfdm_applications_folder');
define('BASE_DIR',$base_dir);
$fname = get_post_meta($app_ID, 'meta_source', true);
$app_download_name = get_post_meta($app_ID, 'meta_program_name', true);
$file_path = '';
$file_path = find_file1(BASE_DIR, $fname, $file_path);
if (!is_file($file_path)) {
die("File does not exist. Make sure you specified correct file name.");
}
$fsize = filesize($file_path);
$fext = strtolower(substr(strrchr($fname,"."),1));
$mime_types = array(
'msi' => 'application/x-ole-storage',
'zip' => 'application/zip',
'exe' => 'application/x-msdownload',
'sh' => 'application/x-sh',
'iso' => 'application/octet-stream',
'dmg' => 'application/octet-stream',
'pdf' => 'application/pdf',
);
$mm_type = $mime_types[$fext];
if ($fd = fopen ($file_path, "r")) {
$fsize = filesize($file_path);
$path_parts = pathinfo($file_path);
$ext = strtolower($path_parts["extension"]);
header("Content-type: $mm_type");
header("Content-Disposition: attachment; filename=\"".$app_download_name."\"");
header("Content-length: $fsize");
header("Cache-control: private"); //use this to open files directly
while(ob_POST_level() > 0) {
@ob_end_clean();
}
while(!feof($fd)) {
$buffer = fread($fd, 2048);
echo $buffer;
}
}
fclose ($fd);
}
?>
(mf_downloads.js):
function downloadLink() {
var id = window.location.search.replace("?", "").split("&")[0];
id = id.split("=")[1];
var url = ProcessLink.downloadHiddenPage;
var form = jQuery('<form action="' + url + '" method="post">' + '<input type="text" name="app" value="' + id + '" hidden="hidden"/>' + '</form>');
jQuery('body').append(form);
form.submit();
}