428 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			PHP
		
	
	
	
			
		
		
	
	
			428 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			PHP
		
	
	
	
<?php
 | 
						|
/*
 | 
						|
$Id$
 | 
						|
 | 
						|
  This code is part of LDAP Account Manager (http://www.sourceforge.net/projects/lam)
 | 
						|
  Copyright (C) 2003 - 2006  Michael Duergner
 | 
						|
 | 
						|
  This program is free software; you can redistribute it and/or modify
 | 
						|
  it under the terms of the GNU General Public License as published by
 | 
						|
  the Free Software Foundation; either version 2 of the License, or
 | 
						|
  (at your option) any later version.
 | 
						|
 | 
						|
  This program is distributed in the hope that it will be useful,
 | 
						|
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
  GNU General Public License for more details.
 | 
						|
 | 
						|
  You should have received a copy of the GNU General Public License
 | 
						|
  along with this program; if not, write to the Free Software
 | 
						|
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
						|
*/
 | 
						|
 | 
						|
/**
 | 
						|
 * LDAP Account Manager PDF printing library. It consists of lamPDF class,
 | 
						|
 * the createModulePDF() function that may be called by other pages
 | 
						|
 * and furthermore some helper functions.
 | 
						|
 * 
 | 
						|
 * @author Michael Duergner
 | 
						|
 * @package PDF
 | 
						|
 */
 | 
						|
 | 
						|
/** PDF line width */
 | 
						|
define('LAMPDF_LINEWIDTH',190);
 | 
						|
 | 
						|
/** PDF generator class */
 | 
						|
include_once("fpdf.php");
 | 
						|
 | 
						|
/** Unicode support for FPDF */
 | 
						|
include_once("ufpdf.php");
 | 
						|
 | 
						|
/** XML functions */
 | 
						|
include_once('xml_parser.inc');
 | 
						|
 | 
						|
/** access to PDF configuration files */
 | 
						|
include_once('pdfstruct.inc');
 | 
						|
 | 
						|
$key = false;
 | 
						|
$line_width = LAMPDF_LINEWIDTH;
 | 
						|
 | 
						|
/**
 | 
						|
 * This function creates the PDF output of one or more accounts. At the moment
 | 
						|
 * this function can create a PDF page for user, group and host accounts. But
 | 
						|
 * this is not limited by the function itself but by the account types that are
 | 
						|
 * allowed in LAM and the exsisting PDF structure definitions. 
 | 
						|
 * 
 | 
						|
 * @param array $accounts A numbered array containing all accounts the PDF page should
 | 
						|
 * be created for. The entries of the array must be AccountContainer objects.
 | 
						|
 * @param string $pdf_structure The filename of the structure definition that should be used
 | 
						|
 * to create the PDF page. If not submitted the 'default.user' structure definition
 | 
						|
 * for the appropriate account type.
 | 
						|
 */
 | 
						|
