<?php
/**
 * pdfgen.php - Generates PDF based on input URL
 *
 * @author $Author: dtong $
 * @version $Id: pdfgen.php,v 1.33 2011/04/27 05:46:27 dtong Exp $
 * @copyright Copyright (c) 2009, Tiller Software Co., Ltd.
*/

class Pdfgen extends CI_Controller{
	private $tmppdf_filepart = 'pdfgen_';
	private $pdf_fileextension = '.pdf';
	private $pdf_output_buffer = NULL;

	function __construct() {
		parent::__construct();
		//Just to make sure user has the basic access
		$this->access_model->checkaccess_any('homepage_access');
	}

	function index($url, $dummy_pdfname='', $download_filename=FALSE) {
		$phpsessionid = osa_save_ci_sess_cookie();
		$url = str_replace('PHPSESSIONID', $phpsessionid, $url);
		//Not using access key any more, too insecure...
		//$url = str_replace('ACCESSKEY', osa_pdfkey(), $url);
		$this->load->view('pdf/pdf_ajax_view', array('url'=>$url, 'dummy_pdfname'=>$dummy_pdfname));
	}

	//Dummy pdfname is needed so the user would save a short file name
	function create($url, $pre_process=FALSE, $dummy_pdfname='', $download_filename=FALSE) {
		$tmpfolder = $this->config->item('cms_pdf_tmp_dir');
		//$tmpfile = $tmpfolder . $this->session->userdata('session_id') . '.pdf';
		$user = $this->login_model->getLogin();
		$userid = '';
		if ( !empty($user) && is_object($user) && property_exists($user, 'id') ) {
			$userid = $user->id;
		}
		else {
			osa_errorlog(__METHOD__ . " - No user session. Failed to create PDF file $cmd.");
			echo lang('gen_internalservererror');
			exit;
		}
		//This should be safe even if we have multiple people using the same account
		//$pdf_file_noext has to be alphanumeric plus the '_' char else the $this->read() function will fail.
		$pdf_file_noext = "{$this->tmppdf_filepart}{$userid}_" . time() . rand(1000000,99999999);
		//Add .pdf extension here to prevent hacking
		$tmpfile = $tmpfolder . $pdf_file_noext . $this->pdf_fileextension;
		if ( osa_mkdir($tmpfolder) !== TRUE ) {
			osa_errorlog(__METHOD__ . " - Failed to create PDF tmp folder $tmpfolder.");
			echo lang(gen_internalservererror);
			exit;
		}
		//Use _ instead of / in the input url
		$url = str_replace('_','/',$url); //For first url
		$url = str_replace('-','_',$url); //For second url
		//make sure we have a PHP session
		if ( !$pre_process ) {
			$phpsessionid = osa_save_ci_sess_cookie();
			$url = str_replace('PHPSESSIONID', $phpsessionid, $url);
		}
		$fullurl = base_url() . $url;
		//$fullurl = "http://$url";
		$config_header_footer = $this->create_header_footer($pdf_file_noext);
		$pdf_options = ' ' . $this->config->item('cms_pdf_exe_options') .' '. $config_header_footer;
		$extra_options = $this->config->item('cms_pdf_exe_options_extra');
		if ( !empty($extra_options)) {
			$pdf_options .= ' ' . $extra_options;
		}
		$cmd = $this->config->item('cms_pdf_exe') . $pdf_options . " $fullurl $tmpfile";
		osa_set_pdf_timeout();
		//Necessary to write session data and make it available to other processes
		session_write_close();
		if ( $this->config->item('cms_pdf_external_url') ) {
			$this->_external_pdf("$pdf_options $fullurl", $tmpfile);
		}
		else {
			@exec($cmd);
		}
		if ( !empty($pre_process) ) {
			//This returns the tmp pdf filename so the javascript can redirect to the newly created pdf file
			header('Cache-Control: must-revalidate');
			if ( is_file($tmpfile) ) {
				echo $pdf_file_noext;
				exit;
			}
			echo 'failed';
			exit;
		}
		//Don't think we ever process the code below.
		if ( !is_file($tmpfile) ) {
			osa_errorlog(__METHOD__ . " - Failed to create PDF file $cmd.");
			echo lang('gen_internalservererror');
			exit;
		}
		//If not pre_process then print the whole PDF document
		//Don't think this is used yet but keep it anyway.
		$this->read($pdf_file_noext);
	}

