1: <?php
2: /* vim: set expandtab tabstop=4 shiftwidth=4: */
3: // +----------------------------------------------------------------------+
4: // | PHP Version 4 |
5: // +----------------------------------------------------------------------+
6: // | Copyright (c) 1997-2002 The PHP Group |
7: // +----------------------------------------------------------------------+
8: // | This source file is subject to version 2.02 of the PHP license, |
9: // | that is bundled with this package in the file LICENSE, and is |
10: // | available at through the world-wide-web at |
11: // | http://www.php.net/license/2_02.txt. |
12: // | If you did not receive a copy of the PHP license and are unable to |
13: // | obtain it through the world-wide-web, please send a note to |
14: // | license@php.net so we can mail you a copy immediately. |
15: // +----------------------------------------------------------------------+
16: // | Author: Xavier Noguer <xnoguer@php.net> |
17: // | Based on OLE::Storage_Lite by Kawai, Takanori |
18: // +----------------------------------------------------------------------+
19: //
20: // $Id: PPS.php,v 1.7 2007/02/13 21:00:42 schmidt Exp $
21:
22:
23: /**
24: * Class for creating PPS's for OLE containers
25: *
26: * @author Xavier Noguer <xnoguer@php.net>
27: * @category PHPExcel
28: * @package PHPExcel_Shared_OLE
29: */
30: class PHPExcel_Shared_OLE_PPS
31: {
32: /**
33: * The PPS index
34: * @var integer
35: */
36: public $No;
37:
38: /**
39: * The PPS name (in Unicode)
40: * @var string
41: */
42: public $Name;
43:
44: /**
45: * The PPS type. Dir, Root or File
46: * @var integer
47: */
48: public $Type;
49:
50: /**
51: * The index of the previous PPS
52: * @var integer
53: */
54: public $PrevPps;
55:
56: /**
57: * The index of the next PPS
58: * @var integer
59: */
60: public $NextPps;
61:
62: /**
63: * The index of it's first child if this is a Dir or Root PPS
64: * @var integer
65: */
66: public $DirPps;
67:
68: /**
69: * A timestamp
70: * @var integer
71: */
72: public $Time1st;
73:
74: /**
75: * A timestamp
76: * @var integer
77: */
78: public $Time2nd;
79:
80: /**
81: * Starting block (small or big) for this PPS's data inside the container
82: * @var integer
83: */
84: public $_StartBlock;
85:
86: /**
87: * The size of the PPS's data (in bytes)
88: * @var integer
89: */
90: public $Size;
91:
92: /**
93: * The PPS's data (only used if it's not using a temporary file)
94: * @var string
95: */
96: public $_data;
97:
98: /**
99: * Array of child PPS's (only used by Root and Dir PPS's)
100: * @var array
101: */
102: public $children = array();
103:
104: /**
105: * Pointer to OLE container
106: * @var OLE
107: */
108: public $ole;
109:
110: /**
111: * The constructor
112: *
113: * @access public
114: * @param integer $No The PPS index
115: * @param string $name The PPS name
116: * @param integer $type The PPS type. Dir, Root or File
117: * @param integer $prev The index of the previous PPS
118: * @param integer $next The index of the next PPS
119: * @param integer $dir The index of it's first child if this is a Dir or Root PPS
120: * @param integer $time_1st A timestamp
121: * @param integer $time_2nd A timestamp
122: * @param string $data The (usually binary) source data of the PPS
123: * @param array $children Array containing children PPS for this PPS
124: */
125: public function __construct($No, $name, $type, $prev, $next, $dir, $time_1st, $time_2nd, $data, $children)
126: {
127: $this->No = $No;
128: $this->Name = $name;
129: $this->Type = $type;
130: $this->PrevPps = $prev;
131: $this->NextPps = $next;
132: $this->DirPps = $dir;
133: $this->Time1st = $time_1st;
134: $this->Time2nd = $time_2nd;
135: $this->_data = $data;
136: $this->children = $children;
137: if ($data != '') {
138: $this->Size = strlen($data);
139: } else {
140: $this->Size = 0;
141: }
142: }
143:
144: /**
145: * Returns the amount of data saved for this PPS
146: *
147: * @access public
148: * @return integer The amount of data (in bytes)
149: */
150: public function _DataLen()
151: {
152: if (!isset($this->_data)) {
153: return 0;
154: }
155: //if (isset($this->_PPS_FILE)) {
156: // fseek($this->_PPS_FILE, 0);
157: // $stats = fstat($this->_PPS_FILE);
158: // return $stats[7];
159: //} else {
160: return strlen($this->_data);
161: //}
162: }
163:
164: /**
165: * Returns a string with the PPS's WK (What is a WK?)
166: *
167: * @access public
168: * @return string The binary string
169: */
170: public function _getPpsWk()
171: {
172: $ret = str_pad($this->Name,64,"\x00");
173:
174: $ret .= pack("v", strlen($this->Name) + 2) // 66
175: . pack("c", $this->Type) // 67
176: . pack("c", 0x00) //UK // 68
177: . pack("V", $this->PrevPps) //Prev // 72
178: . pack("V", $this->NextPps) //Next // 76
179: . pack("V", $this->DirPps) //Dir // 80
180: . "\x00\x09\x02\x00" // 84
181: . "\x00\x00\x00\x00" // 88
182: . "\xc0\x00\x00\x00" // 92
183: . "\x00\x00\x00\x46" // 96 // Seems to be ok only for Root
184: . "\x00\x00\x00\x00" // 100
185: . PHPExcel_Shared_OLE::LocalDate2OLE($this->Time1st) // 108
186: . PHPExcel_Shared_OLE::LocalDate2OLE($this->Time2nd) // 116
187: . pack("V", isset($this->_StartBlock)?
188: $this->_StartBlock:0) // 120
189: . pack("V", $this->Size) // 124
190: . pack("V", 0); // 128
191: return $ret;
192: }
193:
194: /**
195: * Updates index and pointers to previous, next and children PPS's for this
196: * PPS. I don't think it'll work with Dir PPS's.
197: *
198: * @access public
199: * @param array &$raList Reference to the array of PPS's for the whole OLE
200: * container
201: * @return integer The index for this PPS
202: */
203: public static function _savePpsSetPnt(&$raList, $to_save, $depth = 0)
204: {
205: if ( !is_array($to_save) || (empty($to_save)) ) {
206: return 0xFFFFFFFF;
207: } elseif( count($to_save) == 1 ) {
208: $cnt = count($raList);
209: // If the first entry, it's the root... Don't clone it!
210: $raList[$cnt] = ( $depth == 0 ) ? $to_save[0] : clone $to_save[0];
211: $raList[$cnt]->No = $cnt;
212: $raList[$cnt]->PrevPps = 0xFFFFFFFF;
213: $raList[$cnt]->NextPps = 0xFFFFFFFF;
214: $raList[$cnt]->DirPps = self::_savePpsSetPnt($raList, @$raList[$cnt]->children, $depth++);
215: } else {
216: $iPos = floor(count($to_save) / 2);
217: $aPrev = array_slice($to_save, 0, $iPos);
218: $aNext = array_slice($to_save, $iPos + 1);
219: $cnt = count($raList);
220: // If the first entry, it's the root... Don't clone it!
221: $raList[$cnt] = ( $depth == 0 ) ? $to_save[$iPos] : clone $to_save[$iPos];
222: $raList[$cnt]->No = $cnt;
223: $raList[$cnt]->PrevPps = self::_savePpsSetPnt($raList, $aPrev, $depth++);
224: $raList[$cnt]->NextPps = self::_savePpsSetPnt($raList, $aNext, $depth++);
225: $raList[$cnt]->DirPps = self::_savePpsSetPnt($raList, @$raList[$cnt]->children, $depth++);
226:
227: }
228: return $cnt;
229: }
230: }
231: