ppub.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. <?php
  2. class Asset {
  3. public $path = "";
  4. public $mimetype = "";
  5. public $start_location = 0;
  6. public $end_location = 0;
  7. public $flags = array();
  8. public function __construct($path, $mimetype, $slocation, $elocation, $flags) {
  9. $this->path = $path;
  10. $this->mimetype = $mimetype;
  11. $this->start_location = $slocation;
  12. $this->end_location = $elocation;
  13. $this->flags = $flags;
  14. }
  15. }
  16. class Ppub {
  17. public $metadata = array();
  18. public $asset_index = array();
  19. public $asset_list = array();
  20. public $default_asset = null;
  21. private $handle = null;
  22. private $blob_start = 0;
  23. public function read_file($file_path) {
  24. $handle = fopen($file_path, "rb");
  25. if(fread($handle, 5) != "ppub\n"){
  26. throw new Exception("File did not start with PPUB magic number", 1);
  27. }
  28. $head_size_string = "";
  29. $next_char = '';
  30. while($next_char != "\n"){
  31. $head_size_string .= $next_char;
  32. $next_char = fread($handle, 1);
  33. }
  34. $index_length = intval($head_size_string);
  35. $index_data = fread($handle, $index_length);
  36. $this->handle = $handle;
  37. $this->blob_start = strlen($head_size_string) + $index_length + 6;
  38. $this->build_asset_list($index_data);
  39. $this->build_metadata($this->read_asset($this->asset_list[0]));
  40. }
  41. public function read_asset($asset) {
  42. $start_location = $asset->start_location + $this->blob_start;
  43. $length = $asset->end_location - $asset->start_location;
  44. fseek($this->handle, $start_location);
  45. $data = fread($this->handle, $length);
  46. if(in_array("gzip", $asset->flags)) {
  47. $data = gzdecode($data);
  48. }
  49. return $data;
  50. }
  51. public function get_asset_size($asset) {
  52. $start_location = $asset->start_location + $this->blob_start;
  53. $length = $asset->end_location - $asset->start_location;
  54. return $length;
  55. }
  56. public function can_stream_asset($asset) {
  57. return !in_array("gzip", $asset->flags);
  58. }
  59. public function stream_asset($asset, $start = 0, $end = -1) {
  60. $start_location = $asset->start_location + $this->blob_start + $start;
  61. $length = ($end < 0) ? $asset->end_location - $asset->start_location - $start : $end - $start;
  62. fseek($this->handle, $start_location);
  63. $pos = 0;
  64. while($pos < $length) {
  65. $chunksize = min(1024 * 1024, $length - $pos);
  66. echo(fread($this->handle, $chunksize));
  67. flush();
  68. $pos += $chunksize;
  69. }
  70. }
  71. private function build_asset_list($data) {
  72. $asset_list = array();
  73. $lines = explode("\n", $data);
  74. for ($i=0; $i < sizeof($lines); $i++) {
  75. if(trim($lines[$i]) == ''){
  76. continue;
  77. }
  78. $keyval = explode(": ", $lines[$i], 2);
  79. $vals = explode(" ", $keyval[1]);
  80. $asset = new Asset($keyval[0], $vals[0], intval($vals[1]), intval($vals[2]), array_slice($vals, 3));
  81. array_push($asset_list, $asset);
  82. $this->asset_index[$asset->path] = $asset;
  83. }
  84. $this->asset_list = $asset_list;
  85. }
  86. private function build_metadata($data) {
  87. $data_list = array();
  88. $lines = explode("\n", $data);
  89. for ($i=0; $i < sizeof($lines); $i++) {
  90. if(trim($lines[$i]) == ''){
  91. continue;
  92. }
  93. $keyval = explode(": ", $lines[$i], 2);
  94. $data_list[$keyval[0]] = $keyval[1];
  95. }
  96. $this->metadata = $data_list;
  97. }
  98. }
  99. ?>