<?php

/* Downloads attached file with or without compress option
 *
 * input:
 *    $_GET['file_id'] or $_POST['file_id']
 *
 * 1. Temporary file in the download procedure will be made in /tmp.
 * 2. Temporary file will be removed after script shutdown.
 */

// local functions
function downloadError($code, $msg = '') {
	switch ($code) {
		case 403:
			header('HTTP/1.0 403 Forbidden');
			echo 'HTTP/1.0 403 Forbidden';
			break;
		case 404:
			header('HTTP/1.0 404 Not Found');
			echo 'HTTP/1.0 404 Not Found';
			break;
		case 500:
			header('HTTP/1.0 500 Internal Server Error');
			echo $msg;
			break;
	}
	exit();
}

// create zip file
function downloadCreateZipfile($xoonipsFile, $dirname, $file_id, $item_id, $file_name, $metadata) {
	$file_path = $xoonipsFile->getFilePath('item', $file_id);
	if (!file_exists($file_path)) {
		// file not found
		return false;
	}
	// get metafile
	$metadata .= _MD_XOONIPS_ITEM_DETAIL_URL . ': ' . XOOPS_URL . '/modules/' . $dirname . '/detail.php?item_id=' . $item_id . "\r\n";
	$metafile_body = Xoonips_Utils::encodeUtf8($metadata);
	// open zipfile
	$zipfile_path = tempnam('/temp', 'XooNIpsDownloadZipFile');
	$zipfile_fp = fopen($zipfile_path, 'w');
	if ($zipfile_fp === false) {
		// failed to create temporary file for zip
		return false;
	}
	register_shutdown_function('downloadUnlink', $zipfile_path);
	$zip = new zipfile();
	$file_fp = fopen($file_path, 'r');
	$zip->addFile(fread($file_fp, filesize($file_path)), $file_name);
	$zip->addFile($metafile_body, 'metainfo.txt');
	fwrite($zipfile_fp, $zip->file());
	// close fp
	fclose($zipfile_fp);
	return $zipfile_path;
}

function downloadUnlink($file_path) {
	@unlink($file_path);
}

// - main routine
// avoid IE bug1 -> http://jp2.php.net/header  Harry 10-Dec-2004 03:26
session_cache_limiter('none');

require_once 'include/common.inc.php';
require_once XOOPS_TRUST_PATH . '/libs/xoonips/class/core/File.class.php';
require_once XOOPS_TRUST_PATH . '/libs/xoonips/class/core/BeanFactory.class.php';
require_once 'class/core/Item.class.php';
require_once 'class/core/Notification.class.php';
require_once XOOPS_TRUST_PATH . '/libs/xoonips/class/core/Request.class.php';
require_once XOOPS_TRUST_PATH . '/libs/xoonips/class/core/Utils.class.php';
require_once XOOPS_ROOT_PATH . '/class/class.zipfile.php';
require_once XOOPS_ROOT_PATH . '/class/token.php';

$uid = is_object($xoopsUser) ? $xoopsUser->getVar('uid') : XOONIPS_UID_GUEST;

// get parameters
$request = new Xoonips_Request();
$file_id = $request->getParameter('file_id');
if (is_null($file_id)) {
	downloadError(404);
}

// get file object
$dirname = Xoonips_Utils::getDirname();
$trustDirname = Xoonips_Utils::getTrustDirname();
$fileBean = Xoonips_BeanFactory::getBean('ItemFileBean', $dirname, $trustDirname);
$fileInfo = $fileBean->getFile($file_id);
if ($fileInfo === false || count($fileInfo) == 0) {
	downloadError(404);
}
$item_id = $fileInfo['item_id'];

// get item type id
$itemBean = Xoonips_BeanFactory::getBean('ItemBean', $dirname, $trustDirname);
$itemInfo = $itemBean->getItemBasicInfo($item_id);
$item_type_id = $itemInfo['item_type_id'];