function createModulePDF($accounts,$pdf_structure="default") {
 | 
						|
	
 | 
						|
	global $key;
 | 
						|
	
 | 
						|
	// Get account type from account container if none was specified or
 | 
						|
	// if it is different to the submitted or previous stored
 | 
						|
	if($account_type == "" || $account_type != $accounts[0]->get_type()) {
 | 
						|
		$account_type = $accounts[0]->get_type();
 | 
						|
	}
 | 
						|
	// Get PDF structure from xml file
 | 
						|
	$load = loadPDFStructureDefinitions($account_type,$pdf_structure);
 | 
						|
	$structure = $load['structure'];
 | 
						|
	
 | 
						|
	// The decimal separator must be a dot in order to write pdf-files
 | 
						|
	setlocale(LC_NUMERIC, "C");
 | 
						|
	
 | 
						|
	$fontName = "BitstreamVeraSans-Roman"; // TODO: load font name from XML file
 | 
						|
	
 | 
						|
	// Create a new PDF file acording to the account type
 | 
						|
	$pdf = new LamPDF($account_type,$load['page_definitions'],$fontName);
 | 
						|
	
 | 
						|
	// Loop over each account and add a new page in the PDF file for it 
 | 
						|
	foreach($accounts as $account) {
 | 
						|
		
 | 
						|
		// Start a new page for each account
 | 
						|
		$pdf->AddPage();
 | 
						|
		
 | 
						|
		// Get PDF entries for the current account
 | 
						|
		$entries = $account->get_pdfEntries();
 | 
						|
		
 | 
						|
		// Now create the PDF file acording to the structure with the submitted values 
 | 
						|
		foreach($structure as $entry) {
 | 
						|
			// We have a new section to start
 | 
						|
			if($entry['tag'] == "SECTION" && $entry['type'] == "open") {
 | 
						|
				$name = $entry['attributes']['NAME'];
 | 
						|
				if(preg_match("/^\_[a-zA-Z\_]+/",$name)) {
 | 
						|
					$section_headline = getSectionHeadline($entries[substr($name,1)][0]);
 | 
						|
				}
 | 
						|
				else {
 | 
						|
					$section_headline = $name;
 | 
						|
				}
 | 
						|
				$pdf->setFont($fontName,"B",10);
 | 
						|
				$pdf->Write(0,$section_headline . ":");
 | 
						|
				$pdf->Ln(6);
 | 
						|
			}
 | 
						|
			// We have a section to end
 | 
						|
			elseif($entry['tag'] == "SECTION" && $entry['type'] == "close") {
 | 
						|
				$pdf->Ln(9);
 | 
						|
			}
 | 
						|
			// We have to include a static text.
 | 
						|
			elseif($entry['tag'] == "TEXT") {
 | 
						|
				// Load PDF text from structure array
 | 
						|
				$info_string = $entry['value'];
 | 
						|
				// Set font for text
 | 
						|
				$pdf->setFont($fontName,"",10);
 | 
						|
				$pdf->MultiCell(0,5,$info_string,0,"L",0);
 | 
						|
				// Print linebreak afterwards
 | 
						|
				$pdf->Ln(6);
 | 
						|
			}
 | 
						|
			// We have to include an entry from the account
 | 
						|
			elseif($entry['tag'] == "ENTRY") {
 | 
						|
				// Get name of current entry
 | 
						|
				$name = $entry['attributes']['NAME'];
 | 
						|
				
 | 
						|
				// Get current entry
 | 
						|
				$value_entry = $entries[$name];
 | 
						|
				
 | 
						|
				// Print entry only when module sumitted values for it
 | 
						|
				if(is_array($value_entry)) {
 | 
						|
					// Loop over all rows of this entry (most of the time this will be just one)
 | 
						|
					foreach($value_entry as $line) {
 | 
						|
						// Substitue XML syntax with valid FPDF methods
 | 
						|
						$methods = processLine($line,true,$fontName);
 | 
						|
						// Call every method
 | 
						|
						foreach($methods as $method) {
 | 
						|
							call_user_func_array(array(&$pdf,$method[0]),$method[1]);
 | 
						|
						}
 | 
						|
					}
 | 
						|
				}
 | 
						|
				$key = false;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	
 | 
						|
	// Close PDF
 | 
						|
	$pdf->Close();
 | 
						|
	// Get relative url path
 | 
						|
	$fullpath = realpath('.');
 | 
						|
	$subdirs = explode('/', str_replace($_SESSION['lampath'], '', $fullpath));
 | 
						|
	for ($i=0; $i<count($subdirs); $i++ ) $filename .= '../';
 | 
						|
	// use timestamp and random number from ldap.inc as filename so it should be unique.
 | 
						|
	$filename .= 'tmp/' . $_SESSION['ldap']->new_rand() . time() .'.pdf';
 | 
						|
	// Save PDF
 | 
						|
	$pdf->Output($filename);
 | 
						|
	// Output meta refresh to pdf-file
 | 
						|
	metaRefresh($filename);
 | 
						|
	// Return relative path of pdf-file
 | 
						|
	return $filename;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Creates a section headline.
 | 
						|
 * 
 | 
						|
 * @param string $line section name
 | 
						|
 * 
 | 
						|
 * @return string XML code for headline
 | 
						|
 */
 | 
						|
function getSectionHeadline($line) {
 | 
						|
	$headline_pattern = '/<block>.*<value>(.*)<\/value><\/block>/';
 | 
						|
	if(preg_match($headline_pattern,$line,$matches)) {
 | 
						|
		$valueStyle = processFormatTags($matches[1],'');
 | 
						|
		return $valueStyle[1];
 | 
						|
	}
 | 
						|
	else {
 | 
						|
		return '';
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Creates the XML code for an PDF entry.
 | 
						|
 * 
 | 
						|
 * @param string $line XML code of PDF entry
 | 
						|
 * @param boolean $first_td True if this is the first column
 | 
						|
 * 
 | 
						|
 * @return array XML codes
 | 
						|
 */
 | 
						|
function processLine($line,$first_td = true, $fontName) {
 | 
						|
	global $key, $line_width;
 | 
						|
	
 | 
						|
	// PCRE matching <block> tag
 | 
						|
	$block_pattern = '/<block><\/block>/';
 | 
						|
	// PCRE matching a <key> tag
 | 
						|
	$key_pattern = '/(<block>)<key>(.+)<\/key>(.*<\/block>)/';
 | 
						|
	// PCRE matching a <value> tag
 | 
						|
	// !!FIXME!! value must contain at least one character
 | 
						|
	$value_pattern = '/(<block>.*)<value>(.*)<\/value>(<\/block>)/';
 | 
						|
	// PCRE matching a <td> tag
 | 
						|
	$td_pattern = '/(<block>.*?)<td(.*?)>(.+?)<\/td>(.*<\/block>)/';
 | 
						|
	// PCRE matching <tr> tag
 | 
						|
	$tr_pattern = '/<tr><\/tr>/';
 | 
						|
	// PCRE matching a <p> tag
 | 
						|
	$p_pattern = '/(<block>.*)<p>(.+)<\/p>(.*<\/block>)/';
 | 
						|
	// PCRE matching a <br> tag
 | 
						|
	$br_pattern = '/<br \/>/';
 | 
						|
	
 | 
						|
	$return = array();
 | 
						|
	if(preg_match($key_pattern,$line,$matches)) {
 | 
						|
		$key = true;
 | 
						|
		$line_width = $line_width - 50;
 | 
						|
		$format = processFormatTags($matches[2],'B');
 | 
						|
		$return[] = array('setFont',array($fontName,$format[0],7));
 | 
						|
		$return[] = array('Cell',array(50,5,$format[1] . ':',0,0,'R',0));
 | 
						|
		$return[] = array('setFont',array($fontName,'',7));
 | 
						|
		return array_merge($return,processLine($matches[1] . $matches[3],false,$fontName));
 | 
						|
	}
 | 
						|
	elseif(preg_match($value_pattern,$line,$matches)) {
 | 
						|
		$format = processFormatTags($matches[2],'');
 | 
						|
		$return[] = array('setFont',array($fontName,$format[0],7));
 | 
						|
		$return[] = array('MultiCell',array(0,5,$format[1],0,'L',0));
 | 
						|
		$return[] = array('setFont',array($fontName,'',7));
 | 
						|
		return array_merge($return,processLine($matches[1] . $matches[3],true,$fontName));
 | 
						|
	}
 | 
						|
	elseif(preg_match($p_pattern,$line,$matches)) {
 | 
						|
		$format = processFormatTags($matches[2],'');
 | 
						|
		$return[] = array('setFont',array($fontName,$format[0],7));
 | 
						|
		$return[] = array('Write',array(5,$format[1]));
 | 
						|
		$return[] = array('setFont',array($fontName,'',7));
 | 
						|
		return array_merge($return,processLine($matches[1] . $matches[3],true,$fontName));
 | 
						|
	}
 | 
						|
	elseif(preg_match($td_pattern,$line,$matches)) {
 | 
						|
		if($first_td && $key) {
 | 
						|
			$first_td = !$first_td;
 | 
						|
			$return[] = array('Cell',array(50,5,'',0,0,'L',0));
 | 
						|
		}
 | 
						|
		$format = processFormatTags($matches[3],'');
 | 
						|
		$attrs = processAttributes($matches[2],array('width' => $line_width,'height' => 5,'align' => 'L'));
 | 
						|
		$return[] = array('setFont',array($fontName,$format[0],7));
 | 
						|
		$return[] = array('Cell',array($attrs['width'],$attrs['height'],$format[1],0,0,$attrs['align'],0));
 | 
						|
		$return[] = array('setFont',array($fontName,'',7));
 | 
						|
		return array_merge($return,processLine($matches[1] . $matches[4],$first_td,$fontName));
 | 
						|
	}
 | 
						|
	elseif(preg_match($br_pattern,$line,$matches)) {
 | 
						|
		return array(array('Ln',array(5)));
 | 
						|
	}
 | 
						|
	elseif(preg_match($block_pattern,$line,$matches)) {
 | 
						|
		$line_width = LAMPDF_LINEWIDTH;
 | 
						|
		return array();
 | 
						|
	}
 | 
						|
	elseif(preg_match($tr_pattern,$line,$matches)) {
 | 
						|
		$line_width = LAMPDF_LINEWIDTH;
 | 
						|
		return array(array('Ln',array(5)));
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Formats the XML code.
 | 
						|
 * 
 | 
						|
 * @param string $line XML code of PDF entry
 | 
						|
 * @param string $style style commands
 | 
						|
 * 
 | 
						|
 * @return array XML code
 | 
						|
 */
 | 
						|
function processFormatTags($line,$style) {
 | 
						|
	// PCRE matching a <i> tag
 | 
						|
	$i_pattern = '/(.*)<i>(.+)<\/i>(.*)/';
 | 
						|
	// PCRE matching a <b> tag
 | 
						|
	$b_pattern = '/(.*)<b>(.+)<\/b>(.*)/';
 | 
						|
	// PCRE matching a <u> tag
 | 
						|
	$u_pattern = '/(.*)<u>(.+)<\/u>(.*)/';
 | 
						|
	// Replacement pattern when one of the above pattern matched
 | 
						|
	$replace = "\$1\$2\$3";
 | 
						|
	
 | 
						|
	if(preg_match($i_pattern,$line,$matches)) {
 | 
						|
		$style .= "I";
 | 
						|
		$line = preg_replace($i_pattern,$replace,$line);
 | 
						|
	}
 | 
						|
	if(preg_match($b_pattern,$line,$matches)) {
 | 
						|
		$style .= "B";
 | 
						|
		$line = preg_replace($b_pattern,$replace,$line);
 | 
						|
	}
 | 
						|
	if(preg_match($u_pattern,$line,$matches)) {
 | 
						|
		$style .= "U";
 | 
						|
		$line = preg_replace($u_pattern,$replace,$line);
 | 
						|
	}
 | 
						|
	return array($style,$line);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Processes width, height and alignment attributes.
 | 
						|
 * 
 | 
						|
 * @param string $attrs attributes
 | 
						|
 * @param array $return XML code
 | 
						|
 * 
 | 
						|
 * @return array XML code
 | 
						|
 */
 | 
						|
function processAttributes($attrs,$return = array()) {
 | 
						|
	global $line_width;
 | 
						|
	
 | 
						|
	// PCRE matching width attribute
 | 
						|
	$width_pattern = '/(.*)width\=\"(\\d+)(\%?)\"(.*)/';
 | 
						|
	// PCRE matching height attribute
 | 
						|
	$height_pattern = '/(.*)height\=\"(\\d+)\"(.*)/';
 | 
						|
	// PCRE matching align attribute
 | 
						|
	$align_pattern = '/(.*)align\=\"(L|R|C)\"(.*)/';
 | 
						|
	
 | 
						|
	// Remove leading and trailing whitespaces
 | 
						|
	$attrs = trim($attrs);
 | 
						|
	
 | 
						|
	if(preg_match($width_pattern,$attrs,$matches)) {
 | 
						|
		if($matches[3] == '%') {
 | 
						|
			$return['width'] = ceil($line_width * $matches[2] / 100);
 | 
						|
		}
 | 
						|
		else {
 | 
						|
			$return['width'] = ceil($matches[2]);
 | 
						|
		}
 | 
						|
		return processAttributes($matches[1] . $matches[4],$return);
 | 
						|
	}
 | 
						|
	elseif(preg_match($height_pattern,$attrs,$matches)) {
 | 
						|
		$return['height'] = $matches[2];
 | 
						|
		return processAttributes($matches[1] . $matches[3],$return);
 | 
						|
	}
 | 
						|
	elseif(preg_match($align_pattern,$attrs,$matches)) {
 | 
						|
		$return['align'] = $matches[2];
 | 
						|
		return processAttributes($matches[1] . $matches[3],$return);
 | 
						|
	}
 | 
						|
	else {
 | 
						|
		return $return;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Creates a LAM information page in PDF format.
 | 
						|
 * 
 | 
						|
 * @package PDF
 | 
						|
 */
 | 
						|
class lamPDF extends UFPDF {
 | 
						|
	
 | 
						|
	/**
 | 
						|
	 * format settings for page layout
 | 
						|
	 */
 | 
						|
	var $page_definitions;
 | 
						|
	
 | 
						|
	/**
 | 
						|
	* current active font name
 | 
						|
	*/
 | 
						|
	var $fontName;
 | 
						|
	
 | 
						|
	/**
 | 
						|
	* list of supported fonts
 | 
						|
	* format: <font name> => array(<file for default font style>, <file for bold>, <italic>, <bold italic>)
 | 
						|
	*/
 | 
						|
	var $fontList = array(
 | 
						|
		'BitstreamVeraSans-Roman' => array('vera.php', 'verab.php', 'verabi.php', 'verai.php')
 | 
						|
	);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * 
 | 
						|
	 * 
 | 
						|
	 * @param string $account_type
 | 
						|
	 * @param array $page_definitions
 | 
						|
	 */
 | 
						|
	function lamPDF($account_type = "user",$page_definitions = array(),$fontName) {
 | 
						|
		$this->fontName = $fontName;
 | 
						|
		define('FPDF_FONTPATH', $_SESSION['lampath'] . "lib/" . 'font/');
 | 
						|
		// Call constructor of superclass
 | 
						|
		$this->FPDF('P','mm','A4');
 | 
						|
		
 | 
						|
		$this->page_definitions = $page_definitions;
 | 
						|
		
 | 
						|
		// Open PDF file and write some basic information
 | 
						|
		$this->Open();
 | 
						|
		$this->AddFont($this->fontName, '', $this->fontList[$this->fontName][0]);
 | 
						|
		$this->AddFont($this->fontName, 'B', $this->fontList[$this->fontName][1]);
 | 
						|
		$this->AddFont($this->fontName, 'I', $this->fontList[$this->fontName][2]);
 | 
						|
		$this->AddFont($this->fontName, 'BI', $this->fontList[$this->fontName][3]);
 | 
						|
		$this->setFont($this->fontName,"",12);
 | 
						|
		$this->setTitle($this->page_definitions['headline']);
 | 
						|
		$this->setCreator("LDAP Account Manager");
 | 
						|
		$this->setMargins($this->page_definitions['margin-left'],$this->page_definitions['margin-top'],$this->page_definitions['margin-right']);
 | 
						|
		$this->setAutoPageBreak(true,$this->page_definitions['margin-bottom']);
 | 
						|
	}
 | 
						|
	
 | 
						|
	/**
 | 
						|
	 * 
 | 
						|
	 */
 | 
						|
	function header() {
 | 
						|
		if($this->page_definitions['filename'] != 'none') {
 | 
						|
			$imageFile = substr(__FILE__,0,strlen(__FILE__)- 11) . "config/pdf/logos/" . $this->page_definitions['filename'];
 | 
						|
			$width = $this->page_definitions['logo-width'];
 | 
						|
			$height = $this->page_definitions['logo-height'];
 | 
						|
			if($this->page_definitions['logo-max'] == true) {
 | 
						|
				if(($width / $height) <= 2.5) {
 | 
						|
					$factor = 20 / $height;
 | 
						|
					$width = $factor * $width;
 | 
						|
					$height = 20;
 | 
						|
				}
 | 
						|
				else {
 | 
						|
					$factor = 50 / $width;
 | 
						|
					$height = $factor * $height;
 | 
						|
					$width = 50;
 | 
						|
				}
 | 
						|
			}
 | 
						|
			$this->Image($imageFile,10,10,$width,$height,"JPG");
 | 
						|
		}
 | 
						|
		$this->SetY(18);
 | 
						|
		$this->SetFont($this->fontName,"B",18);
 | 
						|
		$this->Cell(170,5,$this->page_definitions['headline'],0,1,"R",0);
 | 
						|
		$this->Ln(3);
 | 
						|
		$this->SetLineWidth(0.4);
 | 
						|
		$this->Line(10,$this->page_definitions['margin-top'] + 30,200,$this->page_definitions['margin-top'] + 30);
 | 
						|
		$this->Line(10,$this->page_definitions['margin-top'] + 32,200,$this->page_definitions['margin-top'] + 32);
 | 
						|
		$this->SetY(50);
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * 
 | 
						|
	 */
 | 
						|
	function footer() {
 | 
						|
		$this->SetLineWidth(0.4);
 | 
						|
		$this->Line(10,280,200,280);
 | 
						|
		$this->Line(10,282,200,282);
 | 
						|
		$this->SetY(286);
 | 
						|
		$this->SetFont($this->fontName,"",7);
 | 
						|
		$this->Cell(0,5,_("This document was automatically created by LDAP Account Manager"),0,0,"C",0);
 | 
						|
	}
 | 
						|
} |