	//Reads PDF file generated by the system
	//This function/URL does not check session so make sure it is robust and no security hole.
	function read($file_noext, $dummy_pdfname='') {
		$file_noext = trim($file_noext);
		$valid_filename = TRUE;
		//CodeIgnitor disallows most characters but check it like we allow everything here.
		if ( empty($file_noext) || stripos($file_noext, $this->tmppdf_filepart) !== 0 ) {
			$valid_filename = FALSE;
		}
		/* elseif ( function_exists('ctype_alnum1') ) {
				//Make sure we only have alphnumeric characters
				$tmp = str_replace('_', '', $file_noext);
				$valid_filename = ctype_alnum($tmp);
			}
		} */
		elseif ( preg_match('/^[A-Za-z0-9\_]+$/', $file_noext) == 0 ) {
			// non-alphanumeric so exit
			$valid_filename = FALSE;
		}

		if ( !$valid_filename )  {
			osa_errorlog(__METHOD__ . " - Invalid pdf input file {$file_noext}.");
			echo lang('gen_internalservererror');
			exit;
		}

		if ( empty($this->pdf_output_buffer) ) {
			$tmpfolder = $this->config->item('cms_pdf_tmp_dir');
			//Add .pdf extension here to prevent hacking
			$tmpfile = $tmpfolder . $file_noext . $this->pdf_fileextension;
			if ( !is_file($tmpfile) ) {
				osa_errorlog(__METHOD__ . " - Failed to retrieve PDF file $tmpfile.");
				echo lang('gen_internalservererror');
				exit;
			}
		}
		header('Content-type: application/pdf');
		//This will cause the browser to do a download
		if ( !empty($download_filename) )
			header('Content-Disposition: attachment; filename="'. $download_filename .'"');
    	header('Cache-Control: must-revalidate');
    	if ( empty($this->pdf_output_buffer) ) {
			readfile($tmpfile);
			@ob_flush();
			@flush();
		   @unlink($tmpfile);
    	}
    	else {
    		echo $this->pdf_output_buffer;
    		@ob_flush();
			@flush();
    	}

	   $htmlfolder = $this->config->item('cms_header_footer_create_folder');
	   $tmpheader_file = $htmlfolder .$this->config->item('cms_header_filename').'_'. $file_noext . '.html';
		$tmpfooter_file = $htmlfolder .$this->config->item('cms_footer_filename').'_'. $file_noext . '.html';
		if ( is_file($tmpheader_file) ) {
			@unlink($tmpheader_file);
		}
		if ( is_file($tmpfooter_file) ) {
			@unlink($tmpfooter_file);
		}
		exit;
	}

	private function create_header_footer($pdf_file_noext) {
 		$tmpfolder = $this->config->item('cms_header_footer_create_folder');

 		if ($tmpfolder == FALSE)
 		 	 return '';

		$header = $this->header($this->config->item('cms_pdf_header_image'), TRUE);
		$footer = $this->footer($this->config->item('cms_pdf_footer_image'), time(), TRUE);

		$header_file = $tmpfolder .$this->config->item('cms_header_filename').'_'.$pdf_file_noext . '.html';
		$footer_file = $tmpfolder .$this->config->item('cms_footer_filename').'_'.$pdf_file_noext . '.html';

		if ( $this->config->item('cms_pdf_header') !== FALSE ) {
			if ( !empty($header) ) {
				$objFopen  = fopen($header_file, 'w');
				fwrite($objFopen, $header);
				fclose($objFopen);
			}
		}

		if ( $this->config->item('cms_pdf_footer') !== FALSE ) {
			if ( !empty($footer) ) {
				$objFopen  = fopen($footer_file, 'w');
				fwrite($objFopen, $footer);
				fclose($objFopen);
			}
		}

		$result = '';
		if ( is_file($header_file) )
			  $result .= ' '.$this->config->item('cms_pdf_header') . base_url() . $header_file;

		if ( is_file($footer_file) )
			  $result .= ' '.$this->config->item('cms_pdf_footer') . base_url() . $footer_file;

 		return $result;//$this->config->item('cms_pdf_header') . $header_file . ' '. $this->config->item('cms_pdf_footer') . $footer_file;
	}

