nyroFwk  0.2
http.class.php
Go to the documentation of this file.
1 <?php
11 
17  protected $headers;
18 
24  protected $beforeOut = array();
25 
26  protected function afterInit() {
27  $this->headers = $this->cfg->headers;
28  }
29 
36  public function getStatus($name = false) {
37  if ($name)
38  return $this->cfg->statusCfg[$this->cfg->status];
39  else
40  return $this->cfg->status;
41  }
42 
49  public function setStatus($status) {
50  if (array_key_exists($status, $this->cfg->statusCfg)) {
51  $this->cfg->status = $status;
52  return true;
53  }
54  return false;
55  }
56 
62  public function getCompress() {
63  return $this->cfg->compress;
64  }
65 
71  public function setCompress($compress) {
72  $this->cfg->compress = (boolean) $compress;
73  }
74 
80  public function getLayout() {
81  return $this->cfg->layout;
82  }
83 
89  public function setlayout($layout) {
90  $this->cfg->layout = $layout;
91  }
92 
98  public function getAjaxLayout() {
99  return $this->cfg->ajaxLayout;
100  }
101 
107  public function setAjaxlayout($ajaxLayout) {
108  $this->cfg->ajaxLayout = $ajaxLayout;
109  }
110 
119  public function addHeader($name, $value, $replace = true) {
120  if ($name == 'Content-Type')
121  return $this->setContentType($value, $replace);
122  if ($replace || !$this->hasHeader($name)) {
123  $this->headers[$name] = $value;
124  return true;
125  }
126  return false;
127  }
128 
137  public function setContentType($value, $replace = true) {
138  if ($replace || !$this->hasHeader('Content-Type')) {
139  if (array_key_exists($value, $this->cfg->contentTypeCfg))
140  $value = $this->cfg->getInArray('contentTypeCfg', $value);
141  else if (strpos($value, '/') === false)
142  $value = 'text/'.$value;
143  $this->headers['Content-Type'] = $value.'; charset='.$this->cfg->charset;
144  return true;
145  }
146  return false;
147  }
148 
152  public function neverExpire() {
153  $this->addHeader('Expires', gmdate('D, j M Y H:i:s', strtotime('+32 days')).' GMT');
154  }
155 
162  public function getHeader($name = null) {
163  if (is_null($name))
164  return $this->headers;
165  if ($this->hasHeader($name))
166  return $this->headers[$name];
167  return null;
168  }
169 
176  public function hasHeader($name) {
177  return array_key_exists($name, $this->headers);
178  }
179 
183  public function clearHeaders() {
184  $this->headers = $this->cfg->headers;
185  }
186 
190  public function sendHeaders() {
191  if (!headers_sent()) {
192  header('HTTP/1.0 '.$this->getStatus().' '.$this->getStatus(true));
193  foreach($this->headers as $name=>$value) {
194  header($name.': '.$value);
195  }
196  }
197  }
198 
204  public function addBeforeOut($callback) {
205  $this->beforeOut[] = $callback;
206  }
207 
211  protected function beforeOut() {
212  foreach($this->beforeOut as $bo)
213  call_user_func($bo);
214 
215  if ($this->cfg->compress && !ob_get_length())
216  ob_start('ob_gzhandler');
217  }
218 
224  public function send($headerOnly = false) {
225  if (!headers_sent()) {
226  $this->sendHeaders();
227  $this->beforeOut();
228  if ($headerOnly)
229  exit(0);
230  }
231 
232  $layout = request::isAjax()? $this->cfg->ajaxLayout : $this->cfg->layout;
233  $ret = null;
234  if (!$layout) {
235  $ret = $this->content;
236  } else {
237  $tpl = factory::get('tpl', array(
238  'module'=>'out',
239  'action'=>$layout,
240  'default'=>'layout',
241  'layout'=>false,
242  'cache'=>array('auto'=>false)
243  ));
244  $tpl->set('content', $this->content);
245  $ret = $tpl->fetch();
246  }
247  //if ($ret) $this->addHeader('Content-Length', strlen($ret), true);
248  return $ret;
249  }
250 
251  public function canGlobalCache() {
252  return $this->getAttr('globalCache');
253  }
254 
255  public function getVarsForGlobalCache() {
256  return array(
257  'status'=>$this->getStatus(),
258  'headers'=>$this->getHeader()
259  );
260  }
261 
262  public function setVarsFromGlobalCache($vars) {
263  if (!is_array($vars) || !isset($vars['status']) || ! is_array($vars['headers']))
264  throw new Exception('Error while retrieving from cache');
265  $this->setStatus($vars['status']);
266 
267  if (isset($vars['headers']['Content-Type'])) {
268  $this->headers['Content-Type'] = $vars['headers']['Content-Type'];
269  unset($vars['headers']['Content-Type']);
270  }
271 
272  foreach($vars['headers'] as $k=>$v)
273  $this->addHeader($k, $v, true);
274  $this->sendHeaders();
275  $this->beforeOut();
276  }
277 
283  public function sendText($text) {
284  //$this->addHeader('Content-Length', strlen($text), true);
285  $this->sendHeaders();
286  $this->beforeOut();
287  echo $text;
288  exit(0);
289  }
290 
298  public function sendFile($file, $name = null, $delete = false) {
299  $name = $name ? $name : basename($file);
300  if (file::exists($file))
301  $this->mediaDownload($file, true, $name, $delete);
302  else
303  $this->error();
304  }
305 
312  public function sendFileAsString($file, $name) {
313  $this->cfg->compress = false;
314  $this->neverExpire();
315  $this->addHeader('Expires', '0');
316  $this->addHeader('Cache-Control', 'must-revalidate, post-check=0, pre-check=0');
317  $this->addHeader('Content-Type', 'application/force-download');
318  $this->addHeader('Content-Disposition', 'attachment; filename='.$name.'');
319  $this->addHeader('Last-Modified', gmdate('D, j M Y H:i:s').' GMT', true);
320  $this->addHeader('Pragma', null, false);
321  $this->sendText($file);
322  }
323 
329  public function showFile($file) {
330  if (file::exists($file)) {
331  $type = file::getType($file);
332  if (strpos($type, 'audio') === 0 || strpos($type, 'video') === 0) {
333  $this->mediaDownload($file);
334  } else {
335  $this->cfg->compress = false;
336  $this->neverExpire();
337  $this->addHeader('Last-Modified', gmdate('D, j M Y H:i:s', filemtime($file)).' GMT', true);
338  $this->addHeader('Content-Type', $type, true);
339  $this->addHeader('Cache-Control', 'public', false);
340  $this->addHeader('Pragma', null, false);
341  $this->addHeader('Content-length', file::size($file), true);
342  $this->sendText(file::read($file));
343  }
344  }
345  }
346 
355  protected function mediaDownload($file, $forceDownload = false, $fileName = null, $delete = false) {
356  $fileName = $fileName ? $fileName : basename($file);
357  if(strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE'))
358  $fileName = preg_replace('/\./', '%2e', $fileName, substr_count($fileName, '.') - 1);
359  $fileModified = filemtime($file);
360  $fileSize = filesize($file);
361  $fileType = file::getType($file);
362  $audio = strpos($fileType, 'audio') === 0;
363  $video = strpos($fileType, 'video') === 0;
364 
365  $seekStart = 0;
366  $seekEnd = -1;
367  $bufferSize = 8*1024;
368  $partialDownload = false;
369  $httpRangeDownload = false;
370 
371  if (isset($_SERVER['HTTP_RANGE'])) {
372  $range = explode('-', substr($_SERVER['HTTP_RANGE'], strlen('bytes=')));
373  if($range[0] > 0)
374  $seekStart = intval($range[0]);
375  $seekEnd = $range[1] > 0 ? intval($range[1]) : -1;
376  $partialDownload = true;
377  $httpRangeDownload = true;
378  } else if ($audio && request::isMobile()) {
379  $partialDownload = true;
380  $httpRangeDownload = true;
381  }
382 
383  if ($seekEnd < $seekStart)
384  $seekEnd = $fileSize - 1;
385 
386  $contentLength = $seekEnd - $seekStart + 1;
387 
388  if(!$fileHandle = fopen($file, 'rb'))
389  $this->error();
390 
391  // headers
392  header('Pragma: public');
393  if ($forceDownload) {
394  if (ini_get('zlib.output_compression'))
395  ini_set('zlib.output_compression', 'Off');
396 
397  header('Expires: 0');
398  header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
399  header('Cache-Control: private', false);
400 
401  header('Content-Type: application/force-download');
402  header('Content-Type: application/octet-stream');
403  header('Content-Type: application/download');
404  header('Content-type: '.$fileType);
405  header('Content-Disposition: attachment; filename='.$fileName.'');
406  } else {
407  header('Cache-Control: public');
408  header('Content-type: '.$fileType);
409  header('Content-Disposition: inline; filename='.$fileName.'');
410  }
411  header('Last-Modified: '.date('D, d M Y H:i:s \G\M\T', $fileModified));
412  header("Content-Transfer-Encoding: binary\n");
413  if ($httpRangeDownload) {
414  header('HTTP/1.0 206 Partial Content');
415  header('Status: 206 Partial Content');
416  header('Accept-Ranges: bytes');
417  header('Content-Range: bytes '.$seekStart.'-'.$seekEnd.'/'.$fileSize);
418  }
419  header('Content-Length: '.$contentLength);
420 
421  if ($seekStart > 0) {
422  $partialDownload = true;
423  fseek($fileHandle, $seekStart);
424  if ($fileType == 'video/x-flv')
425  echo 'FLV', pack('C', 1), pack('C', 1), pack('N', 9), pack('N', 9);
426  }
427 
428  $this->setCompress(false);
429  $this->beforeOut();
430 
431  $speed = 0;
432  $bytesSent = 0;
433  $chunk = 1;
434  $throttle = $video ? 320 : ($audio ? 84 : 0);
435  $burst = 1024 * ($video ? 500 : ($audio ? 120 : 0));
436  while (!(connection_aborted() || connection_status() == 1) && $bytesSent < $contentLength) {
437  // 1st buffer size after the first burst has been sent
438  if ($bytesSent >= $burst)
439  $speed = $throttle;
440 
441  // make sure we don't read past the total file size
442  if ($bytesSent + $bufferSize > $contentLength)
443  $bufferSize = $contentLength - $bytesSent;
444 
445  // send data
446  echo fread($fileHandle, $bufferSize);
447  $bytesSent+= $bufferSize;
448 
449  // clean up
450  flush();
451 
452  // throttle
453  if($speed && ($bytesSent - $burst > $speed * $chunk*1024)) {
454  sleep(1);
455  $chunk++;
456  }
457  }
458 
459  fclose($fileHandle);
460 
461  if ($delete)
462  file::delete($file);
463  exit;
464  }
465 
472  public function comment($comment) {
473  $tmp = '';
474  switch(request::get('out')) {
475  case 'js':
476  case 'json':
477  case 'css':
478  $tmp = "/*\n[comment]\n*/\n";
479  break;
480  case 'html':
481  case 'xml':
482  $tmp = "<!--\n[comment]\n-->\n";
483  break;
484  }
485  return str_replace('[comment]', $comment, $tmp);
486  }
487 
494  public function redirect($url, $status = 301) {
495  $this->clearHeaders();
496  $this->setStatus($status);
497  $this->addHeader('Location', $url);
498  $this->sendHeaders();
499  $this->beforeOut();
500  exit(0);
501  }
502 
509  public function error($url = null, $number = 404) {
510  $this->redirect(request::uri($url? $url : '/'.$number), $number);
511  }
512 
513 }
getHeader($name=null)
Definition: http.class.php:162
setCompress($compress)
Definition: http.class.php:71
static get($get=null)
comment($comment)
Definition: http.class.php:472
static read($file)
Definition: file.class.php:242
sendText($text)
Definition: http.class.php:283
getAttr($name)
sendFile($file, $name=null, $delete=false)
Definition: http.class.php:298
setContentType($value, $replace=true)
Definition: http.class.php:137
static size($file)
Definition: file.class.php:325
getStatus($name=false)
Definition: http.class.php:36
mediaDownload($file, $forceDownload=false, $fileName=null, $delete=false)
Definition: http.class.php:355
static exists($file)
Definition: file.class.php:97
sendFileAsString($file, $name)
Definition: http.class.php:312
redirect($url, $status=301)
Definition: http.class.php:494
setVarsFromGlobalCache($vars)
Definition: http.class.php:262
hasHeader($name)
Definition: http.class.php:176
static getType($file)
Definition: file.class.php:413
static isAjax()
error($url=null, $number=404)
Definition: http.class.php:509
addBeforeOut($callback)
Definition: http.class.php:204
static isMobile($test=null)
static uri($prm=array())
setStatus($status)
Definition: http.class.php:49
static delete($file)
Definition: file.class.php:355
addHeader($name, $value, $replace=true)
Definition: http.class.php:119
setlayout($layout)
Definition: http.class.php:89
setAjaxlayout($ajaxLayout)
Definition: http.class.php:107
send($headerOnly=false)
Definition: http.class.php:224
static get($className, array $cfg=array())
showFile($file)
Definition: http.class.php:329
Generated on Sun Oct 15 2017 22:25:20 for nyroFwk by doxygen 1.8.13