[ Index ]

PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008]

title

Body

[close]

/lib/excel/ -> OLEwriter.php (source)

   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  ?>


Generated: Wed Jan 14 11:33:29 2009 Cross-referenced by PHPXref 0.7