	private function header($img, $return=FALSE) {
		$data = new stdClass();
		$data->classname = 'header_pdf';
		$data->extra_div = FALSE;
		$data->image_url = FALSE;
		if ( $img ) { // if header config is disabled, should not show image tag in view
			$data->image_url = osa_image_toppath() . $img;
		}

		if ( $return ) {
 			 return $this->load->view('pdf/headerfooter_view', $data, $return);
		}
 		else {
			 $this->load->view('pdf/headerfooter_view', $data);
 		}
		/*
 		$url_img = osa_image_toppath() .$img;
		$data->body = '<div class="header_pdf">';
 		if ($img != FALSE){
 			$data->body .= '<img src='.$url_img.'>';
 		}
 		$data->body .= '</div>';
 		if ($return)
 			 return $this->load->view('pdf/url_view', $data, $return);
 		else
			 $this->load->view('pdf/url_view', $data);
		*/
	}

 	private function footer($img, $time=FALSE, $return=FALSE) {
 		$date = date('j F Y, H:i:s', $time);
 		$today = lang('gen_pdf_generated').' '.$date;
 		$data = new stdClass();
 		$data->classname = 'footer_pdf';
 		$data->image_url = FALSE;
		$data->extra_div = TRUE;
 		$data->extra_classname = 'footer_generated';
 		$data->extra_text = $today;
 		if ( $img ) { // if footer config is disabled, should not show image tag in view
			$data->image_url = osa_image_toppath() . $img;
		}

 		if ( $return ) {
 			 return $this->load->view('pdf/headerfooter_view', $data, TRUE);
		}
 		else {
			 $this->load->view('pdf/headerfooter_view', $data);
 		}
 		/*
 		$url_img = osa_image_toppath() . $img;
 		$date = date('j F Y, H:i:s',$time );
 		$today = lang('pdf_generated').' '.$date;
 		$data->body = '<br /><div class="footer_generated">'.$today.'</div>';
 		$data->body .= '<div class="footer_pdf">';
 		if ($img != FALSE){
 			$data->body .= '<img src='.$url_img.'>';
 		}
 		$data->body .= '</div>';
 		if ($return)
 			 return $this->load->view('pdf/url_view', $data, $return);
 		else
			 $this->load->view('pdf/url_view', $data);
		*/
 	}

 	private function _external_pdf($pdf_params, $tmpfile=FALSE) {
 		$pdf_url = $this->config->item('cms_pdf_external_url');
 		if ( is_array($pdf_url) ) {
 			//Poor man's load balancing
 			$count = count($pdf_url);
 			if ( $count > 1 ) {
 				$index = mt_rand(0, $count-1);
 			}
 			else {
 				$index = 0;
 			}
 			$pdf_url = $pdf_url[$index];
 		}
 		$url = $pdf_url . '?url=' . urlencode($pdf_params) . '&code=' . osa_pdfkey();
		$ret = @osa_get_url_content($url);
		if ( $ret == 'failed' || strlen($ret) < 5000 ) {
			echo 'failed';
			exit;
		}
		else {
			if ( $tmpfile ) {
				file_put_contents($tmpfile, $ret);
			}
			else {
				//We can't use this becuase the read operation belongs to a different request.
				//So, $tmpfile is always present.
				$this->pdf_output_buffer = & $ret;
			}
		}
 	}

}
?>