| [ Index ] |
PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008] |
[Summary view] [Print] [Text view]
1 <?php 2 /* 3 * Module written/ported by Xavier Noguer <xnoguer@rezebra.com> 4 * 5 * The majority of this is _NOT_ my code. I simply ported it from the 6 * PERL Spreadsheet::WriteExcel module. 7 * 8 * The author of the Spreadsheet::WriteExcel module is John McNamara 9 * <jmcnamara@cpan.org> 10 * 11 * I _DO_ maintain this code, and John McNamara has nothing to do with the 12 * porting of this code to PHP. Any questions directly related to this 13 * class library should be directed to me. 14 * 15 * License Information: 16 * 17 * Spreadsheet::WriteExcel: A library for generating Excel Spreadsheets 18 * Copyright (C) 2002 Xavier Noguer xnoguer@rezebra.com 19 * 20 * This library is free software; you can redistribute it and/or 21 * modify it under the terms of the GNU Lesser General Public 22 * License as published by the Free Software Foundation; either 23 * version 2.1 of the License, or (at your option) any later version. 24 * 25 * This library is distributed in the hope that it will be useful, 26 * but WITHOUT ANY WARRANTY; without even the implied warranty of 27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 28 * Lesser General Public License for more details. 29 * 30 * You should have received a copy of the GNU Lesser General Public 31 * License along with this library; if not, write to the Free Software 32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 33 */ 34 35 /** 36 * Class for creating OLE streams for Excel Spreadsheets 37 * 38 * @author Xavier Noguer <xnoguer@rezebra.com> 39 * @package Spreadsheet_WriteExcel 40 */ 41 class OLEwriter 42 { 43 /** 44 * Filename for the OLE stream 45 * @var string 46 * @see _initialize() 47 */ 48 var $_OLEfilename; 49 50 /** 51 * Filehandle for the OLE stream 52 * @var resource 53 */ 54 var $_filehandle; 55 56 /** 57 * Name of the temporal file in case OLE stream goes to stdout 58 * @var string 59 */ 60 var $_tmp_filename; 61 62 /** 63 * Variable for preventing closing two times 64 * @var integer 65 */ 66 var $_fileclosed; 67 68 /** 69 * Size of the data to be written to the OLE stream 70 * @var integer 71 */ 72 var $_biffsize; 73 74 /** 75 * Real data size to be written to the OLE stream 76 * @var integer 77 */ 78 var $_booksize; 79 80 /** 81 * Number of big blocks in the OLE stream 82 * @var integer 83 */ 84 var $_big_blocks; 85 86 /** 87 * Number of list blocks in the OLE stream 88 * @var integer 89 */ 90 var $_list_blocks; 91 92 /** 93 * Number of big blocks in the OLE stream 94 * @var integer 95 */ 96 var $_root_start; 97 98 /** 99 * Class for creating an OLEwriter 100 * 101 * @param string $OLEfilename the name of the file for the OLE stream 102 */ 103 function OLEwriter($OLEfilename) 104 { 105 $this->_OLEfilename = $OLEfilename; 106 $this->_filehandle = ""; 107 $this->_tmp_filename = ""; 108 $this->_fileclosed = 0; 109 //$this->_size_allowed = 0; 110 $this->_biffsize = 0; 111 $this->_booksize = 0; 112 $this->_big_blocks = 0; 113 $this->_list_blocks = 0; 114 $this->_root_start = 0; 115 //$this->_block_count = 4; 116 $this->_initialize(); 117 } 118 119 /** 120 * Check for a valid filename and store the filehandle. 121 * Filehandle "-" writes to STDOUT 122 */ 123 function _initialize() 124 { 125 $OLEfile = $this->_OLEfilename; 126 127 if(($OLEfile == '-') or ($OLEfile == '')) 128 { 129 $this->_tmp_filename = tempnam("/tmp", "OLEwriter"); 130 $fh = fopen($this->_tmp_filename,"wb"); 131 if ($fh == false) { 132 die("Can't create temporary file."); 133 } 134 } 135 else 136 { 137 // Create a new file, open for writing (in binmode) 138 $fh = fopen($OLEfile,"wb"); 139 if ($fh == false) { 140 die("Can't open $OLEfile. It may be in use or protected."); 141 } 142 } 143 144 // Store filehandle 145 $this->_filehandle = $fh; 146 } 147 148 149 /** 150 * Set the size of the data to be written to the OLE stream. 151 * The maximun size comes from this: 152 * $big_blocks = (109 depot block x (128 -1 marker word) 153 * - (1 x end words)) = 13842 154 * $maxsize = $big_blocks * 512 bytes = 7087104 155 * 156 * @access public 157 * @see Workbook::store_OLE_file() 158 * @param integer $biffsize The size of the data to be written to the OLE stream 159 * @return integer 1 for success 160 */ 161 function set_size($biffsize) 162 { 163 $maxsize = 7087104; // TODO: extend max size 164 165 if ($biffsize > $maxsize) { 166 die("Maximum file size, $maxsize, exceeded."); 167 } 168 169 $this->_biffsize = $biffsize; 170 // Set the min file size to 4k to avoid having to use small blocks 171 if ($biffsize > 4096) { 172 $this->_booksize = $biffsize; 173 } 174 else { 175 $this->_booksize = 4096; 176 } 177 //$this->_size_allowed = 1; 178 return(1); 179 } 180 181 182 /** 183 * Calculate various sizes needed for the OLE stream 184 */ 185 function _calculate_sizes() 186 { 187 $datasize = $this->_booksize; 188 if ($datasize % 512 == 0) { 189 $this->_big_blocks = $datasize/512; 190 } 191 else { 192 $this->_big_blocks = floor($datasize/512) + 1; 193 } 194 // There are 127 list blocks and 1 marker blocks for each big block 195 // depot + 1 end of chain block 196 $this->_list_blocks = floor(($this->_big_blocks)/127) + 1; 197 $this->_root_start = $this->_big_blocks; 198 } 199 200 /** 201 * Write root entry, big block list and close the filehandle. 202 * This routine is used to explicitly close the open filehandle without 203 * having to wait for DESTROY. 204 * 205 * @access public 206 * @see Workbook::store_OLE_file() 207 */ 208 function close() 209 { 210 //return if not $this->{_size_allowed}; 211 $this->_write_padding(); 212 $this->_write_property_storage(); 213 $this->_write_big_block_depot(); 214 // Close the filehandle 215 fclose($this->_filehandle); 216 if(($this->_OLEfilename == '-') or ($this->_OLEfilename == '')) 217 { 218 $fh = fopen($this->_tmp_filename, "rb"); 219 if ($fh == false) { 220 die("Can't read temporary file."); 221 } 222 fpassthru($fh); 223 // Delete the temporary file. 224 @unlink($this->_tmp_filename); 225 } 226 $this->_fileclosed = 1; 227 } 228 229 230 /** 231 * Write BIFF data to OLE file. 232 * 233 * @param string $data string of bytes to be written 234 */ 235 function write($data) //por ahora sólo a STDOUT 236 { 237 fwrite($this->_filehandle,$data,strlen($data)); 238 } 239 240 241 /** 242 * Write OLE header block. 243 */ 244 function write_header() 245 { 246 $this->_calculate_sizes(); 247 $root_start = $this->_root_start; 248 $num_lists = $this->_list_blocks; 249 $id = pack("nnnn", 0xD0CF, 0x11E0, 0xA1B1, 0x1AE1); 250 $unknown1 = pack("VVVV", 0x00, 0x00, 0x00, 0x00); 251 $unknown2 = pack("vv", 0x3E, 0x03); 252 $unknown3 = pack("v", -2); 253 $unknown4 = pack("v", 0x09); 254 $unknown5 = pack("VVV", 0x06, 0x00, 0x00); 255 $num_bbd_blocks = pack("V", $num_lists); 256 $root_startblock = pack("V", $root_start); 257 $unknown6 = pack("VV", 0x00, 0x1000); 258 $sbd_startblock = pack("V", -2); 259 $unknown7 = pack("VVV", 0x00, -2 ,0x00); 260 $unused = pack("V", -1); 261 262 fwrite($this->_filehandle,$id); 263 fwrite($this->_filehandle,$unknown1); 264 fwrite($this->_filehandle,$unknown2); 265 fwrite($this->_filehandle,$unknown3); 266 fwrite($this->_filehandle,$unknown4); 267 fwrite($this->_filehandle,$unknown5); 268 fwrite($this->_filehandle,$num_bbd_blocks); 269 fwrite($this->_filehandle,$root_startblock); 270 fwrite($this->_filehandle,$unknown6); 271 fwrite($this->_filehandle,$sbd_startblock); 272 fwrite($this->_filehandle,$unknown7); 273 274 for($i=1; $i <= $num_lists; $i++) 275 { 276 $root_start++; 277 fwrite($this->_filehandle,pack("V",$root_start)); 278 } 279 for($i = $num_lists; $i <=108; $i++) 280 { 281 fwrite($this->_filehandle,$unused); 282 } 283 } 284 285 286 /** 287 * Write big block depot. 288 */ 289 function _write_big_block_depot() 290 { 291 $num_blocks = $this->_big_blocks; 292 $num_lists = $this->_list_blocks; 293 $total_blocks = $num_lists *128; 294 $used_blocks = $num_blocks + $num_lists +2; 295 296 $marker = pack("V", -3); 297 $end_of_chain = pack("V", -2); 298 $unused = pack("V", -1); 299 300 for($i=1; $i < $num_blocks; $i++) 301 { 302 fwrite($this->_filehandle,pack("V",$i)); 303 } 304 fwrite($this->_filehandle,$end_of_chain); 305 fwrite($this->_filehandle,$end_of_chain); 306 for($i=0; $i < $num_lists; $i++) 307 { 308 fwrite($this->_filehandle,$marker); 309 } 310 for($i=$used_blocks; $i <= $total_blocks; $i++) 311 { 312 fwrite($this->_filehandle,$unused); 313 } 314 } 315 316 /** 317 * Write property storage. TODO: add summary sheets 318 */ 319 function _write_property_storage() 320 { 321 //$rootsize = -2; 322 /*************** name type dir start size */ 323 $this->_write_pps("Root Entry", 0x05, 1, -2, 0x00); 324 $this->_write_pps("Book", 0x02, -1, 0x00, $this->_booksize); 325 $this->_write_pps('', 0x00, -1, 0x00, 0x0000); 326 $this->_write_pps('', 0x00, -1, 0x00, 0x0000); 327 } 328 329 /** 330 * Write property sheet in property storage 331 * 332 * @param string $name name of the property storage. 333 * @param integer $type type of the property storage. 334 * @param integer $dir dir of the property storage. 335 * @param integer $start start of the property storage. 336 * @param integer $size size of the property storage. 337 * @access private 338 */ 339 function _write_pps($name,$type,$dir,$start,$size) 340 { 341 $length = 0; 342 $rawname = ''; 343 344 if ($name != '') 345 { 346 $name = $name . "\0"; 347 for($i=0;$i<strlen($name);$i++) 348 { 349 // Simulate a Unicode string 350 $rawname .= pack("H*",dechex(ord($name{$i}))).pack("C",0); 351 } 352 $length = strlen($name) * 2; 353 } 354 355 $zero = pack("C", 0); 356 $pps_sizeofname = pack("v", $length); // 0x40 357 $pps_type = pack("v", $type); // 0x42 358 $pps_prev = pack("V", -1); // 0x44 359 $pps_next = pack("V", -1); // 0x48 360 $pps_dir = pack("V", $dir); // 0x4c 361 362 $unknown1 = pack("V", 0); 363 364 $pps_ts1s = pack("V", 0); // 0x64 365 $pps_ts1d = pack("V", 0); // 0x68 366 $pps_ts2s = pack("V", 0); // 0x6c 367 $pps_ts2d = pack("V", 0); // 0x70 368 $pps_sb = pack("V", $start); // 0x74 369 $pps_size = pack("V", $size); // 0x78 370 371 372 fwrite($this->_filehandle,$rawname); 373 for($i=0; $i < (64 -$length); $i++) { 374 fwrite($this->_filehandle,$zero); 375 } 376 fwrite($this->_filehandle,$pps_sizeofname); 377 fwrite($this->_filehandle,$pps_type); 378 fwrite($this->_filehandle,$pps_prev); 379 fwrite($this->_filehandle,$pps_next); 380 fwrite($this->_filehandle,$pps_dir); 381 for($i=0; $i < 5; $i++) { 382 fwrite($this->_filehandle,$unknown1); 383 } 384 fwrite($this->_filehandle,$pps_ts1s); 385 fwrite($this->_filehandle,$pps_ts1d); 386 fwrite($this->_filehandle,$pps_ts2d); 387 fwrite($this->_filehandle,$pps_ts2d); 388 fwrite($this->_filehandle,$pps_sb); 389 fwrite($this->_filehandle,$pps_size); 390 fwrite($this->_filehandle,$unknown1); 391 } 392 393 /** 394 * Pad the end of the file 395 */ 396 function _write_padding() 397 { 398 $biffsize = $this->_biffsize; 399 if ($biffsize < 4096) { 400 $min_size = 4096; 401 } 402 else { 403 $min_size = 512; 404 } 405 if ($biffsize % $min_size != 0) 406 { 407 $padding = $min_size - ($biffsize % $min_size); 408 for($i=0; $i < $padding; $i++) { 409 fwrite($this->_filehandle,"\0"); 410 } 411 } 412 } 413 } 414 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Wed Jan 14 11:33:29 2009 | Cross-referenced by PHPXref 0.7 |