// set page urls
$detail_url = XOOPS_URL . '/modules/' . $dirname . '/detail.php?item_id=' . $item_id;

// get item type name
$itemtypeBean = Xoonips_BeanFactory::getBean('ItemTypeBean', $dirname, $trustDirname);
$itemtypeName = $itemtypeBean->getItemTypeName($item_type_id);

// check the download limitation
$itemBean = Xoonips_BeanFactory::getBean('ItemVirtualBean', $dirname, $trustDirname);
$limit = $itemBean->getDownloadLimit($item_id, $item_type_id);
// only registered user can download file
if ($limit === false && $uid == XOONIPS_UID_GUEST) {
	// if user is guest than redirect to login page
	$parsed = parse_url(XOOPS_URL);
	$xoops_path = isset($parsed['path']) ? $parsed['path'] : '';
	$xoops_redirect = str_replace(XOOPS_URL, $xoops_path, $detail_url);
	header('Location:' . XOOPS_URL . '/user.php?xoops_redirect=' . urlencode($xoops_redirect));
	exit();
}

$notify = $itemBean->getDownloadNotify($item_id, $item_type_id);
$rights = $itemBean->getRights($item_id, $item_type_id);
if ($rights !== false || ($notify !== false && $notify == '1')) {
	if (!XoopsMultiTokenHandler::quickValidate($dirname . '_download_token' . $file_id)) {
		if (isset($_REQUEST['XOOPS_TIKET'])) {
			// bad token ticket, maybe this ticket already used
			redirect_header($detail_url, 5, _MD_XOONIPS_ITEM_ATTACHMENT_BAD_TOKEN_LABEL);
		} else {
			// no token ticket pair found
			header('Location:' . $detail_url);
		}
		exit();
	}
}

// get download mode : file only or zip in metadata.txt
$configBean = Xoonips_BeanFactory::getBean('ConfigBean', $dirname, $trustDirname);
$download_file_compression = $configBean->getConfig('download_file_compression');
if (is_null($download_file_compression)) {
	downloadError(500, _MD_XOONIPS_DOWNLOAD_ABNORMAL_CONFIGURATION);
}
$do_compress = $download_file_compression == 'on';

$filename = Xoonips_Utils::convertToClient($fileInfo['original_file_name']);
$zip_filename = $itemtypeName . '_' . $file_id . '.zip';
$xoonipsFile = new Xoonips_File($dirname, $trustDirname);
if ($do_compress) {
	// get metadata of attachment file
	$item = new Xoonips_Item($item_type_id, $dirname, $trustDirname);
	$metadata = $item->getMetaInfo($item_id);
	// create zip file
	$dl_filepath = downloadCreateZipfile($xoonipsFile, $dirname, $file_id, $item_id, $filename, $metadata);
	if ($dl_filepath === false) {
		downloadError(500, _MD_XOONIPS_ITEM_CANNOT_CREATE_TMPFILE);
	}
	$dl_filename = Xoonips_Utils::convertToClient($zip_filename);
	$dl_mimetype = 'application/x-zip';
} else {
	$dl_filepath = $xoonipsFile->getFilePath('item', $file_id);
	$dl_filename = $filename;
	$dl_mimetype = $fileInfo['mime_type'];
}

// record download file event log.
$eventLogBean = Xoonips_BeanFactory::getBean('EventLogBean', $dirname, $trustDirname);
$eventLogBean->recordDownloadFileEvent($item_id, $file_id);

$dl_filename = Xoonips_Utils::convertFilename($dl_filename);
$xoonipsFile->downloadFile($dl_filepath, $dl_filename, $dl_mimetype);

// download count
$fileBean->updateDownloadCount($file_id);

// check the download notification
if ($notify == '1') {
	global $xoopsDB;
	$notification = new Xoonips_Notification($xoopsDB, $dirname, $trustDirname);
	$notification->userFileDownloaded($file_id, $uid);
}
exit();
?>
